@vellumai/assistant 0.3.3 → 0.3.5

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 (163) hide show
  1. package/Dockerfile +2 -0
  2. package/README.md +45 -18
  3. package/package.json +1 -1
  4. package/scripts/ipc/generate-swift.ts +13 -0
  5. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +100 -0
  6. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +41 -0
  7. package/src/__tests__/approval-message-composer.test.ts +253 -0
  8. package/src/__tests__/call-domain.test.ts +12 -2
  9. package/src/__tests__/call-orchestrator.test.ts +391 -1
  10. package/src/__tests__/call-routes-http.test.ts +27 -2
  11. package/src/__tests__/channel-approval-routes.test.ts +397 -135
  12. package/src/__tests__/channel-approvals.test.ts +99 -3
  13. package/src/__tests__/channel-delivery-store.test.ts +30 -4
  14. package/src/__tests__/channel-guardian.test.ts +261 -22
  15. package/src/__tests__/channel-readiness-service.test.ts +257 -0
  16. package/src/__tests__/config-schema.test.ts +2 -1
  17. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  18. package/src/__tests__/daemon-lifecycle.test.ts +636 -0
  19. package/src/__tests__/dictation-mode-detection.test.ts +63 -0
  20. package/src/__tests__/entity-search.test.ts +615 -0
  21. package/src/__tests__/gateway-only-enforcement.test.ts +19 -13
  22. package/src/__tests__/handlers-twilio-config.test.ts +480 -0
  23. package/src/__tests__/ipc-snapshot.test.ts +63 -0
  24. package/src/__tests__/messaging-send-tool.test.ts +65 -0
  25. package/src/__tests__/run-orchestrator-assistant-events.test.ts +4 -0
  26. package/src/__tests__/run-orchestrator.test.ts +22 -0
  27. package/src/__tests__/secret-scanner.test.ts +223 -0
  28. package/src/__tests__/session-runtime-assembly.test.ts +85 -1
  29. package/src/__tests__/shell-parser-property.test.ts +357 -2
  30. package/src/__tests__/sms-messaging-provider.test.ts +125 -0
  31. package/src/__tests__/system-prompt.test.ts +25 -1
  32. package/src/__tests__/tool-executor-lifecycle-events.test.ts +34 -1
  33. package/src/__tests__/twilio-routes.test.ts +39 -3
  34. package/src/__tests__/twitter-cli-error-shaping.test.ts +2 -2
  35. package/src/__tests__/user-reference.test.ts +68 -0
  36. package/src/__tests__/web-search.test.ts +1 -1
  37. package/src/__tests__/work-item-output.test.ts +110 -0
  38. package/src/calls/call-domain.ts +8 -5
  39. package/src/calls/call-orchestrator.ts +85 -22
  40. package/src/calls/twilio-config.ts +17 -11
  41. package/src/calls/twilio-rest.ts +276 -0
  42. package/src/calls/twilio-routes.ts +39 -1
  43. package/src/cli/map.ts +6 -0
  44. package/src/commands/__tests__/cc-command-registry.test.ts +67 -0
  45. package/src/commands/cc-command-registry.ts +14 -1
  46. package/src/config/bundled-skills/claude-code/TOOLS.json +10 -3
  47. package/src/config/bundled-skills/knowledge-graph/SKILL.md +15 -0
  48. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +56 -0
  49. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +185 -0
  50. package/src/config/bundled-skills/media-processing/SKILL.md +199 -0
  51. package/src/config/bundled-skills/media-processing/TOOLS.json +320 -0
  52. package/src/config/bundled-skills/media-processing/services/capability-registry.ts +137 -0
  53. package/src/config/bundled-skills/media-processing/services/event-detection-service.ts +280 -0
  54. package/src/config/bundled-skills/media-processing/services/feedback-aggregation.ts +144 -0
  55. package/src/config/bundled-skills/media-processing/services/feedback-store.ts +136 -0
  56. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +261 -0
  57. package/src/config/bundled-skills/media-processing/services/retrieval-service.ts +95 -0
  58. package/src/config/bundled-skills/media-processing/services/timeline-service.ts +267 -0
  59. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +301 -0
  60. package/src/config/bundled-skills/media-processing/tools/detect-events.ts +110 -0
  61. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +190 -0
  62. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +195 -0
  63. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +197 -0
  64. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +166 -0
  65. package/src/config/bundled-skills/media-processing/tools/media-status.ts +75 -0
  66. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +300 -0
  67. package/src/config/bundled-skills/media-processing/tools/recalibrate.ts +235 -0
  68. package/src/config/bundled-skills/media-processing/tools/select-tracking-profile.ts +142 -0
  69. package/src/config/bundled-skills/media-processing/tools/submit-feedback.ts +150 -0
  70. package/src/config/bundled-skills/messaging/SKILL.md +24 -5
  71. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -1
  72. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  73. package/src/config/bundled-skills/twitter/SKILL.md +19 -3
  74. package/src/config/defaults.ts +2 -1
  75. package/src/config/schema.ts +9 -3
  76. package/src/config/skills.ts +5 -32
  77. package/src/config/system-prompt.ts +40 -0
  78. package/src/config/templates/IDENTITY.md +2 -2
  79. package/src/config/user-reference.ts +29 -0
  80. package/src/config/vellum-skills/catalog.json +58 -0
  81. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +3 -3
  82. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +3 -3
  83. package/src/config/vellum-skills/sms-setup/SKILL.md +118 -0
  84. package/src/config/vellum-skills/telegram-setup/SKILL.md +6 -1
  85. package/src/config/vellum-skills/twilio-setup/SKILL.md +76 -6
  86. package/src/daemon/auth-manager.ts +103 -0
  87. package/src/daemon/computer-use-session.ts +8 -1
  88. package/src/daemon/config-watcher.ts +253 -0
  89. package/src/daemon/handlers/config.ts +819 -22
  90. package/src/daemon/handlers/dictation.ts +182 -0
  91. package/src/daemon/handlers/identity.ts +14 -23
  92. package/src/daemon/handlers/index.ts +2 -0
  93. package/src/daemon/handlers/sessions.ts +2 -0
  94. package/src/daemon/handlers/shared.ts +3 -0
  95. package/src/daemon/handlers/skills.ts +6 -7
  96. package/src/daemon/handlers/work-items.ts +15 -7
  97. package/src/daemon/ipc-contract-inventory.json +10 -0
  98. package/src/daemon/ipc-contract.ts +114 -4
  99. package/src/daemon/ipc-handler.ts +87 -0
  100. package/src/daemon/lifecycle.ts +18 -4
  101. package/src/daemon/ride-shotgun-handler.ts +11 -1
  102. package/src/daemon/server.ts +111 -504
  103. package/src/daemon/session-agent-loop.ts +10 -15
  104. package/src/daemon/session-runtime-assembly.ts +115 -44
  105. package/src/daemon/session-tool-setup.ts +2 -0
  106. package/src/daemon/session.ts +19 -2
  107. package/src/inbound/public-ingress-urls.ts +3 -3
  108. package/src/memory/channel-guardian-store.ts +2 -1
  109. package/src/memory/db-connection.ts +28 -0
  110. package/src/memory/db-init.ts +1163 -0
  111. package/src/memory/db.ts +2 -2007
  112. package/src/memory/embedding-backend.ts +79 -11
  113. package/src/memory/indexer.ts +2 -0
  114. package/src/memory/job-handlers/media-processing.ts +100 -0
  115. package/src/memory/job-utils.ts +64 -4
  116. package/src/memory/jobs-store.ts +2 -1
  117. package/src/memory/jobs-worker.ts +11 -1
  118. package/src/memory/media-store.ts +759 -0
  119. package/src/memory/recall-cache.ts +107 -0
  120. package/src/memory/retriever.ts +36 -2
  121. package/src/memory/schema-migration.ts +984 -0
  122. package/src/memory/schema.ts +99 -0
  123. package/src/memory/search/entity.ts +208 -25
  124. package/src/memory/search/ranking.ts +6 -1
  125. package/src/memory/search/types.ts +26 -0
  126. package/src/messaging/provider-types.ts +2 -0
  127. package/src/messaging/providers/sms/adapter.ts +204 -0
  128. package/src/messaging/providers/sms/client.ts +93 -0
  129. package/src/messaging/providers/sms/types.ts +7 -0
  130. package/src/permissions/checker.ts +16 -2
  131. package/src/permissions/prompter.ts +14 -3
  132. package/src/permissions/trust-store.ts +7 -0
  133. package/src/runtime/approval-message-composer.ts +143 -0
  134. package/src/runtime/channel-approvals.ts +29 -7
  135. package/src/runtime/channel-guardian-service.ts +44 -18
  136. package/src/runtime/channel-readiness-service.ts +292 -0
  137. package/src/runtime/channel-readiness-types.ts +29 -0
  138. package/src/runtime/gateway-client.ts +2 -1
  139. package/src/runtime/http-server.ts +65 -28
  140. package/src/runtime/http-types.ts +3 -0
  141. package/src/runtime/routes/call-routes.ts +2 -1
  142. package/src/runtime/routes/channel-routes.ts +237 -103
  143. package/src/runtime/routes/run-routes.ts +7 -1
  144. package/src/runtime/run-orchestrator.ts +43 -3
  145. package/src/security/secret-scanner.ts +218 -0
  146. package/src/skills/frontmatter.ts +63 -0
  147. package/src/skills/slash-commands.ts +23 -0
  148. package/src/skills/vellum-catalog-remote.ts +107 -0
  149. package/src/tools/assets/materialize.ts +2 -2
  150. package/src/tools/browser/auto-navigate.ts +132 -24
  151. package/src/tools/browser/browser-manager.ts +67 -61
  152. package/src/tools/calls/call-start.ts +1 -0
  153. package/src/tools/claude-code/claude-code.ts +55 -3
  154. package/src/tools/credentials/vault.ts +1 -1
  155. package/src/tools/execution-target.ts +11 -1
  156. package/src/tools/executor.ts +10 -2
  157. package/src/tools/network/web-search.ts +1 -1
  158. package/src/tools/skills/vellum-catalog.ts +61 -156
  159. package/src/tools/terminal/parser.ts +21 -5
  160. package/src/tools/types.ts +2 -0
  161. package/src/twitter/router.ts +1 -1
  162. package/src/util/platform.ts +43 -1
  163. package/src/util/retry.ts +4 -4
@@ -11,7 +11,7 @@ import { fileURLToPath } from 'node:url';
11
11
  import { timingSafeEqual } from 'node:crypto';
12
12
  import { ConfigError, IngressBlockedError } from '../util/errors.js';
13
13
  import { getLogger } from '../util/logger.js';
14
- import { getWorkspacePromptPath } from '../util/platform.js';
14
+ import { getWorkspacePromptPath, readLockfile } from '../util/platform.js';
15
15
  import { TwilioConversationRelayProvider } from '../calls/twilio-provider.js';
16
16
  import { loadConfig } from '../config/loader.js';
17
17
  import { getPublicBaseUrl } from '../inbound/public-ingress-urls.js';
@@ -41,7 +41,6 @@ import {
41
41
  handleChannelDeliveryAck,
42
42
  handleListDeadLetters,
43
43
  handleReplayDeadLetters,
44
- isChannelApprovalsEnabled,
45
44
  startGuardianExpirySweep,
46
45
  stopGuardianExpirySweep,
47
46
  } from './routes/channel-routes.js';
@@ -75,6 +74,7 @@ import { RelayConnection, activeRelayConnections } from '../calls/relay-server.j
75
74
  import type { RelayWebSocketData } from '../calls/relay-server.js';
76
75
  import { handleSubscribeAssistantEvents } from './routes/events-routes.js';
77
76
  import { consumeCallback, consumeCallbackError } from '../security/oauth-callback-registry.js';
77
+ import type { GuardianRuntimeContext } from '../daemon/session-runtime-assembly.js';
78
78
 
79
79
  // Re-export shared types so existing consumers don't need to update imports
80
80
  export type {
@@ -108,6 +108,37 @@ function getGatewayBaseUrl(): string {
108
108
  /** Global hard cap on request body size (50 MB). Bun rejects larger payloads before they reach handlers. */
109
109
  const MAX_REQUEST_BODY_BYTES = 50 * 1024 * 1024;
110
110
 
111
+ function parseGuardianRuntimeContext(value: unknown): GuardianRuntimeContext | undefined {
112
+ if (!value || typeof value !== 'object') return undefined;
113
+ const raw = value as Record<string, unknown>;
114
+ const actorRole = raw.actorRole;
115
+ if (
116
+ actorRole !== 'guardian'
117
+ && actorRole !== 'non-guardian'
118
+ && actorRole !== 'unverified_channel'
119
+ ) {
120
+ return undefined;
121
+ }
122
+ const sourceChannel = typeof raw.sourceChannel === 'string' && raw.sourceChannel.trim().length > 0
123
+ ? raw.sourceChannel
124
+ : undefined;
125
+ if (!sourceChannel) return undefined;
126
+ const denialReason =
127
+ raw.denialReason === 'no_binding' || raw.denialReason === 'no_identity'
128
+ ? raw.denialReason
129
+ : undefined;
130
+ return {
131
+ sourceChannel,
132
+ actorRole,
133
+ guardianChatId: typeof raw.guardianChatId === 'string' ? raw.guardianChatId : undefined,
134
+ guardianExternalUserId: typeof raw.guardianExternalUserId === 'string' ? raw.guardianExternalUserId : undefined,
135
+ requesterIdentifier: typeof raw.requesterIdentifier === 'string' ? raw.requesterIdentifier : undefined,
136
+ requesterExternalUserId: typeof raw.requesterExternalUserId === 'string' ? raw.requesterExternalUserId : undefined,
137
+ requesterChatId: typeof raw.requesterChatId === 'string' ? raw.requesterChatId : undefined,
138
+ denialReason,
139
+ };
140
+ }
141
+
111
142
  interface DiskSpaceInfo {
112
143
  path: string;
113
144
  totalMb: number;
@@ -414,8 +445,10 @@ export class RuntimeHttpServer {
414
445
  }, 30_000);
415
446
  }
416
447
 
417
- // Start proactive guardian approval expiry sweep when approvals are enabled
418
- if (isChannelApprovalsEnabled() && this.runOrchestrator) {
448
+ // Start proactive guardian approval expiry sweep whenever orchestrator
449
+ // support is available. Guardian approvals can be created even when the
450
+ // generic channel-approval UX flag is disabled.
451
+ if (this.runOrchestrator) {
419
452
  startGuardianExpirySweep(this.runOrchestrator, getGatewayBaseUrl(), this.bearerToken);
420
453
  log.info('Guardian approval expiry sweep started');
421
454
  }
@@ -761,7 +794,7 @@ export class RuntimeHttpServer {
761
794
 
762
795
  // ── Call API routes ───────────────────────────────────────────
763
796
  if (endpoint === 'calls/start' && req.method === 'POST') {
764
- return await handleStartCall(req);
797
+ return await handleStartCall(req, assistantId);
765
798
  }
766
799
 
767
800
  // Match calls/:callSessionId and calls/:callSessionId/cancel, calls/:callSessionId/answer, calls/:callSessionId/instruction
@@ -906,6 +939,10 @@ export class RuntimeHttpServer {
906
939
  const attachmentIds = Array.isArray(payload.attachmentIds) ? payload.attachmentIds as string[] : undefined;
907
940
  const sourceChannel = payload.sourceChannel as string;
908
941
  const sourceMetadata = payload.sourceMetadata as Record<string, unknown> | undefined;
942
+ const assistantId = typeof payload.assistantId === 'string'
943
+ ? payload.assistantId
944
+ : undefined;
945
+ const guardianContext = parseGuardianRuntimeContext(payload.guardianCtx);
909
946
 
910
947
  const metadataHintsRaw = sourceMetadata?.hints;
911
948
  const metadataHints = Array.isArray(metadataHintsRaw)
@@ -926,6 +963,8 @@ export class RuntimeHttpServer {
926
963
  hints: metadataHints.length > 0 ? metadataHints : undefined,
927
964
  uxBrief: metadataUxBrief,
928
965
  },
966
+ assistantId,
967
+ guardianContext,
929
968
  },
930
969
  );
931
970
  channelDeliveryStore.linkMessage(event.id, userMessageId);
@@ -940,7 +979,12 @@ export class RuntimeHttpServer {
940
979
  ? payload.externalChatId
941
980
  : undefined;
942
981
  if (externalChatId) {
943
- await this.deliverReplyViaCallback(event.conversationId, externalChatId, replyCallbackUrl);
982
+ await this.deliverReplyViaCallback(
983
+ event.conversationId,
984
+ externalChatId,
985
+ replyCallbackUrl,
986
+ assistantId,
987
+ );
944
988
  }
945
989
  }
946
990
  } catch (err) {
@@ -954,6 +998,7 @@ export class RuntimeHttpServer {
954
998
  conversationId: string,
955
999
  externalChatId: string,
956
1000
  callbackUrl: string,
1001
+ assistantId?: string,
957
1002
  ): Promise<void> {
958
1003
  const msgs = conversationStore.getMessages(conversationId);
959
1004
  for (let i = msgs.length - 1; i >= 0; i--) {
@@ -976,6 +1021,7 @@ export class RuntimeHttpServer {
976
1021
  chatId: externalChatId,
977
1022
  text: rendered.text || undefined,
978
1023
  attachments: replyAttachments.length > 0 ? replyAttachments : undefined,
1024
+ assistantId,
979
1025
  }, this.bearerToken);
980
1026
  }
981
1027
  break;
@@ -1035,28 +1081,19 @@ export class RuntimeHttpServer {
1035
1081
  let cloud: string | undefined;
1036
1082
  let originSystem: string | undefined;
1037
1083
  try {
1038
- const homedir = process.env.HOME ?? process.env.USERPROFILE ?? '';
1039
- const lockfilePaths = [
1040
- join(homedir, '.vellum.lock.json'),
1041
- join(homedir, '.vellum.lockfile.json'),
1042
- ];
1043
- for (const lockPath of lockfilePaths) {
1044
- if (!existsSync(lockPath)) continue;
1045
- const lockData = JSON.parse(readFileSync(lockPath, 'utf-8'));
1046
- const assistants = lockData.assistants as Array<Record<string, unknown>> | undefined;
1047
- if (assistants && assistants.length > 0) {
1048
- // Use the most recently hatched assistant
1049
- const sorted = [...assistants].sort((a, b) => {
1050
- const dateA = new Date(a.hatchedAt as string || 0).getTime();
1051
- const dateB = new Date(b.hatchedAt as string || 0).getTime();
1052
- return dateB - dateA;
1053
- });
1054
- const latest = sorted[0];
1055
- assistantId = latest.assistantId as string | undefined;
1056
- cloud = latest.cloud as string | undefined;
1057
- originSystem = cloud === 'local' ? 'local' : cloud;
1058
- }
1059
- break;
1084
+ const lockData = readLockfile();
1085
+ const assistants = lockData?.assistants as Array<Record<string, unknown>> | undefined;
1086
+ if (assistants && assistants.length > 0) {
1087
+ // Use the most recently hatched assistant
1088
+ const sorted = [...assistants].sort((a, b) => {
1089
+ const dateA = new Date(a.hatchedAt as string || 0).getTime();
1090
+ const dateB = new Date(b.hatchedAt as string || 0).getTime();
1091
+ return dateB - dateA;
1092
+ });
1093
+ const latest = sorted[0];
1094
+ assistantId = latest.assistantId as string | undefined;
1095
+ cloud = latest.cloud as string | undefined;
1096
+ originSystem = cloud === 'local' ? 'local' : cloud;
1060
1097
  }
1061
1098
  } catch {
1062
1099
  // ignore — lockfile may not exist
@@ -2,6 +2,7 @@
2
2
  * Shared types for the runtime HTTP server and its route handlers.
3
3
  */
4
4
  import type { RunOrchestrator } from './run-orchestrator.js';
5
+ import type { GuardianRuntimeContext } from '../daemon/session-runtime-assembly.js';
5
6
 
6
7
  export interface RuntimeMessageSessionOptions {
7
8
  transport?: {
@@ -9,6 +10,8 @@ export interface RuntimeMessageSessionOptions {
9
10
  hints?: string[];
10
11
  uxBrief?: string;
11
12
  };
13
+ assistantId?: string;
14
+ guardianContext?: GuardianRuntimeContext;
12
15
  }
13
16
 
14
17
  export type MessageProcessor = (
@@ -17,7 +17,7 @@ import { VALID_CALLER_IDENTITY_MODES } from '../../config/schema.js';
17
17
  *
18
18
  * Body: { phoneNumber: string; task: string; context?: string; conversationId: string; callerIdentityMode?: 'assistant_number' | 'user_number' }
19
19
  */
20
- export async function handleStartCall(req: Request): Promise<Response> {
20
+ export async function handleStartCall(req: Request, assistantId: string = 'self'): Promise<Response> {
21
21
  if (!getConfig().calls.enabled) {
22
22
  return Response.json(
23
23
  { error: 'Calls feature is disabled via configuration. Set calls.enabled to true to use this feature.' },
@@ -59,6 +59,7 @@ export async function handleStartCall(req: Request): Promise<Response> {
59
59
  task: body.task ?? '',
60
60
  context: body.context,
61
61
  conversationId: body.conversationId,
62
+ assistantId,
62
63
  callerIdentityMode: body.callerIdentityMode,
63
64
  });
64
65