@vellumai/assistant 0.3.19 → 0.3.21
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/ARCHITECTURE.md +151 -15
- package/Dockerfile +1 -0
- package/README.md +40 -4
- package/bun.lock +139 -2
- package/docs/architecture/integrations.md +7 -11
- package/package.json +2 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +54 -0
- package/src/__tests__/approval-primitive.test.ts +540 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +206 -0
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +198 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +272 -0
- package/src/__tests__/call-controller.test.ts +439 -108
- package/src/__tests__/channel-invite-transport.test.ts +264 -0
- package/src/__tests__/cli.test.ts +42 -1
- package/src/__tests__/config-schema.test.ts +11 -127
- package/src/__tests__/config-watcher.test.ts +0 -8
- package/src/__tests__/daemon-lifecycle.test.ts +1 -0
- package/src/__tests__/daemon-server-session-init.test.ts +8 -2
- package/src/__tests__/diff.test.ts +22 -0
- package/src/__tests__/guardian-action-copy-generator.test.ts +5 -0
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +300 -32
- package/src/__tests__/guardian-action-late-reply.test.ts +546 -1
- package/src/__tests__/guardian-actions-endpoint.test.ts +774 -0
- package/src/__tests__/guardian-control-plane-policy.test.ts +36 -3
- package/src/__tests__/guardian-dispatch.test.ts +124 -0
- package/src/__tests__/guardian-grant-minting.test.ts +6 -17
- package/src/__tests__/inbound-invite-redemption.test.ts +367 -0
- package/src/__tests__/invite-redemption-service.test.ts +306 -0
- package/src/__tests__/ipc-snapshot.test.ts +57 -0
- package/src/__tests__/notification-decision-fallback.test.ts +88 -0
- package/src/__tests__/sandbox-diagnostics.test.ts +6 -249
- package/src/__tests__/sandbox-host-parity.test.ts +6 -13
- package/src/__tests__/scoped-approval-grants.test.ts +6 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -4
- package/src/__tests__/script-proxy-session-manager.test.ts +1 -19
- package/src/__tests__/session-load-history-repair.test.ts +169 -2
- package/src/__tests__/session-runtime-assembly.test.ts +33 -5
- package/src/__tests__/skill-feature-flags-integration.test.ts +171 -0
- package/src/__tests__/skill-feature-flags.test.ts +188 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +141 -0
- package/src/__tests__/skill-mirror-parity.test.ts +1 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +363 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/terminal-sandbox.test.ts +142 -9
- package/src/__tests__/terminal-tools.test.ts +2 -93
- package/src/__tests__/thread-seed-composer.test.ts +18 -0
- package/src/__tests__/tool-approval-handler.test.ts +350 -0
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +8 -10
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +46 -84
- package/src/agent/loop.ts +36 -1
- package/src/approvals/approval-primitive.ts +381 -0
- package/src/approvals/guardian-decision-primitive.ts +191 -0
- package/src/calls/call-controller.ts +252 -209
- package/src/calls/call-domain.ts +44 -6
- package/src/calls/guardian-dispatch.ts +48 -0
- package/src/calls/types.ts +1 -1
- package/src/calls/voice-session-bridge.ts +46 -30
- package/src/cli/core-commands.ts +0 -4
- package/src/cli/mcp.ts +58 -0
- package/src/cli.ts +76 -34
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +179 -0
- package/src/config/assistant-feature-flags.ts +162 -0
- package/src/config/bundled-skills/api-mapping/icon.svg +18 -0
- package/src/config/bundled-skills/messaging/TOOLS.json +30 -0
- package/src/config/bundled-skills/messaging/tools/slack-delete-message.ts +24 -0
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/reminder/SKILL.md +49 -2
- package/src/config/bundled-skills/time-based-actions/SKILL.md +49 -2
- package/src/config/bundled-skills/voice-setup/SKILL.md +122 -0
- package/src/config/core-schema.ts +1 -1
- package/src/config/env-registry.ts +10 -0
- package/src/config/feature-flag-registry.json +61 -0
- package/src/config/loader.ts +22 -1
- package/src/config/mcp-schema.ts +46 -0
- package/src/config/sandbox-schema.ts +0 -39
- package/src/config/schema.ts +18 -2
- package/src/config/skill-state.ts +34 -0
- package/src/config/skills-schema.ts +0 -1
- package/src/config/skills.ts +9 -0
- package/src/config/system-prompt.ts +110 -46
- package/src/config/templates/SOUL.md +1 -1
- package/src/config/types.ts +19 -1
- package/src/config/vellum-skills/catalog.json +1 -1
- package/src/config/vellum-skills/guardian-verify-setup/SKILL.md +1 -0
- package/src/config/vellum-skills/sms-setup/SKILL.md +1 -1
- package/src/config/vellum-skills/telegram-setup/SKILL.md +6 -5
- package/src/config/vellum-skills/trusted-contacts/SKILL.md +105 -3
- package/src/config/vellum-skills/twilio-setup/SKILL.md +1 -1
- package/src/daemon/config-watcher.ts +0 -1
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/guardian-invite-intent.ts +124 -0
- package/src/daemon/handlers/avatar.ts +68 -0
- package/src/daemon/handlers/browser.ts +2 -2
- package/src/daemon/handlers/guardian-actions.ts +120 -0
- package/src/daemon/handlers/index.ts +4 -0
- package/src/daemon/handlers/sessions.ts +19 -0
- package/src/daemon/handlers/shared.ts +3 -1
- package/src/daemon/install-cli-launchers.ts +58 -13
- package/src/daemon/ipc-contract/guardian-actions.ts +53 -0
- package/src/daemon/ipc-contract/sessions.ts +8 -2
- package/src/daemon/ipc-contract/settings.ts +25 -2
- package/src/daemon/ipc-contract-inventory.json +10 -0
- package/src/daemon/ipc-contract.ts +4 -0
- package/src/daemon/lifecycle.ts +14 -2
- package/src/daemon/main.ts +1 -0
- package/src/daemon/providers-setup.ts +26 -1
- package/src/daemon/server.ts +1 -0
- package/src/daemon/session-lifecycle.ts +52 -7
- package/src/daemon/session-memory.ts +45 -0
- package/src/daemon/session-process.ts +258 -432
- package/src/daemon/session-runtime-assembly.ts +12 -0
- package/src/daemon/session-skill-tools.ts +14 -1
- package/src/daemon/session-tool-setup.ts +5 -0
- package/src/daemon/session.ts +11 -0
- package/src/daemon/shutdown-handlers.ts +11 -0
- package/src/daemon/tool-side-effects.ts +35 -9
- package/src/index.ts +2 -2
- package/src/mcp/client.ts +152 -0
- package/src/mcp/manager.ts +139 -0
- package/src/memory/conversation-display-order-migration.ts +44 -0
- package/src/memory/conversation-queries.ts +2 -0
- package/src/memory/conversation-store.ts +91 -0
- package/src/memory/db-init.ts +5 -1
- package/src/memory/embedding-local.ts +13 -8
- package/src/memory/guardian-action-store.ts +125 -2
- package/src/memory/ingress-invite-store.ts +95 -1
- package/src/memory/migrations/035-guardian-action-supersession.ts +23 -0
- package/src/memory/migrations/index.ts +2 -1
- package/src/memory/schema.ts +5 -1
- package/src/memory/scoped-approval-grants.ts +14 -5
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/types.ts +5 -0
- package/src/notifications/decision-engine.ts +49 -12
- package/src/notifications/emit-signal.ts +7 -0
- package/src/notifications/signal.ts +7 -0
- package/src/notifications/thread-seed-composer.ts +2 -1
- package/src/runtime/channel-approval-types.ts +16 -6
- package/src/runtime/channel-approvals.ts +19 -15
- package/src/runtime/channel-invite-transport.ts +85 -0
- package/src/runtime/channel-invite-transports/telegram.ts +105 -0
- package/src/runtime/guardian-action-grant-minter.ts +92 -35
- package/src/runtime/guardian-action-message-composer.ts +30 -0
- package/src/runtime/guardian-decision-types.ts +91 -0
- package/src/runtime/http-server.ts +23 -1
- package/src/runtime/ingress-service.ts +22 -0
- package/src/runtime/invite-redemption-service.ts +181 -0
- package/src/runtime/invite-redemption-templates.ts +39 -0
- package/src/runtime/routes/call-routes.ts +2 -1
- package/src/runtime/routes/guardian-action-routes.ts +206 -0
- package/src/runtime/routes/guardian-approval-interception.ts +66 -190
- package/src/runtime/routes/identity-routes.ts +73 -0
- package/src/runtime/routes/inbound-message-handler.ts +486 -394
- package/src/runtime/routes/pairing-routes.ts +4 -0
- package/src/security/encrypted-store.ts +31 -17
- package/src/security/keychain.ts +176 -2
- package/src/security/secure-keys.ts +97 -0
- package/src/security/tool-approval-digest.ts +1 -1
- package/src/tools/browser/browser-execution.ts +2 -2
- package/src/tools/browser/browser-manager.ts +46 -32
- package/src/tools/browser/browser-screencast.ts +2 -2
- package/src/tools/calls/call-start.ts +1 -1
- package/src/tools/executor.ts +22 -17
- package/src/tools/mcp/mcp-tool-factory.ts +100 -0
- package/src/tools/network/script-proxy/session-manager.ts +1 -5
- package/src/tools/registry.ts +64 -1
- package/src/tools/skills/load.ts +22 -8
- package/src/tools/system/avatar-generator.ts +119 -0
- package/src/tools/system/navigate-settings.ts +65 -0
- package/src/tools/system/open-system-settings.ts +75 -0
- package/src/tools/system/voice-config.ts +121 -32
- package/src/tools/terminal/backends/native.ts +40 -19
- package/src/tools/terminal/backends/types.ts +3 -3
- package/src/tools/terminal/parser.ts +1 -1
- package/src/tools/terminal/sandbox-diagnostics.ts +6 -87
- package/src/tools/terminal/sandbox.ts +1 -12
- package/src/tools/terminal/shell.ts +3 -31
- package/src/tools/tool-approval-handler.ts +141 -3
- package/src/tools/tool-manifest.ts +6 -0
- package/src/tools/types.ts +10 -2
- package/src/util/diff.ts +36 -13
- package/Dockerfile.sandbox +0 -5
- package/src/__tests__/doordash-client.test.ts +0 -187
- package/src/__tests__/doordash-session.test.ts +0 -154
- package/src/__tests__/signup-e2e.test.ts +0 -354
- package/src/__tests__/terminal-sandbox-docker.test.ts +0 -1065
- package/src/__tests__/terminal-sandbox.integration.test.ts +0 -180
- package/src/cli/doordash.ts +0 -1057
- package/src/config/bundled-skills/doordash/SKILL.md +0 -163
- package/src/config/templates/LOOKS.md +0 -25
- package/src/doordash/cart-queries.ts +0 -787
- package/src/doordash/client.ts +0 -1016
- package/src/doordash/order-queries.ts +0 -85
- package/src/doordash/queries.ts +0 -13
- package/src/doordash/query-extractor.ts +0 -94
- package/src/doordash/search-queries.ts +0 -203
- package/src/doordash/session.ts +0 -84
- package/src/doordash/store-queries.ts +0 -246
- package/src/doordash/types.ts +0 -367
- package/src/tools/terminal/backends/docker.ts +0 -379
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime-gated Docker integration tests.
|
|
3
|
-
*
|
|
4
|
-
* These tests run real Docker containers — they are skipped automatically
|
|
5
|
-
* when Docker is not available or the sandbox image is not pulled locally.
|
|
6
|
-
* To run them locally:
|
|
7
|
-
* 1. Install Docker Desktop / Docker Engine
|
|
8
|
-
* 2. docker pull <configured sandbox image>
|
|
9
|
-
* 3. bun test src/__tests__/terminal-sandbox.integration.test.ts
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { execFileSync, spawnSync } from 'node:child_process';
|
|
13
|
-
import {
|
|
14
|
-
existsSync,
|
|
15
|
-
mkdirSync,
|
|
16
|
-
mkdtempSync,
|
|
17
|
-
readFileSync,
|
|
18
|
-
realpathSync,
|
|
19
|
-
rmSync,
|
|
20
|
-
statSync,
|
|
21
|
-
writeFileSync,
|
|
22
|
-
} from 'node:fs';
|
|
23
|
-
import { join } from 'node:path';
|
|
24
|
-
|
|
25
|
-
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
|
|
26
|
-
|
|
27
|
-
import { DEFAULT_CONFIG } from '../config/defaults.js';
|
|
28
|
-
import { getSandboxWorkingDir } from '../util/platform.js';
|
|
29
|
-
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
// Runtime gate: skip entire file if Docker is not usable
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
|
|
34
|
-
function dockerAvailable(): boolean {
|
|
35
|
-
try {
|
|
36
|
-
execFileSync('docker', ['info'], { stdio: 'ignore', timeout: 10000 });
|
|
37
|
-
return true;
|
|
38
|
-
} catch {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const IMAGE = DEFAULT_CONFIG.sandbox.docker.image;
|
|
44
|
-
|
|
45
|
-
function imageAvailable(): boolean {
|
|
46
|
-
try {
|
|
47
|
-
execFileSync('docker', ['image', 'inspect', IMAGE], {
|
|
48
|
-
stdio: 'ignore',
|
|
49
|
-
timeout: 10000,
|
|
50
|
-
});
|
|
51
|
-
return true;
|
|
52
|
-
} catch {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const DOCKER_OK = dockerAvailable() && imageAvailable();
|
|
58
|
-
|
|
59
|
-
// ---------------------------------------------------------------------------
|
|
60
|
-
// Helpers
|
|
61
|
-
// ---------------------------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
let sandboxRoot: string;
|
|
64
|
-
|
|
65
|
-
beforeAll(() => {
|
|
66
|
-
if (!DOCKER_OK) return;
|
|
67
|
-
const parent = getSandboxWorkingDir();
|
|
68
|
-
if (!existsSync(parent)) {
|
|
69
|
-
mkdirSync(parent, { recursive: true });
|
|
70
|
-
}
|
|
71
|
-
sandboxRoot = realpathSync(mkdtempSync(join(parent, 'docker-integ-')));
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
afterAll(() => {
|
|
75
|
-
if (sandboxRoot && existsSync(sandboxRoot)) {
|
|
76
|
-
rmSync(sandboxRoot, { recursive: true, force: true });
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
interface DockerRunOptions {
|
|
81
|
-
/** Run as root instead of the host UID:GID. Useful for testing filesystem-level protections. */
|
|
82
|
-
asRoot?: boolean;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Run a command inside a Docker container with the sandbox root mounted. */
|
|
86
|
-
function dockerRun(cmd: string, opts?: DockerRunOptions): { stdout: string; exitCode: number } {
|
|
87
|
-
const uid = process.getuid?.() ?? 1000;
|
|
88
|
-
const gid = process.getgid?.() ?? 1000;
|
|
89
|
-
const userArgs = opts?.asRoot ? ['--user', '0:0'] : ['--user', `${uid}:${gid}`];
|
|
90
|
-
const result = spawnSync('docker', [
|
|
91
|
-
'run', '--rm',
|
|
92
|
-
'--network=none',
|
|
93
|
-
'--cap-drop=ALL',
|
|
94
|
-
'--security-opt=no-new-privileges',
|
|
95
|
-
'--read-only',
|
|
96
|
-
'--tmpfs', '/tmp:rw,nosuid,nodev,noexec',
|
|
97
|
-
'--mount', `type=bind,src=${sandboxRoot},dst=/workspace`,
|
|
98
|
-
'--workdir', '/workspace',
|
|
99
|
-
...userArgs,
|
|
100
|
-
IMAGE,
|
|
101
|
-
'bash', '-c', cmd,
|
|
102
|
-
], { timeout: 30000, encoding: 'utf-8' });
|
|
103
|
-
return {
|
|
104
|
-
stdout: (result.stdout ?? '').trim(),
|
|
105
|
-
exitCode: result.status ?? -1,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// ---------------------------------------------------------------------------
|
|
110
|
-
// Tests
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
|
|
113
|
-
describe.skipIf(!DOCKER_OK)('Docker integration: write inside sandbox', () => {
|
|
114
|
-
test('writing a file inside /workspace succeeds', () => {
|
|
115
|
-
const { exitCode } = dockerRun('echo "hello" > /workspace/test-write.txt && cat /workspace/test-write.txt');
|
|
116
|
-
expect(exitCode).toBe(0);
|
|
117
|
-
// Verify the file appeared on the host
|
|
118
|
-
const hostPath = join(sandboxRoot, 'test-write.txt');
|
|
119
|
-
expect(existsSync(hostPath)).toBe(true);
|
|
120
|
-
expect(readFileSync(hostPath, 'utf-8').trim()).toBe('hello');
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test('creating nested directories inside /workspace succeeds', () => {
|
|
124
|
-
const { exitCode, stdout } = dockerRun('mkdir -p /workspace/a/b/c && echo ok');
|
|
125
|
-
expect(exitCode).toBe(0);
|
|
126
|
-
expect(stdout).toBe('ok');
|
|
127
|
-
expect(existsSync(join(sandboxRoot, 'a/b/c'))).toBe(true);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe.skipIf(!DOCKER_OK)('Docker integration: write outside workspace fails', () => {
|
|
132
|
-
// Run as root so Unix permissions are not a factor — the read-only
|
|
133
|
-
// filesystem mount is the only thing preventing these writes.
|
|
134
|
-
test('writing to /etc inside container fails (read-only root)', () => {
|
|
135
|
-
const { exitCode } = dockerRun('touch /etc/evil 2>/dev/null', { asRoot: true });
|
|
136
|
-
expect(exitCode).not.toBe(0);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('writing to /home inside container fails (read-only root)', () => {
|
|
140
|
-
const { exitCode } = dockerRun('touch /home/evil 2>/dev/null', { asRoot: true });
|
|
141
|
-
expect(exitCode).not.toBe(0);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test('writing to /tmp succeeds (tmpfs mount)', () => {
|
|
145
|
-
// /tmp is an explicit tmpfs mount so writes should work
|
|
146
|
-
const { exitCode, stdout } = dockerRun('echo ok > /tmp/test.txt && cat /tmp/test.txt');
|
|
147
|
-
expect(exitCode).toBe(0);
|
|
148
|
-
expect(stdout).toBe('ok');
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe.skipIf(!DOCKER_OK)('Docker integration: host-writable files', () => {
|
|
153
|
-
test('files created in container are owned by host UID:GID', () => {
|
|
154
|
-
const filename = 'host-owner-test.txt';
|
|
155
|
-
dockerRun(`echo "owned" > /workspace/${filename}`);
|
|
156
|
-
const hostPath = join(sandboxRoot, filename);
|
|
157
|
-
expect(existsSync(hostPath)).toBe(true);
|
|
158
|
-
const stat = statSync(hostPath);
|
|
159
|
-
const expectedUid = process.getuid?.() ?? 1000;
|
|
160
|
-
const expectedGid = process.getgid?.() ?? 1000;
|
|
161
|
-
expect(stat.uid).toBe(expectedUid);
|
|
162
|
-
expect(stat.gid).toBe(expectedGid);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
test('host can read files created by container', () => {
|
|
166
|
-
const filename = 'host-readable-test.txt';
|
|
167
|
-
const content = 'container-created-content';
|
|
168
|
-
dockerRun(`echo "${content}" > /workspace/${filename}`);
|
|
169
|
-
const hostPath = join(sandboxRoot, filename);
|
|
170
|
-
expect(readFileSync(hostPath, 'utf-8').trim()).toBe(content);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
test('container can read files created by host', () => {
|
|
174
|
-
const filename = 'host-created.txt';
|
|
175
|
-
writeFileSync(join(sandboxRoot, filename), 'from-host');
|
|
176
|
-
const { stdout, exitCode } = dockerRun(`cat /workspace/${filename}`);
|
|
177
|
-
expect(exitCode).toBe(0);
|
|
178
|
-
expect(stdout).toBe('from-host');
|
|
179
|
-
});
|
|
180
|
-
});
|