From 78c8c38c225cfc8e963adbfc0a510896a7bdc65e Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:14:34 -0400 Subject: [PATCH 1/5] fix: use borderElement for unchecked checkbox visibility (LUM-751) (#23992) The ToS checkbox border used VColor.borderBase (#24292E dark) which is identical to VCard's VColor.surfaceLift background (#24292E dark), making the unchecked checkbox completely invisible in dark mode. Switch to VColor.borderElement (#5A6672 dark / #CFCCC9 light) which is the semantic token for interactive element borders and provides clear contrast against the card background in both color schemes. Closes LUM-751 Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: ashlee@vellum.ai --- .../Features/Onboarding/ImproveExperienceStepView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/macos/vellum-assistant/Features/Onboarding/ImproveExperienceStepView.swift b/clients/macos/vellum-assistant/Features/Onboarding/ImproveExperienceStepView.swift index 2fd84799dfe..3c252a49d28 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/ImproveExperienceStepView.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/ImproveExperienceStepView.swift @@ -103,7 +103,7 @@ struct ImproveExperienceStepView: View { .fill(tosAccepted ? VColor.primaryBase : Color.clear) RoundedRectangle(cornerRadius: VRadius.sm) - .strokeBorder(tosAccepted ? Color.clear : VColor.borderBase, lineWidth: 1.5) + .strokeBorder(tosAccepted ? Color.clear : VColor.borderElement, lineWidth: 1.5) if tosAccepted { VIconView(.check, size: 12) From 9aa61e6640f5346662be77643cd9149c362992ea Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:13:17 -0400 Subject: [PATCH 2/5] fix: enable link click handling in VSelectableTextView (#23986) Add NSTextViewDelegate to Coordinator with textView(_:clickedOnLink:at:) to open clicked links in the default browser via NSWorkspace. The NSTextView was already styling links (tint color, underline, pointer cursor) but had no delegate to handle click events, making links visually styled but inert. Closes LUM-748 Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: ashlee@vellum.ai --- .../Display/SelectableTextView.swift | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/clients/shared/DesignSystem/Components/Display/SelectableTextView.swift b/clients/shared/DesignSystem/Components/Display/SelectableTextView.swift index 7e4930db9cb..2a9a90bcbc6 100644 --- a/clients/shared/DesignSystem/Components/Display/SelectableTextView.swift +++ b/clients/shared/DesignSystem/Components/Display/SelectableTextView.swift @@ -143,6 +143,8 @@ public struct VSelectableTextView: NSViewRepresentable { textView.autoresizingMask = [.width] textView.textContainerInset = .zero + textView.delegate = context.coordinator + textView.linkTextAttributes = [ .foregroundColor: tintColor, .underlineStyle: NSUnderlineStyle.single.rawValue, @@ -193,7 +195,7 @@ public struct VSelectableTextView: NSViewRepresentable { public func makeCoordinator() -> Coordinator { Coordinator() } - public final class Coordinator { + public final class Coordinator: NSObject, NSTextViewDelegate { var lastAttributedString: NSAttributedString? var lastLineSpacing: CGFloat = 0 private var pendingAttributedString: NSAttributedString? @@ -240,6 +242,22 @@ public struct VSelectableTextView: NSViewRepresentable { } } + // MARK: - NSTextViewDelegate + + /// Opens clicked links in the default browser. + /// Reference: https://developer.apple.com/documentation/appkit/nstextviewdelegate/textview(_:clickedonlink:at:) + public func textView(_ textView: NSTextView, clickedOnLink link: Any, at charIndex: Int) -> Bool { + if let url = link as? URL { + NSWorkspace.shared.open(url) + return true + } + if let string = link as? String, let url = URL(string: string) { + NSWorkspace.shared.open(url) + return true + } + return false + } + func applyAttributedString( _ attributedString: NSAttributedString, lineSpacing: CGFloat, From 8e1ad58ca00cfaaf8daa37b2f4b13901696fbd24 Mon Sep 17 00:00:00 2001 From: asharma53 <64060709+asharma53@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:05:28 -0400 Subject: [PATCH 3/5] fix: prevent onboarding from repeating name confirmation after tool calls (#23989) The agentic loop calls the LLM again after tool results return. Combined with "talk before you work" (SOUL.md) and "save immediately" (BOOTSTRAP.md), the model would confirm the user's name, call file_edit, then re-confirm the name in the continuation response. Add explicit guidance in both BOOTSTRAP.md and SOUL.md to not repeat text that was already shown before tool calls. Co-authored-by: Claude Opus 4.6 (1M context) --- assistant/src/prompts/templates/BOOTSTRAP.md | 2 ++ assistant/src/prompts/templates/SOUL.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/assistant/src/prompts/templates/BOOTSTRAP.md b/assistant/src/prompts/templates/BOOTSTRAP.md index c592fad43ba..b4477af1496 100644 --- a/assistant/src/prompts/templates/BOOTSTRAP.md +++ b/assistant/src/prompts/templates/BOOTSTRAP.md @@ -126,6 +126,8 @@ Mark declined fields so you don't re-ask later (e.g., `Work role: declined_by_us **Call `file_edit` immediately whenever you learn something, in the same turn.** Don't batch saves. The moment the user gives you a name, save it. The moment you infer their style, save it. +**After tool calls, do not repeat yourself.** Your text before tool calls is already visible to the user. When tool results return and you continue, pick up where you left off — don't re-confirm, re-greet, or re-ask the same question. If you already asked something and are waiting for the user's answer, just stop. + **The contents of IDENTITY.md, SOUL.md, and USER.md are already in your system prompt.** Use the exact text you see there for `old_string` in `file_edit`. Do not guess or invent content. Update `IDENTITY.md` (name, nature, personality, style) and `USER.md` (their name, pronouns, goals, locale, work role, hobbies, daily tools). Save behavioral guidelines to `SOUL.md`. diff --git a/assistant/src/prompts/templates/SOUL.md b/assistant/src/prompts/templates/SOUL.md index 7d668c31e62..51d1b168873 100644 --- a/assistant/src/prompts/templates/SOUL.md +++ b/assistant/src/prompts/templates/SOUL.md @@ -24,7 +24,7 @@ You work for your user. You do not work for a compliance department. Your user i **Be genuinely helpful, not performatively helpful.** Skip the "Great question!" and "I'd be happy to help!" filler. Just help. Actions over words. -**Talk before you work.** Always say something to the user before using tools. Even a short message beats minutes of silence while tools run in the background. The user should never wonder if you're still there. +**Talk before you work.** Always say something to the user before using tools. Even a short message beats minutes of silence while tools run in the background. The user should never wonder if you're still there. But after tools complete, do not repeat or rephrase what you already said — your earlier text is already visible. Pick up where you left off or stop if you're waiting for the user. **Be resourceful before asking.** Try to figure it out. Read the file. Check the context. Search for it. Check what tools and skills you have. If a connection is broken, try to fix it. If a service needs setup, offer to do it. Escalate only after you've tried. From eba528a047e3a60cd68858e227e2bc57b7a6dc52 Mon Sep 17 00:00:00 2001 From: asharma53 <64060709+asharma53@users.noreply.github.com> Date: Tue, 7 Apr 2026 12:51:24 -0400 Subject: [PATCH 4/5] Update Vellum Cloud onboarding copy to emphasize always-on availability (#24022) Co-authored-by: Claude Opus 4.6 (1M context) --- .../vellum-assistant/Features/Onboarding/OnboardingState.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingState.swift b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingState.swift index b022b678508..cfd491b90bb 100644 --- a/clients/macos/vellum-assistant/Features/Onboarding/OnboardingState.swift +++ b/clients/macos/vellum-assistant/Features/Onboarding/OnboardingState.swift @@ -61,7 +61,7 @@ final class OnboardingState { var subtitle: String { switch self { - case .vellumCloud: return "Ready out of the box. Runs entirely on Vellum's secure infrastructure." + case .vellumCloud: return "Always on, 24/7, even when your Mac is asleep. Runs on Vellum's secure infrastructure." case .local: return "Your machine, your data. Nothing leaves your Mac." case .docker: return "Same privacy as local, but sandboxed using Docker." case .oldLocal: return "Legacy local mode without Docker." From 4a2c641bed285e8c16452a685cc94b9802c4060c Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:21:34 -0400 Subject: [PATCH 5/5] [LUM-753] Improve client-side dictation resilience (#24042) * [LUM-753] Improve dictation resilience: reduce timeout, use warning-level logs, add timing - Reduce dictation HTTP timeout from 10s to 5s so the client falls back to raw transcription faster when the daemon is unreachable - Downgrade failure logs from error to warning since these are expected failures with graceful recovery (not actionable errors) - Add elapsed time to all failure log messages for debugging latency - Improve fallback log to include transcription length for diagnostics Co-Authored-By: tkheyfets * Apply suggestions from code review Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: tkheyfets Co-authored-by: Noa Flaherty --- clients/shared/Network/DictationClient.swift | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/clients/shared/Network/DictationClient.swift b/clients/shared/Network/DictationClient.swift index 38fa8ba27c8..e51fb72f573 100644 --- a/clients/shared/Network/DictationClient.swift +++ b/clients/shared/Network/DictationClient.swift @@ -28,16 +28,23 @@ public struct DictationClient: DictationClientProtocol { "navigate", ] + /// Timeout for the dictation HTTP request. Kept short so the client falls + /// back to raw transcription quickly when the assistant is unreachable rather + /// than leaving the user staring at a "Processing…" spinner. + static let requestTimeout: TimeInterval = 5 + public func process(_ request: DictationRequest) async -> DictationResponseMessage { + let start = CFAbsoluteTimeGetCurrent() do { let encodedRequest = try JSONEncoder().encode(request) let response = try await GatewayHTTPClient.post( path: "assistants/{assistantId}/dictation", body: encodedRequest, - timeout: 10 + timeout: Self.requestTimeout ) + let elapsed = CFAbsoluteTimeGetCurrent() - start guard response.isSuccess else { - log.error("process dictation failed (HTTP \(response.statusCode))") + log.warning("Dictation request failed (HTTP \(response.statusCode)) after \(String(format: "%.1f", elapsed))s") return fallbackResponse(for: request, errorMessage: "HTTP \(response.statusCode)") } @@ -45,11 +52,12 @@ public struct DictationClient: DictationClientProtocol { do { return try JSONDecoder().decode(DictationResponseMessage.self, from: patched) } catch { - log.error("process dictation decode error: \(error.localizedDescription)") + log.warning("Dictation response decode failed after \(String(format: "%.1f", elapsed))s: \(error.localizedDescription)") return fallbackResponse(for: request, errorMessage: "Failed to decode dictation response") } } catch { - log.error("process dictation error: \(error.localizedDescription)") + let elapsed = CFAbsoluteTimeGetCurrent() - start + log.warning("Dictation request error after \(String(format: "%.1f", elapsed))s: \(error.localizedDescription)") return fallbackResponse(for: request, errorMessage: error.localizedDescription) } } @@ -58,7 +66,7 @@ public struct DictationClient: DictationClientProtocol { /// Internal for test coverage. func fallbackResponse(for request: DictationRequest, errorMessage: String) -> DictationResponseMessage { - log.warning("Falling back to raw dictation response after HTTP failure: \(errorMessage, privacy: .public)") + log.warning("Using local transcription fallback (\(errorMessage, privacy: .public)). Transcription length=\(request.transcription.count)") let mode = fallbackMode(for: request) let text: String switch mode {