Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/src/adapters/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ symlink_vellum() {

# Append PATH setup to ~/.config/vellum/env so callers can pick up PATH
# changes without restarting their shell:
# curl -fsSL https://assistant.vellum.ai/install.sh | bash && . ~/.config/vellum/env
# curl -fsSL https://vellum.ai/install.sh | bash && . ~/.config/vellum/env
write_env_file() {
local env_dir="${XDG_CONFIG_HOME:-$HOME/.config}/vellum"
local env_file="$env_dir/env"
Expand Down
2 changes: 1 addition & 1 deletion cli/src/commands/hatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export async function buildStartupScript(
cloud: RemoteHost,
): Promise<string> {
const platformUrl =
process.env.VELLUM_PLATFORM_URL ?? "https://assistant.vellum.ai";
process.env.VELLUM_PLATFORM_URL ?? "https://vellum.ai";
const logPath =
cloud === "custom"
? "/tmp/vellum-startup.log"
Expand Down
2 changes: 1 addition & 1 deletion cli/src/lib/gcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ export async function hatchGcp(
species === "vellum" &&
(await checkCurlFailure(instanceName, project, zone, account))
) {
const installScriptUrl = `${process.env.VELLUM_PLATFORM_URL ?? "https://assistant.vellum.ai"}/install.sh`;
const installScriptUrl = `${process.env.VELLUM_PLATFORM_URL ?? "https://vellum.ai"}/install.sh`;
console.log(
`\ud83d\udd04 Detected install script curl failure for ${installScriptUrl}, attempting recovery...`,
);
Expand Down
2 changes: 1 addition & 1 deletion clients/macos/vellum-assistant/App/AssistantCli.swift
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ final class AssistantCli {
#if DEBUG
env["VELLUM_PLATFORM_URL"] = "https://dev-assistant.vellum.ai"
#else
env["VELLUM_PLATFORM_URL"] = "https://assistant.vellum.ai"
env["VELLUM_PLATFORM_URL"] = "https://vellum.ai"
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ extension APIKeyStepView {
.font(.system(size: 13, weight: .medium))
.foregroundColor(VColor.contentSecondary)
VStack(alignment: .leading, spacing: VSpacing.xs) {
setupStep("1. On your Mac mini, run: curl -fsSL https://assistant.vellum.ai/install.sh | bash")
setupStep("1. On your Mac mini, run: curl -fsSL https://vellum.ai/install.sh | bash")
setupStep("2. Upload the QR code PNG generated by the install script below.")
}
}
Expand Down
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 QR code auto-detection from XDG path was not ported from deleted CloudCredentialsStepView

The deleted CloudCredentialsStepView.swift had auto-detection logic (lines 76-86) that checked for a QR code PNG at $XDG_DATA_HOME/vellum/pairing-qr/initial.png and pre-populated state.customQRCodeImageData. This logic was NOT ported to the new inline APIKeyStepView or its cloud fields extension. The onAppear in APIKeyStepView.swift:130-158 only restores file names from existing state but doesn't auto-detect from the filesystem path.

This means users who ran fetch-qr-code.sh before opening the app will no longer have the QR code auto-populated — they'll need to manually select it via the file picker. This may be intentional (simplification) or an oversight.

(Refers to lines 130-158)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — the QR code auto-detection from the XDG path was intentionally not ported. This is called out in the PR description under Notes. If the feature is desired in the inline flow, it can be added separately.

Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ struct APIKeyStepView: View {
}

private var showInlineCloudFields: Bool {
managedSignInEnabled && (hostingMode == .gcp || hostingMode == .aws || hostingMode == .customHardware)
hostingMode == .gcp || hostingMode == .aws || hostingMode == .customHardware
}

var body: some View {
Expand Down Expand Up @@ -159,7 +159,7 @@ struct APIKeyStepView: View {
}

if !managedSignInEnabled {
OnboardingFooter(currentStep: state.currentStep, totalSteps: userHostedEnabled ? 4 : 3)
OnboardingFooter(currentStep: state.currentStep, totalSteps: 3)
.padding(.bottom, VSpacing.lg)
}
}
Expand Down Expand Up @@ -254,6 +254,7 @@ struct APIKeyStepView: View {
guard !hatchButtonDisabled else { return }
saveAndHatch()
} else {
guard !primaryButtonDisabled else { return }
saveAndContinue()
}
}
Expand Down Expand Up @@ -321,7 +322,20 @@ struct APIKeyStepView: View {
// MARK: - Helpers

private var primaryButtonDisabled: Bool {
apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
if apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
return true
}
switch hostingMode {
case .gcp:
return state.gcpProjectId.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|| state.gcpServiceAccountKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
case .aws:
return state.awsRoleArn.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
case .customHardware:
return state.customQRCodeImageData.isEmpty
default:
return false
}
}

private var hatchButtonDisabled: Bool {
Expand Down Expand Up @@ -377,24 +391,19 @@ struct APIKeyStepView: View {
}

private func saveAndContinue() {
if userHostedEnabled {
if showHostingSelector {
state.cloudProvider = hostingMode.rawValue
} else {
state.cloudProvider = "local"
}

let trimmed = apiKey.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return }
APIKeyManager.setKey(trimmed, for: "anthropic")
APIKeyManager.syncKeyToDaemon(provider: "anthropic", value: trimmed)

saveModelToConfig("claude-opus-4-6")
if userHostedEnabled && hostingMode != .local && hostingMode != .docker {
state.advance()
} else if userHostedEnabled {
state.advance()
} else {
state.cloudProvider = "local"
state.advance()
}
saveModelToConfig("claude-opus-4-6")
state.advance()
Comment on lines +405 to +406

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate cloud credentials before advancing on submit

After moving cloud credentials inline, primaryButtonDisabled enforces those fields, but saveAndContinue() now advances as long as the API key is non-empty. The API-key SecureField still calls saveAndContinue() on submit, so pressing Enter in GCP/AWS/custom modes can skip required cloud credential input and continue to hatching with incomplete config. Add equivalent credential validation inside saveAndContinue() (or gate the submit path) so keyboard submit cannot bypass the disabled-button checks.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already addressed in 1373863 — the onSubmit handler now has guard !primaryButtonDisabled else { return } before calling saveAndContinue(), preventing Enter from bypassing cloud credential validation.

}

private func saveModelToConfig(_ model: String) {
Expand Down
Loading
Loading