@vellumai/assistant 0.4.53 → 0.4.55
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/bun.lock +62 -349
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/keychain-broker.md +94 -29
- package/docs/architecture/security.md +2 -2
- package/knip.json +7 -29
- package/package.json +2 -9
- package/src/__tests__/agent-loop.test.ts +1 -1
- package/src/__tests__/app-git-history.test.ts +0 -2
- package/src/__tests__/app-git-service.test.ts +1 -6
- package/src/__tests__/approval-cascade.test.ts +0 -1
- package/src/__tests__/avatar-e2e.test.ts +0 -1
- package/src/__tests__/browser-fill-credential.test.ts +1 -6
- package/src/__tests__/call-domain.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -4
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +13 -11
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -1
- package/src/__tests__/claude-code-tool-profiles.test.ts +1 -2
- package/src/__tests__/config-loader-backfill.test.ts +0 -3
- package/src/__tests__/config-schema.test.ts +3 -9
- package/src/__tests__/config-watcher.test.ts +11 -3
- package/src/__tests__/credential-broker-browser-fill.test.ts +27 -24
- package/src/__tests__/credential-broker-server-use.test.ts +60 -24
- package/src/__tests__/credential-security-e2e.test.ts +1 -6
- package/src/__tests__/credential-security-invariants.test.ts +13 -8
- package/src/__tests__/credential-vault-unit.test.ts +28 -12
- package/src/__tests__/credential-vault.test.ts +40 -28
- package/src/__tests__/credentials-cli.test.ts +1 -21
- package/src/__tests__/email-invite-adapter.test.ts +0 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +3 -3
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -79
- package/src/__tests__/gateway-only-enforcement.test.ts +1 -21
- package/src/__tests__/guardian-action-conversation-turn.test.ts +8 -8
- package/src/__tests__/guardian-action-late-reply.test.ts +13 -14
- package/src/__tests__/guardian-action-store.test.ts +0 -57
- package/src/__tests__/guardian-outbound-http.test.ts +1 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -3
- package/src/__tests__/hooks-blocking.test.ts +1 -1
- package/src/__tests__/hooks-config.test.ts +5 -29
- package/src/__tests__/hooks-discovery.test.ts +1 -1
- package/src/__tests__/hooks-integration.test.ts +1 -1
- package/src/__tests__/hooks-manager.test.ts +1 -1
- package/src/__tests__/hooks-runner.test.ts +1 -23
- package/src/__tests__/hooks-settings.test.ts +1 -1
- package/src/__tests__/hooks-templates.test.ts +1 -1
- package/src/__tests__/integration-status.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +0 -3
- package/src/__tests__/list-messages-attachments.test.ts +4 -4
- package/src/__tests__/llm-usage-store.test.ts +50 -0
- package/src/__tests__/managed-proxy-context.test.ts +41 -41
- package/src/__tests__/media-generate-image.test.ts +2 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -6
- package/src/__tests__/memory-regressions.experimental.test.ts +4 -4
- package/src/__tests__/memory-regressions.test.ts +27 -27
- package/src/__tests__/memory-retrieval.benchmark.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -4
- package/src/__tests__/notification-decision-fallback.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +1 -4
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/openai-provider.test.ts +7 -7
- package/src/__tests__/platform.test.ts +14 -4
- package/src/__tests__/pricing.test.ts +0 -223
- package/src/__tests__/provider-commit-message-generator.test.ts +1 -4
- package/src/__tests__/provider-fail-open-selection.test.ts +58 -54
- package/src/__tests__/provider-managed-proxy-integration.test.ts +63 -63
- package/src/__tests__/provider-registry-ollama.test.ts +3 -3
- package/src/__tests__/public-ingress-urls.test.ts +1 -1
- package/src/__tests__/registry.test.ts +3 -103
- package/src/__tests__/script-proxy-injection-runtime.test.ts +2 -7
- package/src/__tests__/secret-onetime-send.test.ts +1 -6
- package/src/__tests__/secret-routes-managed-proxy.test.ts +6 -13
- package/src/__tests__/secure-keys.test.ts +241 -229
- package/src/__tests__/session-abort-tool-results.test.ts +0 -1
- package/src/__tests__/session-confirmation-signals.test.ts +0 -1
- package/src/__tests__/session-messaging-secret-redirect.test.ts +1 -7
- package/src/__tests__/session-pre-run-repair.test.ts +0 -1
- package/src/__tests__/session-provider-retry-repair.test.ts +0 -1
- package/src/__tests__/session-queue.test.ts +2 -4
- package/src/__tests__/session-slash-known.test.ts +0 -1
- package/src/__tests__/session-slash-queue.test.ts +0 -1
- package/src/__tests__/session-slash-unknown.test.ts +0 -1
- package/src/__tests__/session-workspace-injection.test.ts +0 -1
- package/src/__tests__/session-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +1 -7
- package/src/__tests__/swarm-recursion.test.ts +0 -1
- package/src/__tests__/swarm-session-integration.test.ts +0 -1
- package/src/__tests__/swarm-tool.test.ts +0 -1
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/test-support/browser-skill-harness.ts +0 -18
- package/src/__tests__/test-support/computer-use-skill-harness.ts +0 -23
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trust-store.test.ts +3 -82
- package/src/__tests__/twilio-config.test.ts +0 -1
- package/src/__tests__/twilio-provider.test.ts +0 -5
- package/src/__tests__/twilio-routes.test.ts +0 -1
- package/src/__tests__/usage-cache-backfill-migration.test.ts +10 -10
- package/src/calls/guardian-question-copy.ts +1 -1
- package/src/cli/commands/bash.ts +3 -0
- package/src/cli/commands/doctor.ts +10 -34
- package/src/cli/commands/memory.ts +3 -5
- package/src/cli/commands/sessions.ts +1 -1
- package/src/cli/commands/usage.ts +359 -0
- package/src/cli/http-client.ts +22 -12
- package/src/cli/program.ts +2 -0
- package/src/cli/reference.ts +1 -0
- package/src/cli.ts +251 -181
- package/src/config/assistant-feature-flags.ts +0 -7
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +1 -1
- package/src/config/bundled-skills/claude-code/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/SKILL.md +0 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +0 -1
- package/src/config/bundled-skills/sequences/SKILL.md +0 -1
- package/src/config/env.ts +13 -0
- package/src/config/feature-flag-registry.json +9 -41
- package/src/config/schemas/security.ts +1 -2
- package/src/config/skills.ts +1 -1
- package/src/contacts/contact-store.ts +0 -50
- package/src/daemon/approved-devices-store.ts +0 -44
- package/src/daemon/classifier.ts +1 -1
- package/src/daemon/config-watcher.ts +14 -8
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/sessions.ts +4 -116
- package/src/daemon/handlers/skills.ts +1 -1
- package/src/daemon/lifecycle.ts +13 -15
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +20 -3
- package/src/daemon/session-slash.ts +2 -2
- package/src/daemon/shutdown-handlers.ts +15 -0
- package/src/daemon/watch-handler.ts +2 -2
- package/src/email/guardrails.ts +1 -1
- package/src/email/service.ts +0 -5
- package/src/hooks/templates.ts +1 -1
- package/src/media/app-icon-generator.ts +2 -2
- package/src/media/avatar-router.ts +2 -2
- package/src/media/gemini-image-service.ts +5 -5
- package/src/memory/admin.ts +2 -2
- package/src/memory/app-git-service.ts +0 -7
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-title-service.ts +2 -2
- package/src/memory/embedding-backend.ts +30 -26
- package/src/memory/external-conversation-store.ts +0 -30
- package/src/memory/guardian-action-store.ts +0 -31
- package/src/memory/guardian-approvals.ts +1 -56
- package/src/memory/indexer.ts +4 -3
- package/src/memory/items-extractor.ts +1 -1
- package/src/memory/job-handlers/backfill.ts +5 -2
- package/src/memory/job-handlers/index-maintenance.ts +2 -2
- package/src/memory/job-handlers/media-processing.ts +2 -2
- package/src/memory/job-handlers/summarization.ts +1 -1
- package/src/memory/job-utils.ts +1 -2
- package/src/memory/jobs-worker.ts +2 -2
- package/src/memory/llm-usage-store.ts +57 -11
- package/src/memory/media-store.ts +4 -535
- package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +2 -2
- package/src/memory/migrations/110-channel-guardian.ts +0 -1
- package/src/memory/published-pages-store.ts +0 -83
- package/src/memory/qdrant-circuit-breaker.ts +0 -8
- package/src/memory/retriever.ts +1 -1
- package/src/memory/schema/calls.ts +0 -67
- package/src/memory/search/semantic.ts +1 -8
- package/src/memory/shared-app-links-store.ts +0 -15
- package/src/messaging/registry.ts +0 -5
- package/src/messaging/style-analyzer.ts +1 -1
- package/src/notifications/copy-composer.ts +5 -13
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/deliveries-store.ts +0 -39
- package/src/notifications/guardian-question-mode.ts +6 -10
- package/src/notifications/preference-extractor.ts +1 -1
- package/src/oauth/byo-connection.test.ts +29 -20
- package/src/oauth/provider-behaviors.ts +1 -1
- package/src/permissions/checker.ts +1 -1
- package/src/permissions/shell-identity.ts +0 -5
- package/src/permissions/trust-store.ts +0 -37
- package/src/prompts/system-prompt.ts +4 -4
- package/src/prompts/templates/SOUL.md +1 -1
- package/src/providers/managed-proxy/constants.ts +8 -10
- package/src/providers/managed-proxy/context.ts +14 -9
- package/src/providers/provider-send-message.ts +4 -52
- package/src/providers/registry.ts +16 -50
- package/src/runtime/actor-token-store.ts +0 -23
- package/src/runtime/auth/__tests__/guard-tests.test.ts +64 -0
- package/src/runtime/http-router.ts +5 -1
- package/src/runtime/http-server.ts +101 -4
- package/src/runtime/invite-instruction-generator.ts +25 -51
- package/src/runtime/invite-service.ts +0 -20
- package/src/runtime/routes/attachment-routes.ts +1 -1
- package/src/runtime/routes/brain-graph-routes.ts +1 -1
- package/src/runtime/routes/call-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +32 -11
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +2 -2
- package/src/runtime/routes/documents-routes.ts +3 -3
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -20
- package/src/runtime/routes/guardian-refresh-routes.ts +0 -20
- package/src/runtime/routes/secret-routes.ts +4 -4
- package/src/runtime/routes/session-management-routes.ts +27 -0
- package/src/runtime/routes/trust-rules-routes.ts +1 -1
- package/src/security/credential-backend.ts +148 -0
- package/src/security/oauth2.ts +1 -1
- package/src/security/secret-allowlist.ts +1 -1
- package/src/security/secure-keys.ts +98 -160
- package/src/security/token-manager.ts +0 -7
- package/src/sequence/guardrails.ts +0 -4
- package/src/sequence/store.ts +1 -20
- package/src/sequence/types.ts +1 -36
- package/src/signals/bash.ts +33 -0
- package/src/signals/cancel.ts +69 -0
- package/src/signals/conversation-undo.ts +127 -0
- package/src/signals/trust-rule.ts +174 -0
- package/src/skills/clawhub.ts +5 -5
- package/src/skills/managed-store.ts +4 -4
- package/src/subagent/manager.ts +8 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +366 -0
- package/src/telemetry/usage-telemetry-reporter.ts +181 -0
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/credentials/vault.ts +8 -4
- package/src/tools/memory/handlers.test.ts +24 -26
- package/src/tools/memory/handlers.ts +1 -13
- package/src/tools/registry.ts +5 -100
- package/src/tools/terminal/parser.ts +34 -4
- package/src/tools/tool-manifest.ts +0 -10
- package/src/usage/actors.ts +0 -12
- package/src/util/canonicalize-identity.ts +0 -9
- package/src/util/errors.ts +0 -3
- package/src/util/platform.ts +24 -7
- package/src/util/pricing.ts +0 -38
- package/src/watcher/constants.ts +0 -7
- package/src/watcher/providers/linear.ts +1 -1
- package/src/work-items/work-item-store.ts +4 -4
- package/src/workspace/commit-message-provider.ts +1 -1
- package/src/workspace/git-service.ts +44 -1
- package/src/workspace/provider-commit-message-generator.ts +1 -1
- package/src/__tests__/fixtures/proxy-fixtures.ts +0 -147
- package/src/browser-extension-relay/client.ts +0 -155
- package/src/contacts/index.ts +0 -18
- package/src/daemon/tls-certs.ts +0 -270
- package/src/errors.ts +0 -41
- package/src/events/index.ts +0 -18
- package/src/followups/index.ts +0 -10
- package/src/playbooks/index.ts +0 -10
- package/src/runtime/auth/index.ts +0 -44
- package/src/tasks/candidate-store.ts +0 -95
- package/src/tools/browser/api-map.ts +0 -313
- package/src/tools/browser/auto-navigate.ts +0 -469
- package/src/tools/browser/headless-browser.ts +0 -590
- package/src/tools/browser/recording-store.ts +0 -75
- package/src/tools/computer-use/registry.ts +0 -21
- package/src/tools/tasks/index.ts +0 -27
|
@@ -25,17 +25,11 @@ const metadataByKey = new Map<
|
|
|
25
25
|
>();
|
|
26
26
|
|
|
27
27
|
mock.module("../security/secure-keys.js", () => ({
|
|
28
|
-
getSecureKey: () => undefined,
|
|
29
|
-
setSecureKey: setSecureKeyMock,
|
|
30
28
|
setSecureKeyAsync: async (key?: string, value?: string) =>
|
|
31
29
|
setSecureKeyMock(key, value),
|
|
32
|
-
deleteSecureKey: () => "deleted",
|
|
33
30
|
deleteSecureKeyAsync: async () => "deleted" as const,
|
|
34
|
-
|
|
35
|
-
getBackendType: () => null,
|
|
36
|
-
isDowngradedFromKeychain: () => false,
|
|
31
|
+
listSecureKeysAsync: async () => [],
|
|
37
32
|
_resetBackend: () => {},
|
|
38
|
-
_setBackend: () => {},
|
|
39
33
|
}));
|
|
40
34
|
|
|
41
35
|
mock.module("../tools/credentials/metadata-store.js", () => ({
|
|
@@ -39,7 +39,6 @@ mock.module("../util/platform.js", () => ({
|
|
|
39
39
|
}));
|
|
40
40
|
|
|
41
41
|
mock.module("../memory/guardian-action-store.js", () => ({
|
|
42
|
-
getPendingDeliveryByConversation: () => null,
|
|
43
42
|
getGuardianActionRequest: () => null,
|
|
44
43
|
resolveGuardianActionRequest: () => {},
|
|
45
44
|
}));
|
|
@@ -621,8 +620,7 @@ describe("Session message queue", () => {
|
|
|
621
620
|
const sessionErr = events.find((e) => e.type === "session_error");
|
|
622
621
|
expect(sessionErr).toBeDefined();
|
|
623
622
|
|
|
624
|
-
// Should also emit generic error
|
|
625
|
-
// (callers rely on error events to detect failures)
|
|
623
|
+
// Should also emit generic error (callers rely on error events to detect failures)
|
|
626
624
|
const genericErr = events.find((e) => e.type === "error");
|
|
627
625
|
expect(genericErr).toBeDefined();
|
|
628
626
|
});
|
|
@@ -1674,7 +1672,7 @@ describe("Regression: cancel semantics and error channel split", () => {
|
|
|
1674
1672
|
const sessionErr = allEvents.find((e) => e.type === "session_error");
|
|
1675
1673
|
expect(sessionErr).toBeDefined();
|
|
1676
1674
|
|
|
1677
|
-
// Should also get generic error
|
|
1675
|
+
// Should also get generic error
|
|
1678
1676
|
const genericErr = allEvents.find((e) => e.type === "error");
|
|
1679
1677
|
expect(genericErr).toBeDefined();
|
|
1680
1678
|
});
|
|
@@ -100,19 +100,13 @@ mock.module("../security/secure-keys.js", () => {
|
|
|
100
100
|
return "not-found" as const;
|
|
101
101
|
};
|
|
102
102
|
return {
|
|
103
|
-
getSecureKey: (account: string) => secureKeyStore[account] ?? undefined,
|
|
104
103
|
getSecureKeyAsync: async (account: string) =>
|
|
105
104
|
secureKeyStore[account] ?? undefined,
|
|
106
|
-
setSecureKey: syncSet,
|
|
107
|
-
deleteSecureKey: syncDelete,
|
|
108
105
|
setSecureKeyAsync: async (account: string, value: string) =>
|
|
109
106
|
syncSet(account, value),
|
|
110
107
|
deleteSecureKeyAsync: async (account: string) => syncDelete(account),
|
|
111
|
-
|
|
112
|
-
getBackendType: () => "encrypted",
|
|
113
|
-
isDowngradedFromKeychain: () => false,
|
|
108
|
+
listSecureKeysAsync: async () => Object.keys(secureKeyStore),
|
|
114
109
|
_resetBackend: () => {},
|
|
115
|
-
_setBackend: () => {},
|
|
116
110
|
};
|
|
117
111
|
});
|
|
118
112
|
|
|
@@ -57,7 +57,6 @@ const mockTestProvider = {
|
|
|
57
57
|
let mockAnthropicKey: string | undefined = "test-api-key";
|
|
58
58
|
mock.module("../security/secure-keys.js", () => ({
|
|
59
59
|
getSecureKeyAsync: async () => mockAnthropicKey,
|
|
60
|
-
getSecureKey: () => mockAnthropicKey,
|
|
61
60
|
}));
|
|
62
61
|
|
|
63
62
|
mock.module("../providers/registry.js", () => ({
|
|
@@ -61,24 +61,6 @@ export function buildSkillLoadHistory(
|
|
|
61
61
|
];
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/**
|
|
65
|
-
* Assert that a set of tool names is exactly the expected set (order-independent).
|
|
66
|
-
*/
|
|
67
|
-
export function expectToolNamesEqual(
|
|
68
|
-
actual: string[],
|
|
69
|
-
expected: readonly string[],
|
|
70
|
-
): void {
|
|
71
|
-
const sorted = [...actual].sort();
|
|
72
|
-
const expectedSorted = [...expected].sort();
|
|
73
|
-
if (JSON.stringify(sorted) !== JSON.stringify(expectedSorted)) {
|
|
74
|
-
throw new Error(
|
|
75
|
-
`Tool names mismatch.\nExpected: ${JSON.stringify(
|
|
76
|
-
expectedSorted,
|
|
77
|
-
)}\nActual: ${JSON.stringify(sorted)}`,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
64
|
/**
|
|
83
65
|
* Assert that all browser tool names are present in a given set.
|
|
84
66
|
*/
|
|
@@ -17,28 +17,5 @@ export const COMPUTER_USE_TOOL_NAMES = [
|
|
|
17
17
|
"computer_use_respond",
|
|
18
18
|
] as const;
|
|
19
19
|
|
|
20
|
-
/** The skill ID for the bundled computer-use skill (used in later PRs). */
|
|
21
|
-
export const COMPUTER_USE_SKILL_ID = "computer-use";
|
|
22
|
-
|
|
23
20
|
/** Number of computer_use_* tools. */
|
|
24
21
|
export const COMPUTER_USE_TOOL_COUNT = COMPUTER_USE_TOOL_NAMES.length; // 11
|
|
25
|
-
|
|
26
|
-
import { expect } from "bun:test";
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Assert that every COMPUTER_USE_TOOL_NAMES entry is present in `names`.
|
|
30
|
-
*/
|
|
31
|
-
export function assertComputerUseToolsPresent(names: string[]): void {
|
|
32
|
-
for (const name of COMPUTER_USE_TOOL_NAMES) {
|
|
33
|
-
expect(names).toContain(name);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Assert that no COMPUTER_USE_TOOL_NAMES entry is present in `names`.
|
|
39
|
-
*/
|
|
40
|
-
export function assertComputerUseToolsAbsent(names: string[]): void {
|
|
41
|
-
for (const name of COMPUTER_USE_TOOL_NAMES) {
|
|
42
|
-
expect(names).not.toContain(name);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -196,7 +196,7 @@ describe("ToolExecutor allowedToolNames gating", () => {
|
|
|
196
196
|
}
|
|
197
197
|
});
|
|
198
198
|
|
|
199
|
-
test("executes normally when allowedToolNames is not set
|
|
199
|
+
test("executes normally when allowedToolNames is not set", async () => {
|
|
200
200
|
const executor = new ToolExecutor(makePrompter());
|
|
201
201
|
const result = await executor.execute(
|
|
202
202
|
"file_read",
|
|
@@ -57,7 +57,6 @@ import {
|
|
|
57
57
|
} from "../permissions/trust-store.js";
|
|
58
58
|
|
|
59
59
|
const trustPath = join(testDir, "protected", "trust.json");
|
|
60
|
-
const legacyTrustPath = join(testDir, "trust.json");
|
|
61
60
|
const DEFAULT_TEMPLATES = getDefaultRuleTemplates();
|
|
62
61
|
const NUM_DEFAULTS = DEFAULT_TEMPLATES.length;
|
|
63
62
|
const DEFAULT_PRIORITY_BY_ID = new Map(
|
|
@@ -73,11 +72,6 @@ describe("Trust Store", () => {
|
|
|
73
72
|
} catch {
|
|
74
73
|
/* may not exist */
|
|
75
74
|
}
|
|
76
|
-
try {
|
|
77
|
-
rmSync(legacyTrustPath);
|
|
78
|
-
} catch {
|
|
79
|
-
/* may not exist */
|
|
80
|
-
}
|
|
81
75
|
});
|
|
82
76
|
|
|
83
77
|
// Intentionally do not remove `testDir` in afterAll.
|
|
@@ -1227,79 +1221,6 @@ describe("Trust Store", () => {
|
|
|
1227
1221
|
// ── loadFromDisk resilience (misc) ──────────────────────────────
|
|
1228
1222
|
|
|
1229
1223
|
describe("loadFromDisk resilience (misc)", () => {
|
|
1230
|
-
test("migrates legacy root trust file to protected path", () => {
|
|
1231
|
-
mkdirSync(dirname(legacyTrustPath), { recursive: true });
|
|
1232
|
-
writeFileSync(
|
|
1233
|
-
legacyTrustPath,
|
|
1234
|
-
JSON.stringify({
|
|
1235
|
-
version: 3,
|
|
1236
|
-
rules: [
|
|
1237
|
-
{
|
|
1238
|
-
id: "legacy-deny",
|
|
1239
|
-
tool: "host_bash",
|
|
1240
|
-
pattern: "rm -rf *",
|
|
1241
|
-
scope: "everywhere",
|
|
1242
|
-
decision: "deny",
|
|
1243
|
-
priority: 200,
|
|
1244
|
-
createdAt: 123,
|
|
1245
|
-
},
|
|
1246
|
-
],
|
|
1247
|
-
}),
|
|
1248
|
-
);
|
|
1249
|
-
|
|
1250
|
-
clearCache();
|
|
1251
|
-
const rules = getAllRules();
|
|
1252
|
-
|
|
1253
|
-
expect(rules.find((r) => r.id === "legacy-deny")).toBeDefined();
|
|
1254
|
-
expect(readFileSync(trustPath, "utf-8")).toContain("legacy-deny");
|
|
1255
|
-
expect(() => readFileSync(legacyTrustPath, "utf-8")).toThrow();
|
|
1256
|
-
});
|
|
1257
|
-
|
|
1258
|
-
test("prefers protected trust file when both protected and legacy files exist", () => {
|
|
1259
|
-
mkdirSync(dirname(trustPath), { recursive: true });
|
|
1260
|
-
writeFileSync(
|
|
1261
|
-
trustPath,
|
|
1262
|
-
JSON.stringify({
|
|
1263
|
-
version: 3,
|
|
1264
|
-
rules: [
|
|
1265
|
-
{
|
|
1266
|
-
id: "protected-rule",
|
|
1267
|
-
tool: "bash",
|
|
1268
|
-
pattern: "protected *",
|
|
1269
|
-
scope: "/tmp",
|
|
1270
|
-
decision: "allow",
|
|
1271
|
-
priority: 100,
|
|
1272
|
-
createdAt: 1,
|
|
1273
|
-
},
|
|
1274
|
-
],
|
|
1275
|
-
}),
|
|
1276
|
-
);
|
|
1277
|
-
writeFileSync(
|
|
1278
|
-
legacyTrustPath,
|
|
1279
|
-
JSON.stringify({
|
|
1280
|
-
version: 3,
|
|
1281
|
-
rules: [
|
|
1282
|
-
{
|
|
1283
|
-
id: "legacy-rule",
|
|
1284
|
-
tool: "bash",
|
|
1285
|
-
pattern: "legacy *",
|
|
1286
|
-
scope: "/tmp",
|
|
1287
|
-
decision: "deny",
|
|
1288
|
-
priority: 200,
|
|
1289
|
-
createdAt: 2,
|
|
1290
|
-
},
|
|
1291
|
-
],
|
|
1292
|
-
}),
|
|
1293
|
-
);
|
|
1294
|
-
|
|
1295
|
-
clearCache();
|
|
1296
|
-
const rules = getAllRules();
|
|
1297
|
-
|
|
1298
|
-
expect(rules.find((r) => r.id === "protected-rule")).toBeDefined();
|
|
1299
|
-
expect(rules.find((r) => r.id === "legacy-rule")).toBeUndefined();
|
|
1300
|
-
expect(readFileSync(legacyTrustPath, "utf-8")).toContain("legacy-rule");
|
|
1301
|
-
});
|
|
1302
|
-
|
|
1303
1224
|
test("malformed file (valid JSON but null) is handled gracefully", () => {
|
|
1304
1225
|
mkdirSync(dirname(trustPath), { recursive: true });
|
|
1305
1226
|
writeFileSync(trustPath, "null");
|
|
@@ -1540,10 +1461,10 @@ describe("Trust Store", () => {
|
|
|
1540
1461
|
});
|
|
1541
1462
|
});
|
|
1542
1463
|
|
|
1543
|
-
// ──
|
|
1464
|
+
// ── optional ctx parameter ────────────────────────────────────
|
|
1544
1465
|
|
|
1545
|
-
describe("
|
|
1546
|
-
test("
|
|
1466
|
+
describe("optional ctx parameter", () => {
|
|
1467
|
+
test("callers without ctx parameter still work", () => {
|
|
1547
1468
|
addRule("bash", "git *", "/tmp", "allow", 200);
|
|
1548
1469
|
// Calling without the 4th argument — must still match
|
|
1549
1470
|
const match = findHighestPriorityRule("bash", ["git status"], "/tmp");
|
|
@@ -41,11 +41,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
41
41
|
}));
|
|
42
42
|
|
|
43
43
|
mock.module("../security/secure-keys.js", () => ({
|
|
44
|
-
getSecureKey: (key: string) => {
|
|
45
|
-
if (key === credentialKey("twilio", "auth_token")) return mockAuthToken;
|
|
46
|
-
if (key === credentialKey("twilio", "account_sid")) return mockAccountSid;
|
|
47
|
-
return undefined;
|
|
48
|
-
},
|
|
49
44
|
getSecureKeyAsync: async (key: string) => {
|
|
50
45
|
if (key === credentialKey("twilio", "auth_token")) return mockAuthToken;
|
|
51
46
|
if (key === credentialKey("twilio", "account_sid")) return mockAccountSid;
|
|
@@ -143,7 +143,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
143
143
|
}));
|
|
144
144
|
|
|
145
145
|
mock.module("../security/secure-keys.js", () => ({
|
|
146
|
-
getSecureKey: (key: string) => mockSecureKeyStore[key],
|
|
147
146
|
setSecureKeyAsync: async (key: string, value: string) => {
|
|
148
147
|
mockSecureKeyStore[key] = value;
|
|
149
148
|
return true;
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
import { migrateBackfillUsageCacheAccounting } from "../memory/migrations/140-backfill-usage-cache-accounting.js";
|
|
47
47
|
import type { PricingUsage } from "../usage/types.js";
|
|
48
48
|
import {
|
|
49
|
-
|
|
49
|
+
resolvePricing,
|
|
50
50
|
resolvePricingForUsageWithOverrides,
|
|
51
51
|
} from "../util/pricing.js";
|
|
52
52
|
|
|
@@ -187,7 +187,8 @@ describe("migrateBackfillUsageCacheAccounting", () => {
|
|
|
187
187
|
model,
|
|
188
188
|
inputTokens: 700,
|
|
189
189
|
outputTokens: 70,
|
|
190
|
-
estimatedCostUsd:
|
|
190
|
+
estimatedCostUsd:
|
|
191
|
+
resolvePricing("anthropic", model, 700, 70).estimatedCostUsd ?? 0,
|
|
191
192
|
});
|
|
192
193
|
insertRequestLog({
|
|
193
194
|
id: "log-prev",
|
|
@@ -201,12 +202,9 @@ describe("migrateBackfillUsageCacheAccounting", () => {
|
|
|
201
202
|
}),
|
|
202
203
|
});
|
|
203
204
|
|
|
204
|
-
const flattenedHistoricalCost =
|
|
205
|
-
3_420_218,
|
|
206
|
-
|
|
207
|
-
model,
|
|
208
|
-
"anthropic",
|
|
209
|
-
);
|
|
205
|
+
const flattenedHistoricalCost =
|
|
206
|
+
resolvePricing("anthropic", model, 3_420_218, 11_768).estimatedCostUsd ??
|
|
207
|
+
0;
|
|
210
208
|
insertUsageEvent({
|
|
211
209
|
id: "usage-target",
|
|
212
210
|
conversationId: "conv-usage-1",
|
|
@@ -245,7 +243,8 @@ describe("migrateBackfillUsageCacheAccounting", () => {
|
|
|
245
243
|
}),
|
|
246
244
|
});
|
|
247
245
|
|
|
248
|
-
const noLogCost =
|
|
246
|
+
const noLogCost =
|
|
247
|
+
resolvePricing("anthropic", model, 1_234, 56).estimatedCostUsd ?? 0;
|
|
249
248
|
insertUsageEvent({
|
|
250
249
|
id: "usage-no-logs",
|
|
251
250
|
conversationId: "conv-usage-2",
|
|
@@ -346,7 +345,8 @@ describe("migrateBackfillUsageCacheAccounting", () => {
|
|
|
346
345
|
model,
|
|
347
346
|
inputTokens: 1_200,
|
|
348
347
|
outputTokens: 80,
|
|
349
|
-
estimatedCostUsd:
|
|
348
|
+
estimatedCostUsd:
|
|
349
|
+
resolvePricing("anthropic", model, 1_200, 80).estimatedCostUsd ?? 0,
|
|
350
350
|
});
|
|
351
351
|
insertRequestLog({
|
|
352
352
|
id: "log-target",
|
|
@@ -52,7 +52,7 @@ export async function generateGuardianCopy(
|
|
|
52
52
|
const fallback = buildFallbackCopy(questionText);
|
|
53
53
|
|
|
54
54
|
// If no provider is configured, return fallback immediately
|
|
55
|
-
const resolved = resolveConfiguredProvider();
|
|
55
|
+
const resolved = await resolveConfiguredProvider();
|
|
56
56
|
if (!resolved) {
|
|
57
57
|
log.debug(
|
|
58
58
|
"No provider available for guardian copy generation, using fallback",
|
package/src/cli/commands/bash.ts
CHANGED
|
@@ -47,6 +47,9 @@ This is a developer debugging tool for inspecting how the assistant invokes and
|
|
|
47
47
|
observes shell commands. The command runs with the assistant's environment, working
|
|
48
48
|
directory, and process context — not the caller's shell.
|
|
49
49
|
|
|
50
|
+
Requires the assistant to be running with VELLUM_DEBUG=1. When debug mode is off
|
|
51
|
+
(the default), the assistant ignores bash signal files and returns an error.
|
|
52
|
+
|
|
50
53
|
The CLI writes the command to signals/bash.<requestId> and polls
|
|
51
54
|
signals/bash.<requestId>.result for the output. The assistant must be running
|
|
52
55
|
for this to work.
|
|
@@ -10,10 +10,10 @@ import { isHttpHealthy } from "../../daemon/daemon-control.js";
|
|
|
10
10
|
import { getSecureKeyAsync } from "../../security/secure-keys.js";
|
|
11
11
|
import {
|
|
12
12
|
getDbPath,
|
|
13
|
+
getHooksDir,
|
|
13
14
|
getLogPath,
|
|
14
15
|
getRootDir,
|
|
15
16
|
getWorkspaceDir,
|
|
16
|
-
getWorkspaceHooksDir,
|
|
17
17
|
getWorkspaceSkillsDir,
|
|
18
18
|
} from "../../util/platform.js";
|
|
19
19
|
import { log } from "../logger.js";
|
|
@@ -42,11 +42,10 @@ Diagnostic checks performed:
|
|
|
42
42
|
6. Disk space Ensures at least 100MB free on the data partition
|
|
43
43
|
7. Log file size Warns if the log file exceeds 50MB
|
|
44
44
|
8. Database integrity Runs SQLite PRAGMA integrity_check
|
|
45
|
-
9.
|
|
46
|
-
10.
|
|
47
|
-
11.
|
|
48
|
-
12.
|
|
49
|
-
13. Sandbox diagnostics Reports sandbox backend status and configuration
|
|
45
|
+
9. Trust rule syntax Validates trust.json structure and rule fields
|
|
46
|
+
10. WASM files Checks that tree-sitter WASM binaries are present
|
|
47
|
+
11. Browser runtime Verifies Playwright and Chromium availability
|
|
48
|
+
12. Sandbox diagnostics Reports sandbox backend status and configuration
|
|
50
49
|
|
|
51
50
|
Examples:
|
|
52
51
|
$ assistant doctor`,
|
|
@@ -134,7 +133,7 @@ Examples:
|
|
|
134
133
|
`${dataDir}/db`,
|
|
135
134
|
`${dataDir}/logs`,
|
|
136
135
|
getWorkspaceSkillsDir(),
|
|
137
|
-
|
|
136
|
+
getHooksDir(),
|
|
138
137
|
`${rootDir}/protected`,
|
|
139
138
|
];
|
|
140
139
|
const missing = requiredDirs.filter((d) => !existsSync(d));
|
|
@@ -216,30 +215,7 @@ Examples:
|
|
|
216
215
|
fail("Database integrity check", "database file not found");
|
|
217
216
|
}
|
|
218
217
|
|
|
219
|
-
// 9.
|
|
220
|
-
const tokenPath = `${rootDir}/http-token`;
|
|
221
|
-
if (existsSync(tokenPath)) {
|
|
222
|
-
try {
|
|
223
|
-
const tokenStat = statSync(tokenPath);
|
|
224
|
-
const mode = tokenStat.mode & 0o777;
|
|
225
|
-
if (mode === 0o600 || mode === 0o700) {
|
|
226
|
-
pass(
|
|
227
|
-
`HTTP token permissions (${mode.toString(8).padStart(4, "0")})`,
|
|
228
|
-
);
|
|
229
|
-
} else {
|
|
230
|
-
fail(
|
|
231
|
-
"HTTP token permissions",
|
|
232
|
-
`expected 0600 or 0700, got 0${mode.toString(8)}`,
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
} catch {
|
|
236
|
-
fail("HTTP token permissions", "could not stat http-token file");
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
pass("HTTP token (not present — assistant not running)");
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// 10. Trust rule syntax
|
|
218
|
+
// 9. Trust rule syntax
|
|
243
219
|
const trustPath = `${rootDir}/protected/trust.json`;
|
|
244
220
|
if (existsSync(trustPath)) {
|
|
245
221
|
try {
|
|
@@ -279,7 +255,7 @@ Examples:
|
|
|
279
255
|
pass("Trust rule syntax (no trust.json yet)");
|
|
280
256
|
}
|
|
281
257
|
|
|
282
|
-
//
|
|
258
|
+
// 10. WASM files
|
|
283
259
|
const wasmFiles = [
|
|
284
260
|
{ pkg: "web-tree-sitter", file: "web-tree-sitter.wasm" },
|
|
285
261
|
{ pkg: "tree-sitter-bash", file: "tree-sitter-bash.wasm" },
|
|
@@ -321,7 +297,7 @@ Examples:
|
|
|
321
297
|
fail("WASM files", missingWasm.join(", "));
|
|
322
298
|
}
|
|
323
299
|
|
|
324
|
-
//
|
|
300
|
+
// 11. Browser runtime (Playwright + Chromium)
|
|
325
301
|
const { checkBrowserRuntime } =
|
|
326
302
|
await import("../../tools/browser/runtime-check.js");
|
|
327
303
|
const browserStatus = await checkBrowserRuntime();
|
|
@@ -339,7 +315,7 @@ Examples:
|
|
|
339
315
|
);
|
|
340
316
|
}
|
|
341
317
|
|
|
342
|
-
//
|
|
318
|
+
// 12. Sandbox backend diagnostics
|
|
343
319
|
const { runSandboxDiagnostics } =
|
|
344
320
|
await import("../../tools/terminal/sandbox-diagnostics.js");
|
|
345
321
|
const sandbox = runSandboxDiagnostics();
|
|
@@ -58,9 +58,9 @@ Fields shown:
|
|
|
58
58
|
Examples:
|
|
59
59
|
$ assistant memory status`,
|
|
60
60
|
)
|
|
61
|
-
.action(() => {
|
|
61
|
+
.action(async () => {
|
|
62
62
|
initializeDb();
|
|
63
|
-
const status = getMemorySystemStatus();
|
|
63
|
+
const status = await getMemorySystemStatus();
|
|
64
64
|
log.info(`Memory enabled: ${status.enabled ? "yes" : "no"}`);
|
|
65
65
|
log.info(`Memory degraded: ${status.degraded ? "yes" : "no"}`);
|
|
66
66
|
if (status.reason) log.info(`Reason: ${status.reason}`);
|
|
@@ -112,9 +112,7 @@ Examples:
|
|
|
112
112
|
|
|
113
113
|
memory
|
|
114
114
|
.command("cleanup")
|
|
115
|
-
.description(
|
|
116
|
-
"Queue cleanup jobs for stale superseded items",
|
|
117
|
-
)
|
|
115
|
+
.description("Queue cleanup jobs for stale superseded items")
|
|
118
116
|
.option(
|
|
119
117
|
"--retention-ms <ms>",
|
|
120
118
|
"Optional retention threshold in milliseconds",
|
|
@@ -227,7 +227,7 @@ Examples:
|
|
|
227
227
|
|
|
228
228
|
const config = getConfig();
|
|
229
229
|
const qdrantUrl = getQdrantUrlEnv() || config.memory.qdrant.url;
|
|
230
|
-
const embeddingSelection = selectEmbeddingBackend(config);
|
|
230
|
+
const embeddingSelection = await selectEmbeddingBackend(config);
|
|
231
231
|
const embeddingModel = embeddingSelection.backend
|
|
232
232
|
? `${embeddingSelection.backend.provider}:${embeddingSelection.backend.model}:sparse-v${SPARSE_EMBEDDING_VERSION}`
|
|
233
233
|
: undefined;
|