@vellumai/assistant 0.4.23 → 0.4.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/bun.lock +3 -0
  2. package/package.json +2 -1
  3. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -15
  4. package/src/__tests__/assistant-events-sse-hardening.test.ts +9 -3
  5. package/src/__tests__/call-controller.test.ts +80 -0
  6. package/src/__tests__/config-schema.test.ts +38 -178
  7. package/src/__tests__/conversation-routes-guardian-reply.test.ts +4 -1
  8. package/src/__tests__/credential-security-invariants.test.ts +0 -2
  9. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
  10. package/src/__tests__/ipc-snapshot.test.ts +0 -9
  11. package/src/__tests__/onboarding-template-contract.test.ts +10 -20
  12. package/src/__tests__/relay-server.test.ts +3 -3
  13. package/src/__tests__/runtime-events-sse-parity.test.ts +10 -0
  14. package/src/__tests__/runtime-events-sse.test.ts +7 -0
  15. package/src/__tests__/session-runtime-assembly.test.ts +34 -8
  16. package/src/__tests__/system-prompt.test.ts +7 -1
  17. package/src/__tests__/trusted-contact-approval-notifier.test.ts +12 -8
  18. package/src/__tests__/twilio-routes-twiml.test.ts +2 -2
  19. package/src/__tests__/twilio-routes.test.ts +2 -3
  20. package/src/__tests__/voice-quality.test.ts +21 -132
  21. package/src/calls/call-controller.ts +34 -29
  22. package/src/calls/relay-server.ts +11 -5
  23. package/src/calls/twilio-routes.ts +4 -38
  24. package/src/calls/voice-quality.ts +7 -63
  25. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +7 -10
  26. package/src/config/bundled-skills/messaging/SKILL.md +3 -5
  27. package/src/config/bundled-skills/phone-calls/SKILL.md +144 -83
  28. package/src/config/bundled-skills/sms-setup/SKILL.md +0 -20
  29. package/src/config/bundled-skills/twilio-setup/SKILL.md +9 -17
  30. package/src/config/bundled-skills/voice-setup/SKILL.md +36 -1
  31. package/src/config/bundled-skills/voice-setup/icon.svg +20 -0
  32. package/src/config/calls-schema.ts +3 -53
  33. package/src/config/elevenlabs-schema.ts +33 -0
  34. package/src/config/schema.ts +183 -137
  35. package/src/config/types.ts +0 -1
  36. package/src/daemon/handlers/browser.ts +1 -6
  37. package/src/daemon/ipc-contract/browser.ts +5 -14
  38. package/src/daemon/ipc-contract-inventory.json +0 -2
  39. package/src/daemon/session-agent-loop-handlers.ts +3 -0
  40. package/src/daemon/session-runtime-assembly.ts +9 -7
  41. package/src/mcp/client.ts +2 -1
  42. package/src/memory/conversation-crud.ts +339 -166
  43. package/src/runtime/auth/middleware.ts +87 -26
  44. package/src/runtime/routes/events-routes.ts +7 -0
  45. package/src/runtime/routes/inbound-message-handler.ts +3 -4
  46. package/src/schedule/scheduler.ts +159 -45
  47. package/src/security/secure-keys.ts +3 -3
  48. package/src/tools/browser/browser-manager.ts +72 -228
  49. package/src/tools/browser/browser-screencast.ts +0 -5
  50. package/src/tools/network/script-proxy/certs.ts +7 -237
  51. package/src/tools/network/script-proxy/connect-tunnel.ts +1 -82
  52. package/src/tools/network/script-proxy/http-forwarder.ts +2 -151
  53. package/src/tools/network/script-proxy/logging.ts +12 -196
  54. package/src/tools/network/script-proxy/mitm-handler.ts +2 -270
  55. package/src/tools/network/script-proxy/policy.ts +4 -152
  56. package/src/tools/network/script-proxy/router.ts +2 -60
  57. package/src/tools/network/script-proxy/server.ts +5 -137
  58. package/src/tools/network/script-proxy/types.ts +19 -125
  59. package/src/tools/system/voice-config.ts +23 -1
  60. package/src/util/logger.ts +4 -1
  61. package/src/__tests__/elevenlabs-config.test.ts +0 -95
  62. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -407
  63. package/src/calls/elevenlabs-config.ts +0 -32
@@ -1,37 +1,35 @@
1
- import { z } from 'zod';
1
+ import { z } from "zod";
2
2
 
3
- import { getDataDir } from '../util/platform.js';
3
+ import { getDataDir } from "../util/platform.js";
4
4
 
5
5
  // Re-export all domain schemas
6
6
  export type {
7
7
  HeartbeatConfig,
8
8
  SwarmConfig,
9
9
  WorkspaceGitConfig,
10
- } from './agent-schema.js';
10
+ } from "./agent-schema.js";
11
11
  export {
12
12
  HeartbeatConfigSchema,
13
13
  SwarmConfigSchema,
14
14
  WorkspaceGitConfigSchema,
15
- } from './agent-schema.js';
15
+ } from "./agent-schema.js";
16
16
  export type {
17
17
  CallerIdentityConfig,
18
18
  CallsConfig,
19
19
  CallsDisclosureConfig,
20
- CallsElevenLabsConfig,
21
20
  CallsSafetyConfig,
22
21
  CallsVerificationConfig,
23
22
  CallsVoiceConfig,
24
- } from './calls-schema.js';
23
+ } from "./calls-schema.js";
25
24
  export {
26
25
  CallerIdentityConfigSchema,
27
26
  CallsConfigSchema,
28
27
  CallsDisclosureConfigSchema,
29
- CallsElevenLabsConfigSchema,
30
28
  CallsSafetyConfigSchema,
31
29
  CallsVerificationConfigSchema,
32
30
  CallsVoiceConfigSchema,
33
31
  VALID_CALLER_IDENTITY_MODES,
34
- } from './calls-schema.js';
32
+ } from "./calls-schema.js";
35
33
  export type {
36
34
  AuditLogConfig,
37
35
  ContextWindowConfig,
@@ -49,7 +47,7 @@ export type {
49
47
  ThinkingConfig,
50
48
  TimeoutConfig,
51
49
  UiConfig,
52
- } from './core-schema.js';
50
+ } from "./core-schema.js";
53
51
  export {
54
52
  AuditLogConfigSchema,
55
53
  ContextWindowConfigSchema,
@@ -67,17 +65,18 @@ export {
67
65
  ThinkingConfigSchema,
68
66
  TimeoutConfigSchema,
69
67
  UiConfigSchema,
70
- } from './core-schema.js';
71
- export type {
72
- McpConfig,
73
- McpServerConfig,
74
- McpTransport,
75
- } from './mcp-schema.js';
68
+ } from "./core-schema.js";
69
+ export type { ElevenLabsConfig } from "./elevenlabs-schema.js";
70
+ export {
71
+ DEFAULT_ELEVENLABS_VOICE_ID,
72
+ ElevenLabsConfigSchema,
73
+ } from "./elevenlabs-schema.js";
74
+ export type { McpConfig, McpServerConfig, McpTransport } from "./mcp-schema.js";
76
75
  export {
77
76
  McpConfigSchema,
78
77
  McpServerConfigSchema,
79
78
  McpTransportSchema,
80
- } from './mcp-schema.js';
79
+ } from "./mcp-schema.js";
81
80
  export type {
82
81
  MemoryCleanupConfig,
83
82
  MemoryConfig,
@@ -93,7 +92,7 @@ export type {
93
92
  MemorySegmentationConfig,
94
93
  MemorySummarizationConfig,
95
94
  QdrantConfig,
96
- } from './memory-schema.js';
95
+ } from "./memory-schema.js";
97
96
  export {
98
97
  MemoryCleanupConfigSchema,
99
98
  MemoryConfigSchema,
@@ -111,19 +110,11 @@ export {
111
110
  MemorySegmentationConfigSchema,
112
111
  MemorySummarizationConfigSchema,
113
112
  QdrantConfigSchema,
114
- } from './memory-schema.js';
115
- export type {
116
- NotificationsConfig,
117
- } from './notifications-schema.js';
118
- export {
119
- NotificationsConfigSchema,
120
- } from './notifications-schema.js';
121
- export type {
122
- SandboxConfig,
123
- } from './sandbox-schema.js';
124
- export {
125
- SandboxConfigSchema,
126
- } from './sandbox-schema.js';
113
+ } from "./memory-schema.js";
114
+ export type { NotificationsConfig } from "./notifications-schema.js";
115
+ export { NotificationsConfigSchema } from "./notifications-schema.js";
116
+ export type { SandboxConfig } from "./sandbox-schema.js";
117
+ export { SandboxConfigSchema } from "./sandbox-schema.js";
127
118
  export type {
128
119
  RemotePolicyConfig,
129
120
  RemoteProviderConfig,
@@ -132,7 +123,7 @@ export type {
132
123
  SkillsConfig,
133
124
  SkillsInstallConfig,
134
125
  SkillsLoadConfig,
135
- } from './skills-schema.js';
126
+ } from "./skills-schema.js";
136
127
  export {
137
128
  RemotePolicyConfigSchema,
138
129
  RemoteProviderConfigSchema,
@@ -141,11 +132,15 @@ export {
141
132
  SkillsConfigSchema,
142
133
  SkillsInstallConfigSchema,
143
134
  SkillsLoadConfigSchema,
144
- } from './skills-schema.js';
135
+ } from "./skills-schema.js";
145
136
 
146
137
  // Imports for AssistantConfigSchema composition
147
- import { HeartbeatConfigSchema, SwarmConfigSchema, WorkspaceGitConfigSchema } from './agent-schema.js';
148
- import { CallsConfigSchema } from './calls-schema.js';
138
+ import {
139
+ HeartbeatConfigSchema,
140
+ SwarmConfigSchema,
141
+ WorkspaceGitConfigSchema,
142
+ } from "./agent-schema.js";
143
+ import { CallsConfigSchema } from "./calls-schema.js";
149
144
  import {
150
145
  AuditLogConfigSchema,
151
146
  ContextWindowConfigSchema,
@@ -161,110 +156,161 @@ import {
161
156
  ThinkingConfigSchema,
162
157
  TimeoutConfigSchema,
163
158
  UiConfigSchema,
164
- } from './core-schema.js';
165
- import { McpConfigSchema } from './mcp-schema.js';
166
- import { MemoryConfigSchema } from './memory-schema.js';
167
- import { NotificationsConfigSchema } from './notifications-schema.js';
168
- import { SandboxConfigSchema } from './sandbox-schema.js';
169
- import { SkillsConfigSchema } from './skills-schema.js';
159
+ } from "./core-schema.js";
160
+ import { ElevenLabsConfigSchema } from "./elevenlabs-schema.js";
161
+ import { McpConfigSchema } from "./mcp-schema.js";
162
+ import { MemoryConfigSchema } from "./memory-schema.js";
163
+ import { NotificationsConfigSchema } from "./notifications-schema.js";
164
+ import { SandboxConfigSchema } from "./sandbox-schema.js";
165
+ import { SkillsConfigSchema } from "./skills-schema.js";
170
166
 
171
- const VALID_PROVIDERS = ['anthropic', 'openai', 'gemini', 'ollama', 'fireworks', 'openrouter'] as const;
172
- const VALID_WEB_SEARCH_PROVIDERS = ['perplexity', 'brave', 'anthropic-native'] as const;
167
+ const VALID_PROVIDERS = [
168
+ "anthropic",
169
+ "openai",
170
+ "gemini",
171
+ "ollama",
172
+ "fireworks",
173
+ "openrouter",
174
+ ] as const;
175
+ const VALID_WEB_SEARCH_PROVIDERS = [
176
+ "perplexity",
177
+ "brave",
178
+ "anthropic-native",
179
+ ] as const;
173
180
 
174
- export const AssistantConfigSchema = z.object({
175
- provider: z
176
- .enum(VALID_PROVIDERS, {
177
- error: `provider must be one of: ${VALID_PROVIDERS.join(', ')}`,
178
- })
179
- .default('anthropic'),
180
- model: z
181
- .string({ error: 'model must be a string' })
182
- .default('claude-opus-4-6'),
183
- imageGenModel: z
184
- .string({ error: 'imageGenModel must be a string' })
185
- .default('gemini-2.5-flash-image'),
186
- apiKeys: z
187
- .record(z.string(), z.string({ error: 'Each apiKeys value must be a string' }))
188
- .default({} as any),
189
- webSearchProvider: z
190
- .enum(VALID_WEB_SEARCH_PROVIDERS, {
191
- error: `webSearchProvider must be one of: ${VALID_WEB_SEARCH_PROVIDERS.join(', ')}`,
192
- })
193
- .default('anthropic-native'),
194
- providerOrder: z
195
- .array(z.enum(VALID_PROVIDERS, {
196
- error: `Each providerOrder entry must be one of: ${VALID_PROVIDERS.join(', ')}`,
197
- }))
198
- .default([]),
199
- maxTokens: z
200
- .number({ error: 'maxTokens must be a number' })
201
- .int('maxTokens must be an integer')
202
- .positive('maxTokens must be a positive integer')
203
- .default(16000),
204
- maxToolUseTurns: z
205
- .number({ error: 'maxToolUseTurns must be a number' })
206
- .int('maxToolUseTurns must be an integer')
207
- .nonnegative('maxToolUseTurns must be a non-negative integer')
208
- .default(40),
209
- thinking: ThinkingConfigSchema.default(ThinkingConfigSchema.parse({})),
210
- contextWindow: ContextWindowConfigSchema.default(ContextWindowConfigSchema.parse({})),
211
- memory: MemoryConfigSchema.default(MemoryConfigSchema.parse({})),
212
- dataDir: z
213
- .string({ error: 'dataDir must be a string' })
214
- .default(getDataDir()),
215
- timeouts: TimeoutConfigSchema.default(TimeoutConfigSchema.parse({})),
216
- sandbox: SandboxConfigSchema.default(SandboxConfigSchema.parse({})),
217
- rateLimit: RateLimitConfigSchema.default(RateLimitConfigSchema.parse({})),
218
- secretDetection: SecretDetectionConfigSchema.default(SecretDetectionConfigSchema.parse({})),
219
- permissions: PermissionsConfigSchema.default(PermissionsConfigSchema.parse({})),
220
- auditLog: AuditLogConfigSchema.default(AuditLogConfigSchema.parse({})),
221
- logFile: LogFileConfigSchema.default(LogFileConfigSchema.parse({})),
222
- pricingOverrides: z
223
- .array(ModelPricingOverrideSchema)
224
- .default([]),
225
- heartbeat: HeartbeatConfigSchema.default(HeartbeatConfigSchema.parse({})),
226
- swarm: SwarmConfigSchema.default(SwarmConfigSchema.parse({})),
227
- mcp: McpConfigSchema.default(McpConfigSchema.parse({})),
228
- skills: SkillsConfigSchema.default(SkillsConfigSchema.parse({})),
229
- workspaceGit: WorkspaceGitConfigSchema.default(WorkspaceGitConfigSchema.parse({})),
230
- calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
231
- sms: SmsConfigSchema.default(SmsConfigSchema.parse({})),
232
- ingress: IngressConfigSchema,
233
- platform: PlatformConfigSchema.default(PlatformConfigSchema.parse({})),
234
- daemon: DaemonConfigSchema.default(DaemonConfigSchema.parse({})),
235
- notifications: NotificationsConfigSchema.default(NotificationsConfigSchema.parse({})),
236
- ui: UiConfigSchema.default(UiConfigSchema.parse({})),
237
- featureFlags: z
238
- .record(z.string(), z.boolean({ error: 'featureFlags values must be booleans' }))
239
- .default({} as any),
240
- assistantFeatureFlagValues: z
241
- .record(z.string(), z.boolean({ error: 'assistantFeatureFlagValues values must be booleans' }))
242
- .optional(),
243
- }).superRefine((config, ctx) => {
244
- if (config.contextWindow?.targetInputTokens != null && config.contextWindow?.maxInputTokens != null &&
245
- config.contextWindow.targetInputTokens >= config.contextWindow.maxInputTokens) {
246
- ctx.addIssue({
247
- code: z.ZodIssueCode.custom,
248
- path: ['contextWindow', 'targetInputTokens'],
249
- message: 'contextWindow.targetInputTokens must be less than contextWindow.maxInputTokens',
250
- });
251
- }
252
- const segmentation = config.memory?.segmentation;
253
- if (segmentation && segmentation.overlapTokens >= segmentation.targetTokens) {
254
- ctx.addIssue({
255
- code: z.ZodIssueCode.custom,
256
- path: ['memory', 'segmentation', 'overlapTokens'],
257
- message: 'memory.segmentation.overlapTokens must be less than memory.segmentation.targetTokens',
258
- });
259
- }
260
- const dynamicBudget = config.memory?.retrieval?.dynamicBudget;
261
- if (dynamicBudget && dynamicBudget.minInjectTokens > dynamicBudget.maxInjectTokens) {
262
- ctx.addIssue({
263
- code: z.ZodIssueCode.custom,
264
- path: ['memory', 'retrieval', 'dynamicBudget'],
265
- message: 'memory.retrieval.dynamicBudget.minInjectTokens must be <= memory.retrieval.dynamicBudget.maxInjectTokens',
266
- });
267
- }
268
- });
181
+ export const AssistantConfigSchema = z
182
+ .object({
183
+ provider: z
184
+ .enum(VALID_PROVIDERS, {
185
+ error: `provider must be one of: ${VALID_PROVIDERS.join(", ")}`,
186
+ })
187
+ .default("anthropic"),
188
+ model: z
189
+ .string({ error: "model must be a string" })
190
+ .default("claude-opus-4-6"),
191
+ imageGenModel: z
192
+ .string({ error: "imageGenModel must be a string" })
193
+ .default("gemini-2.5-flash-image"),
194
+ apiKeys: z
195
+ .record(
196
+ z.string(),
197
+ z.string({ error: "Each apiKeys value must be a string" }),
198
+ )
199
+ .default({} as any),
200
+ webSearchProvider: z
201
+ .enum(VALID_WEB_SEARCH_PROVIDERS, {
202
+ error: `webSearchProvider must be one of: ${VALID_WEB_SEARCH_PROVIDERS.join(", ")}`,
203
+ })
204
+ .default("anthropic-native"),
205
+ providerOrder: z
206
+ .array(
207
+ z.enum(VALID_PROVIDERS, {
208
+ error: `Each providerOrder entry must be one of: ${VALID_PROVIDERS.join(", ")}`,
209
+ }),
210
+ )
211
+ .default([]),
212
+ maxTokens: z
213
+ .number({ error: "maxTokens must be a number" })
214
+ .int("maxTokens must be an integer")
215
+ .positive("maxTokens must be a positive integer")
216
+ .default(16000),
217
+ maxToolUseTurns: z
218
+ .number({ error: "maxToolUseTurns must be a number" })
219
+ .int("maxToolUseTurns must be an integer")
220
+ .nonnegative("maxToolUseTurns must be a non-negative integer")
221
+ .default(40),
222
+ thinking: ThinkingConfigSchema.default(ThinkingConfigSchema.parse({})),
223
+ contextWindow: ContextWindowConfigSchema.default(
224
+ ContextWindowConfigSchema.parse({}),
225
+ ),
226
+ memory: MemoryConfigSchema.default(MemoryConfigSchema.parse({})),
227
+ dataDir: z
228
+ .string({ error: "dataDir must be a string" })
229
+ .default(getDataDir()),
230
+ timeouts: TimeoutConfigSchema.default(TimeoutConfigSchema.parse({})),
231
+ sandbox: SandboxConfigSchema.default(SandboxConfigSchema.parse({})),
232
+ rateLimit: RateLimitConfigSchema.default(RateLimitConfigSchema.parse({})),
233
+ secretDetection: SecretDetectionConfigSchema.default(
234
+ SecretDetectionConfigSchema.parse({}),
235
+ ),
236
+ permissions: PermissionsConfigSchema.default(
237
+ PermissionsConfigSchema.parse({}),
238
+ ),
239
+ auditLog: AuditLogConfigSchema.default(AuditLogConfigSchema.parse({})),
240
+ logFile: LogFileConfigSchema.default(LogFileConfigSchema.parse({})),
241
+ pricingOverrides: z.array(ModelPricingOverrideSchema).default([]),
242
+ heartbeat: HeartbeatConfigSchema.default(HeartbeatConfigSchema.parse({})),
243
+ swarm: SwarmConfigSchema.default(SwarmConfigSchema.parse({})),
244
+ mcp: McpConfigSchema.default(McpConfigSchema.parse({})),
245
+ skills: SkillsConfigSchema.default(SkillsConfigSchema.parse({})),
246
+ workspaceGit: WorkspaceGitConfigSchema.default(
247
+ WorkspaceGitConfigSchema.parse({}),
248
+ ),
249
+ calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
250
+ elevenlabs: ElevenLabsConfigSchema.default(
251
+ ElevenLabsConfigSchema.parse({}),
252
+ ),
253
+ sms: SmsConfigSchema.default(SmsConfigSchema.parse({})),
254
+ ingress: IngressConfigSchema,
255
+ platform: PlatformConfigSchema.default(PlatformConfigSchema.parse({})),
256
+ daemon: DaemonConfigSchema.default(DaemonConfigSchema.parse({})),
257
+ notifications: NotificationsConfigSchema.default(
258
+ NotificationsConfigSchema.parse({}),
259
+ ),
260
+ ui: UiConfigSchema.default(UiConfigSchema.parse({})),
261
+ featureFlags: z
262
+ .record(
263
+ z.string(),
264
+ z.boolean({ error: "featureFlags values must be booleans" }),
265
+ )
266
+ .default({} as any),
267
+ assistantFeatureFlagValues: z
268
+ .record(
269
+ z.string(),
270
+ z.boolean({
271
+ error: "assistantFeatureFlagValues values must be booleans",
272
+ }),
273
+ )
274
+ .optional(),
275
+ })
276
+ .superRefine((config, ctx) => {
277
+ if (
278
+ config.contextWindow?.targetInputTokens != null &&
279
+ config.contextWindow?.maxInputTokens != null &&
280
+ config.contextWindow.targetInputTokens >=
281
+ config.contextWindow.maxInputTokens
282
+ ) {
283
+ ctx.addIssue({
284
+ code: z.ZodIssueCode.custom,
285
+ path: ["contextWindow", "targetInputTokens"],
286
+ message:
287
+ "contextWindow.targetInputTokens must be less than contextWindow.maxInputTokens",
288
+ });
289
+ }
290
+ const segmentation = config.memory?.segmentation;
291
+ if (
292
+ segmentation &&
293
+ segmentation.overlapTokens >= segmentation.targetTokens
294
+ ) {
295
+ ctx.addIssue({
296
+ code: z.ZodIssueCode.custom,
297
+ path: ["memory", "segmentation", "overlapTokens"],
298
+ message:
299
+ "memory.segmentation.overlapTokens must be less than memory.segmentation.targetTokens",
300
+ });
301
+ }
302
+ const dynamicBudget = config.memory?.retrieval?.dynamicBudget;
303
+ if (
304
+ dynamicBudget &&
305
+ dynamicBudget.minInjectTokens > dynamicBudget.maxInjectTokens
306
+ ) {
307
+ ctx.addIssue({
308
+ code: z.ZodIssueCode.custom,
309
+ path: ["memory", "retrieval", "dynamicBudget"],
310
+ message:
311
+ "memory.retrieval.dynamicBudget.minInjectTokens must be <= memory.retrieval.dynamicBudget.maxInjectTokens",
312
+ });
313
+ }
314
+ });
269
315
 
270
316
  export type AssistantConfig = z.infer<typeof AssistantConfigSchema>;
@@ -4,7 +4,6 @@ export type {
4
4
  CallerIdentityConfig,
5
5
  CallsConfig,
6
6
  CallsDisclosureConfig,
7
- CallsElevenLabsConfig,
8
7
  CallsSafetyConfig,
9
8
  CallsVoiceConfig,
10
9
  ContextWindowConfig,
@@ -1,8 +1,3 @@
1
- import { browserManager } from "../../tools/browser/browser-manager.js";
2
1
  import { defineHandlers } from "./shared.js";
3
2
 
4
- export const browserHandlers = defineHandlers({
5
- browser_cdp_response: (msg) => {
6
- browserManager.resolveCDPResponse(msg.sessionId, msg.success, msg.declined);
7
- },
8
- });
3
+ export const browserHandlers = defineHandlers({});
@@ -1,19 +1,10 @@
1
1
  // Browser interaction types.
2
-
3
- export interface BrowserCDPRequest {
4
- type: "browser_cdp_request";
5
- sessionId: string;
6
- }
7
-
8
- export interface BrowserCDPResponse {
9
- type: "browser_cdp_response";
10
- sessionId: string;
11
- success: boolean;
12
- declined?: boolean;
13
- }
2
+ // CDP request/response IPC was removed — Playwright's connectOverCDP is broken
3
+ // under Bun's runtime. Browser is now launched directly via Playwright.
14
4
 
15
5
  // --- Domain-level union aliases (consumed by the barrel file) ---
6
+ // These must exist (even as `never`) so the barrel union compiles.
16
7
 
17
- export type _BrowserClientMessages = BrowserCDPResponse;
8
+ export type _BrowserClientMessages = never;
18
9
 
19
- export type _BrowserServerMessages = BrowserCDPRequest;
10
+ export type _BrowserServerMessages = never;
@@ -62,7 +62,6 @@
62
62
  "apps_list",
63
63
  "assistant_inbox_escalation",
64
64
  "auth",
65
- "browser_cdp_response",
66
65
  "bundle_app",
67
66
  "cancel",
68
67
  "confirmation_response",
@@ -206,7 +205,6 @@
206
205
  "assistant_thinking_delta",
207
206
  "auth_result",
208
207
  "avatar_updated",
209
- "browser_cdp_request",
210
208
  "bundle_app_response",
211
209
  "client_settings_update",
212
210
  "confirmation_request",
@@ -150,6 +150,9 @@ const TOOL_FRIENDLY_NAMES: Record<string, string> = {
150
150
  browser_wait: 'browser',
151
151
  app_create: 'app',
152
152
  app_update: 'app',
153
+ skill_load: 'skill',
154
+ app_file_edit: 'app file',
155
+ app_file_write: 'app file',
153
156
  };
154
157
 
155
158
  function friendlyToolName(name: string): string {
@@ -314,7 +314,7 @@ export function resolveChannelCapabilities(
314
314
  return {
315
315
  channel,
316
316
  dashboardCapable: supportsDesktopUi,
317
- supportsDynamicUi: supportsDesktopUi,
317
+ supportsDynamicUi: supportsDesktopUi || iface === "vellum",
318
318
  supportsVoiceInput: supportsDesktopUi,
319
319
  pttActivationKey: sanitizePttActivationKey(
320
320
  pttMetadata?.pttActivationKey,
@@ -592,12 +592,14 @@ export function injectChannelCapabilityContext(
592
592
  lines.push(
593
593
  "- Do NOT reference the dashboard UI, settings panels, or visual preference pickers.",
594
594
  );
595
- lines.push(
596
- "- Do NOT use ui_show, ui_update, or app_create — this channel cannot render them.",
597
- );
598
- lines.push(
599
- "- Present information as well-formatted text instead of dynamic UI.",
600
- );
595
+ if (!caps.supportsDynamicUi) {
596
+ lines.push(
597
+ "- Do NOT use ui_show, ui_update, or app_create — this channel cannot render them.",
598
+ );
599
+ lines.push(
600
+ "- Present information as well-formatted text instead of dynamic UI.",
601
+ );
602
+ }
601
603
  lines.push(
602
604
  "- Defer dashboard-specific actions (e.g. accent color selection) by telling the user",
603
605
  );
package/src/mcp/client.ts CHANGED
@@ -75,7 +75,8 @@ export class McpClient {
75
75
 
76
76
  if (isHttpTransport) {
77
77
  const isAuthError = err instanceof UnauthorizedError
78
- || (err instanceof Error && /\b(401|403|unauthorized|forbidden)\b/i.test(err.message));
78
+ || (err instanceof Error && /\b(401|403|unauthorized|forbidden)\b/i.test(err.message))
79
+ || (err != null && typeof err === 'object' && 'code' in err && (err.code === 401 || err.code === 403));
79
80
 
80
81
  if (isAuthError) {
81
82
  // Auth-related — user can run `vellum mcp auth <name>` to authenticate.