@vellumai/assistant 0.4.11 → 0.4.13

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 (111) hide show
  1. package/ARCHITECTURE.md +401 -385
  2. package/package.json +1 -1
  3. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +75 -61
  4. package/src/__tests__/registry.test.ts +235 -187
  5. package/src/__tests__/secure-keys.test.ts +27 -0
  6. package/src/__tests__/session-agent-loop.test.ts +521 -256
  7. package/src/__tests__/session-surfaces-task-progress.test.ts +1 -0
  8. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -0
  9. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -0
  10. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -0
  11. package/src/__tests__/skills.test.ts +334 -276
  12. package/src/__tests__/slack-skill.test.ts +124 -0
  13. package/src/__tests__/starter-task-flow.test.ts +7 -17
  14. package/src/agent/loop.ts +10 -3
  15. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +449 -0
  16. package/src/config/bundled-skills/doordash/SKILL.md +171 -0
  17. package/src/config/bundled-skills/doordash/__tests__/doordash-client.test.ts +203 -0
  18. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +164 -0
  19. package/src/config/bundled-skills/doordash/doordash-cli.ts +1193 -0
  20. package/src/config/bundled-skills/doordash/doordash-entry.ts +22 -0
  21. package/src/config/bundled-skills/doordash/lib/cart-queries.ts +787 -0
  22. package/src/config/bundled-skills/doordash/lib/client.ts +1071 -0
  23. package/src/config/bundled-skills/doordash/lib/order-queries.ts +85 -0
  24. package/src/config/bundled-skills/doordash/lib/queries.ts +28 -0
  25. package/src/config/bundled-skills/doordash/lib/query-extractor.ts +94 -0
  26. package/src/config/bundled-skills/doordash/lib/search-queries.ts +203 -0
  27. package/src/config/bundled-skills/doordash/lib/session.ts +93 -0
  28. package/src/config/bundled-skills/doordash/lib/shared/errors.ts +61 -0
  29. package/src/config/bundled-skills/doordash/lib/shared/ipc.ts +32 -0
  30. package/src/config/bundled-skills/doordash/lib/shared/network-recorder.ts +380 -0
  31. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +35 -0
  32. package/src/config/bundled-skills/doordash/lib/shared/recording-store.ts +43 -0
  33. package/src/config/bundled-skills/doordash/lib/shared/recording-types.ts +49 -0
  34. package/src/config/bundled-skills/doordash/lib/shared/truncate.ts +6 -0
  35. package/src/config/bundled-skills/doordash/lib/store-queries.ts +246 -0
  36. package/src/config/bundled-skills/doordash/lib/types.ts +367 -0
  37. package/src/config/bundled-skills/google-calendar/SKILL.md +4 -5
  38. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +41 -41
  39. package/src/config/bundled-skills/messaging/SKILL.md +59 -42
  40. package/src/config/bundled-skills/messaging/TOOLS.json +14 -92
  41. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +5 -1
  42. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +11 -2
  43. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +8 -1
  44. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +12 -4
  45. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +5 -1
  46. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +5 -1
  47. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +5 -2
  48. package/src/config/bundled-skills/notion/SKILL.md +240 -0
  49. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +127 -0
  50. package/src/config/bundled-skills/oauth-setup/SKILL.md +144 -0
  51. package/src/config/bundled-skills/phone-calls/SKILL.md +76 -45
  52. package/src/config/bundled-skills/skills-catalog/SKILL.md +32 -29
  53. package/src/config/bundled-skills/slack/SKILL.md +49 -0
  54. package/src/config/bundled-skills/slack/TOOLS.json +167 -0
  55. package/src/config/bundled-skills/slack/tools/shared.ts +23 -0
  56. package/src/config/bundled-skills/{messaging → slack}/tools/slack-add-reaction.ts +2 -5
  57. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +33 -0
  58. package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +75 -0
  59. package/src/config/bundled-skills/{messaging → slack}/tools/slack-delete-message.ts +2 -5
  60. package/src/config/bundled-skills/{messaging → slack}/tools/slack-leave-channel.ts +2 -5
  61. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +193 -0
  62. package/src/config/{vellum-skills → bundled-skills}/sms-setup/SKILL.md +29 -22
  63. package/src/config/{vellum-skills → bundled-skills}/telegram-setup/SKILL.md +17 -14
  64. package/src/config/{vellum-skills → bundled-skills}/twilio-setup/SKILL.md +20 -5
  65. package/src/config/bundled-tool-registry.ts +292 -267
  66. package/src/config/schema.ts +1 -1
  67. package/src/daemon/handlers/skills.ts +334 -234
  68. package/src/daemon/ipc-contract/messages.ts +2 -0
  69. package/src/daemon/ipc-contract/surfaces.ts +2 -0
  70. package/src/daemon/lifecycle.ts +358 -221
  71. package/src/daemon/response-tier.ts +2 -0
  72. package/src/daemon/server.ts +453 -193
  73. package/src/daemon/session-agent-loop-handlers.ts +43 -2
  74. package/src/daemon/session-agent-loop.ts +3 -0
  75. package/src/daemon/session-lifecycle.ts +3 -0
  76. package/src/daemon/session-process.ts +1 -0
  77. package/src/daemon/session-surfaces.ts +22 -20
  78. package/src/daemon/session-tool-setup.ts +1 -0
  79. package/src/daemon/session.ts +5 -2
  80. package/src/messaging/outreach-classifier.ts +12 -5
  81. package/src/messaging/provider-types.ts +5 -0
  82. package/src/messaging/provider.ts +1 -1
  83. package/src/messaging/providers/gmail/adapter.ts +11 -5
  84. package/src/messaging/providers/gmail/client.ts +2 -0
  85. package/src/messaging/providers/slack/adapter.ts +1 -0
  86. package/src/messaging/providers/slack/client.ts +8 -0
  87. package/src/messaging/providers/slack/types.ts +5 -0
  88. package/src/runtime/http-errors.ts +33 -20
  89. package/src/runtime/http-server.ts +706 -291
  90. package/src/runtime/http-types.ts +26 -16
  91. package/src/runtime/routes/secret-routes.ts +57 -2
  92. package/src/runtime/routes/surface-action-routes.ts +66 -0
  93. package/src/runtime/routes/trust-rules-routes.ts +140 -0
  94. package/src/security/keychain-to-encrypted-migration.ts +59 -0
  95. package/src/security/secure-keys.ts +17 -0
  96. package/src/skills/frontmatter.ts +9 -7
  97. package/src/tools/apps/executors.ts +2 -1
  98. package/src/tools/tool-manifest.ts +44 -42
  99. package/src/tools/types.ts +9 -0
  100. package/src/__tests__/skill-mirror-parity.test.ts +0 -176
  101. package/src/config/vellum-skills/catalog.json +0 -63
  102. package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +0 -295
  103. package/src/skills/vellum-catalog-remote.ts +0 -166
  104. package/src/tools/skills/vellum-catalog.ts +0 -168
  105. /package/src/config/{vellum-skills → bundled-skills}/chatgpt-import/SKILL.md +0 -0
  106. /package/src/config/{vellum-skills → bundled-skills}/chatgpt-import/TOOLS.json +0 -0
  107. /package/src/config/{vellum-skills → bundled-skills}/deploy-fullstack-vercel/SKILL.md +0 -0
  108. /package/src/config/{vellum-skills → bundled-skills}/document-writer/SKILL.md +0 -0
  109. /package/src/config/{vellum-skills → bundled-skills}/guardian-verify-setup/SKILL.md +0 -0
  110. /package/src/config/{vellum-skills → bundled-skills}/slack-oauth-setup/SKILL.md +0 -0
  111. /package/src/config/{vellum-skills → bundled-skills}/trusted-contacts/SKILL.md +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.4.11",
3
+ "version": "0.4.13",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "vellum": "./src/index.ts"
@@ -5,113 +5,128 @@
5
5
  * so the user does not have to manually ask whether verification succeeded.
6
6
  */
7
7
 
8
- import { readFileSync } from 'node:fs';
9
- import { resolve } from 'node:path';
8
+ import { readFileSync } from "node:fs";
9
+ import { resolve } from "node:path";
10
10
 
11
- import { describe, expect, test } from 'bun:test';
11
+ import { describe, expect, test } from "bun:test";
12
12
 
13
13
  // ---------------------------------------------------------------------------
14
14
  // Locate the skill SKILL.md
15
15
  // ---------------------------------------------------------------------------
16
16
 
17
- const ASSISTANT_DIR = resolve(import.meta.dirname ?? __dirname, '..', '..');
17
+ const ASSISTANT_DIR = resolve(import.meta.dirname ?? __dirname, "..", "..");
18
18
  const SKILL_PATH = resolve(
19
19
  ASSISTANT_DIR,
20
- 'src',
21
- 'config',
22
- 'vellum-skills',
23
- 'guardian-verify-setup',
24
- 'SKILL.md',
20
+ "src",
21
+ "config",
22
+ "bundled-skills",
23
+ "guardian-verify-setup",
24
+ "SKILL.md",
25
25
  );
26
26
 
27
- const skillContent = readFileSync(SKILL_PATH, 'utf-8');
27
+ const skillContent = readFileSync(SKILL_PATH, "utf-8");
28
28
 
29
29
  // ---------------------------------------------------------------------------
30
30
  // Tests
31
31
  // ---------------------------------------------------------------------------
32
32
 
33
- describe('guardian-verify-setup skill — voice auto-followup', () => {
34
- test('voice path in Step 3 references the auto-check polling loop', () => {
33
+ describe("guardian-verify-setup skill — voice auto-followup", () => {
34
+ test("voice path in Step 3 references the auto-check polling loop", () => {
35
35
  // The voice success instruction in Step 3 must direct the assistant to
36
36
  // begin the polling loop rather than waiting for the user to report back.
37
37
  expect(skillContent).toContain(
38
- 'immediately begin the voice auto-check polling loop',
38
+ "immediately begin the voice auto-check polling loop",
39
39
  );
40
40
  });
41
41
 
42
- test('voice path in Step 4 (resend) references the auto-check polling loop', () => {
42
+ test("voice path in Step 4 (resend) references the auto-check polling loop", () => {
43
43
  // After a voice resend, the same auto-check behavior must kick in.
44
- const resendSection = skillContent.split('## Step 4')[1]?.split('## Step 5')[0] ?? '';
45
- expect(resendSection).toContain(
46
- 'voice auto-check polling loop',
47
- );
44
+ const resendSection =
45
+ skillContent.split("## Step 4")[1]?.split("## Step 5")[0] ?? "";
46
+ expect(resendSection).toContain("voice auto-check polling loop");
48
47
  });
49
48
 
50
- test('contains a Voice Auto-Check Polling section', () => {
51
- expect(skillContent).toContain('## Voice Auto-Check Polling');
49
+ test("contains a Voice Auto-Check Polling section", () => {
50
+ expect(skillContent).toContain("## Voice Auto-Check Polling");
52
51
  });
53
52
 
54
- test('polling section specifies the correct status endpoint for voice', () => {
53
+ test("polling section specifies the correct status endpoint for voice", () => {
55
54
  const pollingSection =
56
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
55
+ skillContent
56
+ .split("## Voice Auto-Check Polling")[1]
57
+ ?.split("## Step 6")[0] ?? "";
57
58
  expect(pollingSection).toContain(
58
- '/v1/integrations/guardian/status?channel=voice',
59
+ "/v1/integrations/guardian/status?channel=voice",
59
60
  );
60
61
  });
61
62
 
62
- test('polling section includes ~15 second interval', () => {
63
+ test("polling section includes ~15 second interval", () => {
63
64
  const pollingSection =
64
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
65
- expect(pollingSection).toContain('~15 seconds');
65
+ skillContent
66
+ .split("## Voice Auto-Check Polling")[1]
67
+ ?.split("## Step 6")[0] ?? "";
68
+ expect(pollingSection).toContain("~15 seconds");
66
69
  });
67
70
 
68
- test('polling section includes 2-minute timeout', () => {
71
+ test("polling section includes 2-minute timeout", () => {
69
72
  const pollingSection =
70
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
71
- expect(pollingSection).toContain('2 minutes');
73
+ skillContent
74
+ .split("## Voice Auto-Check Polling")[1]
75
+ ?.split("## Step 6")[0] ?? "";
76
+ expect(pollingSection).toContain("2 minutes");
72
77
  });
73
78
 
74
- test('polling section checks for bound: true', () => {
79
+ test("polling section checks for bound: true", () => {
75
80
  const pollingSection =
76
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
77
- expect(pollingSection).toContain('bound: true');
81
+ skillContent
82
+ .split("## Voice Auto-Check Polling")[1]
83
+ ?.split("## Step 6")[0] ?? "";
84
+ expect(pollingSection).toContain("bound: true");
78
85
  });
79
86
 
80
- test('polling section includes proactive success confirmation', () => {
87
+ test("polling section includes proactive success confirmation", () => {
81
88
  const pollingSection =
82
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
83
- expect(pollingSection).toContain('proactive success message');
89
+ skillContent
90
+ .split("## Voice Auto-Check Polling")[1]
91
+ ?.split("## Step 6")[0] ?? "";
92
+ expect(pollingSection).toContain("proactive success message");
84
93
  });
85
94
 
86
- test('polling section includes timeout fallback with resend/restart offer', () => {
95
+ test("polling section includes timeout fallback with resend/restart offer", () => {
87
96
  const pollingSection =
88
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
89
- expect(pollingSection).toContain('timeout');
90
- expect(pollingSection).toContain('resend');
97
+ skillContent
98
+ .split("## Voice Auto-Check Polling")[1]
99
+ ?.split("## Step 6")[0] ?? "";
100
+ expect(pollingSection).toContain("timeout");
101
+ expect(pollingSection).toContain("resend");
91
102
  });
92
103
 
93
- test('polling section includes rebind guard against false-success from pre-existing binding', () => {
104
+ test("polling section includes rebind guard against false-success from pre-existing binding", () => {
94
105
  const pollingSection =
95
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
106
+ skillContent
107
+ .split("## Voice Auto-Check Polling")[1]
108
+ ?.split("## Step 6")[0] ?? "";
96
109
  // Must mention rebind guard concept
97
- expect(pollingSection).toContain('Rebind guard');
110
+ expect(pollingSection).toContain("Rebind guard");
98
111
  // Must instruct not to trust the first bound: true in a rebind flow
99
112
  expect(pollingSection).toContain(
100
- 'do NOT treat the first `bound: true` poll result as success',
113
+ "do NOT treat the first `bound: true` poll result as success",
101
114
  );
102
115
  // Must reference bound_at timestamp comparison as the primary mechanism
103
- expect(pollingSection).toContain('bound_at');
116
+ expect(pollingSection).toContain("bound_at");
104
117
  // Must have a fallback for when bound_at is unavailable
105
- expect(pollingSection).toContain('second poll onward');
118
+ expect(pollingSection).toContain("second poll onward");
106
119
  // Must clarify non-rebind flows are unaffected
107
- expect(pollingSection).toContain('Non-rebind flows');
120
+ expect(pollingSection).toContain("Non-rebind flows");
108
121
  });
109
122
 
110
- test('polling is voice-only — does not apply to SMS or Telegram', () => {
123
+ test("polling is voice-only — does not apply to SMS or Telegram", () => {
111
124
  const pollingSection =
112
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
113
- expect(pollingSection).toContain('voice-only');
114
- expect(pollingSection).toContain('Do NOT poll for SMS or Telegram');
125
+ skillContent
126
+ .split("## Voice Auto-Check Polling")[1]
127
+ ?.split("## Step 6")[0] ?? "";
128
+ expect(pollingSection).toContain("voice-only");
129
+ expect(pollingSection).toContain("Do NOT poll for SMS or Telegram");
115
130
  });
116
131
 
117
132
  test('no instruction requires waiting for user to ask "did it work?"', () => {
@@ -119,23 +134,22 @@ describe('guardian-verify-setup skill — voice auto-followup', () => {
119
134
  // confirm that voice verification worked. The auto-check polling loop
120
135
  // makes this unnecessary.
121
136
  const voiceAutoCheckSection =
122
- skillContent.split('## Voice Auto-Check Polling')[1]?.split('## Step 6')[0] ?? '';
123
- expect(voiceAutoCheckSection).toContain(
124
- 'Do NOT require the user to ask',
125
- );
137
+ skillContent
138
+ .split("## Voice Auto-Check Polling")[1]
139
+ ?.split("## Step 6")[0] ?? "";
140
+ expect(voiceAutoCheckSection).toContain("Do NOT require the user to ask");
126
141
  // The voice bullet in Step 3 should not instruct the assistant to wait
127
142
  // for the user to confirm or ask if it worked. Narrow to just the voice
128
143
  // bullet line to avoid false positives from Telegram's "wait for the
129
144
  // user to confirm they clicked the link" which is unrelated to voice.
130
- const step3Section = skillContent
131
- .split('## Step 3')[1]
132
- ?.split('## Step 4')[0] ?? '';
145
+ const step3Section =
146
+ skillContent.split("## Step 3")[1]?.split("## Step 4")[0] ?? "";
133
147
  const voiceBullet = step3Section
134
- .split('\n')
148
+ .split("\n")
135
149
  .filter((line) => /^\s*-\s+\*\*Voice\*\*/.test(line))
136
- .join('\n');
150
+ .join("\n");
137
151
  expect(voiceBullet).not.toHaveLength(0);
138
- expect(voiceBullet).not.toContain('wait for the user to confirm');
139
- expect(voiceBullet).not.toContain('ask the user if it worked');
152
+ expect(voiceBullet).not.toContain("wait for the user to confirm");
153
+ expect(voiceBullet).not.toContain("ask the user if it worked");
140
154
  });
141
155
  });