@vellumai/assistant 0.8.10 → 0.8.11-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +62 -1
- package/docs/workspace-tools.md +196 -0
- package/examples/plugins/echo/README.md +3 -3
- package/knip.json +1 -0
- package/openapi.yaml +460 -128
- package/package.json +2 -1
- package/scripts/build-plugin-api.ts +299 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
- package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
- package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
- package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
- package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
- package/src/__tests__/agent-loop-thinking.test.ts +4 -0
- package/src/__tests__/agent-loop.test.ts +578 -5
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -1
- package/src/__tests__/build-persisted-content.test.ts +75 -1
- package/src/__tests__/catalog-install-normalize.test.ts +141 -0
- package/src/__tests__/ces-startup-timeout.test.ts +60 -0
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
- package/src/__tests__/context-overflow-reducer.test.ts +264 -124
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
- package/src/__tests__/conversation-agent-loop.test.ts +131 -551
- package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-fork-crud.test.ts +259 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +257 -1
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
- package/src/__tests__/conversation-queue.test.ts +1 -39
- package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
- package/src/__tests__/conversation-skill-tools.test.ts +491 -5
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-store.test.ts +74 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
- package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
- package/src/__tests__/credential-execution-tools.test.ts +23 -11
- package/src/__tests__/credential-security-invariants.test.ts +6 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
- package/src/__tests__/device-id.test.ts +70 -1
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
- package/src/__tests__/empty-response-hook.test.ts +242 -66
- package/src/__tests__/external-plugin-loader.test.ts +0 -31
- package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
- package/src/__tests__/history-repair-hook.test.ts +228 -3
- package/src/__tests__/host-app-control-proxy.test.ts +45 -0
- package/src/__tests__/host-browser-proxy.test.ts +254 -9
- package/src/__tests__/identity-routes.test.ts +1 -0
- package/src/__tests__/image-recovery-hook.test.ts +387 -0
- package/src/__tests__/injector-chain.test.ts +5 -4
- package/src/__tests__/injector-v3-suppression.test.ts +373 -47
- package/src/__tests__/intent-routing.test.ts +7 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/oauth-store.test.ts +0 -85
- package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
- package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
- package/src/__tests__/persist-unsendable-image.test.ts +4 -4
- package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
- package/src/__tests__/plugin-bootstrap.test.ts +82 -73
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -8
- package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
- package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
- package/src/__tests__/registry.test.ts +240 -1
- package/src/__tests__/require-fresh-approval.test.ts +3 -0
- package/src/__tests__/schedule-routes.test.ts +116 -1
- package/src/__tests__/schedule-store.test.ts +28 -0
- package/src/__tests__/schedule-tools.test.ts +94 -1
- package/src/__tests__/server-history-render.test.ts +39 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
- package/src/__tests__/skills.test.ts +202 -0
- package/src/__tests__/slim-skill-category.test.ts +195 -0
- package/src/__tests__/strip-memory-injections.test.ts +33 -39
- package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
- package/src/__tests__/title-generate-hook.test.ts +9 -7
- package/src/__tests__/tool-audit-listener.test.ts +264 -1
- package/src/__tests__/tool-error-hook.test.ts +4 -3
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +218 -0
- package/src/__tests__/tools-get-route.test.ts +202 -0
- package/src/__tests__/workspace-tool-loader.test.ts +319 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +569 -319
- package/src/api/events/tool-result.ts +9 -0
- package/src/api/events/tool-use-start.ts +7 -0
- package/src/api/index.ts +10 -0
- package/src/api/responses/conversation-message.ts +135 -27
- package/src/api/responses/memory-v3-selection-log.ts +4 -4
- package/src/approvals/guardian-request-resolvers.ts +26 -0
- package/src/browser-session/backends/host-bridge.ts +29 -0
- package/src/browser-session/index.ts +1 -0
- package/src/browser-session/types.ts +5 -1
- package/src/cli/commands/__tests__/schedules.test.ts +62 -4
- package/src/cli/commands/__tests__/skills.test.ts +53 -0
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/inference-providers.ts +0 -8
- package/src/cli/commands/plugins.ts +2 -2
- package/src/cli/commands/schedules.ts +27 -4
- package/src/cli/commands/skills.ts +187 -146
- package/src/cli/commands/tools.ts +106 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
- package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
- package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
- package/src/cli/lib/install-from-github.ts +187 -117
- package/src/cli/lib/plugin-catalog-cache.ts +9 -9
- package/src/cli/lib/plugin-details.ts +38 -68
- package/src/cli/lib/plugin-marketplace.ts +42 -14
- package/src/cli/lib/search-plugins.ts +29 -129
- package/src/cli/program.ts +2 -0
- package/src/config/bundled-skills/acp/SKILL.md +1 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
- package/src/config/bundled-skills/app-control/SKILL.md +1 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
- package/src/config/bundled-skills/contacts/SKILL.md +1 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
- package/src/config/bundled-skills/followups/SKILL.md +1 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
- package/src/config/bundled-skills/messaging/SKILL.md +1 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
- package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
- package/src/config/bundled-skills/sequences/SKILL.md +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +1 -0
- package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
- package/src/config/bundled-skills/subagent/SKILL.md +1 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
- package/src/config/env-registry.ts +23 -0
- package/src/config/feature-flag-registry.json +17 -81
- package/src/config/loader.ts +5 -22
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
- package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
- package/src/config/schemas/compaction-logs.ts +79 -0
- package/src/config/schemas/memory-v2.ts +0 -8
- package/src/config/schemas/memory-v3.ts +104 -33
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/config/skills.ts +117 -47
- package/src/context/compactor.ts +11 -0
- package/src/context/strip-injections.ts +38 -4
- package/src/credential-execution/feature-gates.ts +0 -21
- package/src/credential-execution/startup-timeout.ts +32 -4
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
- package/src/daemon/conversation-agent-loop.ts +123 -658
- package/src/daemon/conversation-error.ts +6 -33
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-runtime-assembly.ts +183 -22
- package/src/daemon/conversation-skill-tools.ts +137 -8
- package/src/daemon/conversation-slash.ts +0 -14
- package/src/daemon/conversation-store.ts +2 -19
- package/src/daemon/conversation-tool-setup.ts +87 -1
- package/src/daemon/conversation.ts +119 -50
- package/src/daemon/external-plugins-bootstrap.ts +36 -95
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/shared.ts +9 -1
- package/src/daemon/handlers/skills.ts +10 -4
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-browser-proxy.ts +117 -22
- package/src/daemon/lifecycle.ts +34 -5
- package/src/daemon/message-protocol.ts +0 -7
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/skills.ts +17 -0
- package/src/daemon/providers-setup.ts +3 -0
- package/src/daemon/server.ts +3 -3
- package/src/daemon/tool-setup-types.ts +9 -3
- package/src/daemon/trust-context.ts +23 -0
- package/src/daemon/workspace-tools-watcher.ts +324 -0
- package/src/events/tool-audit-listener.ts +78 -16
- package/src/events/tool-metrics-listener.ts +2 -5
- package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
- package/src/memory/__tests__/conversation-queries.test.ts +176 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
- package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
- package/src/memory/conversation-crud.ts +134 -3
- package/src/memory/conversation-queries.ts +64 -7
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.test.ts +130 -1
- package/src/memory/embedding-backend.ts +79 -106
- package/src/memory/embedding-gemini.ts +5 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
- package/src/memory/graph/conversation-graph-memory.ts +36 -25
- package/src/memory/graph/tool-handlers.ts +3 -0
- package/src/memory/job-handlers/cleanup.ts +3 -1
- package/src/memory/jobs-store.ts +0 -28
- package/src/memory/jobs-worker.ts +10 -22
- package/src/memory/memory-marker.ts +29 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
- package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
- package/src/memory/migrations/270-schedule-description.ts +36 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
- package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
- package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
- package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
- package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
- package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +16 -0
- package/src/memory/schema/infrastructure.ts +26 -0
- package/src/memory/skill-loaded-events-store.test.ts +160 -0
- package/src/memory/skill-loaded-events-store.ts +95 -0
- package/src/memory/tool-executed-events-store.test.ts +219 -0
- package/src/memory/tool-executed-events-store.ts +102 -0
- package/src/memory/tool-usage-store.ts +15 -3
- package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
- package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
- package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
- package/src/memory/v2/__tests__/page-store.test.ts +33 -0
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
- package/src/memory/v2/activation-store.ts +50 -1
- package/src/memory/v2/consolidation-job.ts +113 -29
- package/src/memory/v2/injected-block-slugs.ts +79 -0
- package/src/memory/v2/injection.ts +6 -1
- package/src/memory/v2/prompts/consolidation.ts +414 -13
- package/src/memory/v2/router.ts +2 -28
- package/src/memory/v2/static-context.ts +1 -1
- package/src/memory/v2/types.ts +16 -0
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +2 -1
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/oauth/oauth-store.ts +0 -9
- package/src/permissions/checker.test.ts +83 -1
- package/src/permissions/checker.ts +25 -2
- package/src/permissions/gateway-threshold-reader.test.ts +182 -0
- package/src/permissions/gateway-threshold-reader.ts +80 -0
- package/src/platform/client.ts +1 -3
- package/src/platform/feature-gate.ts +3 -12
- package/src/plugin-api/constants.ts +4 -2
- package/src/plugin-api/index.ts +63 -11
- package/src/plugin-api/types.ts +236 -71
- package/src/plugins/defaults/compaction/compact.ts +66 -2
- package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
- package/src/plugins/defaults/compaction/window-manager.ts +303 -1
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
- package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
- package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
- package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
- package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
- package/src/plugins/defaults/history-repair/terminal.ts +39 -2
- package/src/plugins/defaults/image-recovery/detect.ts +25 -0
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
- package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
- package/src/plugins/defaults/image-recovery/package.json +14 -0
- package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
- package/src/plugins/defaults/index.ts +71 -5
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
- package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
- package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
- package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
- package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
- package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
- package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
- package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
- package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
- package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
- package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
- package/src/plugins/pipeline.ts +8 -5
- package/src/plugins/types.ts +5 -51
- package/src/providers/cache-control.ts +26 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
- package/src/providers/model-catalog.ts +13 -1
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
- package/src/providers/openai/chat-completions-provider.ts +46 -0
- package/src/providers/openai/responses-provider.ts +45 -0
- package/src/providers/registry.ts +0 -8
- package/src/runtime/__tests__/agent-wake.test.ts +0 -1
- package/src/runtime/agent-wake.ts +13 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
- package/src/runtime/routes/acp-routes.test.ts +106 -0
- package/src/runtime/routes/acp-routes.ts +248 -2
- package/src/runtime/routes/browser-tabs-routes.ts +1 -1
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
- package/src/runtime/routes/consolidation-routes.ts +6 -82
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +71 -0
- package/src/runtime/routes/identity-routes.ts +8 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
- package/src/runtime/routes/plugins-routes.ts +34 -45
- package/src/runtime/routes/schedule-routes.ts +43 -5
- package/src/runtime/routes/settings-routes.ts +140 -15
- package/src/runtime/routes/skills-routes.ts +18 -6
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
- package/src/runtime/services/conversation-serializer.ts +38 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/schedule/schedule-store.ts +19 -0
- package/src/skills/catalog-install.ts +77 -13
- package/src/tasks/task-scheduler.ts +1 -0
- package/src/telemetry/types.ts +66 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
- package/src/telemetry/usage-telemetry-reporter.ts +213 -20
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
- package/src/tools/browser/browser-execution.ts +27 -9
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
- package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
- package/src/tools/browser/cdp-client/factory.ts +217 -17
- package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
- package/src/tools/browser/cdp-client/types.ts +22 -2
- package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
- package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
- package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
- package/src/tools/executor.ts +39 -7
- package/src/tools/registry.ts +387 -5
- package/src/tools/schedule/create.ts +16 -0
- package/src/tools/schedule/list.ts +12 -4
- package/src/tools/schedule/update.ts +12 -0
- package/src/tools/skills/load.ts +11 -6
- package/src/tools/terminal/safe-env.ts +2 -0
- package/src/tools/types.ts +65 -9
- package/src/tools/workspace-tools/loader.ts +673 -0
- package/src/usage/attribution.ts +28 -0
- package/src/util/device-id.ts +17 -3
- package/src/util/platform.ts +16 -0
- package/tsconfig.plugin-api.json +13 -0
- package/src/__tests__/plugin-external-api.test.ts +0 -68
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
- package/src/daemon/message-types/browser.ts +0 -10
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
- package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
- package/src/plugins/external-api.ts +0 -114
- package/src/plugins/plugin-skill-contributions.ts +0 -292
|
@@ -10,13 +10,12 @@
|
|
|
10
10
|
* creation/reuse lifecycle — provider wiring, rate limiting, system
|
|
11
11
|
* prompt assembly, and DB hydration. DaemonServer calls
|
|
12
12
|
* {@link initConversationLifecycle} once at construction time to
|
|
13
|
-
* supply the few remaining lifecycle references (evictor,
|
|
14
|
-
*
|
|
13
|
+
* supply the few remaining lifecycle references (evictor, shared
|
|
14
|
+
* rate-limit timestamps, broadcast).
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
18
18
|
import { getConfig } from "../config/loader.js";
|
|
19
|
-
import type { CesClient } from "../credential-execution/client.js";
|
|
20
19
|
import { buildSystemPrompt } from "../prompts/system-prompt.js";
|
|
21
20
|
import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
|
|
22
21
|
import { resolveDefaultProvider } from "../providers/connection-resolution.js";
|
|
@@ -68,7 +67,6 @@ const conversationCreating = new Map<string, Promise<Conversation>>();
|
|
|
68
67
|
|
|
69
68
|
/** Lifecycle refs injected once by DaemonServer at construction. */
|
|
70
69
|
let _evictor: ConversationEvictor | null = null;
|
|
71
|
-
let _cesClientPromise: Promise<CesClient | undefined> | undefined;
|
|
72
70
|
let _sharedRequestTimestamps: number[] = [];
|
|
73
71
|
|
|
74
72
|
/**
|
|
@@ -77,23 +75,12 @@ let _sharedRequestTimestamps: number[] = [];
|
|
|
77
75
|
*/
|
|
78
76
|
export function initConversationLifecycle(refs: {
|
|
79
77
|
evictor: ConversationEvictor;
|
|
80
|
-
cesClientPromise?: Promise<CesClient | undefined>;
|
|
81
78
|
sharedRequestTimestamps: number[];
|
|
82
79
|
}): void {
|
|
83
80
|
_evictor = refs.evictor;
|
|
84
|
-
_cesClientPromise = refs.cesClientPromise;
|
|
85
81
|
_sharedRequestTimestamps = refs.sharedRequestTimestamps;
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
/**
|
|
89
|
-
* Update the CES client promise after async initialization completes.
|
|
90
|
-
*/
|
|
91
|
-
export function setCesClientPromise(
|
|
92
|
-
p: Promise<CesClient | undefined> | undefined,
|
|
93
|
-
): void {
|
|
94
|
-
_cesClientPromise = p;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
84
|
function applyTransportMetadata(
|
|
98
85
|
conversation: Conversation,
|
|
99
86
|
options: ConversationCreateOptions | undefined,
|
|
@@ -177,9 +164,6 @@ export async function getOrCreateConversation(
|
|
|
177
164
|
storedOptions?.systemPromptOverride ?? buildSystemPrompt();
|
|
178
165
|
const maxTokens = storedOptions?.maxResponseTokens;
|
|
179
166
|
|
|
180
|
-
const sharedCesClient = _cesClientPromise
|
|
181
|
-
? await _cesClientPromise
|
|
182
|
-
: undefined;
|
|
183
167
|
const newConversation = new Conversation(
|
|
184
168
|
conversationId,
|
|
185
169
|
provider,
|
|
@@ -188,7 +172,6 @@ export async function getOrCreateConversation(
|
|
|
188
172
|
workingDir,
|
|
189
173
|
{
|
|
190
174
|
maxTokens,
|
|
191
|
-
sharedCesClient,
|
|
192
175
|
speedOverride: storedOptions?.speed,
|
|
193
176
|
modelOverride: storedOptions?.modelOverride,
|
|
194
177
|
},
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from "../channels/types.js";
|
|
14
14
|
import { getIsPlatform } from "../config/env-registry.js";
|
|
15
15
|
import { getConfig } from "../config/loader.js";
|
|
16
|
+
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
16
17
|
import { getBindingByConversation } from "../memory/external-conversation-store.js";
|
|
17
18
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
18
19
|
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
@@ -34,6 +35,10 @@ import {
|
|
|
34
35
|
type ToolExecutionResult,
|
|
35
36
|
type ToolLifecycleEventHandler,
|
|
36
37
|
} from "../tools/types.js";
|
|
38
|
+
import {
|
|
39
|
+
resolveUsageAttribution,
|
|
40
|
+
type UsageAttributionSnapshot,
|
|
41
|
+
} from "../usage/attribution.js";
|
|
37
42
|
import { getLogger } from "../util/logger.js";
|
|
38
43
|
import {
|
|
39
44
|
projectSkillTools,
|
|
@@ -59,6 +64,45 @@ import {
|
|
|
59
64
|
import type { ToolSetupContext } from "./tool-setup-types.js";
|
|
60
65
|
export type { ToolSetupContext } from "./tool-setup-types.js";
|
|
61
66
|
|
|
67
|
+
// ── resolveConversationAttribution ───────────────────────────────────
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolve the model attribution snapshot for the conversation at invocation
|
|
71
|
+
* time (provider/model/profile that issued the current turn). Mirrors how
|
|
72
|
+
* the agent-loop usage path builds its `UsageAttributionInput` — the
|
|
73
|
+
* current turn's call site (`runAgentLoopImpl` sets `ctx.currentCallSite`
|
|
74
|
+
* from `options.callSite`, defaulting to `mainAgent`) plus the
|
|
75
|
+
* conversation's per-turn override profile — so `profileSource` resolves
|
|
76
|
+
* to `call_site`/`conversation`/`active`/`default` exactly as `llm_usage`
|
|
77
|
+
* records do for the same turn (non-main turns like voice `callAgent` or
|
|
78
|
+
* `filingAgent` attribute their own call-site config, not the main
|
|
79
|
+
* agent's). The conversation id is threaded as the mix selection seed so
|
|
80
|
+
* mix-profile arms match what the dispatch path actually ran.
|
|
81
|
+
*
|
|
82
|
+
* Returns `null` on any failure: attribution is telemetry-only and must
|
|
83
|
+
* never break tool execution (or skill loads, which reuse this helper).
|
|
84
|
+
*/
|
|
85
|
+
export function resolveConversationAttribution(
|
|
86
|
+
ctx: Pick<
|
|
87
|
+
ToolSetupContext,
|
|
88
|
+
"conversationId" | "currentCallSite" | "currentTurnOverrideProfile"
|
|
89
|
+
>,
|
|
90
|
+
): UsageAttributionSnapshot | null {
|
|
91
|
+
try {
|
|
92
|
+
return resolveUsageAttribution({
|
|
93
|
+
callSite: ctx.currentCallSite ?? "mainAgent",
|
|
94
|
+
overrideProfile: ctx.currentTurnOverrideProfile ?? null,
|
|
95
|
+
selectionSeed: ctx.conversationId,
|
|
96
|
+
});
|
|
97
|
+
} catch (err) {
|
|
98
|
+
log.debug(
|
|
99
|
+
{ err, conversationId: ctx.conversationId },
|
|
100
|
+
"Failed to resolve conversation attribution for telemetry (non-fatal)",
|
|
101
|
+
);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
62
106
|
// ── createToolExecutor ───────────────────────────────────────────────
|
|
63
107
|
|
|
64
108
|
/**
|
|
@@ -128,9 +172,9 @@ export function createToolExecutor(
|
|
|
128
172
|
diskPressureCleanupModeActive: ctx.diskPressureCleanupModeActive,
|
|
129
173
|
toolUseId,
|
|
130
174
|
isPlatformHosted: getIsPlatform(),
|
|
131
|
-
cesClient: ctx.cesClient,
|
|
132
175
|
transportInterface: ctx.transportInterface,
|
|
133
176
|
overrideProfile: ctx.currentTurnOverrideProfile,
|
|
177
|
+
attribution: resolveConversationAttribution(ctx),
|
|
134
178
|
onToolLifecycleEvent: handleToolLifecycleEvent,
|
|
135
179
|
sendToClient: (msg) => {
|
|
136
180
|
// Tool context's sendToClient uses a loose { type: string; [key: string]: unknown }
|
|
@@ -299,6 +343,12 @@ export interface SkillProjectionContext {
|
|
|
299
343
|
readonly skillProjectionCache: SkillProjectionCache;
|
|
300
344
|
readonly coreToolNames: Set<string>;
|
|
301
345
|
allowedToolNames?: Set<string>;
|
|
346
|
+
/**
|
|
347
|
+
* Durable copy of the full tool set resolved on the most recent turn, used
|
|
348
|
+
* by read-only inventory queries. Set alongside {@link allowedToolNames}
|
|
349
|
+
* but, unlike that per-turn execution gate, never cleared at turn teardown.
|
|
350
|
+
*/
|
|
351
|
+
lastResolvedToolNames?: Set<string>;
|
|
302
352
|
/** When > 0, the resolveTools callback returns no tools at all. */
|
|
303
353
|
toolsDisabledDepth: number;
|
|
304
354
|
/** Channel capabilities — read lazily per turn for conditional tool filtering. */
|
|
@@ -326,6 +376,17 @@ export interface SkillProjectionContext {
|
|
|
326
376
|
readonly transportInterface?: InterfaceId;
|
|
327
377
|
/** Per-turn override profile, read by the switch_inference_profile tool injection. */
|
|
328
378
|
currentTurnOverrideProfile?: string;
|
|
379
|
+
/**
|
|
380
|
+
* Conversation id for `skill_loaded` telemetry. Absent (e.g. minimal test
|
|
381
|
+
* contexts) disables telemetry recording in the skill projection.
|
|
382
|
+
*/
|
|
383
|
+
readonly conversationId?: string;
|
|
384
|
+
/**
|
|
385
|
+
* The LLM call site driving the current turn (see
|
|
386
|
+
* {@link ToolSetupContext.currentCallSite}) — read per turn so skill_loaded
|
|
387
|
+
* telemetry attributes the provider/model/profile the turn actually ran on.
|
|
388
|
+
*/
|
|
389
|
+
currentCallSite?: LLMCallSite;
|
|
329
390
|
}
|
|
330
391
|
|
|
331
392
|
// ── Conditional tool sets ────────────────────────────────────────────
|
|
@@ -437,6 +498,13 @@ export function isToolActiveForContext(
|
|
|
437
498
|
) {
|
|
438
499
|
return false;
|
|
439
500
|
}
|
|
501
|
+
if (name === "remember") {
|
|
502
|
+
try {
|
|
503
|
+
return getConfig().memory?.enabled !== false;
|
|
504
|
+
} catch {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
440
508
|
if (UI_SURFACE_TOOL_NAMES.has(name)) {
|
|
441
509
|
if (
|
|
442
510
|
ctx.channelCapabilities?.channel === "slack" &&
|
|
@@ -592,6 +660,19 @@ export function createResolveToolsCallback(
|
|
|
592
660
|
preactivatedSkillIds: effectivePreactivated,
|
|
593
661
|
previouslyActiveSkillIds: ctx.skillProjectionState,
|
|
594
662
|
cache: ctx.skillProjectionCache,
|
|
663
|
+
// skill_loaded telemetry context — resolved per turn so attribution
|
|
664
|
+
// reflects the call site/profile the current turn actually runs on.
|
|
665
|
+
telemetry:
|
|
666
|
+
ctx.conversationId !== undefined
|
|
667
|
+
? {
|
|
668
|
+
conversationId: ctx.conversationId,
|
|
669
|
+
attribution: resolveConversationAttribution({
|
|
670
|
+
conversationId: ctx.conversationId,
|
|
671
|
+
currentCallSite: ctx.currentCallSite,
|
|
672
|
+
currentTurnOverrideProfile: ctx.currentTurnOverrideProfile,
|
|
673
|
+
}),
|
|
674
|
+
}
|
|
675
|
+
: undefined,
|
|
595
676
|
});
|
|
596
677
|
const turnAllowed = new Set(allBaseDefs.map((d) => d.name));
|
|
597
678
|
for (const name of projection.allowedToolNames) {
|
|
@@ -602,6 +683,11 @@ export function createResolveToolsCallback(
|
|
|
602
683
|
if (excluded.has(name)) continue;
|
|
603
684
|
turnAllowed.add(name);
|
|
604
685
|
}
|
|
686
|
+
// Record the full resolved inventory durably for read-only queries before
|
|
687
|
+
// any degraded-mode narrowing below — `allowedToolNames` is the per-turn
|
|
688
|
+
// execution gate (cleared at teardown and restricted under disk pressure),
|
|
689
|
+
// whereas this snapshot answers "what tools does this conversation have".
|
|
690
|
+
ctx.lastResolvedToolNames = turnAllowed;
|
|
605
691
|
if (ctx.diskPressureCleanupModeActive === true) {
|
|
606
692
|
const cleanupDefs = allBaseDefs.filter((d) =>
|
|
607
693
|
isDiskPressureCleanupToolName(d.name),
|
|
@@ -33,7 +33,6 @@ import {
|
|
|
33
33
|
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
34
34
|
import { getConfig } from "../config/loader.js";
|
|
35
35
|
import type { LLMCallSite, Speed } from "../config/schemas/llm.js";
|
|
36
|
-
import type { CesClient } from "../credential-execution/client.js";
|
|
37
36
|
import { EventBus } from "../events/bus.js";
|
|
38
37
|
import type { AssistantDomainEvents } from "../events/domain-events.js";
|
|
39
38
|
import { createToolAuditListener } from "../events/tool-audit-listener.js";
|
|
@@ -53,7 +52,7 @@ import {
|
|
|
53
52
|
setConversationHistoryStrippedAt,
|
|
54
53
|
} from "../memory/conversation-crud.js";
|
|
55
54
|
import { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
|
|
56
|
-
import {
|
|
55
|
+
import { unwrapMemoryBlock, wrapMemoryBlock } from "../memory/memory-marker.js";
|
|
57
56
|
import { PermissionPrompter } from "../permissions/prompter.js";
|
|
58
57
|
import { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
59
58
|
import type { UserDecision } from "../permissions/types.js";
|
|
@@ -68,6 +67,11 @@ import {
|
|
|
68
67
|
createContextSummaryMessage,
|
|
69
68
|
} from "../plugins/defaults/compaction/window-manager.js";
|
|
70
69
|
import { repairHistory } from "../plugins/defaults/history-repair/terminal.js";
|
|
70
|
+
import {
|
|
71
|
+
getPrunedSlugs,
|
|
72
|
+
MEMORY_V3_INJECTED_BLOCK_METADATA_KEY,
|
|
73
|
+
} from "../plugins/defaults/memory-v3-shadow/ever-injected-store.js";
|
|
74
|
+
import { filterPrunedCardSections } from "../plugins/defaults/memory-v3-shadow/prune.js";
|
|
71
75
|
import {
|
|
72
76
|
applyBootstrapTemplate,
|
|
73
77
|
buildSystemPrompt,
|
|
@@ -129,6 +133,7 @@ import { MessageQueue } from "./conversation-queue-manager.js";
|
|
|
129
133
|
import {
|
|
130
134
|
type ChannelCapabilities,
|
|
131
135
|
getSlackCompactionWatermarkForPrefix,
|
|
136
|
+
type InboundActorContext,
|
|
132
137
|
loadSlackChronologicalContext,
|
|
133
138
|
stripInjectionsForCompaction,
|
|
134
139
|
} from "./conversation-runtime-assembly.js";
|
|
@@ -176,11 +181,10 @@ export type {
|
|
|
176
181
|
QueueDrainReason,
|
|
177
182
|
QueuePolicy,
|
|
178
183
|
} from "./conversation-queue-manager.js";
|
|
179
|
-
import {
|
|
184
|
+
import { isPersonalMemoryAllowed, type TrustContext } from "./trust-context.js";
|
|
180
185
|
|
|
181
186
|
export interface ConversationConstructorOptions {
|
|
182
187
|
maxTokens?: number;
|
|
183
|
-
sharedCesClient?: CesClient;
|
|
184
188
|
speedOverride?: Speed;
|
|
185
189
|
cacheTtl?: "5m" | "1h";
|
|
186
190
|
modelOverride?: string;
|
|
@@ -202,6 +206,15 @@ export class Conversation {
|
|
|
202
206
|
/** @internal */ eventBus = new EventBus<AssistantDomainEvents>();
|
|
203
207
|
/** @internal */ workingDir: string;
|
|
204
208
|
/** @internal */ allowedToolNames?: Set<string>;
|
|
209
|
+
/**
|
|
210
|
+
* Durable copy of the full tool set resolved on the most recent turn,
|
|
211
|
+
* kept for read-only inventory queries. Unlike {@link allowedToolNames}
|
|
212
|
+
* — the per-turn execution gate the agent loop clears at turn teardown —
|
|
213
|
+
* this survives between turns so a query against an idle conversation
|
|
214
|
+
* still reports the skill/MCP tools it gained over its lifecycle.
|
|
215
|
+
* @internal
|
|
216
|
+
*/
|
|
217
|
+
lastResolvedToolNames?: Set<string>;
|
|
205
218
|
/** @internal */ diskPressureCleanupModeActive?: boolean;
|
|
206
219
|
/** @internal */ toolsDisabledDepth = 0;
|
|
207
220
|
/** @internal */ preactivatedSkillIds?: string[];
|
|
@@ -256,7 +269,6 @@ export class Conversation {
|
|
|
256
269
|
* @internal
|
|
257
270
|
*/
|
|
258
271
|
hostAppControlProxy?: HostAppControlProxy;
|
|
259
|
-
/** @internal */ cesClient?: CesClient;
|
|
260
272
|
/** @internal */ readonly queue = new MessageQueue();
|
|
261
273
|
/** @internal */ currentActiveSurfaceId?: string;
|
|
262
274
|
/** @internal */ currentPage?: string;
|
|
@@ -269,6 +281,18 @@ export class Conversation {
|
|
|
269
281
|
* another actor's persona mid-turn.
|
|
270
282
|
*/
|
|
271
283
|
/** @internal */ currentTurnTrustContext?: TrustContext;
|
|
284
|
+
/**
|
|
285
|
+
* The model-facing inbound actor context resolved once at turn start from
|
|
286
|
+
* {@link currentTurnTrustContext}. Frozen here because resolving it reads the
|
|
287
|
+
* live contact/member registry (member status/policy, contact notes,
|
|
288
|
+
* interaction count), which a contact tool or the guardian can mutate
|
|
289
|
+
* mid-turn; post-compaction re-injection reads this snapshot so it re-emits
|
|
290
|
+
* the actor context the turn's initial assembly saw rather than re-resolving
|
|
291
|
+
* against drifted registry state. `null` on guardian turns and when there is
|
|
292
|
+
* no trust context (the actor section is suppressed).
|
|
293
|
+
* @internal
|
|
294
|
+
*/
|
|
295
|
+
currentTurnInboundActorContext?: InboundActorContext | null;
|
|
272
296
|
/** @internal */ currentTurnChannelCapabilities?: ChannelCapabilities;
|
|
273
297
|
/** @internal */ currentTurnOverrideProfile?: string;
|
|
274
298
|
/** @internal */ toolRoutedProfile?: string;
|
|
@@ -477,13 +501,7 @@ export class Conversation {
|
|
|
477
501
|
workingDir: string,
|
|
478
502
|
options?: ConversationConstructorOptions,
|
|
479
503
|
) {
|
|
480
|
-
const {
|
|
481
|
-
maxTokens,
|
|
482
|
-
sharedCesClient,
|
|
483
|
-
speedOverride,
|
|
484
|
-
cacheTtl,
|
|
485
|
-
modelOverride,
|
|
486
|
-
} = options ?? {};
|
|
504
|
+
const { maxTokens, speedOverride, cacheTtl, modelOverride } = options ?? {};
|
|
487
505
|
this.conversationId = conversationId;
|
|
488
506
|
this.systemPrompt = systemPrompt;
|
|
489
507
|
this.provider = provider;
|
|
@@ -552,13 +570,6 @@ export class Conversation {
|
|
|
552
570
|
const resolvedMainAgent = resolveCallSiteConfig("mainAgent", config.llm);
|
|
553
571
|
this.streamThinking = resolvedMainAgent.thinking.streamThinking ?? false;
|
|
554
572
|
|
|
555
|
-
// CES (Credential Execution Service) — use the shared server-level client.
|
|
556
|
-
// The CES sidecar accepts exactly one bootstrap connection, so the
|
|
557
|
-
// client is owned by DaemonServer and passed in here.
|
|
558
|
-
if (sharedCesClient) {
|
|
559
|
-
this.cesClient = sharedCesClient;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
573
|
const resolveTools = createResolveToolsCallback(toolDefs, this);
|
|
563
574
|
|
|
564
575
|
const configuredMaxTokens = maxTokens;
|
|
@@ -802,16 +813,30 @@ export class Conversation {
|
|
|
802
813
|
preStrippedCount = boundary === -1 ? slicedDbMessages.length : boundary;
|
|
803
814
|
}
|
|
804
815
|
|
|
805
|
-
//
|
|
806
|
-
// `
|
|
807
|
-
//
|
|
808
|
-
//
|
|
809
|
-
//
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
816
|
+
// The injection-time personal-memory gate, so background/local
|
|
817
|
+
// conversations (sourceChannel `undefined` or `"vellum"`) can rehydrate
|
|
818
|
+
// the persisted v2 static memory block. The shared helper folds in the
|
|
819
|
+
// HTTP-auth-disabled dev bypass so rehydration and injection agree on the
|
|
820
|
+
// effective trust class.
|
|
821
|
+
const personalMemoryAllowed = isPersonalMemoryAllowed(this.trustContext);
|
|
822
|
+
// Pruned v3 card slugs, read lazily on the first row that carries a v3
|
|
823
|
+
// block (most conversations carry none, so most loads never query). The
|
|
824
|
+
// prune valve marks cards pruned in the everInjected store instead of
|
|
825
|
+
// rewriting the persisted metadata, so the v3 rehydration splice below
|
|
826
|
+
// re-applies the filter on every load — that is what makes a prune
|
|
827
|
+
// survive daemon restarts. Defensive catch: a store failure degrades to
|
|
828
|
+
// an unfiltered (pre-prune) rehydration rather than a failed load.
|
|
829
|
+
let v3PrunedSlugsMemo: Set<string> | null = null;
|
|
830
|
+
const v3PrunedSlugs = (): Set<string> => {
|
|
831
|
+
if (v3PrunedSlugsMemo === null) {
|
|
832
|
+
try {
|
|
833
|
+
v3PrunedSlugsMemo = getPrunedSlugs(this.conversationId);
|
|
834
|
+
} catch {
|
|
835
|
+
v3PrunedSlugsMemo = new Set();
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return v3PrunedSlugsMemo;
|
|
839
|
+
};
|
|
815
840
|
const parsedMessages: Message[] = slicedDbMessages.map((m, index, arr) => {
|
|
816
841
|
const isPreStripped = index < preStrippedCount;
|
|
817
842
|
const role = m.role as "user" | "assistant";
|
|
@@ -842,18 +867,21 @@ export class Conversation {
|
|
|
842
867
|
// so the resulting layout matches `applyRuntimeInjections`'s
|
|
843
868
|
// after-memory-prefix splices in ascending injector order
|
|
844
869
|
// (pkb-context 30, pkb-reminder 35, memory-v2-static 38,
|
|
845
|
-
// now-md 40 — the v2 static block lands
|
|
846
|
-
// prefix, so now-md splices *after* it
|
|
870
|
+
// now-md 40, memory-v3-shadow 1000 — the v2 static block lands
|
|
871
|
+
// inside the memory prefix, so now-md splices *after* it; the
|
|
872
|
+
// v3 card block is `<memory>`-wrapped and splices LAST, landing
|
|
873
|
+
// at the memory boundary after the `<info>` block but before
|
|
874
|
+
// now-md's earlier splice):
|
|
847
875
|
// [<workspace>, <turn_context>, <memory>dynamic</memory>,
|
|
848
|
-
// <info>v2static</info>, <NOW.md>,
|
|
849
|
-
// <knowledge_base>, ...original]
|
|
876
|
+
// <info>v2static</info>, <memory>v3cards</memory>, <NOW.md>,
|
|
877
|
+
// <system_reminder>, <knowledge_base>, ...original]
|
|
850
878
|
// The v2 static block is replayed verbatim from stored metadata,
|
|
851
879
|
// so rows may carry either `<info>…</info>` or `<memory>…</memory>`
|
|
852
880
|
// depending on when they were persisted.
|
|
853
881
|
// Required so Anthropic's prefix cache keeps matching msg[0]
|
|
854
882
|
// across daemon restart and conversation eviction. The tail
|
|
855
|
-
// row only rehydrates `memoryInjectedBlock`
|
|
856
|
-
// re-injects the rest fresh.
|
|
883
|
+
// row only rehydrates `memoryInjectedBlock` and the v3 card
|
|
884
|
+
// block — the next turn re-injects the rest fresh.
|
|
857
885
|
if (!isTail && typeof meta.pkbContextBlock === "string") {
|
|
858
886
|
content = [
|
|
859
887
|
{ type: "text" as const, text: meta.pkbContextBlock },
|
|
@@ -875,10 +903,42 @@ export class Conversation {
|
|
|
875
903
|
];
|
|
876
904
|
}
|
|
877
905
|
|
|
906
|
+
// The memory-v3 frozen card block (net-new compact cards) persists
|
|
907
|
+
// under its own key, stored UNWRAPPED like v2's dynamic block below.
|
|
908
|
+
// Rehydrated on ALL rows (tail included): the next turn injects only
|
|
909
|
+
// net-new cards — deduped via the v3 everInjected store — so this
|
|
910
|
+
// row's block must be back in history byte-identical for the dedup
|
|
911
|
+
// (and the provider prefix cache) to hold. A row carries at most one
|
|
912
|
+
// of the v3 and v2-dynamic keys (the user-prompt-submit hook
|
|
913
|
+
// persists them mutually exclusively). Spliced here — before the v2
|
|
914
|
+
// static and dynamic blocks — because prepends invert: executing
|
|
915
|
+
// first leaves it BELOW both in the final content, matching the
|
|
916
|
+
// live after-memory-prefix splice (order 1000 lands at the memory
|
|
917
|
+
// boundary, after `<info>` / `<memory>` prefix blocks).
|
|
918
|
+
// Pruned slugs' card sections are filtered out here (the metadata
|
|
919
|
+
// itself is never rewritten — auditable and reversible); an
|
|
920
|
+
// all-pruned block is skipped entirely, matching the live strip in
|
|
921
|
+
// `memory-v3-shadow/prune.ts`.
|
|
922
|
+
if (typeof meta[MEMORY_V3_INJECTED_BLOCK_METADATA_KEY] === "string") {
|
|
923
|
+
const v3Block = meta[
|
|
924
|
+
MEMORY_V3_INJECTED_BLOCK_METADATA_KEY
|
|
925
|
+
] as string;
|
|
926
|
+
const v3Resident = filterPrunedCardSections(
|
|
927
|
+
unwrapMemoryBlock(v3Block),
|
|
928
|
+
v3PrunedSlugs(),
|
|
929
|
+
);
|
|
930
|
+
if (v3Resident.length > 0) {
|
|
931
|
+
content = [
|
|
932
|
+
{ type: "text" as const, text: wrapMemoryBlock(v3Resident) },
|
|
933
|
+
...content,
|
|
934
|
+
];
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
878
938
|
// The v2 static memory block (essentials/threads/recent/buffer
|
|
879
939
|
// wrapped in either `<info>…</info>` or `<memory>…</memory>`)
|
|
880
940
|
// carries personal user memory. Trust-gated to mirror
|
|
881
|
-
// `
|
|
941
|
+
// `isPersonalMemoryAllowed` at injection time — untrusted-actor
|
|
882
942
|
// views must not read persisted personal memory back through
|
|
883
943
|
// metadata. Skipped on the tail row because the next turn
|
|
884
944
|
// re-injects fresh content on full-mode turns.
|
|
@@ -902,15 +962,12 @@ export class Conversation {
|
|
|
902
962
|
// legitimate unwrapped payloads that happen to start with
|
|
903
963
|
// "<memory>\n" or end with "\n</memory>".
|
|
904
964
|
if (typeof meta.memoryInjectedBlock === "string") {
|
|
905
|
-
const block = meta.memoryInjectedBlock;
|
|
906
|
-
const inner =
|
|
907
|
-
block.startsWith("<memory>\n") && block.endsWith("\n</memory>")
|
|
908
|
-
? block.slice("<memory>\n".length, -"\n</memory>".length)
|
|
909
|
-
: block;
|
|
910
965
|
content = [
|
|
911
966
|
{
|
|
912
967
|
type: "text" as const,
|
|
913
|
-
text:
|
|
968
|
+
text: wrapMemoryBlock(
|
|
969
|
+
unwrapMemoryBlock(meta.memoryInjectedBlock),
|
|
970
|
+
),
|
|
914
971
|
},
|
|
915
972
|
...content,
|
|
916
973
|
];
|
|
@@ -1044,14 +1101,13 @@ export class Conversation {
|
|
|
1044
1101
|
async ensureActorScopedHistory(): Promise<void> {
|
|
1045
1102
|
const currentTrustClass = this.trustContext?.trustClass;
|
|
1046
1103
|
// `loadFromDb` gates personal-memory rehydration on `sourceChannel` too
|
|
1047
|
-
// (via `
|
|
1104
|
+
// (via `isPersonalMemoryAllowed`), so a same-trust-class reuse from a
|
|
1048
1105
|
// different channel (e.g. internal `vellum` → remote channel) must also
|
|
1049
1106
|
// trigger a reload. Otherwise stale personal-memory blocks can leak to
|
|
1050
1107
|
// an untrusted remote turn, or be hidden when they should be present.
|
|
1051
|
-
const currentPersonalMemoryAllowed =
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
});
|
|
1108
|
+
const currentPersonalMemoryAllowed = isPersonalMemoryAllowed(
|
|
1109
|
+
this.trustContext,
|
|
1110
|
+
);
|
|
1055
1111
|
if (
|
|
1056
1112
|
this.loadedHistoryTrustClass === currentTrustClass &&
|
|
1057
1113
|
this.loadedHistoryPersonalMemoryAllowed === currentPersonalMemoryAllowed
|
|
@@ -1207,9 +1263,6 @@ export class Conversation {
|
|
|
1207
1263
|
this.hostCuProxy?.dispose();
|
|
1208
1264
|
this.hostAppControlProxy?.dispose();
|
|
1209
1265
|
this.hostAppControlProxy = undefined;
|
|
1210
|
-
// CES client is owned by DaemonServer — just drop the reference.
|
|
1211
|
-
// Do NOT close it here; the server manages the CES lifecycle.
|
|
1212
|
-
this.cesClient = undefined;
|
|
1213
1266
|
this.activeContextNodeIds = this.graphMemory.tracker.getActiveNodeIds();
|
|
1214
1267
|
this.graphMemory.persistState();
|
|
1215
1268
|
this.graphMemory.dispose();
|
|
@@ -1706,6 +1759,22 @@ export class Conversation {
|
|
|
1706
1759
|
});
|
|
1707
1760
|
}
|
|
1708
1761
|
|
|
1762
|
+
// ── Tools ────────────────────────────────────────────────────────
|
|
1763
|
+
|
|
1764
|
+
/**
|
|
1765
|
+
* The set of tool names available to this conversation as of its most
|
|
1766
|
+
* recent turn — including skill/MCP tools registered over the
|
|
1767
|
+
* conversation's lifecycle. Reads the durable {@link lastResolvedToolNames}
|
|
1768
|
+
* snapshot the `resolveTools` callback records each turn (which, unlike the
|
|
1769
|
+
* per-turn `allowedToolNames` gate, is not cleared at turn teardown); before
|
|
1770
|
+
* the first turn it falls back to the core tool set. This is a pure read: it
|
|
1771
|
+
* does not re-run `resolveTools`, which has registry/projection side effects
|
|
1772
|
+
* that must not fire outside a turn.
|
|
1773
|
+
*/
|
|
1774
|
+
getRegisteredToolNames(): Set<string> {
|
|
1775
|
+
return new Set(this.lastResolvedToolNames ?? this.coreToolNames);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1709
1778
|
// ── History ──────────────────────────────────────────────────────
|
|
1710
1779
|
|
|
1711
1780
|
getMessages(): Message[] {
|