@vellumai/assistant 0.4.49 → 0.4.51
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 +24 -33
- package/README.md +3 -3
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/keychain-broker.md +6 -6
- package/docs/architecture/memory.md +180 -119
- package/knip.json +32 -0
- package/package.json +3 -2
- package/src/__tests__/agent-loop.test.ts +3 -1
- package/src/__tests__/anthropic-provider.test.ts +114 -23
- package/src/__tests__/approval-cascade.test.ts +1 -15
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
- package/src/__tests__/btw-routes.test.ts +61 -5
- package/src/__tests__/canonical-guardian-store.test.ts +95 -0
- package/src/__tests__/checker.test.ts +13 -0
- package/src/__tests__/config-schema.test.ts +1 -68
- package/src/__tests__/config-watcher.test.ts +8 -0
- package/src/__tests__/context-memory-e2e.test.ts +11 -100
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/credential-security-e2e.test.ts +1 -0
- package/src/__tests__/credential-security-invariants.test.ts +8 -7
- package/src/__tests__/credential-vault-unit.test.ts +23 -18
- package/src/__tests__/credential-vault.test.ts +30 -18
- package/src/__tests__/credentials-cli.test.ts +257 -82
- package/src/__tests__/cu-unified-flow.test.ts +532 -0
- package/src/__tests__/date-context.test.ts +93 -77
- package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -0
- package/src/__tests__/history-repair.test.ts +245 -0
- package/src/__tests__/host-cu-proxy.test.ts +165 -3
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +36 -7
- package/src/__tests__/integration-status.test.ts +31 -30
- package/src/__tests__/invite-redemption-service.test.ts +166 -13
- package/src/__tests__/invite-routes-http.test.ts +166 -5
- package/src/__tests__/keychain-broker-client.test.ts +4 -4
- package/src/__tests__/list-messages-attachments.test.ts +193 -0
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
- package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
- package/src/__tests__/memory-recall-quality.test.ts +244 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
- package/src/__tests__/memory-regressions.test.ts +477 -2841
- package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
- package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
- package/src/__tests__/mime-builder.test.ts +28 -0
- package/src/__tests__/native-web-search.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +824 -31
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +363 -17
- package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
- package/src/__tests__/registry.test.ts +0 -1
- package/src/__tests__/relay-server.test.ts +55 -1
- package/src/__tests__/schedule-tools.test.ts +32 -0
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +183 -0
- package/src/__tests__/secure-keys.test.ts +78 -18
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/session-abort-tool-results.test.ts +1 -14
- package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
- package/src/__tests__/session-agent-loop.test.ts +19 -15
- package/src/__tests__/session-confirmation-signals.test.ts +1 -15
- package/src/__tests__/session-error.test.ts +124 -2
- package/src/__tests__/session-history-web-search.test.ts +918 -0
- package/src/__tests__/session-pre-run-repair.test.ts +1 -14
- package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
- package/src/__tests__/session-queue.test.ts +37 -27
- package/src/__tests__/session-runtime-assembly.test.ts +54 -0
- package/src/__tests__/session-slash-known.test.ts +1 -15
- package/src/__tests__/session-slash-queue.test.ts +1 -15
- package/src/__tests__/session-slash-unknown.test.ts +1 -15
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
- package/src/__tests__/session-workspace-injection.test.ts +3 -37
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
- package/src/__tests__/skills-install-extract.test.ts +93 -0
- package/src/__tests__/skills.test.ts +2 -2
- package/src/__tests__/skillssh-registry.test.ts +451 -0
- package/src/__tests__/slack-channel-config.test.ts +10 -8
- package/src/__tests__/trust-store.test.ts +15 -0
- package/src/__tests__/twilio-config.test.ts +11 -10
- package/src/__tests__/twilio-provider.test.ts +9 -4
- package/src/__tests__/voice-invite-redemption.test.ts +85 -5
- package/src/agent/ax-tree-compaction.test.ts +51 -0
- package/src/agent/loop.ts +39 -12
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-request-resolvers.ts +14 -2
- package/src/bundler/compiler-tools.ts +66 -2
- package/src/calls/call-domain.ts +134 -3
- package/src/calls/call-store.ts +6 -0
- package/src/calls/relay-server.ts +44 -6
- package/src/calls/relay-setup-router.ts +17 -1
- package/src/calls/twilio-config.ts +5 -4
- package/src/calls/twilio-provider.ts +14 -9
- package/src/calls/twilio-rest.ts +10 -7
- package/src/calls/types.ts +3 -1
- package/src/cli/commands/config.ts +14 -9
- package/src/cli/commands/contacts.ts +3 -0
- package/src/cli/commands/credentials.ts +170 -174
- package/src/cli/commands/doctor.ts +11 -8
- package/src/cli/commands/keys.ts +9 -9
- package/src/cli/commands/mcp.ts +46 -59
- package/src/cli/commands/memory.ts +16 -165
- package/src/cli/commands/oauth/apps.ts +68 -10
- package/src/cli/commands/oauth/connections.ts +475 -105
- package/src/cli/commands/oauth/index.ts +3 -3
- package/src/cli/commands/oauth/providers.ts +18 -4
- package/src/cli/commands/sessions.ts +5 -2
- package/src/cli/commands/skills.ts +173 -1
- package/src/cli/http-client.ts +0 -20
- package/src/cli/main-screen.tsx +2 -2
- package/src/cli/program.ts +5 -6
- package/src/cli.ts +20 -22
- package/src/config/__tests__/feature-flag-registry-bundled.test.ts +39 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +1 -1
- package/src/config/bundled-skills/computer-use/tools/computer-use-observe.ts +12 -0
- package/src/config/bundled-skills/contacts/SKILL.md +35 -11
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
- package/src/config/bundled-skills/gmail/SKILL.md +1 -1
- package/src/config/bundled-skills/gmail/TOOLS.json +52 -0
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +13 -3
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +9 -2
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +9 -2
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +5 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +20 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +8 -2
- package/src/config/bundled-skills/messaging/SKILL.md +1 -1
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +7 -5
- package/src/config/bundled-skills/slack/tools/shared.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +1 -1
- package/src/config/bundled-tool-registry.ts +2 -5
- package/src/config/loader.ts +6 -42
- package/src/config/schema.ts +1 -12
- package/src/config/schemas/memory-lifecycle.ts +0 -9
- package/src/config/schemas/memory-processing.ts +0 -180
- package/src/config/schemas/memory-retrieval.ts +32 -104
- package/src/config/schemas/memory.ts +0 -10
- package/src/config/types.ts +0 -4
- package/src/contacts/contact-store.ts +39 -2
- package/src/contacts/contacts-write.ts +9 -0
- package/src/context/window-manager.ts +4 -1
- package/src/daemon/config-watcher.ts +55 -2
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +114 -31
- package/src/daemon/handlers/config-ingress.ts +2 -2
- package/src/daemon/handlers/config-slack-channel.ts +59 -39
- package/src/daemon/handlers/config-telegram.ts +23 -14
- package/src/daemon/handlers/session-history.ts +1 -358
- package/src/daemon/handlers/sessions.ts +18 -13
- package/src/daemon/handlers/shared.ts +3 -17
- package/src/daemon/handlers/skills.ts +20 -1
- package/src/daemon/history-repair.ts +72 -8
- package/src/daemon/host-cu-proxy.ts +55 -26
- package/src/daemon/lifecycle.ts +39 -4
- package/src/daemon/mcp-reload-service.ts +2 -2
- package/src/daemon/message-types/computer-use.ts +1 -12
- package/src/daemon/message-types/memory.ts +4 -16
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/sessions.ts +4 -42
- package/src/daemon/server.ts +6 -1
- package/src/daemon/session-agent-loop-handlers.ts +38 -0
- package/src/daemon/session-agent-loop.ts +334 -48
- package/src/daemon/session-error.ts +89 -6
- package/src/daemon/session-history.ts +17 -7
- package/src/daemon/session-media-retry.ts +6 -2
- package/src/daemon/session-memory.ts +69 -149
- package/src/daemon/session-process.ts +10 -1
- package/src/daemon/session-runtime-assembly.ts +49 -19
- package/src/daemon/session-slash.ts +3 -5
- package/src/daemon/session-surfaces.ts +4 -1
- package/src/daemon/session-tool-setup.ts +7 -1
- package/src/daemon/session.ts +12 -2
- package/src/email/providers/index.ts +2 -2
- package/src/instrument.ts +61 -1
- package/src/media/avatar-router.ts +1 -1
- package/src/memory/admin.ts +2 -191
- package/src/memory/canonical-guardian-store.ts +38 -2
- package/src/memory/conversation-crud.ts +0 -33
- package/src/memory/conversation-queries.ts +25 -83
- package/src/memory/db-init.ts +32 -0
- package/src/memory/embedding-backend.ts +84 -8
- package/src/memory/embedding-types.ts +9 -1
- package/src/memory/indexer.ts +7 -46
- package/src/memory/invite-store.ts +19 -0
- package/src/memory/items-extractor.ts +274 -76
- package/src/memory/job-handlers/backfill.ts +2 -127
- package/src/memory/job-handlers/cleanup.ts +2 -16
- package/src/memory/job-handlers/extraction.ts +2 -138
- package/src/memory/job-handlers/index-maintenance.ts +1 -6
- package/src/memory/job-handlers/summarization.ts +3 -148
- package/src/memory/job-utils.ts +21 -59
- package/src/memory/jobs-store.ts +1 -159
- package/src/memory/jobs-worker.ts +9 -52
- package/src/memory/migrations/104-core-indexes.ts +3 -3
- package/src/memory/migrations/149-oauth-tables.ts +2 -0
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
- package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
- package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
- package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
- package/src/memory/migrations/154-drop-fts.ts +20 -0
- package/src/memory/migrations/155-drop-conflicts.ts +7 -0
- package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
- package/src/memory/migrations/157-invite-contact-id.ts +104 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/migrations/registry.ts +6 -0
- package/src/memory/qdrant-client.ts +148 -51
- package/src/memory/raw-query.ts +1 -1
- package/src/memory/retriever.test.ts +294 -273
- package/src/memory/retriever.ts +421 -645
- package/src/memory/schema/calls.ts +2 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/memory-core.ts +3 -48
- package/src/memory/schema/oauth.ts +2 -0
- package/src/memory/search/formatting.ts +263 -176
- package/src/memory/search/lexical.ts +1 -254
- package/src/memory/search/ranking.ts +0 -455
- package/src/memory/search/semantic.ts +100 -14
- package/src/memory/search/staleness.ts +47 -0
- package/src/memory/search/tier-classifier.ts +21 -0
- package/src/memory/search/types.ts +15 -77
- package/src/memory/task-memory-cleanup.ts +4 -6
- package/src/messaging/provider.ts +1 -1
- package/src/messaging/providers/gmail/adapter.ts +1 -1
- package/src/messaging/providers/gmail/mime-builder.ts +17 -7
- package/src/messaging/providers/telegram-bot/adapter.ts +17 -8
- package/src/messaging/providers/whatsapp/adapter.ts +13 -9
- package/src/messaging/registry.ts +9 -5
- package/src/oauth/byo-connection.test.ts +40 -25
- package/src/oauth/connect-orchestrator.ts +4 -10
- package/src/oauth/connection-resolver.ts +20 -6
- package/src/oauth/manual-token-connection.ts +5 -5
- package/src/oauth/oauth-store.ts +183 -31
- package/src/oauth/platform-connection.test.ts +1 -1
- package/src/oauth/provider-behaviors.ts +503 -4
- package/src/oauth/seed-providers.ts +214 -8
- package/src/oauth/token-persistence.ts +31 -16
- package/src/permissions/defaults.ts +1 -0
- package/src/permissions/trust-store.ts +23 -1
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -2
- package/src/providers/anthropic/client.ts +56 -126
- package/src/providers/types.ts +7 -1
- package/src/runtime/AGENTS.md +9 -0
- package/src/runtime/auth/route-policy.ts +6 -3
- package/src/runtime/channel-readiness-service.ts +48 -40
- package/src/runtime/guardian-reply-router.ts +24 -22
- package/src/runtime/http-server.ts +2 -2
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/invite-redemption-service.ts +72 -12
- package/src/runtime/invite-service.ts +43 -0
- package/src/runtime/middleware/twilio-validation.ts +1 -1
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/brain-graph-routes.ts +10 -90
- package/src/runtime/routes/btw-routes.ts +10 -5
- package/src/runtime/routes/conversation-routes.ts +56 -11
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
- package/src/runtime/routes/integrations/slack/channel.ts +2 -2
- package/src/runtime/routes/integrations/telegram.ts +2 -2
- package/src/runtime/routes/integrations/twilio.ts +17 -17
- package/src/runtime/routes/invite-routes.ts +29 -4
- package/src/runtime/routes/memory-item-routes.test.ts +754 -0
- package/src/runtime/routes/memory-item-routes.ts +503 -0
- package/src/runtime/routes/secret-routes.ts +17 -0
- package/src/runtime/routes/session-management-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +3 -3
- package/src/runtime/routes/trust-rules-routes.ts +14 -0
- package/src/runtime/routes/workspace-routes.ts +9 -4
- package/src/runtime/routes/workspace-utils.ts +8 -2
- package/src/schedule/integration-status.ts +26 -19
- package/src/security/keychain-broker-client.ts +17 -4
- package/src/security/oauth2.ts +6 -7
- package/src/security/secure-keys.ts +44 -19
- package/src/security/token-manager.ts +46 -39
- package/src/services/vercel-deploy.ts +0 -24
- package/src/signals/confirm.ts +78 -0
- package/src/signals/mcp-reload.ts +18 -0
- package/src/skills/catalog-install.ts +74 -18
- package/src/skills/skillssh-registry.ts +503 -0
- package/src/tools/assets/search.ts +5 -1
- package/src/tools/computer-use/definitions.ts +0 -10
- package/src/tools/computer-use/registry.ts +1 -1
- package/src/tools/credentials/vault.ts +22 -7
- package/src/tools/memory/definitions.ts +4 -13
- package/src/tools/memory/handlers.test.ts +83 -103
- package/src/tools/memory/handlers.ts +50 -85
- package/src/tools/network/script-proxy/session-manager.ts +8 -8
- package/src/tools/schedule/create.ts +10 -3
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/skills/load.ts +25 -2
- package/src/watcher/provider-types.ts +1 -1
- package/src/watcher/providers/github.ts +1 -1
- package/src/watcher/providers/gmail.ts +3 -3
- package/src/watcher/providers/google-calendar.ts +3 -3
- package/src/watcher/providers/linear.ts +1 -1
- package/src/__tests__/clarification-resolver.test.ts +0 -193
- package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
- package/src/__tests__/conflict-policy.test.ts +0 -269
- package/src/__tests__/conflict-store.test.ts +0 -372
- package/src/__tests__/contradiction-checker.test.ts +0 -361
- package/src/__tests__/entity-extractor.test.ts +0 -211
- package/src/__tests__/entity-search.test.ts +0 -1117
- package/src/__tests__/profile-compiler.test.ts +0 -392
- package/src/__tests__/session-conflict-gate.test.ts +0 -1228
- package/src/__tests__/session-profile-injection.test.ts +0 -557
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
- package/src/daemon/session-conflict-gate.ts +0 -167
- package/src/daemon/session-dynamic-profile.ts +0 -77
- package/src/memory/clarification-resolver.ts +0 -417
- package/src/memory/conflict-intent.ts +0 -205
- package/src/memory/conflict-policy.ts +0 -127
- package/src/memory/conflict-store.ts +0 -410
- package/src/memory/contradiction-checker.ts +0 -508
- package/src/memory/entity-extractor.ts +0 -535
- package/src/memory/format-recall.ts +0 -47
- package/src/memory/fts-reconciler.ts +0 -165
- package/src/memory/job-handlers/conflict.ts +0 -200
- package/src/memory/profile-compiler.ts +0 -195
- package/src/memory/recall-cache.ts +0 -117
- package/src/memory/search/entity.ts +0 -535
- package/src/memory/search/query-expansion.test.ts +0 -70
- package/src/memory/search/query-expansion.ts +0 -118
- package/src/runtime/routes/mcp-routes.ts +0 -20
|
@@ -149,13 +149,12 @@ mock.module("../memory/retriever.js", () => ({
|
|
|
149
149
|
enabled: false,
|
|
150
150
|
degraded: false,
|
|
151
151
|
injectedText: "",
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
semanticHits: 0,
|
|
154
154
|
recencyHits: 0,
|
|
155
155
|
injectedTokens: 0,
|
|
156
156
|
latencyMs: 0,
|
|
157
157
|
}),
|
|
158
|
-
injectMemoryRecallIntoUserMessage: (msg: Message) => msg,
|
|
159
158
|
stripMemoryRecallMessages: (msgs: Message[]) => msgs,
|
|
160
159
|
}));
|
|
161
160
|
|
|
@@ -181,14 +180,15 @@ mock.module("../daemon/session-memory.js", () => ({
|
|
|
181
180
|
enabled: false,
|
|
182
181
|
degraded: false,
|
|
183
182
|
injectedText: "",
|
|
184
|
-
|
|
183
|
+
|
|
185
184
|
semanticHits: 0,
|
|
186
185
|
recencyHits: 0,
|
|
187
186
|
injectedTokens: 0,
|
|
188
187
|
latencyMs: 0,
|
|
188
|
+
tier1Count: 0,
|
|
189
|
+
tier2Count: 0,
|
|
190
|
+
hybridSearchMs: 0,
|
|
189
191
|
},
|
|
190
|
-
dynamicProfile: { text: "" },
|
|
191
|
-
recallInjectionStrategy: "prepend_user_block" as const,
|
|
192
192
|
}),
|
|
193
193
|
}));
|
|
194
194
|
|
|
@@ -197,11 +197,6 @@ mock.module("../daemon/session-runtime-assembly.js", () => ({
|
|
|
197
197
|
stripInjectedContext: (msgs: Message[]) => msgs,
|
|
198
198
|
}));
|
|
199
199
|
|
|
200
|
-
mock.module("../daemon/session-dynamic-profile.js", () => ({
|
|
201
|
-
stripDynamicProfileMessages: (msgs: Message[]) => msgs,
|
|
202
|
-
injectDynamicProfileIntoUserMessage: (msg: Message) => msg,
|
|
203
|
-
}));
|
|
204
|
-
|
|
205
200
|
mock.module("../daemon/date-context.js", () => ({
|
|
206
201
|
buildTemporalContext: () => null,
|
|
207
202
|
}));
|
|
@@ -276,6 +271,7 @@ mock.module("../daemon/session-error.js", () => ({
|
|
|
276
271
|
code: "SESSION_PROCESSING_FAILED",
|
|
277
272
|
userMessage: "Something went wrong processing your message.",
|
|
278
273
|
retryable: false,
|
|
274
|
+
errorCategory: "processing_failed",
|
|
279
275
|
}),
|
|
280
276
|
isUserCancellation: (err: unknown, ctx: { aborted?: boolean }) => {
|
|
281
277
|
if (!ctx.aborted) return false;
|
|
@@ -376,9 +372,6 @@ function makeCtx(
|
|
|
376
372
|
contextCompactedMessageCount: 0,
|
|
377
373
|
contextCompactedAt: null,
|
|
378
374
|
|
|
379
|
-
conflictGate: {
|
|
380
|
-
evaluate: async () => null,
|
|
381
|
-
} as unknown as AgentLoopSessionContext["conflictGate"],
|
|
382
375
|
memoryPolicy: { scopeId: "default", includeDefaultFallback: true },
|
|
383
376
|
|
|
384
377
|
currentActiveSurfaceId: undefined,
|
|
@@ -1300,6 +1293,7 @@ describe("session-agent-loop", () => {
|
|
|
1300
1293
|
turnIndex: 0,
|
|
1301
1294
|
toolCount: 1,
|
|
1302
1295
|
hasToolUse: true,
|
|
1296
|
+
history: messages,
|
|
1303
1297
|
});
|
|
1304
1298
|
if (decision === "yield") {
|
|
1305
1299
|
return [
|
|
@@ -1363,7 +1357,12 @@ describe("session-agent-loop", () => {
|
|
|
1363
1357
|
providerDurationMs: 100,
|
|
1364
1358
|
});
|
|
1365
1359
|
if (onCheckpoint) {
|
|
1366
|
-
onCheckpoint({
|
|
1360
|
+
onCheckpoint({
|
|
1361
|
+
turnIndex: 0,
|
|
1362
|
+
toolCount: 1,
|
|
1363
|
+
hasToolUse: true,
|
|
1364
|
+
history: messages,
|
|
1365
|
+
});
|
|
1367
1366
|
}
|
|
1368
1367
|
return [
|
|
1369
1368
|
...messages,
|
|
@@ -1425,7 +1424,12 @@ describe("session-agent-loop", () => {
|
|
|
1425
1424
|
providerDurationMs: 100,
|
|
1426
1425
|
});
|
|
1427
1426
|
if (onCheckpoint) {
|
|
1428
|
-
onCheckpoint({
|
|
1427
|
+
onCheckpoint({
|
|
1428
|
+
turnIndex: 0,
|
|
1429
|
+
toolCount: 1,
|
|
1430
|
+
hasToolUse: true,
|
|
1431
|
+
history: messages,
|
|
1432
|
+
});
|
|
1429
1433
|
}
|
|
1430
1434
|
return [
|
|
1431
1435
|
...messages,
|
|
@@ -83,7 +83,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
83
83
|
timeouts: { permissionTimeoutSec: 1 },
|
|
84
84
|
apiKeys: {},
|
|
85
85
|
skills: { entries: {}, allowBundled: true },
|
|
86
|
-
memory: { retrieval: { injectionStrategy: "inline" } },
|
|
87
86
|
permissions: { mode: "workspace" },
|
|
88
87
|
}),
|
|
89
88
|
loadRawConfig: () => ({}),
|
|
@@ -122,18 +121,6 @@ mock.module("../security/secret-allowlist.js", () => ({
|
|
|
122
121
|
resetAllowlist: () => {},
|
|
123
122
|
}));
|
|
124
123
|
|
|
125
|
-
mock.module("../memory/admin.js", () => ({
|
|
126
|
-
getMemoryConflictAndCleanupStats: () => ({
|
|
127
|
-
conflicts: { pending: 0, resolved: 0, oldestPendingAgeMs: null },
|
|
128
|
-
cleanup: {
|
|
129
|
-
resolvedBacklog: 0,
|
|
130
|
-
supersededBacklog: 0,
|
|
131
|
-
resolvedCompleted24h: 0,
|
|
132
|
-
supersededCompleted24h: 0,
|
|
133
|
-
},
|
|
134
|
-
}),
|
|
135
|
-
}));
|
|
136
|
-
|
|
137
124
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
138
125
|
getConversationThreadType: () => "default",
|
|
139
126
|
setConversationOriginChannelIfUnset: () => {},
|
|
@@ -174,13 +161,12 @@ mock.module("../memory/retriever.js", () => ({
|
|
|
174
161
|
enabled: false,
|
|
175
162
|
degraded: false,
|
|
176
163
|
injectedText: "",
|
|
177
|
-
|
|
164
|
+
|
|
178
165
|
semanticHits: 0,
|
|
179
166
|
recencyHits: 0,
|
|
180
167
|
injectedTokens: 0,
|
|
181
168
|
latencyMs: 0,
|
|
182
169
|
}),
|
|
183
|
-
injectMemoryRecallIntoUserMessage: (msg: Message) => msg,
|
|
184
170
|
stripMemoryRecallMessages: (msgs: Message[]) => msgs,
|
|
185
171
|
}));
|
|
186
172
|
|
|
@@ -77,6 +77,7 @@ describe("classifySessionError", () => {
|
|
|
77
77
|
const result = classifySessionError(new Error(msg), baseCtx);
|
|
78
78
|
expect(result.code).toBe("PROVIDER_NETWORK");
|
|
79
79
|
expect(result.retryable).toBe(true);
|
|
80
|
+
expect(result.errorCategory).toBe("provider_network");
|
|
80
81
|
});
|
|
81
82
|
}
|
|
82
83
|
});
|
|
@@ -95,6 +96,8 @@ describe("classifySessionError", () => {
|
|
|
95
96
|
const result = classifySessionError(new Error(msg), baseCtx);
|
|
96
97
|
expect(result.code).toBe("PROVIDER_RATE_LIMIT");
|
|
97
98
|
expect(result.retryable).toBe(true);
|
|
99
|
+
expect(result.userMessage).toContain("busy");
|
|
100
|
+
expect(result.errorCategory).toBe("rate_limit");
|
|
98
101
|
});
|
|
99
102
|
}
|
|
100
103
|
});
|
|
@@ -127,6 +130,7 @@ describe("classifySessionError", () => {
|
|
|
127
130
|
expect(result.code).toBe("PROVIDER_API");
|
|
128
131
|
expect(result.userMessage).toContain("timed out");
|
|
129
132
|
expect(result.retryable).toBe(true);
|
|
133
|
+
expect(result.errorCategory).toBe("provider_timeout");
|
|
130
134
|
});
|
|
131
135
|
}
|
|
132
136
|
|
|
@@ -166,6 +170,8 @@ describe("classifySessionError", () => {
|
|
|
166
170
|
const result = classifySessionError(new Error(msg), baseCtx);
|
|
167
171
|
expect(result.code).toBe("CONTEXT_TOO_LARGE");
|
|
168
172
|
expect(result.retryable).toBe(false);
|
|
173
|
+
expect(result.userMessage).toContain("too long");
|
|
174
|
+
expect(result.errorCategory).toBe("context_too_large");
|
|
169
175
|
});
|
|
170
176
|
}
|
|
171
177
|
});
|
|
@@ -205,6 +211,71 @@ describe("classifySessionError", () => {
|
|
|
205
211
|
});
|
|
206
212
|
});
|
|
207
213
|
|
|
214
|
+
describe("ordering errors (tool_use/tool_result mismatches)", () => {
|
|
215
|
+
const cases = [
|
|
216
|
+
"tool_result block not immediately after tool_use block",
|
|
217
|
+
"tool_use block must have a matching tool_result",
|
|
218
|
+
"tool_use_id abc123 without corresponding tool_result",
|
|
219
|
+
"tool_result references tool_use_id not found in conversation",
|
|
220
|
+
"messages have invalid order",
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
for (const msg of cases) {
|
|
224
|
+
it(`classifies "${msg}" as PROVIDER_ORDERING`, () => {
|
|
225
|
+
const result = classifySessionError(new Error(msg), baseCtx);
|
|
226
|
+
expect(result.code).toBe("PROVIDER_ORDERING");
|
|
227
|
+
expect(result.retryable).toBe(true);
|
|
228
|
+
expect(result.userMessage).toBe(
|
|
229
|
+
"An internal error occurred. Retrying...",
|
|
230
|
+
);
|
|
231
|
+
expect(result.errorCategory).toBe("tool_ordering");
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
it("classifies ProviderError 400 with ordering message as PROVIDER_ORDERING", () => {
|
|
236
|
+
const err = new ProviderError(
|
|
237
|
+
"Anthropic API error (400): tool_use_id abc without tool_result",
|
|
238
|
+
"anthropic",
|
|
239
|
+
400,
|
|
240
|
+
);
|
|
241
|
+
const result = classifySessionError(err, baseCtx);
|
|
242
|
+
expect(result.code).toBe("PROVIDER_ORDERING");
|
|
243
|
+
expect(result.retryable).toBe(true);
|
|
244
|
+
expect(result.errorCategory).toBe("tool_ordering");
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
describe("web search ordering errors", () => {
|
|
249
|
+
const cases = [
|
|
250
|
+
"web_search tool_use block without result",
|
|
251
|
+
"web_search tool_result missing from conversation",
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
for (const msg of cases) {
|
|
255
|
+
it(`classifies "${msg}" as PROVIDER_WEB_SEARCH`, () => {
|
|
256
|
+
const result = classifySessionError(new Error(msg), baseCtx);
|
|
257
|
+
expect(result.code).toBe("PROVIDER_WEB_SEARCH");
|
|
258
|
+
expect(result.retryable).toBe(true);
|
|
259
|
+
expect(result.userMessage).toBe(
|
|
260
|
+
"An internal error occurred with web search. Retrying...",
|
|
261
|
+
);
|
|
262
|
+
expect(result.errorCategory).toBe("web_search_ordering");
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
it("classifies ProviderError 400 with web_search ordering message as PROVIDER_WEB_SEARCH", () => {
|
|
267
|
+
const err = new ProviderError(
|
|
268
|
+
"Anthropic API error (400): web_search tool_use without result block",
|
|
269
|
+
"anthropic",
|
|
270
|
+
400,
|
|
271
|
+
);
|
|
272
|
+
const result = classifySessionError(err, baseCtx);
|
|
273
|
+
expect(result.code).toBe("PROVIDER_WEB_SEARCH");
|
|
274
|
+
expect(result.retryable).toBe(true);
|
|
275
|
+
expect(result.errorCategory).toBe("web_search_ordering");
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
208
279
|
describe("abort/cancel errors (non-user-initiated)", () => {
|
|
209
280
|
it('classifies "aborted" as SESSION_ABORTED', () => {
|
|
210
281
|
const result = classifySessionError(
|
|
@@ -232,6 +303,7 @@ describe("classifySessionError", () => {
|
|
|
232
303
|
expect(result.code).toBe("REGENERATE_FAILED");
|
|
233
304
|
expect(result.retryable).toBe(true);
|
|
234
305
|
expect(result.userMessage).toContain("regenerate");
|
|
306
|
+
expect(result.errorCategory).toContain("regenerate:");
|
|
235
307
|
});
|
|
236
308
|
|
|
237
309
|
it("returns REGENERATE_FAILED for generic errors", () => {
|
|
@@ -251,6 +323,7 @@ describe("classifySessionError", () => {
|
|
|
251
323
|
expect(result.code).toBe("SESSION_PROCESSING_FAILED");
|
|
252
324
|
expect(result.retryable).toBe(false);
|
|
253
325
|
expect(result.userMessage).toContain("something completely unexpected");
|
|
326
|
+
expect(result.errorCategory).toBe("processing_failed");
|
|
254
327
|
});
|
|
255
328
|
|
|
256
329
|
it("includes debugDetails with stack trace", () => {
|
|
@@ -291,6 +364,7 @@ describe("classifySessionError", () => {
|
|
|
291
364
|
const result = classifySessionError(err, baseCtx);
|
|
292
365
|
expect(result.code).toBe("PROVIDER_RATE_LIMIT");
|
|
293
366
|
expect(result.retryable).toBe(true);
|
|
367
|
+
expect(result.errorCategory).toBe("rate_limit");
|
|
294
368
|
});
|
|
295
369
|
|
|
296
370
|
it("classifies ProviderError with 500 as PROVIDER_API (retryable)", () => {
|
|
@@ -344,19 +418,39 @@ describe("classifySessionError", () => {
|
|
|
344
418
|
});
|
|
345
419
|
});
|
|
346
420
|
|
|
421
|
+
describe("errorCategory is always present", () => {
|
|
422
|
+
it("includes errorCategory on all classified errors", () => {
|
|
423
|
+
const cases: Array<{ error: unknown; ctx: ErrorContext }> = [
|
|
424
|
+
{ error: new Error("ECONNREFUSED"), ctx: baseCtx },
|
|
425
|
+
{ error: new Error("rate limit"), ctx: baseCtx },
|
|
426
|
+
{ error: new Error("prompt is too long"), ctx: baseCtx },
|
|
427
|
+
{ error: new Error("unknown"), ctx: baseCtx },
|
|
428
|
+
{
|
|
429
|
+
error: new ProviderError("error", "anthropic", 500),
|
|
430
|
+
ctx: baseCtx,
|
|
431
|
+
},
|
|
432
|
+
];
|
|
433
|
+
for (const { error, ctx } of cases) {
|
|
434
|
+
const result = classifySessionError(error, ctx);
|
|
435
|
+
expect(result.errorCategory).toBeDefined();
|
|
436
|
+
expect(result.errorCategory.length).toBeGreaterThan(0);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
347
441
|
describe("debug detail truncation", () => {
|
|
348
442
|
it("truncates debugDetails longer than 4000 chars", () => {
|
|
349
443
|
const longMsg = "x".repeat(5000);
|
|
350
444
|
const result = classifySessionError(new Error(longMsg), baseCtx);
|
|
351
445
|
expect(result.debugDetails!.length).toBeLessThanOrEqual(4020); // 4000 + truncation marker
|
|
352
|
-
expect(result.debugDetails!).toContain("
|
|
446
|
+
expect(result.debugDetails!).toContain("(truncated)");
|
|
353
447
|
});
|
|
354
448
|
|
|
355
449
|
it("preserves debugDetails under 4000 chars", () => {
|
|
356
450
|
const shortMsg = "short error message";
|
|
357
451
|
const result = classifySessionError(new Error(shortMsg), baseCtx);
|
|
358
452
|
expect(result.debugDetails).toBeDefined();
|
|
359
|
-
expect(result.debugDetails!).not.toContain("
|
|
453
|
+
expect(result.debugDetails!).not.toContain("(truncated)");
|
|
360
454
|
});
|
|
361
455
|
});
|
|
362
456
|
|
|
@@ -391,6 +485,7 @@ describe("buildSessionErrorMessage", () => {
|
|
|
391
485
|
userMessage: "Network error",
|
|
392
486
|
retryable: true,
|
|
393
487
|
debugDetails: "ECONNREFUSED",
|
|
488
|
+
errorCategory: "provider_network",
|
|
394
489
|
});
|
|
395
490
|
|
|
396
491
|
expect(msg.type).toBe("session_error");
|
|
@@ -399,6 +494,7 @@ describe("buildSessionErrorMessage", () => {
|
|
|
399
494
|
expect(msg.userMessage).toBe("Network error");
|
|
400
495
|
expect(msg.retryable).toBe(true);
|
|
401
496
|
expect(msg.debugDetails).toBe("ECONNREFUSED");
|
|
497
|
+
expect(msg.errorCategory).toBe("provider_network");
|
|
402
498
|
});
|
|
403
499
|
|
|
404
500
|
it("omits debugDetails when not provided", () => {
|
|
@@ -406,9 +502,35 @@ describe("buildSessionErrorMessage", () => {
|
|
|
406
502
|
code: "UNKNOWN",
|
|
407
503
|
userMessage: "Something went wrong",
|
|
408
504
|
retryable: false,
|
|
505
|
+
errorCategory: "processing_failed",
|
|
409
506
|
});
|
|
410
507
|
|
|
411
508
|
expect(msg.type).toBe("session_error");
|
|
412
509
|
expect(msg.debugDetails).toBeUndefined();
|
|
510
|
+
expect(msg.errorCategory).toBe("processing_failed");
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it("includes errorCategory for ordering errors", () => {
|
|
514
|
+
const msg = buildSessionErrorMessage("session-789", {
|
|
515
|
+
code: "PROVIDER_ORDERING",
|
|
516
|
+
userMessage: "An internal error occurred. Retrying...",
|
|
517
|
+
retryable: true,
|
|
518
|
+
errorCategory: "tool_ordering",
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
expect(msg.errorCategory).toBe("tool_ordering");
|
|
522
|
+
expect(msg.code).toBe("PROVIDER_ORDERING");
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
it("includes errorCategory for web search errors", () => {
|
|
526
|
+
const msg = buildSessionErrorMessage("session-abc", {
|
|
527
|
+
code: "PROVIDER_WEB_SEARCH",
|
|
528
|
+
userMessage: "An internal error occurred with web search. Retrying...",
|
|
529
|
+
retryable: true,
|
|
530
|
+
errorCategory: "web_search_ordering",
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
expect(msg.errorCategory).toBe("web_search_ordering");
|
|
534
|
+
expect(msg.code).toBe("PROVIDER_WEB_SEARCH");
|
|
413
535
|
});
|
|
414
536
|
});
|