vellum 0.2.13 → 0.2.14
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.
- package/README.md +32 -0
- package/bun.lock +2 -2
- package/docs/skills.md +4 -4
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +213 -3
- package/src/__tests__/app-git-history.test.ts +176 -0
- package/src/__tests__/app-git-service.test.ts +169 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +315 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +8 -8
- package/src/__tests__/browser-skill-endstate.test.ts +6 -6
- package/src/__tests__/call-bridge.test.ts +105 -13
- package/src/__tests__/call-domain.test.ts +163 -0
- package/src/__tests__/call-orchestrator.test.ts +113 -0
- package/src/__tests__/call-routes-http.test.ts +246 -6
- package/src/__tests__/channel-approval-routes.test.ts +438 -0
- package/src/__tests__/channel-approval.test.ts +266 -0
- package/src/__tests__/channel-approvals.test.ts +393 -0
- package/src/__tests__/channel-delivery-store.test.ts +447 -0
- package/src/__tests__/checker.test.ts +607 -1048
- package/src/__tests__/cli.test.ts +1 -56
- package/src/__tests__/config-schema.test.ts +137 -18
- package/src/__tests__/conflict-intent-tokenization.test.ts +141 -0
- package/src/__tests__/conflict-policy.test.ts +121 -0
- package/src/__tests__/conflict-store.test.ts +2 -0
- package/src/__tests__/contacts-tools.test.ts +3 -3
- package/src/__tests__/contradiction-checker.test.ts +99 -1
- package/src/__tests__/credential-security-invariants.test.ts +22 -6
- package/src/__tests__/credential-vault-unit.test.ts +780 -0
- package/src/__tests__/elevenlabs-client.test.ts +62 -0
- package/src/__tests__/ephemeral-permissions.test.ts +73 -23
- package/src/__tests__/filesystem-tools.test.ts +579 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +114 -4
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +202 -0
- package/src/__tests__/handlers-cu-observation-blob.test.ts +2 -1
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +2 -1
- package/src/__tests__/handlers-slack-config.test.ts +2 -1
- package/src/__tests__/handlers-telegram-config.test.ts +855 -0
- package/src/__tests__/handlers-twitter-config.test.ts +141 -1
- package/src/__tests__/hooks-runner.test.ts +6 -2
- package/src/__tests__/host-file-edit-tool.test.ts +124 -0
- package/src/__tests__/host-file-read-tool.test.ts +62 -0
- package/src/__tests__/host-file-write-tool.test.ts +59 -0
- package/src/__tests__/host-shell-tool.test.ts +251 -0
- package/src/__tests__/ingress-reconcile.test.ts +581 -0
- package/src/__tests__/ipc-snapshot.test.ts +100 -41
- package/src/__tests__/ipc-validate.test.ts +50 -0
- package/src/__tests__/key-migration.test.ts +23 -0
- package/src/__tests__/memory-regressions.test.ts +99 -0
- package/src/__tests__/memory-retrieval.benchmark.test.ts +1 -1
- package/src/__tests__/oauth-callback-registry.test.ts +11 -4
- package/src/__tests__/playbook-execution.test.ts +502 -0
- package/src/__tests__/playbook-tools.test.ts +4 -6
- package/src/__tests__/public-ingress-urls.test.ts +34 -0
- package/src/__tests__/qdrant-manager.test.ts +267 -0
- package/src/__tests__/recurrence-engine-rruleset.test.ts +97 -0
- package/src/__tests__/recurrence-engine.test.ts +9 -0
- package/src/__tests__/recurrence-types.test.ts +8 -0
- package/src/__tests__/registry.test.ts +1 -1
- package/src/__tests__/runtime-runs.test.ts +1 -25
- package/src/__tests__/schedule-store.test.ts +16 -14
- package/src/__tests__/schedule-tools.test.ts +83 -0
- package/src/__tests__/scheduler-recurrence.test.ts +111 -10
- package/src/__tests__/secret-allowlist.test.ts +18 -17
- package/src/__tests__/secret-ingress-handler.test.ts +11 -0
- package/src/__tests__/secret-scanner.test.ts +43 -0
- package/src/__tests__/session-conflict-gate.test.ts +442 -6
- package/src/__tests__/session-init.benchmark.test.ts +3 -0
- package/src/__tests__/session-process-bridge.test.ts +242 -0
- package/src/__tests__/session-skill-tools.test.ts +1 -1
- package/src/__tests__/shell-identity.test.ts +256 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +11 -1
- package/src/__tests__/subagent-tools.test.ts +637 -54
- package/src/__tests__/task-management-tools.test.ts +936 -0
- package/src/__tests__/task-runner.test.ts +2 -2
- package/src/__tests__/terminal-tools.test.ts +840 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +301 -0
- package/src/__tests__/tool-executor.test.ts +85 -151
- package/src/__tests__/tool-permission-simulate-handler.test.ts +336 -0
- package/src/__tests__/trust-store.test.ts +27 -453
- package/src/__tests__/twilio-provider.test.ts +153 -3
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +375 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +4 -4
- package/src/__tests__/twilio-routes.test.ts +17 -262
- package/src/__tests__/twitter-auth-handler.test.ts +2 -1
- package/src/__tests__/twitter-cli-error-shaping.test.ts +208 -0
- package/src/__tests__/twitter-cli-routing.test.ts +252 -0
- package/src/__tests__/twitter-oauth-client.test.ts +209 -0
- package/src/__tests__/workspace-policy.test.ts +213 -0
- package/src/calls/call-bridge.ts +92 -19
- package/src/calls/call-domain.ts +157 -5
- package/src/calls/call-orchestrator.ts +93 -7
- package/src/calls/call-store.ts +6 -0
- package/src/calls/elevenlabs-client.ts +8 -0
- package/src/calls/elevenlabs-config.ts +7 -5
- package/src/calls/twilio-provider.ts +91 -0
- package/src/calls/twilio-routes.ts +32 -37
- package/src/calls/types.ts +3 -1
- package/src/calls/voice-quality.ts +29 -7
- package/src/cli/twitter.ts +200 -21
- package/src/cli.ts +1 -20
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +52 -4
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +55 -4
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +61 -4
- package/src/config/bundled-skills/messaging/SKILL.md +17 -2
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +4 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -1
- package/src/config/bundled-skills/messaging/tools/shared.ts +5 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +142 -34
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +95 -6
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +51 -6
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +73 -6
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +110 -6
- package/src/config/bundled-skills/public-ingress/SKILL.md +22 -5
- package/src/config/bundled-skills/twitter/SKILL.md +103 -17
- package/src/config/defaults.ts +10 -4
- package/src/config/schema.ts +80 -21
- package/src/config/types.ts +1 -0
- package/src/config/vellum-skills/telegram-setup/SKILL.md +56 -61
- package/src/daemon/assistant-attachments.ts +4 -2
- package/src/daemon/handlers/apps.ts +69 -0
- package/src/daemon/handlers/config.ts +543 -24
- package/src/daemon/handlers/index.ts +1 -0
- package/src/daemon/handlers/sessions.ts +22 -6
- package/src/daemon/handlers/shared.ts +2 -1
- package/src/daemon/handlers/skills.ts +5 -20
- package/src/daemon/ipc-contract-inventory.json +28 -0
- package/src/daemon/ipc-contract.ts +168 -10
- package/src/daemon/ipc-validate.ts +17 -0
- package/src/daemon/lifecycle.ts +2 -0
- package/src/daemon/server.ts +78 -72
- package/src/daemon/session-attachments.ts +1 -1
- package/src/daemon/session-conflict-gate.ts +62 -6
- package/src/daemon/session-notifiers.ts +1 -1
- package/src/daemon/session-process.ts +62 -3
- package/src/daemon/session-tool-setup.ts +1 -2
- package/src/daemon/tls-certs.ts +189 -0
- package/src/daemon/video-thumbnail.ts +5 -3
- package/src/hooks/manager.ts +5 -9
- package/src/memory/app-git-service.ts +295 -0
- package/src/memory/app-store.ts +21 -0
- package/src/memory/conflict-intent.ts +47 -4
- package/src/memory/conflict-policy.ts +73 -0
- package/src/memory/conflict-store.ts +9 -1
- package/src/memory/contradiction-checker.ts +28 -0
- package/src/memory/conversation-key-store.ts +15 -0
- package/src/memory/db.ts +81 -0
- package/src/memory/embedding-local.ts +3 -13
- package/src/memory/external-conversation-store.ts +234 -0
- package/src/memory/job-handlers/conflict.ts +22 -2
- package/src/memory/jobs-worker.ts +67 -28
- package/src/memory/runs-store.ts +54 -7
- package/src/memory/schema.ts +20 -0
- package/src/messaging/provider.ts +9 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +162 -0
- package/src/messaging/providers/telegram-bot/client.ts +104 -0
- package/src/messaging/providers/telegram-bot/types.ts +15 -0
- package/src/messaging/registry.ts +1 -0
- package/src/permissions/checker.ts +48 -44
- package/src/permissions/prompter.ts +0 -4
- package/src/permissions/shell-identity.ts +227 -0
- package/src/permissions/trust-store.ts +76 -53
- package/src/permissions/types.ts +0 -19
- package/src/permissions/workspace-policy.ts +114 -0
- package/src/providers/retry.ts +12 -37
- package/src/runtime/assistant-event-hub.ts +41 -4
- package/src/runtime/channel-approval-parser.ts +60 -0
- package/src/runtime/channel-approval-types.ts +71 -0
- package/src/runtime/channel-approvals.ts +145 -0
- package/src/runtime/gateway-client.ts +16 -0
- package/src/runtime/http-server.ts +29 -9
- package/src/runtime/routes/call-routes.ts +52 -2
- package/src/runtime/routes/channel-routes.ts +296 -16
- package/src/runtime/routes/events-routes.ts +97 -28
- package/src/runtime/routes/run-routes.ts +2 -7
- package/src/runtime/run-orchestrator.ts +0 -3
- package/src/schedule/recurrence-engine.ts +26 -2
- package/src/schedule/recurrence-types.ts +1 -1
- package/src/schedule/schedule-store.ts +12 -3
- package/src/security/secret-scanner.ts +7 -0
- package/src/tasks/ephemeral-permissions.ts +0 -2
- package/src/tasks/task-scheduler.ts +2 -1
- package/src/tools/calls/call-start.ts +8 -0
- package/src/tools/execution-target.ts +21 -0
- package/src/tools/execution-timeout.ts +49 -0
- package/src/tools/executor.ts +6 -135
- package/src/tools/network/web-search.ts +9 -32
- package/src/tools/policy-context.ts +29 -0
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/terminal/parser.ts +16 -18
- package/src/tools/types.ts +4 -11
- package/src/twitter/oauth-client.ts +102 -0
- package/src/twitter/router.ts +101 -0
- package/src/util/debounce.ts +88 -0
- package/src/util/network-info.ts +47 -0
- package/src/util/platform.ts +29 -4
- package/src/util/promise-guard.ts +37 -0
- package/src/util/retry.ts +98 -0
- package/src/util/truncate.ts +1 -1
- package/src/workspace/git-service.ts +129 -112
- package/src/tools/contacts/contact-merge.ts +0 -55
- package/src/tools/contacts/contact-search.ts +0 -58
- package/src/tools/contacts/contact-upsert.ts +0 -64
- package/src/tools/playbooks/index.ts +0 -4
- package/src/tools/playbooks/playbook-create.ts +0 -96
- package/src/tools/playbooks/playbook-delete.ts +0 -52
- package/src/tools/playbooks/playbook-list.ts +0 -74
- package/src/tools/playbooks/playbook-update.ts +0 -111
|
@@ -51,9 +51,18 @@ mock.module('../util/logger.js', () => ({
|
|
|
51
51
|
}),
|
|
52
52
|
}));
|
|
53
53
|
|
|
54
|
+
let mockConflictableKinds: string[] = [
|
|
55
|
+
'preference', 'profile', 'constraint', 'instruction', 'style',
|
|
56
|
+
];
|
|
57
|
+
|
|
54
58
|
mock.module('../config/loader.js', () => ({
|
|
55
59
|
getConfig: () => ({
|
|
56
60
|
apiKeys: { anthropic: 'test-key' },
|
|
61
|
+
memory: {
|
|
62
|
+
conflicts: {
|
|
63
|
+
conflictableKinds: mockConflictableKinds,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
57
66
|
}),
|
|
58
67
|
}));
|
|
59
68
|
|
|
@@ -67,6 +76,9 @@ beforeAll(() => {
|
|
|
67
76
|
|
|
68
77
|
beforeEach(() => {
|
|
69
78
|
classifyCallCount = 0;
|
|
79
|
+
mockConflictableKinds = [
|
|
80
|
+
'preference', 'profile', 'constraint', 'instruction', 'style',
|
|
81
|
+
];
|
|
70
82
|
const db = getDb();
|
|
71
83
|
db.run('DELETE FROM memory_item_conflicts');
|
|
72
84
|
db.run('DELETE FROM memory_item_sources');
|
|
@@ -88,12 +100,13 @@ function insertMemoryItem(params: {
|
|
|
88
100
|
statement: string;
|
|
89
101
|
scopeId?: string;
|
|
90
102
|
status?: 'active' | 'pending_clarification';
|
|
103
|
+
kind?: string;
|
|
91
104
|
}): void {
|
|
92
105
|
const now = Date.now();
|
|
93
106
|
const db = getDb();
|
|
94
107
|
db.insert(memoryItems).values({
|
|
95
108
|
id: params.id,
|
|
96
|
-
kind: 'preference',
|
|
109
|
+
kind: params.kind ?? 'preference',
|
|
97
110
|
subject: 'framework preference',
|
|
98
111
|
statement: params.statement,
|
|
99
112
|
status: params.status ?? 'active',
|
|
@@ -213,4 +226,89 @@ describe('checkContradictions', () => {
|
|
|
213
226
|
expect(candidate?.status).toBe('active');
|
|
214
227
|
expect(conflicts).toHaveLength(0);
|
|
215
228
|
});
|
|
229
|
+
|
|
230
|
+
test('project kind ambiguous contradiction does not generate pending conflict with default config', async () => {
|
|
231
|
+
nextRelationship = 'ambiguous_contradiction';
|
|
232
|
+
nextExplanation = 'Project items may conflict but are not durable.';
|
|
233
|
+
|
|
234
|
+
insertMemoryItem({
|
|
235
|
+
id: 'item-existing-project',
|
|
236
|
+
statement: 'The backend uses Node.js.',
|
|
237
|
+
kind: 'project',
|
|
238
|
+
});
|
|
239
|
+
insertMemoryItem({
|
|
240
|
+
id: 'item-candidate-project',
|
|
241
|
+
statement: 'The backend uses Deno.',
|
|
242
|
+
kind: 'project',
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
await checkContradictions('item-candidate-project');
|
|
246
|
+
|
|
247
|
+
expect(classifyCallCount).toBe(0);
|
|
248
|
+
const db = getDb();
|
|
249
|
+
const conflicts = db.select().from(memoryItemConflicts).all();
|
|
250
|
+
expect(conflicts).toHaveLength(0);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test('skips classification when item kind is not in conflictableKinds', async () => {
|
|
254
|
+
mockConflictableKinds = ['instruction', 'style'];
|
|
255
|
+
nextRelationship = 'ambiguous_contradiction';
|
|
256
|
+
|
|
257
|
+
insertMemoryItem({
|
|
258
|
+
id: 'item-existing-ineligible',
|
|
259
|
+
statement: 'User prefers React for frontend work.',
|
|
260
|
+
});
|
|
261
|
+
insertMemoryItem({
|
|
262
|
+
id: 'item-candidate-ineligible',
|
|
263
|
+
statement: 'User prefers Vue for frontend work.',
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
await checkContradictions('item-candidate-ineligible');
|
|
267
|
+
|
|
268
|
+
expect(classifyCallCount).toBe(0);
|
|
269
|
+
const db = getDb();
|
|
270
|
+
const conflicts = db.select().from(memoryItemConflicts).all();
|
|
271
|
+
expect(conflicts).toHaveLength(0);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('skips classification when candidate statement contains PR-tracking content', async () => {
|
|
275
|
+
nextRelationship = 'ambiguous_contradiction';
|
|
276
|
+
|
|
277
|
+
insertMemoryItem({
|
|
278
|
+
id: 'item-existing-pr-tracking',
|
|
279
|
+
statement: 'Track PR #5526 for review.',
|
|
280
|
+
});
|
|
281
|
+
insertMemoryItem({
|
|
282
|
+
id: 'item-candidate-pr-tracking',
|
|
283
|
+
statement: 'Track PR #5525 for review.',
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await checkContradictions('item-candidate-pr-tracking');
|
|
287
|
+
|
|
288
|
+
expect(classifyCallCount).toBe(0);
|
|
289
|
+
const db = getDb();
|
|
290
|
+
const conflicts = db.select().from(memoryItemConflicts).all();
|
|
291
|
+
expect(conflicts).toHaveLength(0);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test('durable preference contradiction still runs normal flow', async () => {
|
|
295
|
+
nextRelationship = 'ambiguous_contradiction';
|
|
296
|
+
nextExplanation = 'Both are valid preferences that conflict.';
|
|
297
|
+
|
|
298
|
+
insertMemoryItem({
|
|
299
|
+
id: 'item-existing-durable',
|
|
300
|
+
statement: 'User prefers React for frontend work.',
|
|
301
|
+
});
|
|
302
|
+
insertMemoryItem({
|
|
303
|
+
id: 'item-candidate-durable',
|
|
304
|
+
statement: 'User prefers Vue for frontend work.',
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
await checkContradictions('item-candidate-durable');
|
|
308
|
+
|
|
309
|
+
expect(classifyCallCount).toBe(1);
|
|
310
|
+
const db = getDb();
|
|
311
|
+
const conflicts = db.select().from(memoryItemConflicts).all();
|
|
312
|
+
expect(conflicts).toHaveLength(1);
|
|
313
|
+
});
|
|
216
314
|
});
|
|
@@ -185,10 +185,17 @@ describe('Invariant 2: no generic plaintext secret read API', () => {
|
|
|
185
185
|
'email/providers/index.ts', // email provider API key lookup
|
|
186
186
|
'tools/network/script-proxy/session-manager.ts', // proxy credential injection at runtime
|
|
187
187
|
'messaging/registry.ts', // checks stored credentials for connected providers
|
|
188
|
+
'calls/call-domain.ts', // caller identity resolution (user phone number lookup)
|
|
189
|
+
'calls/elevenlabs-config.ts', // ElevenLabs voice quality API key lookup
|
|
188
190
|
'calls/twilio-config.ts', // call infrastructure credential lookup
|
|
189
191
|
'calls/twilio-provider.ts', // call infrastructure credential lookup
|
|
192
|
+
'cli/config-commands.ts', // CLI credential management commands
|
|
190
193
|
'runtime/http-server.ts', // HTTP server credential lookup
|
|
191
194
|
'daemon/handlers/twitter-auth.ts', // Twitter OAuth token storage
|
|
195
|
+
'twitter/oauth-client.ts', // Twitter OAuth API client (reads access token for API calls)
|
|
196
|
+
'calls/elevenlabs-config.ts', // ElevenLabs credential lookup
|
|
197
|
+
'cli/config-commands.ts', // CLI config management
|
|
198
|
+
'messaging/providers/telegram-bot/adapter.ts', // Telegram bot token lookup for connectivity check
|
|
192
199
|
]);
|
|
193
200
|
|
|
194
201
|
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -267,18 +274,27 @@ describe('Invariant 3: secrets never logged in plaintext', () => {
|
|
|
267
274
|
});
|
|
268
275
|
} else if (tc.component === 'ipc_decode') {
|
|
269
276
|
// PR 24 — IPC decode log hygiene: the TS daemon's IPC parser must
|
|
270
|
-
// not
|
|
277
|
+
// not log raw message content that could contain secrets.
|
|
278
|
+
// Logging metadata (line length, error type) is acceptable; logging
|
|
279
|
+
// the raw line, trimmed content, or error.message is not.
|
|
271
280
|
test(`${tc.label}`, () => {
|
|
272
281
|
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
273
282
|
const ipcSrc = readFileSync(
|
|
274
283
|
resolve(thisDir, '../daemon/ipc-protocol.ts'),
|
|
275
284
|
'utf-8',
|
|
276
285
|
);
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
286
|
+
// Verify log calls never include raw content fields — only safe
|
|
287
|
+
// metadata like lineLength and errorType are permitted.
|
|
288
|
+
// `trimmed.length` is safe (numeric); `trimmed` alone would leak raw content.
|
|
289
|
+
// Use [^\n]* instead of [^)]* so that inner parentheses (e.g.
|
|
290
|
+
// helper calls like formatErr(err)) don't terminate the match
|
|
291
|
+
// early — avoiding false negatives — while still scoping each
|
|
292
|
+
// pattern to a single line (no cross-statement matching).
|
|
293
|
+
expect(ipcSrc).not.toMatch(/\blog\.\w+\([^\n]*[{,]\s*trimmed[^.]/);
|
|
294
|
+
expect(ipcSrc).not.toMatch(/\blog\.\w+\([^\n]*[{,]\s*line[^L]/);
|
|
295
|
+
expect(ipcSrc).not.toMatch(/\blog\.\w+\([^\n]*[{,]\s*data\b/);
|
|
296
|
+
expect(ipcSrc).not.toMatch(/\blog\.\w+\([^\n]*[{,]\s*buffer\b/);
|
|
297
|
+
expect(ipcSrc).not.toMatch(/\blog\.\w+\([^\n]*err\.message\b/);
|
|
282
298
|
});
|
|
283
299
|
} else {
|
|
284
300
|
// PR 25 — secret prompter log hygiene: verify the prompter source
|