@vellumai/assistant 0.8.3 → 0.8.4
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/docker-entrypoint.sh +0 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +610 -16
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +272 -0
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/compaction-events.test.ts +1 -1
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
- package/src/__tests__/conversation-agent-loop.test.ts +25 -7
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +161 -0
- package/src/__tests__/conversation-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +6 -0
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-resolver.test.ts +85 -1
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/openai-provider.test.ts +105 -0
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
- package/src/__tests__/platform.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +51 -28
- package/src/__tests__/terminal-tools.test.ts +11 -1
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-executor.test.ts +90 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +88 -5
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +57 -20
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/memory-v2.ts +308 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +19 -0
- package/src/config/feature-flag-registry.json +99 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +4 -0
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/llm.ts +3 -0
- package/src/config/schemas/memory-v2.ts +48 -1
- package/src/context/compactor.ts +8 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +153 -23
- package/src/daemon/conversation-agent-loop.ts +223 -54
- package/src/daemon/conversation-lifecycle.ts +142 -116
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +135 -75
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +7 -0
- package/src/daemon/conversation.ts +42 -5
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +79 -0
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +18 -4
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +8 -0
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/messages.ts +68 -1
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +94 -0
- package/src/home/suggested-prompts.ts +177 -9
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +320 -6
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/db-init.ts +16 -0
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/jobs-worker.ts +21 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -2
- package/src/memory/memory-retrospective-job.ts +408 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +26 -8
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/index.ts +17 -0
- package/src/memory/migrations/registry.ts +25 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +31 -14
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/router.test.ts +489 -1
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +21 -10
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +9 -1
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +4 -1
- package/src/plugins/defaults/injectors.ts +82 -9
- package/src/prompts/__tests__/system-prompt.test.ts +46 -2
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -68
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +8 -0
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +53 -3
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +15 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/model-catalog.ts +48 -1
- package/src/providers/openai/chat-completions-provider.ts +57 -20
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/types.ts +25 -0
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +151 -56
- package/src/runtime/auth/route-policy.ts +7 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -4
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +55 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +146 -1
- package/src/runtime/routes/conversation-query-routes.ts +60 -1
- package/src/runtime/routes/conversation-routes.ts +281 -76
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +8 -1
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +12 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-v2-routes.ts +217 -0
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/slack-channel-routes.ts +187 -0
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
- package/src/tools/browser/browser-execution.ts +93 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
- package/src/tools/browser/cdp-client/factory.ts +87 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
- package/src/tools/browser/cdp-client/types.ts +36 -0
- package/src/tools/browser/pinned-tabs.ts +90 -0
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +128 -2
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +213 -64
- package/src/tools/network/web-search.ts +191 -66
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +4 -0
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/types/onboarding-context.ts +4 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/platform.ts +0 -5
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
package/package.json
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* throw → catch-block fallback case).
|
|
8
8
|
* 2. **Reason matches break site** — for each reachable break site, the
|
|
9
9
|
* emitted reason is the one documented in `AgentLoopExitReason`.
|
|
10
|
-
* 3. **Always the last AgentEvent of
|
|
11
|
-
* positional ordering to find it.
|
|
10
|
+
* 3. **Always the last AgentEvent of terminal runs** — consumers can rely on
|
|
11
|
+
* positional ordering to find it when a run reaches a terminal state.
|
|
12
12
|
*
|
|
13
13
|
* Sites not exercised here (`empty_response_exhausted`, `aborted_via_error`)
|
|
14
14
|
* require deeper provider fakery and are best covered by integration tests
|
|
@@ -172,7 +172,7 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
172
172
|
expect(lastExitEvent(events)?.reason).toBe("yield_to_user");
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
test("
|
|
175
|
+
test("does not emit agent_loop_exit when onCheckpoint yields control", async () => {
|
|
176
176
|
const { provider } = createMockProvider([
|
|
177
177
|
toolUseResponse("t1", "read_file", { path: "/a.txt" }),
|
|
178
178
|
textResponse("never reached"),
|
|
@@ -198,8 +198,7 @@ describe("AgentLoop exit-reason instrumentation", () => {
|
|
|
198
198
|
onCheckpoint,
|
|
199
199
|
);
|
|
200
200
|
|
|
201
|
-
expect(countExitEvents(events)).toBe(
|
|
202
|
-
expect(lastExitEvent(events)?.reason).toBe("checkpoint_yield");
|
|
201
|
+
expect(countExitEvents(events)).toBe(0);
|
|
203
202
|
});
|
|
204
203
|
|
|
205
204
|
test("emits 'error' when provider throws an unhandled error", async () => {
|
|
@@ -257,7 +257,7 @@ const anthropicStub = { name: "anthropic" };
|
|
|
257
257
|
mock.module("../providers/registry.js", () => ({
|
|
258
258
|
getProvider: () => anthropicStub,
|
|
259
259
|
listProviders: () => ["anthropic"],
|
|
260
|
-
initializeProviders: () => {},
|
|
260
|
+
initializeProviders: async () => {},
|
|
261
261
|
resolveProviderFromConnection: async () => anthropicStub,
|
|
262
262
|
}));
|
|
263
263
|
|
|
@@ -181,6 +181,88 @@ describe("AgentLoop", () => {
|
|
|
181
181
|
]);
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
test("re-resolves override profile before each provider call", async () => {
|
|
185
|
+
const toolCallId = "tool-1";
|
|
186
|
+
const { provider, calls } = createMockProvider([
|
|
187
|
+
toolUseResponse(toolCallId, "read_file", { path: "/tmp/test.txt" }),
|
|
188
|
+
textResponse("File contents received."),
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
let overrideProfile: string | undefined;
|
|
192
|
+
const toolExecutor = async () => {
|
|
193
|
+
overrideProfile = "quality-optimized";
|
|
194
|
+
return { content: "ok", isError: false };
|
|
195
|
+
};
|
|
196
|
+
const loop = new AgentLoop(
|
|
197
|
+
provider,
|
|
198
|
+
"system",
|
|
199
|
+
{},
|
|
200
|
+
dummyTools,
|
|
201
|
+
toolExecutor,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
await loop.run(
|
|
205
|
+
[userMessage],
|
|
206
|
+
collectEvents([]),
|
|
207
|
+
undefined,
|
|
208
|
+
"req-1",
|
|
209
|
+
undefined,
|
|
210
|
+
"mainAgent",
|
|
211
|
+
undefined,
|
|
212
|
+
undefined,
|
|
213
|
+
undefined,
|
|
214
|
+
() => overrideProfile,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
expect(calls).toHaveLength(2);
|
|
218
|
+
expect(calls[0].options?.config?.overrideProfile).toBeUndefined();
|
|
219
|
+
expect(calls[1].options?.config?.overrideProfile).toBe("quality-optimized");
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test("re-resolves max input tokens before truncating tool results", async () => {
|
|
223
|
+
const toolCallId = "tool-1";
|
|
224
|
+
const toolOutput = "x".repeat(2_500);
|
|
225
|
+
const { provider, calls } = createMockProvider([
|
|
226
|
+
toolUseResponse(toolCallId, "read_file", { path: "/tmp/test.txt" }),
|
|
227
|
+
textResponse("File contents received."),
|
|
228
|
+
]);
|
|
229
|
+
|
|
230
|
+
let maxInputTokens = 1_000;
|
|
231
|
+
const toolExecutor = async () => {
|
|
232
|
+
maxInputTokens = 10_000;
|
|
233
|
+
return { content: toolOutput, isError: false };
|
|
234
|
+
};
|
|
235
|
+
const loop = new AgentLoop(
|
|
236
|
+
provider,
|
|
237
|
+
"system",
|
|
238
|
+
{},
|
|
239
|
+
dummyTools,
|
|
240
|
+
toolExecutor,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
await loop.run(
|
|
244
|
+
[userMessage],
|
|
245
|
+
collectEvents([]),
|
|
246
|
+
undefined,
|
|
247
|
+
"req-1",
|
|
248
|
+
undefined,
|
|
249
|
+
"mainAgent",
|
|
250
|
+
undefined,
|
|
251
|
+
undefined,
|
|
252
|
+
1_000,
|
|
253
|
+
undefined,
|
|
254
|
+
() => maxInputTokens,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const secondCallMessages = calls[1].messages;
|
|
258
|
+
const lastMsg = secondCallMessages[secondCallMessages.length - 1];
|
|
259
|
+
const toolResultBlock = lastMsg.content.find(
|
|
260
|
+
(b): b is Extract<ContentBlock, { type: "tool_result" }> =>
|
|
261
|
+
b.type === "tool_result",
|
|
262
|
+
);
|
|
263
|
+
expect(toolResultBlock?.content).toBe(toolOutput);
|
|
264
|
+
});
|
|
265
|
+
|
|
184
266
|
// 3. Multi-turn tool loop
|
|
185
267
|
test("supports multi-turn tool execution", async () => {
|
|
186
268
|
const { provider, calls } = createMockProvider([
|
|
@@ -470,7 +552,6 @@ describe("AgentLoop", () => {
|
|
|
470
552
|
).toBe(false);
|
|
471
553
|
});
|
|
472
554
|
|
|
473
|
-
|
|
474
555
|
// 9. Tool executor error results are forwarded correctly
|
|
475
556
|
test("forwards tool error results to provider", async () => {
|
|
476
557
|
const { provider, calls } = createMockProvider([
|
|
@@ -1767,7 +1848,9 @@ describe("AgentLoop", () => {
|
|
|
1767
1848
|
]);
|
|
1768
1849
|
|
|
1769
1850
|
// message_complete emitted for tool_use response + retry text response (not the empty one)
|
|
1770
|
-
const messageCompletes = events.filter(
|
|
1851
|
+
const messageCompletes = events.filter(
|
|
1852
|
+
(e) => e.type === "message_complete",
|
|
1853
|
+
);
|
|
1771
1854
|
expect(messageCompletes).toHaveLength(2);
|
|
1772
1855
|
});
|
|
1773
1856
|
|
|
@@ -1883,7 +1966,9 @@ describe("AgentLoop", () => {
|
|
|
1883
1966
|
expect(calls).toHaveLength(3);
|
|
1884
1967
|
|
|
1885
1968
|
// message_complete: tool_use response + final empty response (retry exhausted)
|
|
1886
|
-
const messageCompletes = events.filter(
|
|
1969
|
+
const messageCompletes = events.filter(
|
|
1970
|
+
(e) => e.type === "message_complete",
|
|
1971
|
+
);
|
|
1887
1972
|
expect(messageCompletes).toHaveLength(2);
|
|
1888
1973
|
|
|
1889
1974
|
// The last assistant message in history is the empty one
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import type { Anthropic } from "@anthropic-ai/sdk";
|
|
4
|
+
|
|
3
5
|
import type { Message, ToolDefinition } from "../providers/types.js";
|
|
4
6
|
|
|
5
7
|
// ---------------------------------------------------------------------------
|
|
@@ -204,6 +206,28 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
204
206
|
expect(lastStreamParams!.thinking).toEqual({ type: "disabled" });
|
|
205
207
|
});
|
|
206
208
|
|
|
209
|
+
test("drops unsigned thinking blocks from prior assistant messages", async () => {
|
|
210
|
+
await provider.sendMessage([
|
|
211
|
+
userMsg("Hi"),
|
|
212
|
+
{
|
|
213
|
+
role: "assistant",
|
|
214
|
+
content: [
|
|
215
|
+
{ type: "thinking", thinking: "non-native reasoning", signature: "" },
|
|
216
|
+
{ type: "text", text: "I can help." },
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
userMsg("Continue"),
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
const messages = lastStreamParams!.messages as Array<{
|
|
223
|
+
role: string;
|
|
224
|
+
content: Array<{ type: string; text?: string; thinking?: string }>;
|
|
225
|
+
}>;
|
|
226
|
+
const assistant = messages.find((message) => message.role === "assistant");
|
|
227
|
+
|
|
228
|
+
expect(assistant?.content).toEqual([{ type: "text", text: "I can help." }]);
|
|
229
|
+
});
|
|
230
|
+
|
|
207
231
|
test("splits system prompt into two cache blocks on boundary marker", async () => {
|
|
208
232
|
const staticBlock = "You are a helpful assistant.";
|
|
209
233
|
const dynamicBlock = "User workspace files here.";
|
|
@@ -2405,3 +2429,251 @@ describe("OpenRouterProvider — Anthropic dispatch", () => {
|
|
|
2405
2429
|
expect(lastStreamParams!.model).toBe("anthropic/claude-haiku-4.5");
|
|
2406
2430
|
});
|
|
2407
2431
|
});
|
|
2432
|
+
|
|
2433
|
+
// ---------------------------------------------------------------------------
|
|
2434
|
+
// Thinking block send-time filtering
|
|
2435
|
+
// ---------------------------------------------------------------------------
|
|
2436
|
+
|
|
2437
|
+
describe("AnthropicProvider — thinking block send-time filtering", () => {
|
|
2438
|
+
let provider: AnthropicProvider;
|
|
2439
|
+
|
|
2440
|
+
beforeEach(() => {
|
|
2441
|
+
lastStreamParams = null;
|
|
2442
|
+
_lastStreamOptions = null;
|
|
2443
|
+
lastConstructorArgs = null;
|
|
2444
|
+
scriptedStream = null;
|
|
2445
|
+
provider = new AnthropicProvider("sk-ant-test", "claude-sonnet-4-6");
|
|
2446
|
+
});
|
|
2447
|
+
|
|
2448
|
+
function assistantThinkingMsg(
|
|
2449
|
+
thinking: string,
|
|
2450
|
+
signature: string,
|
|
2451
|
+
text: string,
|
|
2452
|
+
): Message {
|
|
2453
|
+
return {
|
|
2454
|
+
role: "assistant",
|
|
2455
|
+
content: [
|
|
2456
|
+
{ type: "thinking", thinking, signature },
|
|
2457
|
+
{ type: "text", text },
|
|
2458
|
+
],
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
function assistantThinkingToolUseMsg(
|
|
2463
|
+
thinking: string,
|
|
2464
|
+
signature: string,
|
|
2465
|
+
toolUseId: string,
|
|
2466
|
+
toolName: string,
|
|
2467
|
+
): Message {
|
|
2468
|
+
return {
|
|
2469
|
+
role: "assistant",
|
|
2470
|
+
content: [
|
|
2471
|
+
{ type: "thinking", thinking, signature },
|
|
2472
|
+
{ type: "tool_use", id: toolUseId, name: toolName, input: {} },
|
|
2473
|
+
],
|
|
2474
|
+
};
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
function assistantRedactedThinkingMsg(data: string, text: string): Message {
|
|
2478
|
+
return {
|
|
2479
|
+
role: "assistant",
|
|
2480
|
+
content: [
|
|
2481
|
+
{ type: "redacted_thinking", data },
|
|
2482
|
+
{ type: "text", text },
|
|
2483
|
+
],
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
test("strips thinking blocks from completed historical assistant turns", async () => {
|
|
2488
|
+
const messages: Message[] = [
|
|
2489
|
+
userMsg("What is 2+2?"),
|
|
2490
|
+
assistantThinkingMsg("let me think...", "sig-abc-old", "4"),
|
|
2491
|
+
userMsg("And what is 3+3?"),
|
|
2492
|
+
];
|
|
2493
|
+
|
|
2494
|
+
await provider.sendMessage(messages, sampleTools, "system");
|
|
2495
|
+
expect(lastStreamParams).toBeTruthy();
|
|
2496
|
+
|
|
2497
|
+
const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
|
|
2498
|
+
const assistantTurn = sent.find((m) => m.role === "assistant");
|
|
2499
|
+
expect(assistantTurn).toBeTruthy();
|
|
2500
|
+
|
|
2501
|
+
const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
|
|
2502
|
+
const thinkingBlocks = blocks.filter(
|
|
2503
|
+
(b) => typeof b !== "string" && b.type === "thinking",
|
|
2504
|
+
);
|
|
2505
|
+
expect(thinkingBlocks).toHaveLength(0);
|
|
2506
|
+
|
|
2507
|
+
const textBlocks = blocks.filter(
|
|
2508
|
+
(b) => typeof b !== "string" && b.type === "text",
|
|
2509
|
+
);
|
|
2510
|
+
expect(textBlocks).toHaveLength(1);
|
|
2511
|
+
});
|
|
2512
|
+
|
|
2513
|
+
test("strips redacted_thinking blocks from completed historical turns", async () => {
|
|
2514
|
+
const messages: Message[] = [
|
|
2515
|
+
userMsg("What is 2+2?"),
|
|
2516
|
+
assistantRedactedThinkingMsg("encrypted-data-xyz", "4"),
|
|
2517
|
+
userMsg("And what is 3+3?"),
|
|
2518
|
+
];
|
|
2519
|
+
|
|
2520
|
+
await provider.sendMessage(messages, sampleTools, "system");
|
|
2521
|
+
expect(lastStreamParams).toBeTruthy();
|
|
2522
|
+
|
|
2523
|
+
const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
|
|
2524
|
+
const assistantTurn = sent.find((m) => m.role === "assistant");
|
|
2525
|
+
expect(assistantTurn).toBeTruthy();
|
|
2526
|
+
|
|
2527
|
+
const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
|
|
2528
|
+
const redactedBlocks = blocks.filter(
|
|
2529
|
+
(b) => typeof b !== "string" && b.type === "redacted_thinking",
|
|
2530
|
+
);
|
|
2531
|
+
expect(redactedBlocks).toHaveLength(0);
|
|
2532
|
+
});
|
|
2533
|
+
|
|
2534
|
+
test("preserves thinking blocks in active tool-use continuation span", async () => {
|
|
2535
|
+
const messages: Message[] = [
|
|
2536
|
+
userMsg("Read the file"),
|
|
2537
|
+
assistantThinkingToolUseMsg(
|
|
2538
|
+
"I should read the file",
|
|
2539
|
+
"sig-valid-123",
|
|
2540
|
+
"tu-1",
|
|
2541
|
+
"file_read",
|
|
2542
|
+
),
|
|
2543
|
+
toolResultMsg("tu-1", "file contents here"),
|
|
2544
|
+
];
|
|
2545
|
+
|
|
2546
|
+
await provider.sendMessage(messages, sampleTools, "system");
|
|
2547
|
+
expect(lastStreamParams).toBeTruthy();
|
|
2548
|
+
|
|
2549
|
+
const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
|
|
2550
|
+
const assistantTurn = sent.find((m) => m.role === "assistant");
|
|
2551
|
+
expect(assistantTurn).toBeTruthy();
|
|
2552
|
+
|
|
2553
|
+
const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
|
|
2554
|
+
const thinkingBlocks = blocks.filter(
|
|
2555
|
+
(b) => typeof b !== "string" && b.type === "thinking",
|
|
2556
|
+
);
|
|
2557
|
+
expect(thinkingBlocks).toHaveLength(1);
|
|
2558
|
+
expect((thinkingBlocks[0] as { signature: string }).signature).toBe(
|
|
2559
|
+
"sig-valid-123",
|
|
2560
|
+
);
|
|
2561
|
+
});
|
|
2562
|
+
|
|
2563
|
+
test("strips historical thinking but preserves active continuation in same conversation", async () => {
|
|
2564
|
+
const messages: Message[] = [
|
|
2565
|
+
// Completed historical turn
|
|
2566
|
+
userMsg("What is 2+2?"),
|
|
2567
|
+
assistantThinkingMsg("old thinking", "sig-old-stale", "4"),
|
|
2568
|
+
// Active tool-use continuation
|
|
2569
|
+
userMsg("Now read the file"),
|
|
2570
|
+
assistantThinkingToolUseMsg(
|
|
2571
|
+
"current thinking",
|
|
2572
|
+
"sig-current-valid",
|
|
2573
|
+
"tu-2",
|
|
2574
|
+
"file_read",
|
|
2575
|
+
),
|
|
2576
|
+
toolResultMsg("tu-2", "file contents"),
|
|
2577
|
+
];
|
|
2578
|
+
|
|
2579
|
+
await provider.sendMessage(messages, sampleTools, "system");
|
|
2580
|
+
expect(lastStreamParams).toBeTruthy();
|
|
2581
|
+
|
|
2582
|
+
const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
|
|
2583
|
+
const assistantTurns = sent.filter((m) => m.role === "assistant");
|
|
2584
|
+
expect(assistantTurns.length).toBeGreaterThanOrEqual(2);
|
|
2585
|
+
|
|
2586
|
+
// Historical turn: thinking stripped
|
|
2587
|
+
const historicalBlocks = assistantTurns[0]
|
|
2588
|
+
.content as Anthropic.ContentBlockParam[];
|
|
2589
|
+
const historicalThinking = historicalBlocks.filter(
|
|
2590
|
+
(b) => typeof b !== "string" && b.type === "thinking",
|
|
2591
|
+
);
|
|
2592
|
+
expect(historicalThinking).toHaveLength(0);
|
|
2593
|
+
|
|
2594
|
+
// Active turn: thinking preserved
|
|
2595
|
+
const activeBlocks = assistantTurns[1]
|
|
2596
|
+
.content as Anthropic.ContentBlockParam[];
|
|
2597
|
+
const activeThinking = activeBlocks.filter(
|
|
2598
|
+
(b) => typeof b !== "string" && b.type === "thinking",
|
|
2599
|
+
);
|
|
2600
|
+
expect(activeThinking).toHaveLength(1);
|
|
2601
|
+
expect((activeThinking[0] as { signature: string }).signature).toBe(
|
|
2602
|
+
"sig-current-valid",
|
|
2603
|
+
);
|
|
2604
|
+
});
|
|
2605
|
+
|
|
2606
|
+
test("uses placeholder when stripping thinking leaves assistant message empty", async () => {
|
|
2607
|
+
const messages: Message[] = [
|
|
2608
|
+
userMsg("Think about this"),
|
|
2609
|
+
{
|
|
2610
|
+
role: "assistant",
|
|
2611
|
+
content: [{ type: "thinking", thinking: "hmm...", signature: "sig-x" }],
|
|
2612
|
+
},
|
|
2613
|
+
userMsg("What did you conclude?"),
|
|
2614
|
+
];
|
|
2615
|
+
|
|
2616
|
+
await provider.sendMessage(messages, sampleTools, "system");
|
|
2617
|
+
expect(lastStreamParams).toBeTruthy();
|
|
2618
|
+
|
|
2619
|
+
const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
|
|
2620
|
+
const assistantTurn = sent.find((m) => m.role === "assistant");
|
|
2621
|
+
expect(assistantTurn).toBeTruthy();
|
|
2622
|
+
|
|
2623
|
+
const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
|
|
2624
|
+
expect(blocks).toHaveLength(1);
|
|
2625
|
+
expect((blocks[0] as { type: string; text: string }).type).toBe("text");
|
|
2626
|
+
expect(
|
|
2627
|
+
isPlaceholderSentinelText((blocks[0] as { text: string }).text),
|
|
2628
|
+
).toBe(true);
|
|
2629
|
+
});
|
|
2630
|
+
|
|
2631
|
+
test("multi-step tool-use chain preserves all thinking in the active span", async () => {
|
|
2632
|
+
const messages: Message[] = [
|
|
2633
|
+
// Completed historical turn
|
|
2634
|
+
userMsg("Hello"),
|
|
2635
|
+
assistantThinkingMsg("old thinking", "sig-old", "Hi there"),
|
|
2636
|
+
// Multi-step active tool-use chain
|
|
2637
|
+
userMsg("Do two things"),
|
|
2638
|
+
assistantThinkingToolUseMsg(
|
|
2639
|
+
"step 1 thinking",
|
|
2640
|
+
"sig-step1",
|
|
2641
|
+
"tu-a",
|
|
2642
|
+
"file_read",
|
|
2643
|
+
),
|
|
2644
|
+
toolResultMsg("tu-a", "result a"),
|
|
2645
|
+
assistantThinkingToolUseMsg(
|
|
2646
|
+
"step 2 thinking",
|
|
2647
|
+
"sig-step2",
|
|
2648
|
+
"tu-b",
|
|
2649
|
+
"file_write",
|
|
2650
|
+
),
|
|
2651
|
+
toolResultMsg("tu-b", "result b"),
|
|
2652
|
+
];
|
|
2653
|
+
|
|
2654
|
+
await provider.sendMessage(messages, sampleTools, "system");
|
|
2655
|
+
expect(lastStreamParams).toBeTruthy();
|
|
2656
|
+
|
|
2657
|
+
const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
|
|
2658
|
+
|
|
2659
|
+
// Collect all thinking blocks across all assistant messages
|
|
2660
|
+
const allThinking: Anthropic.ContentBlockParam[] = [];
|
|
2661
|
+
for (const m of sent) {
|
|
2662
|
+
if (m.role !== "assistant") continue;
|
|
2663
|
+
const blocks = m.content as Anthropic.ContentBlockParam[];
|
|
2664
|
+
for (const b of blocks) {
|
|
2665
|
+
if (typeof b !== "string" && b.type === "thinking") {
|
|
2666
|
+
allThinking.push(b);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
// Only the active span's thinking blocks should remain
|
|
2672
|
+
const signatures = allThinking.map(
|
|
2673
|
+
(b) => (b as { signature: string }).signature,
|
|
2674
|
+
);
|
|
2675
|
+
expect(signatures).not.toContain("sig-old");
|
|
2676
|
+
expect(signatures).toContain("sig-step1");
|
|
2677
|
+
expect(signatures).toContain("sig-step2");
|
|
2678
|
+
});
|
|
2679
|
+
});
|
|
@@ -50,7 +50,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
|
|
|
50
50
|
|
|
51
51
|
mock.module("../providers/registry.js", () => ({
|
|
52
52
|
getProvider: () => ({ name: "mock-provider" }),
|
|
53
|
-
initializeProviders: () => {},
|
|
53
|
+
initializeProviders: async () => {},
|
|
54
54
|
}));
|
|
55
55
|
|
|
56
56
|
mock.module("../config/loader.js", () => ({
|
|
@@ -131,7 +131,6 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
131
131
|
getConversationSource: () => null,
|
|
132
132
|
getAssistantMessageIdsInTurn: () => [],
|
|
133
133
|
getDisplayMetaForConversations: () => new Map(),
|
|
134
|
-
getLastAssistantTimestampBefore: () => null,
|
|
135
134
|
getLastUserTimestampBefore: () => null,
|
|
136
135
|
getMessageById: () => null,
|
|
137
136
|
getMessages: () => [],
|
|
@@ -156,6 +155,8 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
156
155
|
updateConversationSlackContextWatermark: mock(() => {}),
|
|
157
156
|
updateConversationTitle: mock(() => {}),
|
|
158
157
|
updateConversationUsage: mock(() => {}),
|
|
158
|
+
setLastNotifiedInferenceProfile: mock(() => {}),
|
|
159
|
+
setConversationCleanedAt: mock(() => {}),
|
|
159
160
|
wipeConversation: mock(() => ({ memoryIds: [] })),
|
|
160
161
|
}));
|
|
161
162
|
|