@vellumai/assistant 0.5.7 → 0.5.9
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/Dockerfile +2 -1
- package/docker-entrypoint.sh +9 -0
- package/docs/architecture/memory.md +13 -11
- package/eslint.config.mjs +0 -31
- package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +1 -1
- package/package.json +1 -1
- package/src/__tests__/approval-cascade.test.ts +0 -1
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/ces-rpc-credential-backend.test.ts +3 -3
- package/src/__tests__/ces-startup-timeout.test.ts +40 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-schema.test.ts +2 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +2 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
- package/src/__tests__/conversation-queue.test.ts +0 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +227 -0
- package/src/__tests__/conversation-slash-queue.test.ts +0 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/credential-execution-client.test.ts +5 -2
- package/src/__tests__/credential-execution-feature-gates.test.ts +31 -16
- package/src/__tests__/credential-execution-managed-contract.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +1 -1
- package/src/__tests__/credential-security-invariants.test.ts +2 -5
- package/src/__tests__/credentials-cli.test.ts +4 -3
- package/src/__tests__/daemon-credential-client.test.ts +123 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
- package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
- package/src/__tests__/journal-context.test.ts +335 -0
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
- package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
- package/src/__tests__/memory-recall-quality.test.ts +48 -17
- package/src/__tests__/memory-regressions.test.ts +408 -363
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
- package/src/__tests__/non-member-access-request.test.ts +2 -2
- package/src/__tests__/notification-decision-strategy.test.ts +71 -0
- package/src/__tests__/oauth-cli.test.ts +5 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
- package/src/__tests__/provider-error-scenarios.test.ts +0 -267
- package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
- package/src/__tests__/relay-server.test.ts +1 -2
- package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -1
- package/src/__tests__/secure-keys.test.ts +18 -15
- package/src/__tests__/skill-memory.test.ts +17 -3
- package/src/__tests__/stale-approval-dedup.test.ts +171 -0
- package/src/__tests__/stt-hints.test.ts +437 -0
- package/src/__tests__/task-memory-cleanup.test.ts +14 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
- package/src/__tests__/voice-quality.test.ts +58 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +5 -3
- package/src/acp/agent-process.ts +9 -1
- package/src/agent/loop.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +164 -38
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
- package/src/calls/call-controller.ts +9 -5
- package/src/calls/fish-audio-client.ts +26 -14
- package/src/calls/stt-hints.ts +189 -0
- package/src/calls/tts-text-sanitizer.ts +61 -0
- package/src/calls/twilio-routes.ts +32 -4
- package/src/calls/voice-quality.ts +15 -3
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/commands/avatar.ts +2 -2
- package/src/cli/commands/credentials.ts +110 -94
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/keys.ts +7 -7
- package/src/cli/commands/memory.ts +1 -1
- package/src/cli/commands/oauth/connections.ts +11 -29
- package/src/cli/commands/oauth/platform.ts +389 -43
- package/src/cli/lib/daemon-credential-client.ts +284 -0
- package/src/cli.ts +1 -1
- package/src/config/bundled-skills/AGENTS.md +34 -0
- package/src/config/bundled-skills/acp/SKILL.md +10 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +15 -2
- package/src/config/bundled-skills/settings/TOOLS.json +46 -1
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
- package/src/config/bundled-skills/slack/SKILL.md +1 -1
- package/src/config/bundled-tool-registry.ts +4 -0
- package/src/config/defaults.ts +0 -2
- package/src/config/env-registry.ts +4 -4
- package/src/config/env.ts +14 -1
- package/src/config/feature-flag-registry.json +1 -1
- package/src/config/loader.ts +8 -11
- package/src/config/schema.ts +5 -16
- package/src/config/schemas/calls.ts +17 -0
- package/src/config/schemas/inference.ts +2 -2
- package/src/config/schemas/journal.ts +16 -0
- package/src/config/schemas/memory-processing.ts +2 -2
- package/src/config/types.ts +1 -0
- package/src/contacts/contact-store.ts +2 -2
- package/src/credential-execution/executable-discovery.ts +1 -1
- package/src/credential-execution/startup-timeout.ts +36 -0
- package/src/daemon/approval-generators.ts +3 -9
- package/src/daemon/conversation-agent-loop.ts +6 -0
- package/src/daemon/conversation-error.ts +13 -1
- package/src/daemon/conversation-memory.ts +1 -2
- package/src/daemon/conversation-process.ts +18 -1
- package/src/daemon/conversation-runtime-assembly.ts +61 -1
- package/src/daemon/conversation-surfaces.ts +30 -1
- package/src/daemon/conversation.ts +20 -9
- package/src/daemon/guardian-action-generators.ts +3 -9
- package/src/daemon/lifecycle.ts +18 -11
- package/src/daemon/message-types/conversations.ts +1 -0
- package/src/daemon/server.ts +2 -3
- package/src/memory/app-store.ts +31 -0
- package/src/memory/db-init.ts +4 -0
- package/src/memory/indexer.ts +19 -10
- package/src/memory/items-extractor.ts +315 -322
- package/src/memory/job-handlers/summarization.ts +26 -16
- package/src/memory/jobs-store.ts +33 -1
- package/src/memory/journal-memory.ts +214 -0
- package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/retriever.test.ts +37 -25
- package/src/memory/retriever.ts +24 -49
- package/src/memory/schema/memory-core.ts +2 -0
- package/src/memory/search/formatting.ts +7 -44
- package/src/memory/search/staleness.ts +4 -0
- package/src/memory/search/tier-classifier.ts +10 -2
- package/src/memory/search/types.ts +2 -5
- package/src/memory/task-memory-cleanup.ts +4 -3
- package/src/notifications/adapters/slack.ts +168 -6
- package/src/notifications/broadcaster.ts +1 -0
- package/src/notifications/copy-composer.ts +59 -2
- package/src/notifications/signal.ts +2 -0
- package/src/notifications/types.ts +2 -0
- package/src/prompts/journal-context.ts +133 -0
- package/src/prompts/persona-resolver.ts +80 -24
- package/src/prompts/system-prompt.ts +30 -0
- package/src/prompts/templates/NOW.md +26 -0
- package/src/prompts/templates/SOUL.md +20 -0
- package/src/prompts/update-bulletin-format.ts +0 -2
- package/src/providers/provider-send-message.ts +3 -32
- package/src/providers/registry.ts +2 -139
- package/src/providers/types.ts +1 -1
- package/src/runtime/access-request-helper.ts +4 -0
- package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
- package/src/runtime/auth/route-policy.ts +2 -0
- package/src/runtime/gateway-client.ts +47 -4
- package/src/runtime/guardian-decision-types.ts +45 -4
- package/src/runtime/http-server.ts +5 -2
- package/src/runtime/routes/access-request-decision.ts +2 -2
- package/src/runtime/routes/app-management-routes.ts +2 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
- package/src/runtime/routes/channel-readiness-routes.ts +9 -4
- package/src/runtime/routes/debug-routes.ts +12 -9
- package/src/runtime/routes/guardian-approval-interception.ts +168 -11
- package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
- package/src/runtime/routes/identity-routes.ts +1 -1
- package/src/runtime/routes/inbound-message-handler.ts +31 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
- package/src/runtime/routes/integrations/twilio.ts +52 -10
- package/src/runtime/routes/memory-item-routes.test.ts +3 -3
- package/src/runtime/routes/memory-item-routes.ts +25 -11
- package/src/runtime/routes/secret-routes.ts +141 -10
- package/src/runtime/routes/tts-routes.ts +11 -1
- package/src/security/ces-credential-client.ts +18 -9
- package/src/security/ces-rpc-credential-backend.ts +4 -3
- package/src/security/credential-backend.ts +10 -4
- package/src/security/secure-keys.ts +21 -4
- package/src/skills/catalog-install.ts +4 -36
- package/src/skills/inline-command-expansions.ts +7 -7
- package/src/skills/skill-memory.ts +1 -0
- package/src/subagent/manager.ts +2 -5
- package/src/tools/acp/spawn.ts +78 -1
- package/src/tools/credentials/vault.ts +5 -3
- package/src/tools/memory/definitions.ts +3 -2
- package/src/tools/memory/handlers.ts +10 -7
- package/src/tools/sensitive-output-placeholders.ts +2 -2
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/util/browser.ts +15 -0
- package/src/util/platform.ts +1 -1
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +4 -4
- package/src/workspace/migrations/017-seed-persona-dirs.ts +2 -1
- package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -4
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/provider-commit-message-generator.ts +12 -21
- package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
- package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
- package/src/memory/search/lexical.ts +0 -48
- package/src/providers/failover.ts +0 -186
package/Dockerfile
CHANGED
|
@@ -92,6 +92,7 @@ ENV IS_CONTAINERIZED=true
|
|
|
92
92
|
|
|
93
93
|
# Copy from builder
|
|
94
94
|
COPY --from=builder /app /app
|
|
95
|
+
RUN chmod +x /app/assistant/docker-entrypoint.sh
|
|
95
96
|
|
|
96
97
|
# Run the daemon + http server
|
|
97
|
-
CMD ["
|
|
98
|
+
CMD ["/app/assistant/docker-entrypoint.sh"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
if [ "$(id -u)" = "0" ] && [ "${VELLUM_WORKSPACE_DIR:-}" = "/workspace" ] && [ -d /workspace ]; then
|
|
5
|
+
git config --global --add safe.directory /workspace >/dev/null 2>&1 || true
|
|
6
|
+
git config --global --add safe.directory '/workspace/*' >/dev/null 2>&1 || true
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
exec bun run src/daemon/main.ts
|
|
@@ -273,7 +273,7 @@ The key distinction: normal compaction is a cost-optimized background process th
|
|
|
273
273
|
|
|
274
274
|
1. Run a recall-heavy turn and inspect `memory_recalled` events in the client trace stream.
|
|
275
275
|
2. Validate baseline counters:
|
|
276
|
-
- `semanticHits
|
|
276
|
+
- `semanticHits`
|
|
277
277
|
- `tier1Count`, `tier2Count`
|
|
278
278
|
- `hybridSearchLatencyMs`
|
|
279
279
|
- `mergedCount`, `selectedCount`, `injectedTokens`, `latencyMs`
|
|
@@ -304,16 +304,18 @@ stateDiagram-v2
|
|
|
304
304
|
Superseded --> Cleanup : cleanup_stale_superseded_items\n(delete from DB + Qdrant)
|
|
305
305
|
```
|
|
306
306
|
|
|
307
|
-
**Item extraction** uses LLM-powered extraction (with pattern-based fallback) to identify memorable information from conversation messages. Each extracted item belongs to one of
|
|
308
|
-
|
|
309
|
-
| Kind | Description
|
|
310
|
-
| ------------ |
|
|
311
|
-
| `identity` | Personal info, facts, relationships
|
|
312
|
-
| `preference` | Likes, dislikes, preferred approaches/tools
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
307
|
+
**Item extraction** uses LLM-powered extraction (with pattern-based fallback) to identify memorable information from conversation messages. Each extracted item belongs to one of eight kinds:
|
|
308
|
+
|
|
309
|
+
| Kind | Description | Base Lifetime |
|
|
310
|
+
| ------------ | ------------------------------------------------------------------ | ------------- |
|
|
311
|
+
| `identity` | Personal info, facts, relationships | 6 months |
|
|
312
|
+
| `preference` | Likes, dislikes, preferred approaches/tools | 3 months |
|
|
313
|
+
| `journal` | Experiential reflections, journal-style notes, forward-looking items | 3 months |
|
|
314
|
+
| `constraint` | Rules, requirements, directives | 1 month |
|
|
315
|
+
| `project` | Project details, repos, tech stacks, action items | 2 weeks |
|
|
316
|
+
| `decision` | Choices made, approaches selected | 2 weeks |
|
|
317
|
+
| `event` | Deadlines, milestones, meetings, dates | 3 days |
|
|
318
|
+
| `capability` | Skill catalog entries (system-generated, not LLM-extracted) | never expires |
|
|
317
319
|
|
|
318
320
|
**Supersession chains** replace the old conflict resolution system. When the LLM extracts a new item that updates an existing one, it sets `supersedes` to the old item's ID and `overrideConfidence` to one of three levels:
|
|
319
321
|
|
package/eslint.config.mjs
CHANGED
|
@@ -29,37 +29,6 @@ const eslintConfig = defineConfig([
|
|
|
29
29
|
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
|
30
30
|
],
|
|
31
31
|
"@typescript-eslint/no-explicit-any": "error",
|
|
32
|
-
|
|
33
|
-
// Standardize on `undefined` only — avoid `null` in new code.
|
|
34
|
-
// Prefer `=== undefined`, `?? fallback`, or `?.` optional chaining
|
|
35
|
-
// instead of `=== null`.
|
|
36
|
-
"no-restricted-syntax": [
|
|
37
|
-
"error",
|
|
38
|
-
{
|
|
39
|
-
selector:
|
|
40
|
-
"BinaryExpression[operator='==='][right.type='Literal'][right.raw='null']",
|
|
41
|
-
message:
|
|
42
|
-
"Avoid `=== null`. Prefer `=== undefined`, `?? fallback`, or optional chaining `?.` instead.",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
selector:
|
|
46
|
-
"BinaryExpression[operator='==='][left.type='Literal'][left.raw='null']",
|
|
47
|
-
message:
|
|
48
|
-
"Avoid `null ===`. Prefer `=== undefined`, `?? fallback`, or optional chaining `?.` instead.",
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
selector:
|
|
52
|
-
"BinaryExpression[operator='!=='][right.type='Literal'][right.raw='null']",
|
|
53
|
-
message:
|
|
54
|
-
"Avoid `!== null`. Prefer `!== undefined`, nullish coalescing `??`, or optional chaining `?.` instead.",
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
selector:
|
|
58
|
-
"BinaryExpression[operator='!=='][left.type='Literal'][left.raw='null']",
|
|
59
|
-
message:
|
|
60
|
-
"Avoid `null !==`. Prefer `!== undefined`, nullish coalescing `??`, or optional chaining `?.` instead.",
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
32
|
},
|
|
64
33
|
},
|
|
65
34
|
{
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* module so that both sides can depend on it without circular references.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { z } from "zod
|
|
10
|
+
import { z } from "zod";
|
|
11
11
|
import { RpcErrorSchema } from "./error.js";
|
|
12
12
|
|
|
13
13
|
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -61,7 +61,7 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
61
61
|
getSecureKeyAsync: async (...args: unknown[]) => mockGetSecureKey(...args),
|
|
62
62
|
setSecureKeyAsync: async () => true,
|
|
63
63
|
deleteSecureKeyAsync: async () => "deleted",
|
|
64
|
-
listSecureKeysAsync: async () => [],
|
|
64
|
+
listSecureKeysAsync: async () => ({ accounts: [], unreachable: false }),
|
|
65
65
|
_resetBackend: () => {},
|
|
66
66
|
}));
|
|
67
67
|
|
|
@@ -185,15 +185,15 @@ describe("CesRpcCredentialBackend", () => {
|
|
|
185
185
|
const result = await backend.list();
|
|
186
186
|
|
|
187
187
|
expect(callFn).toHaveBeenCalledWith(CesRpcMethod.ListCredentials, {});
|
|
188
|
-
expect(result).toEqual(["account-a", "account-b"]);
|
|
188
|
+
expect(result).toEqual({ accounts: ["account-a", "account-b"], unreachable: false });
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
-
test("returns
|
|
191
|
+
test("returns unreachable when RPC call throws", async () => {
|
|
192
192
|
callFn.mockRejectedValue(new Error("transport error"));
|
|
193
193
|
|
|
194
194
|
const result = await backend.list();
|
|
195
195
|
|
|
196
|
-
expect(result).toEqual([]);
|
|
196
|
+
expect(result).toEqual({ accounts: [], unreachable: true });
|
|
197
197
|
});
|
|
198
198
|
});
|
|
199
199
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { CesClient } from "../credential-execution/client.js";
|
|
4
|
+
import {
|
|
5
|
+
awaitCesClientWithTimeout,
|
|
6
|
+
DEFAULT_CES_STARTUP_TIMEOUT_MS,
|
|
7
|
+
} from "../credential-execution/startup-timeout.js";
|
|
8
|
+
|
|
9
|
+
describe("awaitCesClientWithTimeout", () => {
|
|
10
|
+
test("clears the fallback timer when the CES client resolves first", async () => {
|
|
11
|
+
const onTimeout = mock(() => {});
|
|
12
|
+
const client = { isReady: () => true } as unknown as CesClient;
|
|
13
|
+
|
|
14
|
+
const result = await awaitCesClientWithTimeout(Promise.resolve(client), {
|
|
15
|
+
timeoutMs: 25,
|
|
16
|
+
onTimeout,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expect(result).toBe(client);
|
|
20
|
+
|
|
21
|
+
await new Promise((resolve) => setTimeout(resolve, 40));
|
|
22
|
+
expect(onTimeout).not.toHaveBeenCalled();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("returns undefined and runs the fallback handler when the timeout wins", async () => {
|
|
26
|
+
const onTimeout = mock(() => {});
|
|
27
|
+
|
|
28
|
+
const result = await awaitCesClientWithTimeout(new Promise(() => {}), {
|
|
29
|
+
timeoutMs: 10,
|
|
30
|
+
onTimeout,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
expect(result).toBeUndefined();
|
|
34
|
+
expect(onTimeout).toHaveBeenCalledTimes(1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("exports the daemon CES startup timeout constant", () => {
|
|
38
|
+
expect(DEFAULT_CES_STARTUP_TIMEOUT_MS).toBe(20_000);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -204,7 +204,6 @@ describe("z.toJSONSchema integration", () => {
|
|
|
204
204
|
expect(properties).toBeDefined();
|
|
205
205
|
// Check that top-level keys are present
|
|
206
206
|
expect(properties.services).toBeDefined();
|
|
207
|
-
expect(properties.providerOrder).toBeDefined();
|
|
208
207
|
expect(properties.maxTokens).toBeDefined();
|
|
209
208
|
expect(properties.calls).toBeDefined();
|
|
210
209
|
expect(properties.memory).toBeDefined();
|
|
@@ -168,7 +168,6 @@ mock.module("../memory/retriever.js", () => ({
|
|
|
168
168
|
injectedText: "",
|
|
169
169
|
|
|
170
170
|
semanticHits: 0,
|
|
171
|
-
recencyHits: 0,
|
|
172
171
|
injectedTokens: 0,
|
|
173
172
|
latencyMs: 0,
|
|
174
173
|
}),
|
|
@@ -199,7 +198,6 @@ mock.module("../daemon/conversation-memory.js", () => ({
|
|
|
199
198
|
injectedText: "",
|
|
200
199
|
|
|
201
200
|
semanticHits: 0,
|
|
202
|
-
recencyHits: 0,
|
|
203
201
|
injectedTokens: 0,
|
|
204
202
|
latencyMs: 0,
|
|
205
203
|
tier1Count: 0,
|
|
@@ -158,7 +158,6 @@ mock.module("../memory/retriever.js", () => ({
|
|
|
158
158
|
injectedText: "",
|
|
159
159
|
|
|
160
160
|
semanticHits: 0,
|
|
161
|
-
recencyHits: 0,
|
|
162
161
|
injectedTokens: 0,
|
|
163
162
|
latencyMs: 0,
|
|
164
163
|
}),
|
|
@@ -189,7 +188,6 @@ mock.module("../daemon/conversation-memory.js", () => ({
|
|
|
189
188
|
injectedText: "",
|
|
190
189
|
|
|
191
190
|
semanticHits: 0,
|
|
192
|
-
recencyHits: 0,
|
|
193
191
|
injectedTokens: 0,
|
|
194
192
|
latencyMs: 0,
|
|
195
193
|
tier1Count: 0,
|
|
@@ -614,7 +612,7 @@ describe("session-agent-loop", () => {
|
|
|
614
612
|
});
|
|
615
613
|
|
|
616
614
|
describe("LLM request log persistence", () => {
|
|
617
|
-
test("record request log
|
|
615
|
+
test("record request log captures the actual provider name", async () => {
|
|
618
616
|
const events: ServerMessage[] = [];
|
|
619
617
|
const rawRequest = {
|
|
620
618
|
model: "gpt-4.1",
|
|
@@ -768,7 +766,7 @@ describe("session-agent-loop", () => {
|
|
|
768
766
|
});
|
|
769
767
|
|
|
770
768
|
describe("usage accounting", () => {
|
|
771
|
-
test("records the actual provider for
|
|
769
|
+
test("records the actual provider for usage accounting", async () => {
|
|
772
770
|
const events: ServerMessage[] = [];
|
|
773
771
|
|
|
774
772
|
const agentLoopRun: AgentLoopRun = async (messages, onEvent) => {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
classifyConversationError,
|
|
7
7
|
isUserCancellation,
|
|
8
8
|
} from "../daemon/conversation-error.js";
|
|
9
|
-
import { ProviderError } from "../util/errors.js";
|
|
9
|
+
import { ProviderError, ProviderNotConfiguredError } from "../util/errors.js";
|
|
10
10
|
|
|
11
11
|
describe("isUserCancellation", () => {
|
|
12
12
|
it("returns false for non-AbortError even when abort flag is set", () => {
|
|
@@ -278,6 +278,20 @@ describe("classifyConversationError", () => {
|
|
|
278
278
|
});
|
|
279
279
|
});
|
|
280
280
|
|
|
281
|
+
describe("provider not configured errors", () => {
|
|
282
|
+
it("classifies ProviderNotConfiguredError as PROVIDER_NOT_CONFIGURED", () => {
|
|
283
|
+
const err = new ProviderNotConfiguredError("anthropic", []);
|
|
284
|
+
const result = classifyConversationError(err, baseCtx);
|
|
285
|
+
expect(result.code).toBe("PROVIDER_NOT_CONFIGURED");
|
|
286
|
+
expect(result.userMessage).toBe(
|
|
287
|
+
"No API key configured for inference. Add one in Settings to start chatting.",
|
|
288
|
+
);
|
|
289
|
+
expect(result.retryable).toBe(true);
|
|
290
|
+
expect(result.errorCategory).toBe("provider_not_configured");
|
|
291
|
+
expect(result.debugDetails).toBeDefined();
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
281
295
|
describe("streaming corruption errors", () => {
|
|
282
296
|
const cases = [
|
|
283
297
|
"Unexpected event order, got message_start before receiving message_stop",
|
|
@@ -28,7 +28,7 @@ mock.module("../security/secure-keys.js", () => ({
|
|
|
28
28
|
setSecureKeyAsync: async (key?: string, value?: string) =>
|
|
29
29
|
setSecureKeyMock(key, value),
|
|
30
30
|
deleteSecureKeyAsync: async () => "deleted" as const,
|
|
31
|
-
listSecureKeysAsync: async () => [],
|
|
31
|
+
listSecureKeysAsync: async () => ({ accounts: [], unreachable: false }),
|
|
32
32
|
_resetBackend: () => {},
|
|
33
33
|
}));
|
|
34
34
|
|