@vellumai/assistant 0.7.2 → 0.7.3
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 +16 -1
- package/docs/architecture/memory.md +5 -2
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
- package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- package/openapi.yaml +449 -22
- package/package.json +1 -1
- package/src/__tests__/app-control-flow.test.ts +21 -11
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/assistant-event.test.ts +0 -10
- package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
- package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- package/src/__tests__/call-conversation-messages.test.ts +8 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +4 -2
- package/src/__tests__/config-loader-backfill.test.ts +379 -0
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
- package/src/__tests__/config-watcher.test.ts +140 -69
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +3 -7
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop.test.ts +454 -5
- package/src/__tests__/conversation-error.test.ts +150 -3
- package/src/__tests__/conversation-process-callsite.test.ts +43 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credentials-cli.test.ts +7 -0
- package/src/__tests__/cu-unified-flow.test.ts +176 -10
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +3 -4
- package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +260 -11
- package/src/__tests__/host-app-control-proxy.test.ts +195 -25
- package/src/__tests__/host-bash-proxy.test.ts +227 -34
- package/src/__tests__/host-bash-routes.test.ts +178 -13
- package/src/__tests__/host-cu-proxy.test.ts +210 -3
- package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
- package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
- package/src/__tests__/host-file-proxy.test.ts +268 -6
- package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
- package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
- package/src/__tests__/http-user-message-parity.test.ts +107 -1
- package/src/__tests__/injector-chain.test.ts +18 -6
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- package/src/__tests__/managed-profile-guard.test.ts +18 -0
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
- package/src/__tests__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/relay-server.test.ts +15 -4
- package/src/__tests__/runtime-events-sse.test.ts +4 -8
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -1
- package/src/__tests__/suggestion-routes.test.ts +46 -0
- package/src/__tests__/twilio-validation.test.ts +2 -2
- package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
- package/src/approvals/guardian-decision-primitive.ts +13 -0
- package/src/approvals/guardian-request-resolvers.ts +16 -17
- package/src/backup/snapshot-lock.ts +2 -27
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-conversation-messages.ts +46 -10
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/contacts.ts +64 -25
- package/src/cli/commands/credentials.ts +56 -0
- package/src/cli/commands/memory-v2.ts +7 -6
- package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
- package/src/cli/commands/oauth/connect.ts +127 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
- package/src/cli/commands/platform/index.ts +16 -7
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/program.ts +4 -2
- package/src/config/assistant-feature-flags.ts +13 -3
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- package/src/config/env.ts +0 -8
- package/src/config/feature-flag-registry.json +27 -3
- package/src/config/loader.ts +127 -8
- package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +13 -0
- package/src/config/schemas/memory-v2.ts +75 -11
- package/src/config/schemas/platform.ts +43 -3
- package/src/config/schemas/services.ts +28 -0
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -25
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/config-watcher.ts +85 -57
- package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
- package/src/daemon/conversation-agent-loop.ts +170 -33
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +1 -3
- package/src/daemon/conversation-process.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +26 -0
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +195 -15
- package/src/daemon/conversation-tool-setup.ts +57 -14
- package/src/daemon/conversation.ts +17 -22
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/handlers/shared.ts +0 -1
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +137 -41
- package/src/daemon/host-bash-proxy.ts +46 -21
- package/src/daemon/host-cu-proxy.ts +49 -3
- package/src/daemon/host-file-proxy.ts +43 -7
- package/src/daemon/host-transfer-proxy.ts +95 -4
- package/src/daemon/lifecycle.ts +79 -28
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +14 -4
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +4 -0
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/profiler-run-store.ts +5 -5
- package/src/daemon/tool-setup-types.ts +2 -2
- package/src/documents/document-store.ts +85 -0
- package/src/filing/filing-service.ts +30 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
- package/src/heartbeat/heartbeat-run-store.ts +13 -0
- package/src/heartbeat/heartbeat-service.ts +205 -31
- package/src/home/feed-scheduler.ts +18 -0
- package/src/inbound/platform-callback-registration.ts +8 -15
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/assistant-server.ts +56 -2
- package/src/ipc/gateway-client.ts +37 -3
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/protocol.ts +5 -7
- package/src/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
- package/src/memory/admin.ts +5 -9
- package/src/memory/context-search/agent-runner.ts +19 -2
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +5 -4
- package/src/memory/context-search/sources/memory.ts +0 -1
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +4 -12
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +32 -21
- package/src/memory/graph/conversation-graph-memory.ts +42 -54
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +10 -67
- package/src/memory/graph/graph-search.ts +1 -20
- package/src/memory/graph/retriever.test.ts +6 -0
- package/src/memory/graph/retriever.ts +6 -10
- package/src/memory/indexer.ts +54 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- package/src/memory/jobs-store.ts +48 -0
- package/src/memory/jobs-worker.ts +81 -43
- package/src/memory/memory-v2-activation-log-store.ts +32 -14
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -0
- package/src/memory/qdrant-client.ts +0 -13
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/search/semantic.ts +6 -67
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +311 -250
- package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
- package/src/memory/v2/__tests__/injection.test.ts +157 -167
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +5 -199
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/static-context.test.ts +76 -1
- package/src/memory/v2/activation.ts +149 -156
- package/src/memory/v2/consolidation-job.ts +62 -12
- package/src/memory/v2/injection.ts +47 -60
- package/src/memory/v2/prompts/consolidation.ts +36 -1
- package/src/memory/v2/qdrant.ts +99 -0
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +10 -84
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +82 -59
- package/src/memory/v2/static-context.ts +22 -0
- package/src/memory/v2/types.ts +10 -10
- package/src/notifications/copy-composer.ts +13 -0
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- package/src/plugins/defaults/injectors.ts +35 -2
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +867 -0
- package/src/proactive-artifact/job.ts +352 -0
- package/src/proactive-artifact/message-copy.ts +41 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +21 -7
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +36 -6
- package/src/runtime/assistant-event.ts +0 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/route-policy.ts +14 -1
- package/src/runtime/auth/same-actor.ts +216 -0
- package/src/runtime/channel-retry-sweep.ts +65 -1
- package/src/runtime/guardian-reply-router.ts +10 -0
- package/src/runtime/local-actor-identity.ts +52 -11
- package/src/runtime/pending-interactions.ts +8 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/client-routes.ts +20 -2
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-routes.ts +35 -26
- package/src/runtime/routes/debug-bash-routes.ts +163 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +6 -2
- package/src/runtime/routes/documents-routes.ts +2 -75
- package/src/runtime/routes/events-routes.ts +41 -9
- package/src/runtime/routes/host-bash-routes.ts +23 -3
- package/src/runtime/routes/host-cu-routes.ts +33 -6
- package/src/runtime/routes/host-file-routes.ts +32 -6
- package/src/runtime/routes/host-transfer-routes.ts +79 -16
- package/src/runtime/routes/identity-routes.ts +7 -138
- package/src/runtime/routes/inbound-message-handler.ts +77 -12
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/memory-item-routes.test.ts +41 -15
- package/src/runtime/routes/memory-v2-routes.ts +33 -0
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- package/src/schedule/run-script.ts +37 -5
- package/src/schedule/scheduler.ts +20 -1
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/secure-keys.ts +55 -0
- package/src/skills/remote-skill-policy.ts +4 -10
- package/src/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- package/src/tools/background-tool-registry.ts +17 -3
- package/src/tools/host-filesystem/edit.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +43 -1
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +43 -1
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +56 -11
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +43 -1
- package/src/tools/host-terminal/host-shell.ts +13 -6
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +12 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- package/src/tools/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +31 -6
- package/src/tools/types.ts +24 -2
- package/src/tts/provider-catalog.ts +3 -5
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/heartbeat-service.ts +19 -0
- package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -404
- package/src/signals/bash.ts +0 -198
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Seed a cheap, bounded default for the `heartbeatAgent` LLM call site.
|
|
8
|
+
*
|
|
9
|
+
* Heartbeats are default-on and now run frequently, so they should not inherit
|
|
10
|
+
* the workspace's active chat profile. The default managed profile is Sonnet
|
|
11
|
+
* with high effort and thinking enabled, which is appropriate for interactive
|
|
12
|
+
* chat but too expensive for a periodic background triage pass.
|
|
13
|
+
*
|
|
14
|
+
* Preserve user-owned model selection. If `heartbeatAgent` already has a
|
|
15
|
+
* `profile`, `provider`, or `model`, this migration leaves the entry unchanged
|
|
16
|
+
* so call-site leaves do not silently override the selected profile/model.
|
|
17
|
+
* Speed-only legacy entries from migration 038 are treated as defaultable.
|
|
18
|
+
*/
|
|
19
|
+
export const seedHeartbeatCallsiteCostDefaultMigration: WorkspaceMigration = {
|
|
20
|
+
id: "066-seed-heartbeat-callsite-cost-default",
|
|
21
|
+
description:
|
|
22
|
+
"Seed cost-optimized defaults for the heartbeatAgent LLM call site",
|
|
23
|
+
run(workspaceDir: string): void {
|
|
24
|
+
if (process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH) return;
|
|
25
|
+
|
|
26
|
+
const configPath = join(workspaceDir, "config.json");
|
|
27
|
+
const configExisted = existsSync(configPath);
|
|
28
|
+
|
|
29
|
+
let config: Record<string, unknown> = {};
|
|
30
|
+
if (configExisted) {
|
|
31
|
+
try {
|
|
32
|
+
const raw = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
33
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
|
|
34
|
+
config = raw as Record<string, unknown>;
|
|
35
|
+
} catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const llm = readObject(config.llm) ?? {};
|
|
41
|
+
const defaultBlock = readObject(llm.default);
|
|
42
|
+
const provider = readString(defaultBlock?.provider) ?? "anthropic";
|
|
43
|
+
const cheapModel = resolveCheapModel(provider);
|
|
44
|
+
if (cheapModel === undefined) return;
|
|
45
|
+
|
|
46
|
+
const callSites = readObject(llm.callSites) ?? {};
|
|
47
|
+
const existing = readObject(callSites.heartbeatAgent) ?? {};
|
|
48
|
+
if (hasExplicitModelSelection(existing)) return;
|
|
49
|
+
|
|
50
|
+
const seeded: Record<string, unknown> = { ...existing };
|
|
51
|
+
let changed = false;
|
|
52
|
+
|
|
53
|
+
const profiles = readObject(llm.profiles) ?? {};
|
|
54
|
+
const costProfile = readObject(profiles["cost-optimized"]);
|
|
55
|
+
if (readString(costProfile?.provider) === provider) {
|
|
56
|
+
seeded.profile = "cost-optimized";
|
|
57
|
+
} else {
|
|
58
|
+
seeded.provider = provider;
|
|
59
|
+
seeded.model = cheapModel;
|
|
60
|
+
}
|
|
61
|
+
changed = true;
|
|
62
|
+
|
|
63
|
+
changed = seedMissingLeaf(seeded, "maxTokens", 2048) || changed;
|
|
64
|
+
changed = seedMissingLeaf(seeded, "effort", "low") || changed;
|
|
65
|
+
changed = seedMissingLeaf(seeded, "temperature", 0) || changed;
|
|
66
|
+
|
|
67
|
+
const thinking = readObject(seeded.thinking) ?? {};
|
|
68
|
+
const seededThinking = { ...thinking };
|
|
69
|
+
const enabledChanged = seedMissingLeaf(seededThinking, "enabled", false);
|
|
70
|
+
const streamThinkingChanged = seedMissingLeaf(
|
|
71
|
+
seededThinking,
|
|
72
|
+
"streamThinking",
|
|
73
|
+
false,
|
|
74
|
+
);
|
|
75
|
+
const thinkingChanged = enabledChanged || streamThinkingChanged;
|
|
76
|
+
if (thinkingChanged || readObject(seeded.thinking) === null) {
|
|
77
|
+
seeded.thinking = seededThinking;
|
|
78
|
+
changed = true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const contextWindow = readObject(seeded.contextWindow) ?? {};
|
|
82
|
+
const seededContextWindow = { ...contextWindow };
|
|
83
|
+
const contextChanged = seedMissingLeaf(
|
|
84
|
+
seededContextWindow,
|
|
85
|
+
"maxInputTokens",
|
|
86
|
+
16_000,
|
|
87
|
+
);
|
|
88
|
+
if (contextChanged || readObject(seeded.contextWindow) === null) {
|
|
89
|
+
seeded.contextWindow = seededContextWindow;
|
|
90
|
+
changed = true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!changed) return;
|
|
94
|
+
|
|
95
|
+
callSites.heartbeatAgent = seeded;
|
|
96
|
+
llm.callSites = callSites;
|
|
97
|
+
config.llm = llm;
|
|
98
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
99
|
+
},
|
|
100
|
+
down(_workspaceDir: string): void {
|
|
101
|
+
// Forward-only: removing the seeded default would make frequent
|
|
102
|
+
// heartbeats inherit the user's potentially expensive chat profile again.
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Helpers — self-contained per workspace migrations AGENTS.md
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
const CHEAP_MODELS_BY_PROVIDER: Record<string, string> = {
|
|
111
|
+
anthropic: "claude-haiku-4-5-20251001",
|
|
112
|
+
openai: "gpt-5.4-nano",
|
|
113
|
+
gemini: "gemini-3-flash",
|
|
114
|
+
ollama: "llama3.2",
|
|
115
|
+
fireworks: "accounts/fireworks/models/kimi-k2p5",
|
|
116
|
+
openrouter: "anthropic/claude-haiku-4.5",
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
function resolveCheapModel(provider: string): string | undefined {
|
|
120
|
+
return CHEAP_MODELS_BY_PROVIDER[provider];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function hasExplicitModelSelection(value: Record<string, unknown>): boolean {
|
|
124
|
+
return "profile" in value || "provider" in value || "model" in value;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function seedMissingLeaf(
|
|
128
|
+
target: Record<string, unknown>,
|
|
129
|
+
key: string,
|
|
130
|
+
value: unknown,
|
|
131
|
+
): boolean {
|
|
132
|
+
if (key in target) return false;
|
|
133
|
+
target[key] = value;
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function readObject(value: unknown): Record<string, unknown> | null {
|
|
138
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
return value as Record<string, unknown>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function readString(value: unknown): string | undefined {
|
|
145
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
146
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendFileSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
writeFileSync,
|
|
6
|
+
} from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
import { getLogger } from "../../util/logger.js";
|
|
10
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
11
|
+
|
|
12
|
+
const log = getLogger(
|
|
13
|
+
"workspace-migration-067-release-notes-safe-storage-limits",
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const MIGRATION_ID = "067-release-notes-safe-storage-limits";
|
|
17
|
+
const MARKER = `<!-- release-note-id:${MIGRATION_ID} -->`;
|
|
18
|
+
|
|
19
|
+
const RELEASE_NOTE = `${MARKER}
|
|
20
|
+
## Safe storage limits
|
|
21
|
+
|
|
22
|
+
A new storage protection mode is available behind the safe-storage-limits
|
|
23
|
+
rollout flag. When enabled, the assistant watches workspace disk usage and
|
|
24
|
+
enters cleanup mode if the volume reaches the critical 95% threshold.
|
|
25
|
+
|
|
26
|
+
In cleanup mode, background processes pause and remote messages, including
|
|
27
|
+
trusted-contact messages, are blocked until the guardian frees enough space or
|
|
28
|
+
explicitly overrides the lock. The macOS app now shows a storage cleanup banner
|
|
29
|
+
that must be acknowledged before cleanup chat continues, then keeps a status
|
|
30
|
+
banner visible while cleanup mode is active.
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
export const releaseNotesSafeStorageLimitsMigration: WorkspaceMigration = {
|
|
34
|
+
id: MIGRATION_ID,
|
|
35
|
+
description: "Append release notes for safe storage limits to UPDATES.md",
|
|
36
|
+
|
|
37
|
+
run(workspaceDir: string): void {
|
|
38
|
+
const updatesPath = join(workspaceDir, "UPDATES.md");
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
if (existsSync(updatesPath)) {
|
|
42
|
+
const existing = readFileSync(updatesPath, "utf-8");
|
|
43
|
+
if (existing.includes(MARKER)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const needsLeadingNewline = !existing.endsWith("\n\n");
|
|
47
|
+
const prefix = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
48
|
+
appendFileSync(
|
|
49
|
+
updatesPath,
|
|
50
|
+
needsLeadingNewline ? `${prefix}${RELEASE_NOTE}` : RELEASE_NOTE,
|
|
51
|
+
"utf-8",
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
writeFileSync(updatesPath, RELEASE_NOTE, "utf-8");
|
|
55
|
+
}
|
|
56
|
+
log.info(
|
|
57
|
+
{ path: updatesPath },
|
|
58
|
+
"Appended safe storage limits release note",
|
|
59
|
+
);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
log.warn(
|
|
62
|
+
{ err, path: updatesPath },
|
|
63
|
+
"Failed to append safe storage limits release note to UPDATES.md",
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
down(_workspaceDir: string): void {
|
|
69
|
+
// Forward-only: UPDATES.md is a user-facing bulletin the assistant
|
|
70
|
+
// processes and deletes on its own.
|
|
71
|
+
},
|
|
72
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendFileSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
writeFileSync,
|
|
6
|
+
} from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
import { getLogger } from "../../util/logger.js";
|
|
10
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
11
|
+
|
|
12
|
+
const log = getLogger("workspace-migration-068-release-notes-local-timezone");
|
|
13
|
+
|
|
14
|
+
const MIGRATION_ID = "068-release-notes-local-timezone";
|
|
15
|
+
const MARKER = `<!-- release-note-id:${MIGRATION_ID} -->`;
|
|
16
|
+
|
|
17
|
+
const RELEASE_NOTE = `${MARKER}
|
|
18
|
+
## Local timezone grounding
|
|
19
|
+
|
|
20
|
+
The assistant now grounds \`current_time\` in your local timezone across clients,
|
|
21
|
+
instead of falling back to UTC when the client can report the device timezone.
|
|
22
|
+
|
|
23
|
+
Manual timezone overrides still win when configured, and the assistant can help
|
|
24
|
+
update a stale override after you confirm that your device timezone should be
|
|
25
|
+
used going forward.
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
export const releaseNotesLocalTimezoneMigration: WorkspaceMigration = {
|
|
29
|
+
id: MIGRATION_ID,
|
|
30
|
+
description:
|
|
31
|
+
"Append release notes for local timezone grounding to UPDATES.md",
|
|
32
|
+
|
|
33
|
+
run(workspaceDir: string): void {
|
|
34
|
+
const updatesPath = join(workspaceDir, "UPDATES.md");
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
if (existsSync(updatesPath)) {
|
|
38
|
+
const existing = readFileSync(updatesPath, "utf-8");
|
|
39
|
+
if (existing.includes(MARKER)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const needsLeadingNewline = !existing.endsWith("\n\n");
|
|
43
|
+
const prefix = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
44
|
+
appendFileSync(
|
|
45
|
+
updatesPath,
|
|
46
|
+
needsLeadingNewline ? `${prefix}${RELEASE_NOTE}` : RELEASE_NOTE,
|
|
47
|
+
"utf-8",
|
|
48
|
+
);
|
|
49
|
+
} else {
|
|
50
|
+
writeFileSync(updatesPath, RELEASE_NOTE, "utf-8");
|
|
51
|
+
}
|
|
52
|
+
log.info({ path: updatesPath }, "Appended local timezone release note");
|
|
53
|
+
} catch (err) {
|
|
54
|
+
log.warn(
|
|
55
|
+
{ err, path: updatesPath },
|
|
56
|
+
"Failed to append local timezone release note to UPDATES.md",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
down(_workspaceDir: string): void {
|
|
62
|
+
// Forward-only: UPDATES.md is a user-facing bulletin the assistant
|
|
63
|
+
// processes and deletes on its own.
|
|
64
|
+
},
|
|
65
|
+
};
|
|
@@ -62,6 +62,10 @@ import { moveBackupKeyToWorkspaceMigration } from "./061-move-backup-key-to-work
|
|
|
62
62
|
import { dropMemoryV2EdgesJsonMigration } from "./062-drop-memory-v2-edges-json.js";
|
|
63
63
|
import { releaseNotesDynamicModelContextMigration } from "./063-release-notes-dynamic-model-context.js";
|
|
64
64
|
import { unwindMainAgentOpusSeedMigration } from "./064-unwind-main-agent-opus-seed.js";
|
|
65
|
+
import { bumpStaleHeartbeatIntervalMigration } from "./065-bump-stale-heartbeat-interval.js";
|
|
66
|
+
import { seedHeartbeatCallsiteCostDefaultMigration } from "./066-seed-heartbeat-callsite-cost-default.js";
|
|
67
|
+
import { releaseNotesSafeStorageLimitsMigration } from "./067-release-notes-safe-storage-limits.js";
|
|
68
|
+
import { releaseNotesLocalTimezoneMigration } from "./068-release-notes-local-timezone.js";
|
|
65
69
|
import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
|
|
66
70
|
import type { WorkspaceMigration } from "./types.js";
|
|
67
71
|
|
|
@@ -135,4 +139,8 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
|
|
|
135
139
|
dropMemoryV2EdgesJsonMigration,
|
|
136
140
|
releaseNotesDynamicModelContextMigration,
|
|
137
141
|
unwindMainAgentOpusSeedMigration,
|
|
142
|
+
bumpStaleHeartbeatIntervalMigration,
|
|
143
|
+
seedHeartbeatCallsiteCostDefaultMigration,
|
|
144
|
+
releaseNotesSafeStorageLimitsMigration,
|
|
145
|
+
releaseNotesLocalTimezoneMigration,
|
|
138
146
|
];
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests that createToolExecutor propagates memoryScopeId from the session's
|
|
3
|
-
* memory policy into the ToolContext passed to the underlying executor.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, expect, mock, test } from "bun:test";
|
|
7
|
-
|
|
8
|
-
import type { ToolSetupContext } from "../daemon/conversation-tool-setup.js";
|
|
9
|
-
import type { SurfaceData, SurfaceType } from "../daemon/message-protocol.js";
|
|
10
|
-
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
11
|
-
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
12
|
-
import type { ToolExecutor } from "../tools/executor.js";
|
|
13
|
-
import type { ToolContext, ToolExecutionResult } from "../tools/types.js";
|
|
14
|
-
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
// Mocks — must be set up before importing the module under test
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
mock.module("../daemon/conversation-surfaces.js", () => ({
|
|
20
|
-
refreshSurfacesForApp: mock(() => {}),
|
|
21
|
-
surfaceProxyResolver: mock(() =>
|
|
22
|
-
Promise.resolve({ content: "", isError: false }),
|
|
23
|
-
),
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
mock.module("../services/published-app-updater.js", () => ({
|
|
27
|
-
updatePublishedAppDeployment: mock(() => Promise.resolve()),
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
mock.module("../tools/browser/browser-screencast.js", () => ({
|
|
31
|
-
registerConversationSender: mock(() => {}),
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
// Import after mocks
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
|
|
38
|
-
import { createToolExecutor } from "../daemon/conversation-tool-setup.js";
|
|
39
|
-
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
// Helpers
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
|
|
44
|
-
function makeCtx(overrides: Partial<ToolSetupContext> = {}): ToolSetupContext {
|
|
45
|
-
return {
|
|
46
|
-
conversationId: "conv-scope",
|
|
47
|
-
currentRequestId: "req-1",
|
|
48
|
-
workingDir: "/tmp/test",
|
|
49
|
-
abortController: null,
|
|
50
|
-
traceEmitter: { emit: () => {} },
|
|
51
|
-
sendToClient: mock(() => {}),
|
|
52
|
-
pendingSurfaceActions: new Map(),
|
|
53
|
-
lastSurfaceAction: new Map(),
|
|
54
|
-
surfaceState: new Map<
|
|
55
|
-
string,
|
|
56
|
-
{ surfaceType: SurfaceType; data: SurfaceData; title?: string }
|
|
57
|
-
>(),
|
|
58
|
-
surfaceUndoStacks: new Map(),
|
|
59
|
-
accumulatedSurfaceState: new Map(),
|
|
60
|
-
surfaceActionRequestIds: new Set<string>(),
|
|
61
|
-
currentTurnSurfaces: [],
|
|
62
|
-
isProcessing: () => false,
|
|
63
|
-
enqueueMessage: () => ({ queued: false, requestId: "r" }),
|
|
64
|
-
getQueueDepth: () => 0,
|
|
65
|
-
processMessage: async () => "",
|
|
66
|
-
withSurface: async <T>(_id: string, fn: () => T | Promise<T>) => fn(),
|
|
67
|
-
memoryPolicy: { scopeId: "default" },
|
|
68
|
-
...overrides,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** Executor spy that captures the ToolContext passed to execute(). */
|
|
73
|
-
function makeCapturingExecutor(
|
|
74
|
-
result: ToolExecutionResult = { content: "ok", isError: false },
|
|
75
|
-
) {
|
|
76
|
-
let captured: ToolContext | undefined;
|
|
77
|
-
return {
|
|
78
|
-
executor: {
|
|
79
|
-
execute: mock(
|
|
80
|
-
async (
|
|
81
|
-
_name: string,
|
|
82
|
-
_input: Record<string, unknown>,
|
|
83
|
-
ctx: ToolContext,
|
|
84
|
-
) => {
|
|
85
|
-
captured = ctx;
|
|
86
|
-
return result;
|
|
87
|
-
},
|
|
88
|
-
),
|
|
89
|
-
},
|
|
90
|
-
getCaptured: () => captured,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const noopPrompter = {
|
|
95
|
-
prompt: mock(async () => ({ decision: "allow" as const })),
|
|
96
|
-
} as unknown as PermissionPrompter;
|
|
97
|
-
const noopSecretPrompter = {
|
|
98
|
-
prompt: mock(async () => ({ cancelled: true })),
|
|
99
|
-
} as unknown as SecretPrompter;
|
|
100
|
-
const noopLifecycleHandler = mock(() => {});
|
|
101
|
-
|
|
102
|
-
// ---------------------------------------------------------------------------
|
|
103
|
-
// Tests
|
|
104
|
-
// ---------------------------------------------------------------------------
|
|
105
|
-
|
|
106
|
-
describe("session-tool-setup memoryScopeId propagation", () => {
|
|
107
|
-
test("passes default memoryScopeId to executor context", async () => {
|
|
108
|
-
const ctx = makeCtx({
|
|
109
|
-
memoryPolicy: { scopeId: "default" },
|
|
110
|
-
});
|
|
111
|
-
const { executor, getCaptured } = makeCapturingExecutor();
|
|
112
|
-
|
|
113
|
-
const toolFn = createToolExecutor(
|
|
114
|
-
executor as unknown as ToolExecutor,
|
|
115
|
-
noopPrompter,
|
|
116
|
-
noopSecretPrompter,
|
|
117
|
-
ctx,
|
|
118
|
-
noopLifecycleHandler,
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
await toolFn("some_tool", { key: "value" });
|
|
122
|
-
|
|
123
|
-
expect(getCaptured()).toBeDefined();
|
|
124
|
-
expect(getCaptured()!.memoryScopeId).toBe("default");
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test("passes custom memoryScopeId from session memory policy", async () => {
|
|
128
|
-
const ctx = makeCtx({
|
|
129
|
-
memoryPolicy: { scopeId: "custom-scope-abc" },
|
|
130
|
-
});
|
|
131
|
-
const { executor, getCaptured } = makeCapturingExecutor();
|
|
132
|
-
|
|
133
|
-
const toolFn = createToolExecutor(
|
|
134
|
-
executor as unknown as ToolExecutor,
|
|
135
|
-
noopPrompter,
|
|
136
|
-
noopSecretPrompter,
|
|
137
|
-
ctx,
|
|
138
|
-
noopLifecycleHandler,
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
await toolFn("memory_write", { content: "test" });
|
|
142
|
-
|
|
143
|
-
expect(getCaptured()!.memoryScopeId).toBe("custom-scope-abc");
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test("reads memoryScopeId at call time, not construction time", async () => {
|
|
147
|
-
const ctx = makeCtx({
|
|
148
|
-
memoryPolicy: { scopeId: "initial" },
|
|
149
|
-
});
|
|
150
|
-
const { executor, getCaptured } = makeCapturingExecutor();
|
|
151
|
-
|
|
152
|
-
const toolFn = createToolExecutor(
|
|
153
|
-
executor as unknown as ToolExecutor,
|
|
154
|
-
noopPrompter,
|
|
155
|
-
noopSecretPrompter,
|
|
156
|
-
ctx,
|
|
157
|
-
noopLifecycleHandler,
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
// Mutate the memory policy after construction
|
|
161
|
-
ctx.memoryPolicy = { scopeId: "updated-scope" };
|
|
162
|
-
|
|
163
|
-
await toolFn("some_tool", {});
|
|
164
|
-
|
|
165
|
-
expect(getCaptured()!.memoryScopeId).toBe("updated-scope");
|
|
166
|
-
});
|
|
167
|
-
});
|