@vellumai/assistant 0.4.29 → 0.4.30
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 +39 -37
- package/README.md +5 -6
- package/docs/runbook-trusted-contacts.md +79 -43
- package/package.json +1 -1
- package/scripts/ipc/check-swift-decoder-drift.ts +2 -3
- package/scripts/test.sh +1 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +4 -37
- package/src/__tests__/actor-token-service.test.ts +4 -3
- package/src/__tests__/app-executors.test.ts +7 -17
- package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -10
- package/src/__tests__/browser-skill-endstate.test.ts +10 -1
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +44 -44
- package/src/__tests__/channel-approval.test.ts +8 -0
- package/src/__tests__/channel-approvals.test.ts +39 -1
- package/src/__tests__/channel-guardian.test.ts +15 -5
- package/src/__tests__/channel-reply-delivery.test.ts +31 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +4 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +9 -0
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +2 -2
- package/src/__tests__/guardian-grant-minting.test.ts +6 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +34 -11
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +4 -6
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -1
- package/src/__tests__/integrations-cli.test.ts +3 -27
- package/src/__tests__/intent-routing.test.ts +3 -0
- package/src/__tests__/invite-redemption-service.test.ts +1 -1
- package/src/__tests__/{ingress-routes-http.test.ts → invite-routes-http.test.ts} +40 -320
- package/src/__tests__/ipc-snapshot.test.ts +4 -31
- package/src/__tests__/nl-approval-parser.test.ts +305 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +34 -0
- package/src/__tests__/provider-error-scenarios.test.ts +68 -0
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/retry-after-extraction.test.ts +111 -0
- package/src/__tests__/script-proxy-profile-template-fallback.test.ts +127 -0
- package/src/__tests__/session-media-retry.test.ts +147 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +9 -5
- package/src/__tests__/skill-feature-flags.test.ts +18 -12
- package/src/__tests__/skill-load-feature-flag.test.ts +4 -3
- package/src/__tests__/slack-block-formatting.test.ts +100 -0
- package/src/__tests__/slack-inbound-verification.test.ts +346 -0
- package/src/__tests__/slack-reaction-approvals.test.ts +77 -0
- package/src/__tests__/slack-skill.test.ts +3 -2
- package/src/__tests__/starter-task-flow.test.ts +0 -1
- package/src/__tests__/trusted-contact-verification.test.ts +3 -1
- package/src/__tests__/voice-invite-redemption.test.ts +1 -1
- package/src/amazon/client.ts +7 -24
- package/src/calls/relay-server.ts +39 -11
- package/src/channels/config.ts +1 -1
- package/src/cli/integrations.ts +10 -66
- package/src/config/bundled-skills/app-builder/SKILL.md +193 -1500
- package/src/config/bundled-skills/app-builder/TOOLS.json +70 -18
- package/src/config/bundled-skills/browser/TOOLS.json +59 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +4 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +50 -2
- package/src/config/bundled-skills/contacts/SKILL.md +42 -35
- package/src/config/bundled-skills/contacts/TOOLS.json +22 -2
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +38 -58
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +11 -31
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +19 -37
- package/src/config/bundled-skills/document/TOOLS.json +8 -0
- package/src/config/bundled-skills/email-setup/SKILL.md +10 -7
- package/src/config/bundled-skills/followups/TOOLS.json +12 -0
- package/src/config/bundled-skills/google-calendar/TOOLS.json +124 -26
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +54 -21
- package/src/config/bundled-skills/image-studio/TOOLS.json +12 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +14 -8
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +13 -3
- package/src/config/bundled-skills/media-processing/SKILL.md +1 -1
- package/src/config/bundled-skills/media-processing/TOOLS.json +28 -0
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +26 -6
- package/src/config/bundled-skills/messaging/TOOLS.json +228 -182
- package/src/config/bundled-skills/notifications/SKILL.md +3 -2
- package/src/config/bundled-skills/notifications/TOOLS.json +7 -13
- package/src/config/bundled-skills/phone-calls/TOOLS.json +13 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +16 -0
- package/src/config/bundled-skills/reminder/TOOLS.json +15 -2
- package/src/config/bundled-skills/schedule/SKILL.md +33 -15
- package/src/config/bundled-skills/schedule/TOOLS.json +17 -1
- package/src/config/bundled-skills/slack/SKILL.md +30 -1
- package/src/config/bundled-skills/slack/TOOLS.json +89 -2
- package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +146 -0
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +120 -0
- package/src/config/bundled-skills/slack-app-setup/SKILL.md +200 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +22 -2
- package/src/config/bundled-skills/tasks/TOOLS.json +86 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +4 -0
- package/src/config/bundled-skills/watcher/TOOLS.json +20 -0
- package/src/config/bundled-skills/weather/TOOLS.json +4 -0
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/channel-permission-profiles.ts +155 -0
- package/src/config/env.ts +4 -1
- package/src/contacts/contact-store.ts +195 -4
- package/src/contacts/types.ts +26 -0
- package/src/daemon/assistant-attachments.ts +23 -3
- package/src/daemon/guardian-verification-intent.ts +7 -4
- package/src/daemon/handlers/apps.ts +1 -2
- package/src/daemon/handlers/config-inbox.ts +16 -134
- package/src/daemon/handlers/guardian-actions.ts +20 -87
- package/src/daemon/handlers/sessions.ts +0 -1
- package/src/daemon/ipc-contract/apps.ts +0 -1
- package/src/daemon/ipc-contract/inbox.ts +7 -66
- package/src/daemon/ipc-contract/sessions.ts +1 -0
- package/src/daemon/ipc-contract/surfaces.ts +0 -1
- package/src/daemon/ipc-contract-inventory.json +2 -4
- package/src/daemon/lifecycle.ts +14 -2
- package/src/daemon/session-agent-loop-handlers.ts +9 -0
- package/src/daemon/session-agent-loop.ts +1 -0
- package/src/daemon/session-attachments.ts +5 -1
- package/src/daemon/session-error.ts +18 -0
- package/src/daemon/session-lifecycle.ts +4 -5
- package/src/daemon/session-media-retry.ts +15 -1
- package/src/daemon/session-surfaces.ts +0 -1
- package/src/daemon/session-tool-setup.ts +7 -4
- package/src/events/domain-events.ts +2 -1
- package/src/home-base/prebuilt/seed.ts +0 -1
- package/src/influencer/client.ts +7 -24
- package/src/media/gemini-image-service.ts +48 -3
- package/src/memory/app-store.ts +0 -4
- package/src/memory/conversation-attention-store.ts +3 -1
- package/src/memory/db-init.ts +4 -0
- package/src/memory/migrations/133-assistant-contact-metadata.ts +21 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/schema.ts +12 -0
- package/src/memory/slack-thread-store.ts +187 -0
- package/src/messaging/providers/slack/client.ts +84 -26
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/adapters/slack.ts +90 -0
- package/src/notifications/destination-resolver.ts +42 -1
- package/src/notifications/emit-signal.ts +17 -1
- package/src/oauth/provider-profiles.ts +22 -0
- package/src/providers/anthropic/client.ts +3 -0
- package/src/providers/openai/client.ts +3 -0
- package/src/providers/retry.ts +9 -1
- package/src/runtime/actor-trust-resolver.ts +8 -0
- package/src/runtime/auth/require-bound-guardian.ts +44 -0
- package/src/runtime/auth/route-policy.ts +4 -8
- package/src/runtime/channel-approval-types.ts +18 -0
- package/src/runtime/channel-approvals.ts +8 -0
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-reply-delivery.ts +62 -3
- package/src/runtime/gateway-client.ts +36 -2
- package/src/runtime/gateway-internal-client.ts +86 -0
- package/src/runtime/guardian-action-service.ts +127 -0
- package/src/runtime/guardian-verification-templates.ts +16 -1
- package/src/runtime/http-server.ts +20 -49
- package/src/runtime/invite-redemption-service.ts +1 -1
- package/src/runtime/{ingress-service.ts → invite-service.ts} +5 -157
- package/src/runtime/nl-approval-parser.ts +138 -0
- package/src/runtime/routes/approval-routes.ts +1 -40
- package/src/runtime/routes/channel-route-shared.ts +35 -1
- package/src/runtime/routes/contact-routes.ts +196 -28
- package/src/runtime/routes/guardian-action-routes.ts +19 -111
- package/src/runtime/routes/guardian-approval-interception.ts +76 -0
- package/src/runtime/routes/inbound-message-handler.ts +40 -12
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +222 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +108 -0
- package/src/runtime/routes/{ingress-routes.ts → invite-routes.ts} +10 -110
- package/src/runtime/slack-block-formatting.ts +176 -0
- package/src/schedule/scheduler.ts +11 -2
- package/src/tools/apps/executors.ts +16 -15
- package/src/tools/calls/call-end.ts +1 -1
- package/src/tools/computer-use/definitions.ts +16 -0
- package/src/tools/credentials/vault.ts +86 -2
- package/src/tools/network/script-proxy/session-manager.ts +28 -3
- package/src/tools/permission-checker.ts +18 -0
- package/src/tools/terminal/shell.ts +15 -5
- package/src/tools/tool-approval-handler.ts +48 -4
- package/src/tools/types.ts +38 -1
- package/src/util/errors.ts +5 -1
- package/src/util/retry.ts +21 -0
- package/src/watcher/providers/slack.ts +33 -3
- /package/src/memory/{ingress-invite-store.ts → invite-store.ts} +0 -0
|
@@ -46,6 +46,15 @@ mock.module("../util/logger.js", () => ({
|
|
|
46
46
|
truncateForLog: (v: string) => v,
|
|
47
47
|
}));
|
|
48
48
|
|
|
49
|
+
mock.module("../config/loader.js", () => ({
|
|
50
|
+
getConfig: () => ({
|
|
51
|
+
sandbox: { enabled: false, backend: "native" },
|
|
52
|
+
assistantFeatureFlagValues: {
|
|
53
|
+
"feature_flags.browser.enabled": true,
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
}));
|
|
57
|
+
|
|
49
58
|
const { buildSystemPrompt } = await import("../config/system-prompt.js");
|
|
50
59
|
|
|
51
60
|
describe("Dynamic Skill Authoring Workflow prompt section", () => {
|
|
@@ -32,6 +32,7 @@ const ALLOWLIST = new Set([
|
|
|
32
32
|
|
|
33
33
|
// --- Documentation and comments that mention the port for explanatory purposes ---
|
|
34
34
|
"AGENTS.md", // documents the gateway-only rule itself
|
|
35
|
+
"assistant/docs/runbook-trusted-contacts.md", // operator runbook targeting runtime-only /v1/contacts endpoints
|
|
35
36
|
"assistant/src/runtime/middleware/twilio-validation.ts", // comment explaining proxy URL rewriting
|
|
36
37
|
]);
|
|
37
38
|
|
|
@@ -137,8 +137,8 @@ describe("generateImage", () => {
|
|
|
137
137
|
.contents as Array<Record<string, unknown>>;
|
|
138
138
|
const parts = contents[0].parts as Array<Record<string, unknown>>;
|
|
139
139
|
|
|
140
|
-
// First part is the text prompt
|
|
141
|
-
expect(parts[0]
|
|
140
|
+
// First part is the text prompt (with appended title instruction)
|
|
141
|
+
expect((parts[0] as { text: string }).text).toContain("remove background");
|
|
142
142
|
// Second part is the source image
|
|
143
143
|
expect(parts[1]).toEqual({
|
|
144
144
|
inlineData: { mimeType: "image/jpeg", data: "srcdata" },
|
|
@@ -189,9 +189,9 @@ describe("guardian grant minting on tool-approval decisions", () => {
|
|
|
189
189
|
|
|
190
190
|
beforeEach(() => {
|
|
191
191
|
resetTables();
|
|
192
|
-
deliverSpy = spyOn(gatewayClient, "deliverChannelReply").mockResolvedValue(
|
|
193
|
-
|
|
194
|
-
);
|
|
192
|
+
deliverSpy = spyOn(gatewayClient, "deliverChannelReply").mockResolvedValue({
|
|
193
|
+
ok: true,
|
|
194
|
+
});
|
|
195
195
|
composeSpy = spyOn(
|
|
196
196
|
approvalMessageComposer,
|
|
197
197
|
"composeApprovalMessageGenerative",
|
|
@@ -593,9 +593,9 @@ describe("approval interception trust-class regression coverage", () => {
|
|
|
593
593
|
|
|
594
594
|
beforeEach(() => {
|
|
595
595
|
resetTables();
|
|
596
|
-
deliverSpy = spyOn(gatewayClient, "deliverChannelReply").mockResolvedValue(
|
|
597
|
-
|
|
598
|
-
);
|
|
596
|
+
deliverSpy = spyOn(gatewayClient, "deliverChannelReply").mockResolvedValue({
|
|
597
|
+
ok: true,
|
|
598
|
+
});
|
|
599
599
|
composeSpy = spyOn(
|
|
600
600
|
approvalMessageComposer,
|
|
601
601
|
"composeApprovalMessageGenerative",
|
|
@@ -169,22 +169,45 @@ function registerPendingToolApprovalInteraction(
|
|
|
169
169
|
describe("routing invariant: all decision paths reference applyCanonicalGuardianDecision", () => {
|
|
170
170
|
const srcRoot = resolve(__dirname, "..");
|
|
171
171
|
|
|
172
|
-
// The files that constitute decision entrypoints. Each must
|
|
173
|
-
// `applyCanonicalGuardianDecision`
|
|
174
|
-
|
|
172
|
+
// The files that constitute decision entrypoints. Each must reference
|
|
173
|
+
// `applyCanonicalGuardianDecision` (directly) or `processGuardianDecision`
|
|
174
|
+
// (shared wrapper that calls applyCanonicalGuardianDecision internally).
|
|
175
|
+
const DECISION_ENTRYPOINTS: Array<{
|
|
176
|
+
path: string;
|
|
177
|
+
symbols: string[];
|
|
178
|
+
}> = [
|
|
175
179
|
// Inbound channel router (Telegram/SMS/WhatsApp)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
{
|
|
181
|
+
path: "runtime/guardian-reply-router.ts",
|
|
182
|
+
symbols: ["applyCanonicalGuardianDecision"],
|
|
183
|
+
},
|
|
184
|
+
// HTTP API route handler (desktop and API clients) — uses processGuardianDecision
|
|
185
|
+
// which is a shared wrapper around applyCanonicalGuardianDecision
|
|
186
|
+
{
|
|
187
|
+
path: "runtime/routes/guardian-action-routes.ts",
|
|
188
|
+
symbols: ["processGuardianDecision"],
|
|
189
|
+
},
|
|
190
|
+
// IPC handler (desktop socket clients) — uses processGuardianDecision
|
|
191
|
+
// which is a shared wrapper around applyCanonicalGuardianDecision
|
|
192
|
+
{
|
|
193
|
+
path: "daemon/handlers/guardian-actions.ts",
|
|
194
|
+
symbols: ["processGuardianDecision"],
|
|
195
|
+
},
|
|
196
|
+
// Shared service where processGuardianDecision is defined — must route
|
|
197
|
+
// through the canonical primitive to complete the chain:
|
|
198
|
+
// entrypoint → processGuardianDecision → applyCanonicalGuardianDecision
|
|
199
|
+
{
|
|
200
|
+
path: "runtime/guardian-action-service.ts",
|
|
201
|
+
symbols: ["applyCanonicalGuardianDecision"],
|
|
202
|
+
},
|
|
181
203
|
];
|
|
182
204
|
|
|
183
|
-
for (const relPath of DECISION_ENTRYPOINTS) {
|
|
184
|
-
test(`${relPath} imports
|
|
205
|
+
for (const { path: relPath, symbols } of DECISION_ENTRYPOINTS) {
|
|
206
|
+
test(`${relPath} imports ${symbols.join(" or ")}`, () => {
|
|
185
207
|
const fullPath = join(srcRoot, relPath);
|
|
186
208
|
const source = readFileSync(fullPath, "utf-8");
|
|
187
|
-
|
|
209
|
+
const found = symbols.some((s) => source.includes(s));
|
|
210
|
+
expect(found).toBe(true);
|
|
188
211
|
});
|
|
189
212
|
}
|
|
190
213
|
|
|
@@ -107,14 +107,12 @@ describe("guardian-verify-setup skill — voice auto-followup", () => {
|
|
|
107
107
|
?.split("## Step 6")[0] ?? "";
|
|
108
108
|
// Must mention rebind guard concept
|
|
109
109
|
expect(pollingSection).toContain("Rebind guard");
|
|
110
|
-
// Must instruct not to trust
|
|
110
|
+
// Must instruct not to trust bound: true alone in a rebind flow
|
|
111
111
|
expect(pollingSection).toContain(
|
|
112
|
-
"do NOT treat
|
|
112
|
+
"do NOT treat `bound: true` alone as success",
|
|
113
113
|
);
|
|
114
|
-
// Must reference
|
|
115
|
-
expect(pollingSection).toContain("
|
|
116
|
-
// Must have a fallback for when bound_at is unavailable
|
|
117
|
-
expect(pollingSection).toContain("second poll onward");
|
|
114
|
+
// Must reference verificationSessionId as the mechanism to detect fresh binding
|
|
115
|
+
expect(pollingSection).toContain("verificationSessionId");
|
|
118
116
|
// Must clarify non-rebind flows are unaffected
|
|
119
117
|
expect(pollingSection).toContain("Non-rebind flows");
|
|
120
118
|
});
|
|
@@ -90,7 +90,7 @@ mock.module("../runtime/approval-message-composer.js", () => ({
|
|
|
90
90
|
import { findContactChannel } from "../contacts/contact-store.js";
|
|
91
91
|
import { upsertMember } from "../contacts/contacts-write.js";
|
|
92
92
|
import { getDb, initializeDb, resetDb } from "../memory/db.js";
|
|
93
|
-
import { createInvite, revokeInvite } from "../memory/
|
|
93
|
+
import { createInvite, revokeInvite } from "../memory/invite-store.js";
|
|
94
94
|
import { handleChannelInbound } from "../runtime/routes/channel-routes.js";
|
|
95
95
|
|
|
96
96
|
initializeDb();
|
|
@@ -108,7 +108,6 @@ describe("vellum integrations CLI", () => {
|
|
|
108
108
|
|
|
109
109
|
afterEach(() => {
|
|
110
110
|
delete process.env.GATEWAY_AUTH_TOKEN;
|
|
111
|
-
delete process.env.INTERNAL_GATEWAY_BASE_URL;
|
|
112
111
|
process.exitCode = 0;
|
|
113
112
|
});
|
|
114
113
|
|
|
@@ -141,8 +140,8 @@ describe("vellum integrations CLI", () => {
|
|
|
141
140
|
expect(mintCalls).toBe(1);
|
|
142
141
|
});
|
|
143
142
|
|
|
144
|
-
test("
|
|
145
|
-
|
|
143
|
+
test("uses configured gateway base for requests", async () => {
|
|
144
|
+
gatewayBase = "http://gateway.internal:9900";
|
|
146
145
|
const result = await runCli(["--json", "twilio", "config"], {
|
|
147
146
|
success: true,
|
|
148
147
|
});
|
|
@@ -163,28 +162,6 @@ describe("vellum integrations CLI", () => {
|
|
|
163
162
|
);
|
|
164
163
|
});
|
|
165
164
|
|
|
166
|
-
test("passes filters for ingress members (now calls /v1/contacts)", async () => {
|
|
167
|
-
const result = await runCli(
|
|
168
|
-
["--json", "ingress", "members", "--role", "contact", "--limit", "20"],
|
|
169
|
-
{ ok: true, contacts: [] },
|
|
170
|
-
);
|
|
171
|
-
expect(result.exitCode).toBe(0);
|
|
172
|
-
expect(result.fetchCalls[0]?.url).toBe(
|
|
173
|
-
"http://gateway.test/v1/contacts?role=contact&limit=20",
|
|
174
|
-
);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
test("ingress members defaults role to contact", async () => {
|
|
178
|
-
const result = await runCli(["--json", "ingress", "members"], {
|
|
179
|
-
ok: true,
|
|
180
|
-
contacts: [],
|
|
181
|
-
});
|
|
182
|
-
expect(result.exitCode).toBe(0);
|
|
183
|
-
expect(result.fetchCalls[0]?.url).toBe(
|
|
184
|
-
"http://gateway.test/v1/contacts?role=contact",
|
|
185
|
-
);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
165
|
test("reads ingress config without gateway fetch", async () => {
|
|
189
166
|
rawConfig = {
|
|
190
167
|
ingress: {
|
|
@@ -192,7 +169,6 @@ describe("vellum integrations CLI", () => {
|
|
|
192
169
|
publicBaseUrl: "https://public.example.com",
|
|
193
170
|
},
|
|
194
171
|
};
|
|
195
|
-
process.env.INTERNAL_GATEWAY_BASE_URL = "http://gateway.internal:9900/";
|
|
196
172
|
const result = await runCli(["--json", "ingress", "config"], { ok: true });
|
|
197
173
|
|
|
198
174
|
expect(result.exitCode).toBe(0);
|
|
@@ -201,7 +177,7 @@ describe("vellum integrations CLI", () => {
|
|
|
201
177
|
success: true,
|
|
202
178
|
enabled: true,
|
|
203
179
|
publicBaseUrl: "https://public.example.com",
|
|
204
|
-
localGatewayTarget: "http://gateway.
|
|
180
|
+
localGatewayTarget: "http://gateway.test",
|
|
205
181
|
});
|
|
206
182
|
});
|
|
207
183
|
|
|
@@ -29,7 +29,7 @@ import { getSqlite, initializeDb, resetDb } from "../memory/db.js";
|
|
|
29
29
|
import {
|
|
30
30
|
createInvite,
|
|
31
31
|
revokeInvite as revokeStoreFn,
|
|
32
|
-
} from "../memory/
|
|
32
|
+
} from "../memory/invite-store.js";
|
|
33
33
|
import {
|
|
34
34
|
type InviteRedemptionOutcome,
|
|
35
35
|
redeemInvite,
|