@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
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tests for `pool-select.ts` — the single forced-tool selector over the
|
|
3
|
-
* candidate pool.
|
|
2
|
+
* Tests for `pool-select.ts` — the single forced-tool selector over the
|
|
3
|
+
* two-segment candidate pool (stable-prefix cards + dynamic finder tail).
|
|
4
4
|
*
|
|
5
5
|
* Coverage matrix:
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
-
*
|
|
6
|
+
* - Segment ordering: the stable prefix (full cards, `[1]…[m]`) renders as
|
|
7
|
+
* its own content block carrying the `cache_control` breakpoint; the
|
|
8
|
+
* dynamic tail (finder lines `[m+1]…` + per-turn context) follows in an
|
|
9
|
+
* un-cached block.
|
|
10
|
+
* - Numbering stability: for identical stable lanes the rendered prefix
|
|
11
|
+
* block is byte-identical across renders; only the tail varies.
|
|
12
|
+
* - Returned IDs map over the CONCATENATED numbering, with `pinned` driven
|
|
13
|
+
* by `pinned_ids`; out-of-range IDs dropped; selections deduped by slug
|
|
14
|
+
* (a page can appear as both a card and a finder line; pinned flags OR).
|
|
15
|
+
* - Omitted `ids` → keep ALL candidates (recall-safe, slug-deduped).
|
|
10
16
|
* - Explicit `ids: []` → keep none (deliberate abstention).
|
|
11
|
-
* -
|
|
17
|
+
* - Finder snippets are whitespace-collapsed and truncated (~300 chars).
|
|
12
18
|
* - No provider / missing tool_use / schema mismatch / throw → keep none
|
|
13
19
|
* (degrade to deterministic lanes), the last three after a re-prompt retry.
|
|
14
|
-
* - One forced-tool `select_pages` call on the v3 L2 call site
|
|
15
|
-
*
|
|
20
|
+
* - One forced-tool `select_pages` call on the v3 L2 call site with
|
|
21
|
+
* `disableTurnStartCache` (the tail varies per turn — the provider's
|
|
22
|
+
* auto-anchor would never hit).
|
|
16
23
|
*
|
|
17
24
|
* The provider is stubbed so no network calls fire; mirrors selector.test.ts.
|
|
18
25
|
*/
|
|
@@ -55,7 +62,7 @@ mock.module("../../../../util/logger.js", () => ({
|
|
|
55
62
|
}));
|
|
56
63
|
|
|
57
64
|
const { selectPool } = await import("../pool-select.js");
|
|
58
|
-
type
|
|
65
|
+
type SelectorPool = Parameters<typeof selectPool>[0];
|
|
59
66
|
|
|
60
67
|
// ---------------------------------------------------------------------------
|
|
61
68
|
// Helpers.
|
|
@@ -118,12 +125,23 @@ function makeThrowingProvider(): Provider {
|
|
|
118
125
|
};
|
|
119
126
|
}
|
|
120
127
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
const CARD_A =
|
|
129
|
+
"# memory/concepts/page-a.md\nlead for page a\n\n[sections: §Alpha · §Beta]";
|
|
130
|
+
const CARD_B = "# memory/concepts/page-b.md\nlead for page b";
|
|
131
|
+
|
|
132
|
+
/** Two stable-prefix cards (`[1] page-a`, `[2] page-b`) and two finder lines
|
|
133
|
+
* (`[3] topic-x`, `[4] page-a` — a finder hit on a stable-prefix page). */
|
|
134
|
+
function makePool(): SelectorPool {
|
|
135
|
+
return {
|
|
136
|
+
stable: [
|
|
137
|
+
{ slug: "page-a", card: CARD_A },
|
|
138
|
+
{ slug: "page-b", card: CARD_B },
|
|
139
|
+
],
|
|
140
|
+
finder: [
|
|
141
|
+
{ slug: "topic-x", descriptor: "section: about topic x" },
|
|
142
|
+
{ slug: "page-a", descriptor: "section: the alpha rollout plan" },
|
|
143
|
+
],
|
|
144
|
+
};
|
|
127
145
|
}
|
|
128
146
|
|
|
129
147
|
function makeTurn(currentMessage: string): MemoryRoutingTurn {
|
|
@@ -135,17 +153,28 @@ function makeTurn(currentMessage: string): MemoryRoutingTurn {
|
|
|
135
153
|
};
|
|
136
154
|
}
|
|
137
155
|
|
|
156
|
+
interface RenderedBlock {
|
|
157
|
+
type: string;
|
|
158
|
+
text: string;
|
|
159
|
+
cache_control?: { type: string; ttl?: string };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function sentBlocks(callIndex = 0): RenderedBlock[] {
|
|
163
|
+
return providerCalls[callIndex]!.messages[0]!
|
|
164
|
+
.content as unknown as RenderedBlock[];
|
|
165
|
+
}
|
|
166
|
+
|
|
138
167
|
beforeEach(() => {
|
|
139
168
|
providerStub = null;
|
|
140
169
|
providerCalls.length = 0;
|
|
141
170
|
});
|
|
142
171
|
|
|
143
172
|
// ---------------------------------------------------------------------------
|
|
144
|
-
// selectPool — id mapping.
|
|
173
|
+
// selectPool — id mapping over the concatenated numbering.
|
|
145
174
|
// ---------------------------------------------------------------------------
|
|
146
175
|
|
|
147
176
|
describe("selectPool — id mapping", () => {
|
|
148
|
-
test("
|
|
177
|
+
test("IDs map over cards then finder lines, pinned driven by pinned_ids", async () => {
|
|
149
178
|
providerStub = makeProvider(
|
|
150
179
|
toolUseResponse({ ids: [3, 1], pinned_ids: [1] }),
|
|
151
180
|
);
|
|
@@ -156,7 +185,17 @@ describe("selectPool — id mapping", () => {
|
|
|
156
185
|
]);
|
|
157
186
|
});
|
|
158
187
|
|
|
159
|
-
test("
|
|
188
|
+
test("a page selected as both card and finder line dedupes to one slug, pinned ORed", async () => {
|
|
189
|
+
// page-a is id 1 (card) AND id 4 (finder line); pinned only via the
|
|
190
|
+
// finder-line id.
|
|
191
|
+
providerStub = makeProvider(
|
|
192
|
+
toolUseResponse({ ids: [1, 4], pinned_ids: [4] }),
|
|
193
|
+
);
|
|
194
|
+
const result = await selectPool(makePool(), makeTurn("the alpha plan"));
|
|
195
|
+
expect(result).toEqual([{ slug: "page-a", pinned: true }]);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("omitted ids keeps ALL candidates, deduped by slug (recall-safe)", async () => {
|
|
160
199
|
providerStub = makeProvider(toolUseResponse({}));
|
|
161
200
|
const result = await selectPool(makePool(), makeTurn("anything"));
|
|
162
201
|
expect(result).toEqual([
|
|
@@ -180,7 +219,7 @@ describe("selectPool — id mapping", () => {
|
|
|
180
219
|
|
|
181
220
|
test("empty pool returns no pages and never calls the provider", async () => {
|
|
182
221
|
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
183
|
-
const result = await selectPool([], makeTurn("hi"));
|
|
222
|
+
const result = await selectPool({ stable: [], finder: [] }, makeTurn("hi"));
|
|
184
223
|
expect(result).toEqual([]);
|
|
185
224
|
expect(providerCalls).toHaveLength(0);
|
|
186
225
|
});
|
|
@@ -231,11 +270,12 @@ describe("selectPool — degradation on failure", () => {
|
|
|
231
270
|
});
|
|
232
271
|
|
|
233
272
|
// ---------------------------------------------------------------------------
|
|
234
|
-
// selectPool — request shape
|
|
273
|
+
// selectPool — request shape: stable-prefix cards block with the cache
|
|
274
|
+
// breakpoint, dynamic tail block without.
|
|
235
275
|
// ---------------------------------------------------------------------------
|
|
236
276
|
|
|
237
277
|
describe("selectPool — request shape", () => {
|
|
238
|
-
test("forces tool_choice to select_pages
|
|
278
|
+
test("forces tool_choice to select_pages on the v3 L2 call site with disableTurnStartCache", async () => {
|
|
239
279
|
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
240
280
|
await selectPool(makePool(), makeTurn("rollout?"));
|
|
241
281
|
|
|
@@ -244,63 +284,115 @@ describe("selectPool — request shape", () => {
|
|
|
244
284
|
const cfg = call.options?.config as Record<string, unknown>;
|
|
245
285
|
expect(cfg?.callSite).toBe("memoryV3SelectL2");
|
|
246
286
|
expect(cfg?.tool_choice).toEqual({ type: "tool", name: "select_pages" });
|
|
287
|
+
expect(cfg?.disableTurnStartCache).toBe(true);
|
|
247
288
|
expect(call.options?.tools?.[0]?.name).toBe("select_pages");
|
|
248
289
|
});
|
|
249
290
|
|
|
250
|
-
test("renders
|
|
291
|
+
test("stable prefix renders full cards in its own block carrying cache_control", async () => {
|
|
251
292
|
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
252
293
|
await selectPool(makePool(), makeTurn("rollout?"));
|
|
253
294
|
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
//
|
|
260
|
-
expect(
|
|
261
|
-
|
|
262
|
-
expect(
|
|
263
|
-
expect(
|
|
264
|
-
|
|
295
|
+
const blocks = sentBlocks();
|
|
296
|
+
expect(blocks).toHaveLength(2);
|
|
297
|
+
|
|
298
|
+
const [prefix, tail] = blocks;
|
|
299
|
+
expect(prefix.type).toBe("text");
|
|
300
|
+
// FULL cards, numbered in pool order, inside the cards segment.
|
|
301
|
+
expect(prefix.text).toContain(`[1] ${CARD_A}`);
|
|
302
|
+
expect(prefix.text).toContain(`[2] ${CARD_B}`);
|
|
303
|
+
expect(prefix.text.startsWith("<candidate_cards>\n")).toBe(true);
|
|
304
|
+
expect(prefix.text.endsWith("\n</candidate_cards>")).toBe(true);
|
|
305
|
+
// The breakpoint rides THIS block (preserved by toAnthropicBlockSafe).
|
|
306
|
+
expect(prefix.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
|
|
307
|
+
|
|
308
|
+
// The tail continues the numbering after the cards and is NOT cached.
|
|
309
|
+
expect(tail.type).toBe("text");
|
|
310
|
+
expect(tail.text).toContain("[3] topic-x — section: about topic x");
|
|
311
|
+
expect(tail.text).toContain("[4] page-a — section: the alpha rollout plan");
|
|
312
|
+
expect(tail.text).toContain("<current_message>rollout?</current_message>");
|
|
313
|
+
expect(tail.text).toContain("<recent_context>");
|
|
314
|
+
expect(tail.cache_control).toBeUndefined();
|
|
315
|
+
// No cards leak into the tail.
|
|
316
|
+
expect(tail.text).not.toContain("<candidate_cards>");
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test("the rendered prefix is byte-identical across turns; only the tail varies", async () => {
|
|
320
|
+
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
321
|
+
await selectPool(makePool(), makeTurn("first question"));
|
|
322
|
+
|
|
323
|
+
// Same stable lanes, different finder hits + message (a new turn).
|
|
324
|
+
const pool2 = makePool();
|
|
325
|
+
pool2.finder = [{ slug: "page-c", descriptor: "section: something else" }];
|
|
326
|
+
await selectPool(pool2, makeTurn("second question"));
|
|
327
|
+
|
|
328
|
+
const [prefix1, tail1] = sentBlocks(0);
|
|
329
|
+
const [prefix2, tail2] = sentBlocks(1);
|
|
330
|
+
expect(prefix2.text).toBe(prefix1.text);
|
|
331
|
+
expect(prefix2.cache_control).toEqual(prefix1.cache_control!);
|
|
332
|
+
expect(tail2.text).not.toBe(tail1.text);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
test("an empty stable prefix renders a single un-cached block", async () => {
|
|
336
|
+
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
337
|
+
await selectPool(
|
|
338
|
+
{ stable: [], finder: [{ slug: "page-a", descriptor: "d" }] },
|
|
339
|
+
makeTurn("x"),
|
|
265
340
|
);
|
|
266
|
-
|
|
267
|
-
|
|
341
|
+
const blocks = sentBlocks();
|
|
342
|
+
expect(blocks).toHaveLength(1);
|
|
343
|
+
expect(blocks[0].text).toContain("[1] page-a — d");
|
|
344
|
+
expect(blocks[0].cache_control).toBeUndefined();
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
test("long finder snippets are whitespace-collapsed and truncated (~300 chars)", async () => {
|
|
348
|
+
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
349
|
+
const longDescriptor = `padded ${"z".repeat(1000)}`;
|
|
350
|
+
await selectPool(
|
|
351
|
+
{ stable: [], finder: [{ slug: "page-a", descriptor: longDescriptor }] },
|
|
352
|
+
makeTurn("x"),
|
|
268
353
|
);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
354
|
+
const [block] = sentBlocks();
|
|
355
|
+
const line = block.text
|
|
356
|
+
.split("\n")
|
|
357
|
+
.find((l) => l.startsWith("[1] page-a — "))!;
|
|
358
|
+
expect(line).toContain("...");
|
|
359
|
+
expect(line).not.toContain("z".repeat(1000));
|
|
360
|
+
// snippet cap (300) + the `[1] page-a — ` prefix.
|
|
361
|
+
expect(line.length).toBeLessThanOrEqual(300 + "[1] page-a — ".length);
|
|
273
362
|
});
|
|
274
363
|
|
|
275
|
-
test("
|
|
364
|
+
test("a finder candidate with an empty descriptor renders without a dangling dash", async () => {
|
|
276
365
|
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
277
|
-
const longDescriptor = "z".repeat(1000);
|
|
278
366
|
await selectPool(
|
|
279
|
-
[{ slug: "page-a", descriptor:
|
|
367
|
+
{ stable: [], finder: [{ slug: "page-a", descriptor: " " }] },
|
|
280
368
|
makeTurn("x"),
|
|
281
369
|
);
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
expect(text).toContain("
|
|
285
|
-
expect(text).not.toContain("z".repeat(1000));
|
|
370
|
+
const [block] = sentBlocks();
|
|
371
|
+
expect(block.text).toContain("[1] page-a\n");
|
|
372
|
+
expect(block.text).not.toContain("[1] page-a — ");
|
|
286
373
|
});
|
|
287
374
|
|
|
288
|
-
test("situational context renders in the
|
|
375
|
+
test("situational context renders in the tail when present", async () => {
|
|
289
376
|
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
290
377
|
await selectPool(makePool(), {
|
|
291
378
|
...makeTurn("rollout?"),
|
|
292
379
|
situationalContext: "Today is Saturday. The launch is today.",
|
|
293
380
|
});
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
expect(text).toContain(
|
|
381
|
+
const blocks = sentBlocks();
|
|
382
|
+
expect(blocks[1].text).toContain(
|
|
297
383
|
"<situation>Today is Saturday. The launch is today.</situation>",
|
|
298
384
|
);
|
|
299
385
|
});
|
|
300
386
|
|
|
301
|
-
test("system prompt
|
|
387
|
+
test("system prompt is carry-aware and generous (persistence + pinned + no limit)", async () => {
|
|
302
388
|
providerStub = makeProvider(toolUseResponse({ ids: [1] }));
|
|
303
389
|
await selectPool(makePool(), makeTurn("x"));
|
|
304
|
-
|
|
390
|
+
const prompt = providerCalls[0].options?.systemPrompt ?? "";
|
|
391
|
+
// Carry-aware: previously selected pages persist automatically.
|
|
392
|
+
expect(prompt).toMatch(/persist/);
|
|
393
|
+
// Generous: explicitly no selection limit.
|
|
394
|
+
expect(prompt).toMatch(/no limit/i);
|
|
395
|
+
// Pinning commitment.
|
|
396
|
+
expect(prompt).toMatch(/pinned/);
|
|
305
397
|
});
|
|
306
398
|
});
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import { wrapMemoryBlock } from "../../../../memory/memory-marker.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
renderCardsBlockInner,
|
|
6
|
+
renderMemoryBlock,
|
|
7
|
+
renderSpotlightInner,
|
|
8
|
+
V3_CARDS_INJECTION_HEADER,
|
|
9
|
+
} from "../render-injection.js";
|
|
5
10
|
import type { Section, Slug } from "../types.js";
|
|
6
11
|
|
|
7
12
|
function section(article: Slug, text: string): Section {
|
|
@@ -17,6 +22,38 @@ const resolver =
|
|
|
17
22
|
async (slug: Slug, sec: Section | undefined): Promise<string> =>
|
|
18
23
|
sec ? sec.text : (fullBodies[slug] ?? "");
|
|
19
24
|
|
|
25
|
+
describe("renderCardsBlockInner", () => {
|
|
26
|
+
test("prefixes the v2 read-affordance header and joins cards with blank lines", () => {
|
|
27
|
+
const inner = renderCardsBlockInner([
|
|
28
|
+
"# memory/concepts/page-a.md\nhead a",
|
|
29
|
+
"# memory/concepts/page-b.md\nhead b",
|
|
30
|
+
]);
|
|
31
|
+
expect(inner).toBe(
|
|
32
|
+
`${V3_CARDS_INJECTION_HEADER}\n\n# memory/concepts/page-a.md\nhead a\n\n# memory/concepts/page-b.md\nhead b`,
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("empty card list renders the empty string (no header-only block)", () => {
|
|
37
|
+
expect(renderCardsBlockInner([])).toBe("");
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("renderSpotlightInner", () => {
|
|
42
|
+
test("renders each entry as a § header plus section text", () => {
|
|
43
|
+
const inner = renderSpotlightInner([
|
|
44
|
+
{ slug: "page-a", title: "Alpha", text: "alpha text" },
|
|
45
|
+
{ slug: "page-b", title: "Beta", text: "beta text" },
|
|
46
|
+
]);
|
|
47
|
+
expect(inner).toBe(
|
|
48
|
+
"## memory/concepts/page-a.md § Alpha\nalpha text\n\n## memory/concepts/page-b.md § Beta\nbeta text",
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("empty window renders the empty string", () => {
|
|
53
|
+
expect(renderSpotlightInner([])).toBe("");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
20
57
|
describe("renderMemoryBlock", () => {
|
|
21
58
|
test("renders the matched section (not the full body) for each slug", async () => {
|
|
22
59
|
const sections = new Map<Slug, Section>([
|
|
@@ -151,15 +151,17 @@ describe("getMemoryV3SelectionForInspector", () => {
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
test("maps source/pinned and renders the <memory> block", async () => {
|
|
154
|
+
// The second row carries a retired free-text source label (the column is
|
|
155
|
+
// permissive); the inspector passes it through verbatim.
|
|
154
156
|
seed("conv-4", 1, [
|
|
155
157
|
{ slug: "domain-a/page-1", source: "edge", pinned: true },
|
|
156
|
-
{ slug: "domain-b/page-2", source: "carry
|
|
158
|
+
{ slug: "domain-b/page-2", source: "legacy-carry", pinned: false },
|
|
157
159
|
]);
|
|
158
160
|
|
|
159
161
|
const log = await getMemoryV3SelectionForInspector("conv-4", 1);
|
|
160
162
|
expect(log?.selections).toEqual([
|
|
161
163
|
{ slug: "domain-a/page-1", source: "edge", pinned: true },
|
|
162
|
-
{ slug: "domain-b/page-2", source: "carry
|
|
164
|
+
{ slug: "domain-b/page-2", source: "legacy-carry", pinned: false },
|
|
163
165
|
]);
|
|
164
166
|
expect(log?.injectedText).toContain("<memory>");
|
|
165
167
|
expect(log?.injectedText).toContain("body for domain-a/page-1");
|
|
@@ -188,20 +190,21 @@ describe("summarizeSelections", () => {
|
|
|
188
190
|
{ slug: "domain-a/page-1", source: "needle" },
|
|
189
191
|
{ slug: "domain-b/page-2", source: "edge" },
|
|
190
192
|
]);
|
|
191
|
-
// Turn 2: page-1 re-selected (needle) + page-2
|
|
193
|
+
// Turn 2: page-1 re-selected (needle) + page-2 re-surfaced by edge.
|
|
192
194
|
seed("conv-a", 2, [
|
|
193
195
|
{ slug: "domain-a/page-1", source: "needle", pinned: true },
|
|
194
|
-
{ slug: "domain-b/page-2", source: "
|
|
196
|
+
{ slug: "domain-b/page-2", source: "edge" },
|
|
195
197
|
]);
|
|
196
198
|
// A different conversation must not bleed into the aggregate.
|
|
197
199
|
seed("conv-b", 1, [{ slug: "domain-c/page-9", source: "dense" }]);
|
|
198
200
|
|
|
199
201
|
const summary = summarizeSelections("conv-a");
|
|
200
202
|
expect(summary.bySource).toEqual({
|
|
203
|
+
core: 0,
|
|
204
|
+
hot: 0,
|
|
201
205
|
needle: 2,
|
|
202
206
|
dense: 0,
|
|
203
|
-
edge:
|
|
204
|
-
"carry-forward": 1,
|
|
207
|
+
edge: 2,
|
|
205
208
|
});
|
|
206
209
|
expect(summary.turns).toBe(2);
|
|
207
210
|
// page-1 and page-2 — distinct across the two turns.
|
|
@@ -210,14 +213,21 @@ describe("summarizeSelections", () => {
|
|
|
210
213
|
|
|
211
214
|
test("returns zeroed counts for a conversation with no rows", () => {
|
|
212
215
|
expect(summarizeSelections("conv-none")).toEqual({
|
|
213
|
-
bySource: {
|
|
216
|
+
bySource: {
|
|
217
|
+
core: 0,
|
|
218
|
+
hot: 0,
|
|
219
|
+
needle: 0,
|
|
220
|
+
dense: 0,
|
|
221
|
+
edge: 0,
|
|
222
|
+
},
|
|
214
223
|
turns: 0,
|
|
215
224
|
distinctSlugs: 0,
|
|
216
225
|
});
|
|
217
226
|
});
|
|
218
227
|
|
|
219
228
|
test("ignores unknown/free-text historical source labels in bySource but counts the turn", () => {
|
|
220
|
-
// A pre-lane historical row with a legacy label (column is free-text)
|
|
229
|
+
// A pre-lane historical row with a legacy label (column is free-text) —
|
|
230
|
+
// retired labels like the old per-turn carry source land here too.
|
|
221
231
|
seed("conv-c", 1, [
|
|
222
232
|
{ slug: "domain-a/page-1", source: "l1+l2" },
|
|
223
233
|
{ slug: "domain-a/page-2", source: "needle" },
|