@vellumai/assistant 0.3.4 → 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 (122) hide show
  1. package/Dockerfile +2 -0
  2. package/README.md +37 -2
  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 +70 -1
  10. package/src/__tests__/call-routes-http.test.ts +27 -2
  11. package/src/__tests__/channel-approval-routes.test.ts +21 -17
  12. package/src/__tests__/channel-approvals.test.ts +48 -1
  13. package/src/__tests__/channel-guardian.test.ts +74 -22
  14. package/src/__tests__/channel-readiness-service.test.ts +257 -0
  15. package/src/__tests__/config-schema.test.ts +2 -1
  16. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  17. package/src/__tests__/daemon-lifecycle.test.ts +13 -12
  18. package/src/__tests__/dictation-mode-detection.test.ts +63 -0
  19. package/src/__tests__/entity-search.test.ts +615 -0
  20. package/src/__tests__/handlers-twilio-config.test.ts +407 -0
  21. package/src/__tests__/ipc-snapshot.test.ts +63 -0
  22. package/src/__tests__/messaging-send-tool.test.ts +65 -0
  23. package/src/__tests__/run-orchestrator-assistant-events.test.ts +4 -0
  24. package/src/__tests__/run-orchestrator.test.ts +22 -0
  25. package/src/__tests__/session-runtime-assembly.test.ts +85 -1
  26. package/src/__tests__/sms-messaging-provider.test.ts +125 -0
  27. package/src/__tests__/twilio-routes.test.ts +39 -3
  28. package/src/__tests__/twitter-cli-error-shaping.test.ts +2 -2
  29. package/src/__tests__/web-search.test.ts +1 -1
  30. package/src/__tests__/work-item-output.test.ts +110 -0
  31. package/src/calls/call-domain.ts +8 -5
  32. package/src/calls/call-orchestrator.ts +22 -11
  33. package/src/calls/twilio-config.ts +17 -11
  34. package/src/calls/twilio-rest.ts +276 -0
  35. package/src/calls/twilio-routes.ts +39 -1
  36. package/src/config/bundled-skills/knowledge-graph/SKILL.md +15 -0
  37. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +56 -0
  38. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +185 -0
  39. package/src/config/bundled-skills/media-processing/SKILL.md +199 -0
  40. package/src/config/bundled-skills/media-processing/TOOLS.json +320 -0
  41. package/src/config/bundled-skills/media-processing/services/capability-registry.ts +137 -0
  42. package/src/config/bundled-skills/media-processing/services/event-detection-service.ts +280 -0
  43. package/src/config/bundled-skills/media-processing/services/feedback-aggregation.ts +144 -0
  44. package/src/config/bundled-skills/media-processing/services/feedback-store.ts +136 -0
  45. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +261 -0
  46. package/src/config/bundled-skills/media-processing/services/retrieval-service.ts +95 -0
  47. package/src/config/bundled-skills/media-processing/services/timeline-service.ts +267 -0
  48. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +301 -0
  49. package/src/config/bundled-skills/media-processing/tools/detect-events.ts +110 -0
  50. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +190 -0
  51. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +195 -0
  52. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +197 -0
  53. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +166 -0
  54. package/src/config/bundled-skills/media-processing/tools/media-status.ts +75 -0
  55. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +300 -0
  56. package/src/config/bundled-skills/media-processing/tools/recalibrate.ts +235 -0
  57. package/src/config/bundled-skills/media-processing/tools/select-tracking-profile.ts +142 -0
  58. package/src/config/bundled-skills/media-processing/tools/submit-feedback.ts +150 -0
  59. package/src/config/bundled-skills/messaging/SKILL.md +21 -6
  60. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -1
  61. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  62. package/src/config/bundled-skills/twitter/SKILL.md +19 -3
  63. package/src/config/defaults.ts +2 -1
  64. package/src/config/schema.ts +9 -3
  65. package/src/config/system-prompt.ts +24 -0
  66. package/src/config/templates/IDENTITY.md +2 -2
  67. package/src/config/vellum-skills/catalog.json +6 -0
  68. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +3 -3
  69. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +3 -3
  70. package/src/config/vellum-skills/sms-setup/SKILL.md +118 -0
  71. package/src/config/vellum-skills/twilio-setup/SKILL.md +40 -8
  72. package/src/daemon/handlers/config.ts +783 -9
  73. package/src/daemon/handlers/dictation.ts +182 -0
  74. package/src/daemon/handlers/identity.ts +14 -23
  75. package/src/daemon/handlers/index.ts +2 -0
  76. package/src/daemon/handlers/sessions.ts +2 -0
  77. package/src/daemon/handlers/shared.ts +3 -0
  78. package/src/daemon/handlers/work-items.ts +15 -7
  79. package/src/daemon/ipc-contract-inventory.json +10 -0
  80. package/src/daemon/ipc-contract.ts +108 -4
  81. package/src/daemon/lifecycle.ts +2 -0
  82. package/src/daemon/ride-shotgun-handler.ts +1 -1
  83. package/src/daemon/server.ts +6 -2
  84. package/src/daemon/session-agent-loop.ts +5 -1
  85. package/src/daemon/session-runtime-assembly.ts +55 -0
  86. package/src/daemon/session-tool-setup.ts +2 -0
  87. package/src/daemon/session.ts +11 -1
  88. package/src/inbound/public-ingress-urls.ts +3 -3
  89. package/src/memory/channel-guardian-store.ts +2 -1
  90. package/src/memory/db-init.ts +144 -0
  91. package/src/memory/job-handlers/media-processing.ts +100 -0
  92. package/src/memory/jobs-store.ts +2 -1
  93. package/src/memory/jobs-worker.ts +4 -0
  94. package/src/memory/media-store.ts +759 -0
  95. package/src/memory/retriever.ts +6 -1
  96. package/src/memory/schema.ts +98 -0
  97. package/src/memory/search/entity.ts +208 -25
  98. package/src/memory/search/ranking.ts +6 -1
  99. package/src/memory/search/types.ts +24 -0
  100. package/src/messaging/provider-types.ts +2 -0
  101. package/src/messaging/providers/sms/adapter.ts +204 -0
  102. package/src/messaging/providers/sms/client.ts +93 -0
  103. package/src/messaging/providers/sms/types.ts +7 -0
  104. package/src/permissions/checker.ts +16 -2
  105. package/src/runtime/approval-message-composer.ts +143 -0
  106. package/src/runtime/channel-approvals.ts +12 -4
  107. package/src/runtime/channel-guardian-service.ts +44 -18
  108. package/src/runtime/channel-readiness-service.ts +292 -0
  109. package/src/runtime/channel-readiness-types.ts +29 -0
  110. package/src/runtime/http-server.ts +53 -27
  111. package/src/runtime/http-types.ts +3 -0
  112. package/src/runtime/routes/call-routes.ts +2 -1
  113. package/src/runtime/routes/channel-routes.ts +67 -21
  114. package/src/runtime/run-orchestrator.ts +35 -2
  115. package/src/tools/assets/materialize.ts +2 -2
  116. package/src/tools/calls/call-start.ts +1 -0
  117. package/src/tools/credentials/vault.ts +1 -1
  118. package/src/tools/execution-target.ts +11 -1
  119. package/src/tools/network/web-search.ts +1 -1
  120. package/src/tools/types.ts +2 -0
  121. package/src/twitter/router.ts +1 -1
  122. package/src/util/platform.ts +35 -0
@@ -197,6 +197,7 @@ describe('Invariant 2: no generic plaintext secret read API', () => {
197
197
  'calls/elevenlabs-config.ts', // ElevenLabs credential lookup
198
198
  'cli/config-commands.ts', // CLI config management
199
199
  'messaging/providers/telegram-bot/adapter.ts', // Telegram bot token lookup for connectivity check
200
+ 'messaging/providers/sms/adapter.ts', // Twilio credential lookup for SMS connectivity check
200
201
  ]);
201
202
 
202
203
  const thisDir = dirname(fileURLToPath(import.meta.url));
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test';
1
+ import { beforeEach, describe, expect, mock, test } from 'bun:test';
2
2
  import type * as net from 'node:net';
3
3
 
4
4
  // ── Mocks ────────────────────────────────────────────────────────────
@@ -141,7 +141,7 @@ mock.module('../daemon/session.js', () => ({
141
141
 
142
142
  import { DaemonServer } from '../daemon/server.js';
143
143
  import { SessionEvictor, type EvictableSession } from '../daemon/session-evictor.js';
144
- import { createMessageParser, serialize, MAX_LINE_SIZE } from '../daemon/ipc-protocol.js';
144
+ import { createMessageParser, serialize } from '../daemon/ipc-protocol.js';
145
145
 
146
146
  // ── Test Helpers ─────────────────────────────────────────────────────
147
147
 
@@ -165,7 +165,7 @@ function internals(server: DaemonServer): DaemonServerInternals {
165
165
 
166
166
  function createFakeSocket(overrides?: Partial<net.Socket>) {
167
167
  const writes: string[] = [];
168
- const socket = {
168
+ const base: Record<string, unknown> = {
169
169
  destroyed: false,
170
170
  writable: true,
171
171
  remoteAddress: '127.0.0.1',
@@ -174,16 +174,17 @@ function createFakeSocket(overrides?: Partial<net.Socket>) {
174
174
  return true;
175
175
  },
176
176
  destroy(): void {
177
- this.destroyed = true;
177
+ base.destroyed = true;
178
178
  },
179
179
  on(_event: string, _handler: (...args: unknown[]) => void): unknown {
180
- return this;
180
+ return socket;
181
181
  },
182
182
  once(_event: string, _handler: (...args: unknown[]) => void): unknown {
183
- return this;
183
+ return socket;
184
184
  },
185
185
  ...overrides,
186
- } as unknown as net.Socket;
186
+ };
187
+ const socket = base as unknown as net.Socket;
187
188
  return { socket, writes };
188
189
  }
189
190
 
@@ -586,7 +587,7 @@ describe('IPC protocol', () => {
586
587
  const parser = createMessageParser();
587
588
  const messages = parser.feed('{"type":"ping"}\n');
588
589
  expect(messages).toHaveLength(1);
589
- expect((messages[0] as Record<string, unknown>).type).toBe('ping');
590
+ expect((messages[0] as unknown as Record<string, unknown>).type).toBe('ping');
590
591
  });
591
592
 
592
593
  test('buffers partial messages until newline arrives', () => {
@@ -597,22 +598,22 @@ describe('IPC protocol', () => {
597
598
 
598
599
  const partial2 = parser.feed('"ping"}\n');
599
600
  expect(partial2).toHaveLength(1);
600
- expect((partial2[0] as Record<string, unknown>).type).toBe('ping');
601
+ expect((partial2[0] as unknown as Record<string, unknown>).type).toBe('ping');
601
602
  });
602
603
 
603
604
  test('handles multiple messages in a single chunk', () => {
604
605
  const parser = createMessageParser();
605
606
  const messages = parser.feed('{"type":"ping"}\n{"type":"pong"}\n');
606
607
  expect(messages).toHaveLength(2);
607
- expect((messages[0] as Record<string, unknown>).type).toBe('ping');
608
- expect((messages[1] as Record<string, unknown>).type).toBe('pong');
608
+ expect((messages[0] as unknown as Record<string, unknown>).type).toBe('ping');
609
+ expect((messages[1] as unknown as Record<string, unknown>).type).toBe('pong');
609
610
  });
610
611
 
611
612
  test('skips malformed JSON lines gracefully', () => {
612
613
  const parser = createMessageParser();
613
614
  const messages = parser.feed('not json\n{"type":"valid"}\n');
614
615
  expect(messages).toHaveLength(1);
615
- expect((messages[0] as Record<string, unknown>).type).toBe('valid');
616
+ expect((messages[0] as unknown as Record<string, unknown>).type).toBe('valid');
616
617
  });
617
618
 
618
619
  test('throws when line exceeds maxLineSize', () => {
@@ -0,0 +1,63 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import type { DictationRequest } from '../daemon/ipc-protocol.js';
3
+ import { detectDictationMode } from '../daemon/handlers/dictation.js';
4
+
5
+ type DictationRequestOverrides = Omit<Partial<DictationRequest>, 'context'> & {
6
+ context?: Partial<DictationRequest['context']>;
7
+ };
8
+
9
+ function makeRequest(overrides: DictationRequestOverrides = {}): DictationRequest {
10
+ const base: DictationRequest = {
11
+ type: 'dictation_request',
12
+ transcription: 'hello there',
13
+ context: {
14
+ bundleIdentifier: 'com.google.Chrome',
15
+ appName: 'Google Chrome',
16
+ windowTitle: 'Inbox - Gmail',
17
+ selectedText: undefined,
18
+ cursorInTextField: false,
19
+ },
20
+ };
21
+ return {
22
+ ...base,
23
+ ...overrides,
24
+ context: {
25
+ ...base.context,
26
+ ...(overrides.context ?? {}),
27
+ },
28
+ };
29
+ }
30
+
31
+ describe('detectDictationMode', () => {
32
+ test('uses command mode when selected text exists', () => {
33
+ const mode = detectDictationMode(makeRequest({
34
+ transcription: 'make this friendlier',
35
+ context: { selectedText: 'Please send me the files.', cursorInTextField: true },
36
+ }));
37
+ expect(mode).toBe('command');
38
+ });
39
+
40
+ test('uses action mode for action-verb utterances', () => {
41
+ const mode = detectDictationMode(makeRequest({
42
+ transcription: 'send Alex a follow up',
43
+ context: { selectedText: undefined, cursorInTextField: false },
44
+ }));
45
+ expect(mode).toBe('action');
46
+ });
47
+
48
+ test('uses dictation mode when cursor is in a text field', () => {
49
+ const mode = detectDictationMode(makeRequest({
50
+ transcription: 'quick update on status',
51
+ context: { cursorInTextField: true },
52
+ }));
53
+ expect(mode).toBe('dictation');
54
+ });
55
+
56
+ test('defaults to dictation when context is ambiguous', () => {
57
+ const mode = detectDictationMode(makeRequest({
58
+ transcription: 'just checking in about tomorrow',
59
+ context: { selectedText: undefined, cursorInTextField: false },
60
+ }));
61
+ expect(mode).toBe('dictation');
62
+ });
63
+ });