@vellumai/assistant 0.6.4 → 0.6.6
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/.prettierignore +5 -0
- package/AGENTS.md +9 -1
- package/ARCHITECTURE.md +43 -49
- package/Dockerfile +17 -3
- package/README.md +3 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +33 -59
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +19 -18
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/error-handling.md +111 -0
- package/docs/plugins.md +761 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/examples/plugins/echo/README.md +132 -0
- package/examples/plugins/echo/package.json +17 -0
- package/examples/plugins/echo/register.ts +187 -0
- package/knip.json +9 -2
- package/node_modules/@vellumai/ces-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +334 -78
- package/package.json +6 -3
- package/scripts/generate-openapi.ts +50 -11
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +112 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +171 -2
- package/src/__tests__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +36 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +51 -182
- package/src/__tests__/btw-routes.test.ts +47 -1
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +96 -4
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +870 -655
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-events.test.ts +501 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +11 -28
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +440 -114
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +883 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +32 -15
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +86 -46
- package/src/__tests__/conversation-agent-loop.test.ts +435 -216
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +36 -10
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +34 -12
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +32 -15
- package/src/__tests__/conversation-process-callsite.test.ts +309 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +44 -21
- package/src/__tests__/conversation-queue.test.ts +68 -38
- package/src/__tests__/conversation-routes-disk-view.test.ts +36 -7
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2877 -152
- package/src/__tests__/conversation-runtime-workspace.test.ts +35 -50
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +39 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +53 -16
- package/src/__tests__/conversation-speed-override.test.ts +36 -12
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +118 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +4 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +33 -9
- package/src/__tests__/conversation-workspace-injection.test.ts +46 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -15
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +5 -2
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +135 -19
- package/src/__tests__/credentials-cli.test.ts +1 -9
- package/src/__tests__/cross-provider-web-search.test.ts +84 -0
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/empty-response-pipeline.test.ts +305 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +29 -10
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/first-greeting.test.ts +247 -5
- package/src/__tests__/gemini-provider.test.ts +0 -3
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +57 -0
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/history-repair-pipeline.test.ts +399 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
- package/src/__tests__/host-proxy-interface.test.ts +36 -2
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +1 -66
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +121 -0
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/media-generate-image.test.ts +119 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
- package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +621 -0
- package/src/__tests__/model-intents.test.ts +11 -83
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/notification-decision-strategy.test.ts +0 -11
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +14 -12
- package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
- package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
- package/src/__tests__/oauth-providers-routes.test.ts +3 -2
- package/src/__tests__/oauth-store.test.ts +46 -78
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -0
- package/src/__tests__/openai-provider.test.ts +7 -0
- package/src/__tests__/openai-responses-provider.test.ts +396 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -25
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/platform.test.ts +5 -2
- package/src/__tests__/plugin-bootstrap.test.ts +483 -0
- package/src/__tests__/plugin-registry.test.ts +273 -0
- package/src/__tests__/plugin-route-contribution.test.ts +288 -0
- package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
- package/src/__tests__/plugin-types.test.ts +320 -0
- package/src/__tests__/pricing.test.ts +93 -14
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +69 -9
- package/src/__tests__/reaction-persistence.test.ts +561 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/schedule-routes.test.ts +131 -1
- package/src/__tests__/scheduler-recurrence.test.ts +14 -70
- package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
- package/src/__tests__/secret-detection-handler.test.ts +0 -10
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +29 -1
- package/src/__tests__/server-history-render.test.ts +31 -0
- package/src/__tests__/shell-identity.test.ts +0 -134
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skills.test.ts +19 -33
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +259 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-preload.ts +11 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/title-generate-pipeline.test.ts +224 -0
- package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
- package/src/__tests__/tool-error-pipeline.test.ts +244 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -8
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +201 -94
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- package/src/__tests__/trust-store.test.ts +442 -109
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/user-plugin-loader.test.ts +191 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
- package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
- package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
- package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +22 -16
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +545 -115
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/telephony-stt-routing.ts +1 -1
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/email-list.test.ts +6 -0
- package/src/cli/commands/__tests__/email-send.test.ts +93 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +886 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +463 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +606 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/backup.ts +2 -2
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -12
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +69 -8
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +299 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/notifications.ts +68 -103
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/oauth/providers.ts +176 -8
- package/src/cli/commands/oauth/status.ts +46 -36
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
- package/src/cli/commands/skills.ts +3 -4
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +39 -24
- package/src/cli.ts +0 -37
- package/src/config/__tests__/backup-schema.test.ts +7 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +20 -1
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +69 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/schedule/SKILL.md +8 -3
- package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -190
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +42 -10
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +194 -10
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +49 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/conversations.ts +16 -0
- package/src/config/schemas/filing.ts +2 -7
- package/src/config/schemas/heartbeat.ts +0 -5
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +317 -0
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +9 -4
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/schemas/tts.ts +64 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +96 -7
- package/src/context/__tests__/compact-prompt.test.ts +63 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/prompts/compact.md +26 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +417 -39
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +19 -8
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +65 -2
- package/src/credential-health/credential-health-service.ts +19 -6
- package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +0 -3
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +162 -34
- package/src/daemon/conversation-agent-loop.ts +1282 -599
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +59 -17
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +1063 -211
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +51 -9
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +197 -64
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/first-greeting.ts +191 -14
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +65 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +7 -3
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +109 -82
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +63 -0
- package/src/daemon/message-types/messages.ts +21 -1
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +122 -12
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -65
- package/src/daemon/web-search-history.ts +126 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +99 -28
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- package/src/home/__tests__/feed-scheduler.test.ts +39 -11
- package/src/home/__tests__/rollup-producer.test.ts +44 -0
- package/src/home/assistant-feed-authoring.ts +4 -0
- package/src/home/emit-feed-event.ts +11 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +97 -4
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- package/src/home/rollup-producer.ts +34 -5
- package/src/home/suggested-prompts.ts +101 -0
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/socket-path.test.ts +34 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +2 -1
- package/src/ipc/cli-server.ts +26 -8
- package/src/ipc/gateway-client.ts +6 -3
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +63 -0
- package/src/ipc/routes/browser.ts +97 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +31 -1
- package/src/ipc/routes/list-clients.ts +31 -0
- package/src/ipc/routes/merge-contacts.ts +17 -0
- package/src/ipc/routes/notification.ts +133 -0
- package/src/ipc/routes/rename-conversation.ts +59 -0
- package/src/ipc/routes/search-contacts.ts +19 -0
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/upsert-contact.ts +25 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +76 -0
- package/src/media/app-icon-generator.ts +23 -46
- package/src/media/avatar-router.ts +26 -41
- package/src/media/gemini-image-service.ts +8 -41
- package/src/media/image-credentials.ts +73 -0
- package/src/media/image-service.ts +85 -0
- package/src/media/openai-image-service.ts +131 -0
- package/src/media/types.ts +46 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/conversation-analyze-job.ts +14 -13
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +133 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +32 -4
- package/src/memory/db-init.ts +10 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/embedding-gemini.test.ts +41 -2
- package/src/memory/embedding-gemini.ts +6 -1
- package/src/memory/graph/bootstrap.test.ts +282 -0
- package/src/memory/graph/bootstrap.ts +8 -5
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +89 -29
- package/src/memory/graph/extraction.test.ts +272 -2
- package/src/memory/graph/extraction.ts +183 -53
- package/src/memory/graph/graph-search.test.ts +93 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/inspect.ts +2 -2
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +237 -48
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/indexer.ts +5 -5
- package/src/memory/job-handlers/conversation-starters.ts +23 -20
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +44 -3
- package/src/memory/jobs-worker.ts +4 -0
- package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +1 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/223-schedule-script-column.ts +11 -0
- package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
- package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/pkb/pkb-index.test.ts +369 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +252 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +499 -0
- package/src/memory/pkb/pkb-search.ts +159 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +147 -1
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -1
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +22 -0
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/adapter.ts +14 -2
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1421 -0
- package/src/messaging/providers/slack/render-transcript.ts +501 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/notifications/signal.ts +1 -2
- package/src/oauth/AGENTS.md +1 -1
- package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
- package/src/oauth/connect-orchestrator.ts +8 -34
- package/src/oauth/connect-types.ts +6 -10
- package/src/oauth/manual-token-connection.ts +23 -0
- package/src/oauth/oauth-store.ts +31 -14
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -106
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +1223 -0
- package/src/permissions/approval-policy.ts +309 -0
- package/src/permissions/arg-parser.test.ts +161 -0
- package/src/permissions/arg-parser.ts +141 -0
- package/src/permissions/bash-risk-classifier.test.ts +1620 -0
- package/src/permissions/bash-risk-classifier.ts +950 -0
- package/src/permissions/checker.ts +348 -711
- package/src/permissions/command-registry.test.ts +774 -0
- package/src/permissions/command-registry.ts +1005 -0
- package/src/permissions/defaults.ts +28 -79
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +262 -0
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/shell-identity.ts +2 -42
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +161 -62
- package/src/permissions/types.ts +25 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +9 -19
- package/src/platform/client.ts +19 -1
- package/src/plugins/defaults/circuit-breaker.ts +146 -0
- package/src/plugins/defaults/compaction.ts +145 -0
- package/src/plugins/defaults/empty-response.ts +126 -0
- package/src/plugins/defaults/history-repair.ts +85 -0
- package/src/plugins/defaults/index.ts +116 -0
- package/src/plugins/defaults/injectors.ts +491 -0
- package/src/plugins/defaults/llm-call.ts +82 -0
- package/src/plugins/defaults/memory-retrieval.ts +226 -0
- package/src/plugins/defaults/overflow-reduce.ts +181 -0
- package/src/plugins/defaults/persistence.ts +129 -0
- package/src/plugins/defaults/title-generate.ts +95 -0
- package/src/plugins/defaults/token-estimate.ts +104 -0
- package/src/plugins/defaults/tool-error.ts +126 -0
- package/src/plugins/defaults/tool-execute.ts +89 -0
- package/src/plugins/defaults/tool-result-truncate.ts +88 -0
- package/src/plugins/pipeline.ts +316 -0
- package/src/plugins/plugin-skill-contributions.ts +292 -0
- package/src/plugins/registry.ts +241 -0
- package/src/plugins/types.ts +1134 -0
- package/src/plugins/user-loader.ts +177 -0
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/BOOTSTRAP.md +27 -77
- package/src/prompts/templates/SOUL.md +2 -2
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +183 -14
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/gemini/client.ts +65 -2
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +524 -33
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +57 -1
- package/src/providers/openai/responses-provider.ts +86 -9
- package/src/providers/openrouter/client.ts +80 -9
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +19 -8
- package/src/providers/retry.ts +174 -39
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +7 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +646 -0
- package/src/providers/speech-to-text/xai-realtime.ts +821 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +93 -3
- package/src/runtime/AGENTS.md +27 -18
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
- package/src/runtime/__tests__/client-registry.test.ts +293 -0
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/agent-wake.ts +63 -22
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/btw-sidechain.ts +13 -3
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/client-registry.ts +261 -0
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +129 -9
- package/src/runtime/http-types.ts +23 -3
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/vbundle-builder.ts +1 -22
- package/src/runtime/migrations/vbundle-importer.ts +154 -9
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +78 -0
- package/src/runtime/routes/approval-routes.ts +29 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
- package/src/runtime/routes/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +351 -138
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +120 -2
- package/src/runtime/routes/inbound-message-handler.ts +987 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/integrations/slack/channel.ts +25 -3
- package/src/runtime/routes/llm-context-normalization.ts +23 -1
- package/src/runtime/routes/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +720 -127
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
- package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
- package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
- package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
- package/src/runtime/routes/playground/deps.ts +56 -0
- package/src/runtime/routes/playground/force-compact.ts +73 -0
- package/src/runtime/routes/playground/guard.ts +37 -0
- package/src/runtime/routes/playground/index.ts +28 -0
- package/src/runtime/routes/playground/inject-failures.ts +159 -0
- package/src/runtime/routes/playground/reset-circuit.ts +115 -0
- package/src/runtime/routes/playground/seed-conversation.ts +139 -0
- package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
- package/src/runtime/routes/playground/state.ts +78 -0
- package/src/runtime/routes/schedule-routes.ts +89 -8
- package/src/runtime/routes/settings-routes.ts +4 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +3 -2
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
- package/src/runtime/services/analyze-conversation.ts +12 -16
- package/src/runtime/skill-route-registry.ts +97 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +56 -8
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +98 -35
- package/src/security/secure-keys.ts +7 -8
- package/src/security/token-manager.ts +27 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/skills/catalog-cache.ts +35 -9
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
- package/src/stt/daemon-batch-transcriber.ts +33 -0
- package/src/stt/stt-stream-session.ts +8 -1
- package/src/stt/types.ts +5 -1
- package/src/subagent/manager.ts +41 -13
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +234 -2
- package/src/tools/browser/browser-execution.ts +150 -54
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +129 -73
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/script-proxy/session-manager.ts +37 -1
- package/src/tools/network/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +116 -46
- package/src/tools/policy-context.ts +29 -8
- package/src/tools/registry.ts +195 -6
- package/src/tools/schedule/create.ts +23 -8
- package/src/tools/schedule/update.ts +3 -1
- package/src/tools/secret-detection-handler.ts +0 -51
- package/src/tools/side-effects.ts +0 -11
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/system/avatar-generator.ts +6 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +1 -0
- package/src/tools/tool-manifest.ts +6 -21
- package/src/tools/types.ts +40 -5
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +240 -13
- package/src/tts/provider-catalog.ts +18 -0
- package/src/tts/providers/index.ts +2 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/types.ts +46 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +9 -4
- package/src/util/pricing.ts +41 -8
- package/src/watcher/engine.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/006-services-config.ts +2 -4
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +56 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
- package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
- package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +28 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/tsconfig.json +1 -1
- package/hook-templates/debug-prompt-logger/hook.json +0 -7
- package/hook-templates/debug-prompt-logger/run.sh +0 -66
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
- package/src/__tests__/gmail-archive-gate.test.ts +0 -246
- package/src/__tests__/gmail-preferences.test.ts +0 -117
- package/src/__tests__/hooks-blocking.test.ts +0 -178
- package/src/__tests__/hooks-cli.test.ts +0 -182
- package/src/__tests__/hooks-config.test.ts +0 -108
- package/src/__tests__/hooks-discovery.test.ts +0 -211
- package/src/__tests__/hooks-integration.test.ts +0 -196
- package/src/__tests__/hooks-manager.test.ts +0 -226
- package/src/__tests__/hooks-runner.test.ts +0 -175
- package/src/__tests__/hooks-settings.test.ts +0 -160
- package/src/__tests__/hooks-templates.test.ts +0 -169
- package/src/__tests__/hooks-ts-runner.test.ts +0 -170
- package/src/__tests__/hooks-watch.test.ts +0 -112
- package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
- package/src/__tests__/oauth-scope-policy.test.ts +0 -180
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
- package/src/__tests__/send-notification-tool.test.ts +0 -83
- package/src/__tests__/update-bulletin-format.test.ts +0 -181
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -478
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/doctor.ts +0 -341
- package/src/cli/commands/shotgun.ts +0 -266
- package/src/config/bundled-skills/browser/SKILL.md +0 -88
- package/src/config/bundled-skills/browser/TOOLS.json +0 -516
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/conversations/SKILL.md +0 -20
- package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -66
- package/src/config/bundled-skills/gmail/SKILL.md +0 -221
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
- package/src/config/bundled-skills/notifications/SKILL.md +0 -40
- package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
- package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
- package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
- package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
- package/src/config/bundled-skills/slack/SKILL.md +0 -108
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/daemon/context-overflow-approval.ts +0 -52
- package/src/daemon/watch-handler.ts +0 -399
- package/src/hooks/cli.ts +0 -253
- package/src/hooks/config.ts +0 -100
- package/src/hooks/discovery.ts +0 -135
- package/src/hooks/manager.ts +0 -179
- package/src/hooks/runner.ts +0 -117
- package/src/hooks/templates.ts +0 -77
- package/src/hooks/types.ts +0 -75
- package/src/oauth/scope-policy.ts +0 -89
- package/src/prompts/templates/UPDATES.md +0 -50
- package/src/prompts/update-bulletin-format.ts +0 -85
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -139
- package/src/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/signals/shotgun.ts +0 -203
- package/src/tools/watch/screen-watch.ts +0 -144
- package/src/tools/watch/watch-state.ts +0 -142
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -23,6 +23,10 @@ export interface UserMessage {
|
|
|
23
23
|
microphonePermissionGranted?: boolean;
|
|
24
24
|
/** Structured command intent — bypasses text parsing when present. */
|
|
25
25
|
commandIntent?: CommandIntent;
|
|
26
|
+
/** Client-generated correlation nonce for echo dedup. See
|
|
27
|
+
* `UserMessageEcho.clientMessageId` — the server echoes this value
|
|
28
|
+
* back on the matching `user_message_echo` event. */
|
|
29
|
+
clientMessageId?: string;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export interface ConfirmationResponse {
|
|
@@ -33,7 +37,6 @@ export interface ConfirmationResponse {
|
|
|
33
37
|
| "allow_10m"
|
|
34
38
|
| "allow_conversation"
|
|
35
39
|
| "always_allow"
|
|
36
|
-
| "always_allow_high_risk"
|
|
37
40
|
| "deny"
|
|
38
41
|
| "always_deny";
|
|
39
42
|
selectedPattern?: string;
|
|
@@ -67,6 +70,11 @@ export interface UserMessageEcho {
|
|
|
67
70
|
/** Server-generated request ID for the send. Allows correlation with
|
|
68
71
|
* `message_queued` / `message_dequeued` events for the same turn. */
|
|
69
72
|
requestId?: string;
|
|
73
|
+
/** Client-generated correlation nonce from the HTTP POST body. Echoed
|
|
74
|
+
* back so the originating client can dedupe its optimistic row even
|
|
75
|
+
* if the SSE echo beats the 202 response. Absent for synthetic echoes
|
|
76
|
+
* (e.g. surface-action prompts) that did not originate from a client POST. */
|
|
77
|
+
clientMessageId?: string;
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
export interface AssistantTextDelta {
|
|
@@ -137,6 +145,14 @@ export interface ToolResult {
|
|
|
137
145
|
imageDataList?: string[];
|
|
138
146
|
/** The tool_use block ID for client-side correlation. */
|
|
139
147
|
toolUseId?: string;
|
|
148
|
+
/** Risk level from the classifier ("low" | "medium" | "high" | "unknown"). */
|
|
149
|
+
riskLevel?: string;
|
|
150
|
+
/** Human-readable reason for the risk classification. */
|
|
151
|
+
riskReason?: string;
|
|
152
|
+
/** Whether the daemon is running in a containerized (Docker) environment. */
|
|
153
|
+
isContainerized?: boolean;
|
|
154
|
+
/** Scope options ladder for the rule editor modal (narrowest to broadest). */
|
|
155
|
+
riskScopeOptions?: Array<{ pattern: string; label: string }>;
|
|
140
156
|
}
|
|
141
157
|
|
|
142
158
|
export interface ConfirmationRequest {
|
|
@@ -145,6 +161,10 @@ export interface ConfirmationRequest {
|
|
|
145
161
|
toolName: string;
|
|
146
162
|
input: Record<string, unknown>;
|
|
147
163
|
riskLevel: string;
|
|
164
|
+
/** Human-readable reason for the risk classification (e.g. "Modifies remote repository state"). */
|
|
165
|
+
riskReason?: string;
|
|
166
|
+
/** Whether the daemon is running in a containerized (Docker) environment. */
|
|
167
|
+
isContainerized?: boolean;
|
|
148
168
|
executionTarget?: "sandbox" | "host";
|
|
149
169
|
allowlistOptions: Array<{
|
|
150
170
|
label: string;
|
|
@@ -8,8 +8,6 @@ export interface AddTrustRule {
|
|
|
8
8
|
pattern: string;
|
|
9
9
|
scope: string;
|
|
10
10
|
decision: "allow" | "deny" | "ask";
|
|
11
|
-
/** When true, the rule also covers high-risk invocations. */
|
|
12
|
-
allowHighRisk?: boolean;
|
|
13
11
|
/** Execution target override for this rule. */
|
|
14
12
|
executionTarget?: "host" | "sandbox";
|
|
15
13
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ContextOverflowError } from "../providers/types.js";
|
|
4
|
+
import { parseActualTokensFromError } from "./parse-actual-tokens-from-error.js";
|
|
4
5
|
|
|
5
6
|
describe("parseActualTokensFromError", () => {
|
|
6
7
|
test("returns null for null input", () => {
|
|
@@ -68,4 +69,59 @@ describe("parseActualTokensFromError", () => {
|
|
|
68
69
|
test("returns null when no numeric pattern matches", () => {
|
|
69
70
|
expect(parseActualTokensFromError("context window exceeded")).toBeNull();
|
|
70
71
|
});
|
|
72
|
+
|
|
73
|
+
// ── Typed-error branch ─────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
test("prefers ContextOverflowError.actualTokens over string-regex match", () => {
|
|
76
|
+
// Message would regex-parse to 999999, but typed field wins.
|
|
77
|
+
const err = new ContextOverflowError(
|
|
78
|
+
"Anthropic API error (400): prompt is too long: 999999 tokens > 200000 maximum",
|
|
79
|
+
"anthropic",
|
|
80
|
+
{
|
|
81
|
+
actualTokens: 242201,
|
|
82
|
+
maxTokens: 200000,
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("falls back to regex when ContextOverflowError has no actualTokens", () => {
|
|
89
|
+
const err = new ContextOverflowError(
|
|
90
|
+
"OpenAI API error (400): too many input tokens: 150000 > 128000",
|
|
91
|
+
"openai",
|
|
92
|
+
{},
|
|
93
|
+
);
|
|
94
|
+
expect(parseActualTokensFromError(err)).toBe(150000);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("returns null when ContextOverflowError has neither typed field nor matching message", () => {
|
|
98
|
+
const err = new ContextOverflowError("context window exceeded", "openai");
|
|
99
|
+
expect(parseActualTokensFromError(err)).toBeNull();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("typed-error parsing takes precedence over string regex even when both present", () => {
|
|
103
|
+
// String has 999999 tokens > 200000; typed field says 242201.
|
|
104
|
+
// The typed field MUST win — this is the core contract.
|
|
105
|
+
const err = new ContextOverflowError(
|
|
106
|
+
"prompt is too long: 999999 tokens > 200000 maximum",
|
|
107
|
+
"anthropic",
|
|
108
|
+
{ actualTokens: 242201 },
|
|
109
|
+
);
|
|
110
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("accepts an untyped Error instance and parses its message", () => {
|
|
114
|
+
const err = new Error("prompt is too long: 242201 tokens > 200000 maximum");
|
|
115
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("ignores non-numeric/invalid actualTokens on typed error", () => {
|
|
119
|
+
// actualTokens of 0 should fall through (typed check requires > 0).
|
|
120
|
+
const err = new ContextOverflowError(
|
|
121
|
+
"prompt is too long: 242201 tokens > 200000 maximum",
|
|
122
|
+
"anthropic",
|
|
123
|
+
{ actualTokens: 0 },
|
|
124
|
+
);
|
|
125
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
126
|
+
});
|
|
71
127
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { isContextOverflowError } from "../providers/types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse the actual token count reported by the provider for a
|
|
5
|
+
* context-too-large failure.
|
|
6
|
+
*
|
|
7
|
+
* Prefers the typed `ContextOverflowError.actualTokens` field when the
|
|
8
|
+
* thrown error is one. Falls back to regex-parsing the message for patterns
|
|
9
|
+
* like:
|
|
10
|
+
* "prompt is too long: 242201 tokens > 200000 maximum" (Anthropic)
|
|
11
|
+
* "too many input tokens: 242201 > 200000" (OpenAI)
|
|
12
|
+
*
|
|
13
|
+
* The regex path remains a safety net for provider-adapter paths (e.g.
|
|
14
|
+
* managed-proxy rewrappers) that surface untyped errors.
|
|
15
|
+
*
|
|
16
|
+
* Accepts a raw error object, an `Error` instance, or a plain string.
|
|
17
|
+
* Returns the actual token count, or `null` when it cannot be determined.
|
|
18
|
+
*/
|
|
19
|
+
export function parseActualTokensFromError(
|
|
20
|
+
errorOrMessage: unknown,
|
|
21
|
+
): number | null {
|
|
22
|
+
// Typed path — the provider client wrapped a matching upstream error as
|
|
23
|
+
// ContextOverflowError. Use the parsed field directly when available.
|
|
24
|
+
if (isContextOverflowError(errorOrMessage)) {
|
|
25
|
+
const actual = errorOrMessage.actualTokens;
|
|
26
|
+
if (typeof actual === "number" && actual > 0) return actual;
|
|
27
|
+
// Typed error without `actualTokens` — fall through to regex-parse the
|
|
28
|
+
// underlying message in case the upstream body carries it in text form.
|
|
29
|
+
return parseFromMessage(errorOrMessage.message ?? null);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Untyped path — accept either an Error or a string.
|
|
33
|
+
if (errorOrMessage == null) return null;
|
|
34
|
+
if (typeof errorOrMessage === "string") {
|
|
35
|
+
return parseFromMessage(errorOrMessage);
|
|
36
|
+
}
|
|
37
|
+
if (typeof errorOrMessage === "object" && "message" in errorOrMessage) {
|
|
38
|
+
const msg = (errorOrMessage as { message?: unknown }).message;
|
|
39
|
+
if (typeof msg === "string") return parseFromMessage(msg);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function parseFromMessage(errorMessage: string | null): number | null {
|
|
45
|
+
if (!errorMessage) return null;
|
|
46
|
+
|
|
47
|
+
// Match patterns like "242201 tokens > 200000" or "242201 > 200000 maximum"
|
|
48
|
+
const match = errorMessage.match(
|
|
49
|
+
/(\d[\d,]*)\s*tokens?\s*[>≥]|:\s*(\d[\d,]*)\s*[>≥]/i,
|
|
50
|
+
);
|
|
51
|
+
if (match) {
|
|
52
|
+
const raw = (match[1] || match[2]).replace(/,/g, "");
|
|
53
|
+
const parsed = parseInt(raw, 10);
|
|
54
|
+
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Fallback: match "too many input tokens: N > M"
|
|
58
|
+
const fallback = errorMessage.match(/(\d[\d,]*)\s*[>≥]\s*\d/);
|
|
59
|
+
if (fallback) {
|
|
60
|
+
const raw = fallback[1].replace(/,/g, "");
|
|
61
|
+
const parsed = parseInt(raw, 10);
|
|
62
|
+
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
|
|
4
|
+
import type { ContentBlock, Message } from "../providers/types.js";
|
|
5
|
+
import type { Conversation } from "./conversation.js";
|
|
6
|
+
import { getInContextPkbPaths } from "./pkb-context-tracker.js";
|
|
7
|
+
|
|
8
|
+
const WORKING_DIR = path.resolve("/tmp/test-pkb-root");
|
|
9
|
+
const PKB_ROOT = path.join(WORKING_DIR, "pkb");
|
|
10
|
+
|
|
11
|
+
// The helper only reads `conversation.messages`. Constructing a real
|
|
12
|
+
// `Conversation` instance would require a full daemon setup; casting a
|
|
13
|
+
// minimal object through `unknown` keeps the test isolated and pure while
|
|
14
|
+
// still exercising the public type.
|
|
15
|
+
function makeConversation(messages: Message[]): Conversation {
|
|
16
|
+
return { messages } as unknown as Conversation;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function fileReadToolUse(filePath: string): ContentBlock {
|
|
20
|
+
return {
|
|
21
|
+
type: "tool_use",
|
|
22
|
+
id: `toolu_${Math.random().toString(36).slice(2, 10)}`,
|
|
23
|
+
name: "file_read",
|
|
24
|
+
input: { path: filePath },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function assistantMessageWithBlocks(blocks: ContentBlock[]): Message {
|
|
29
|
+
return { role: "assistant", content: blocks };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe("getInContextPkbPaths", () => {
|
|
33
|
+
test("auto-inject paths are always present (even with empty conversation)", () => {
|
|
34
|
+
const conversation = makeConversation([]);
|
|
35
|
+
const result = getInContextPkbPaths(
|
|
36
|
+
conversation,
|
|
37
|
+
["notes/index.md", "journal/2026-04-18.md"],
|
|
38
|
+
PKB_ROOT,
|
|
39
|
+
WORKING_DIR,
|
|
40
|
+
);
|
|
41
|
+
expect(result).toEqual(
|
|
42
|
+
new Set([
|
|
43
|
+
path.join(PKB_ROOT, "notes/index.md"),
|
|
44
|
+
path.join(PKB_ROOT, "journal/2026-04-18.md"),
|
|
45
|
+
]),
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("includes a file_read tool_use with a path inside pkbRoot", () => {
|
|
50
|
+
const insidePath = path.join(PKB_ROOT, "notes/thoughts.md");
|
|
51
|
+
const conversation = makeConversation([
|
|
52
|
+
assistantMessageWithBlocks([fileReadToolUse(insidePath)]),
|
|
53
|
+
]);
|
|
54
|
+
const result = getInContextPkbPaths(conversation, [], PKB_ROOT, WORKING_DIR);
|
|
55
|
+
expect(result).toEqual(new Set([insidePath]));
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("excludes a file_read tool_use whose path is outside pkbRoot", () => {
|
|
59
|
+
const conversation = makeConversation([
|
|
60
|
+
assistantMessageWithBlocks([fileReadToolUse("/etc/hosts")]),
|
|
61
|
+
]);
|
|
62
|
+
const result = getInContextPkbPaths(conversation, [], PKB_ROOT, WORKING_DIR);
|
|
63
|
+
expect(result).toEqual(new Set());
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("excludes a non-file_read tool_use with a PKB-like path", () => {
|
|
67
|
+
const insidePath = path.join(PKB_ROOT, "notes/thoughts.md");
|
|
68
|
+
const bogus: ContentBlock = {
|
|
69
|
+
type: "tool_use",
|
|
70
|
+
id: "toolu_bogus",
|
|
71
|
+
name: "file_write",
|
|
72
|
+
input: { path: insidePath },
|
|
73
|
+
};
|
|
74
|
+
const conversation = makeConversation([
|
|
75
|
+
assistantMessageWithBlocks([bogus]),
|
|
76
|
+
]);
|
|
77
|
+
const result = getInContextPkbPaths(conversation, [], PKB_ROOT, WORKING_DIR);
|
|
78
|
+
expect(result).toEqual(new Set());
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("post-compaction context-summary user message returns only auto-inject paths", () => {
|
|
82
|
+
// After compaction, the structured tool_use blocks have been serialized
|
|
83
|
+
// away and the conversation is just a user-role text message containing
|
|
84
|
+
// the summary.
|
|
85
|
+
const summaryMessage: Message = {
|
|
86
|
+
role: "user",
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
text: "[Context summary] Previously you read notes/thoughts.md and journal/2026-04-18.md...",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
const conversation = makeConversation([summaryMessage]);
|
|
95
|
+
const autoInject = ["profile/identity.md"];
|
|
96
|
+
const result = getInContextPkbPaths(
|
|
97
|
+
conversation,
|
|
98
|
+
autoInject,
|
|
99
|
+
PKB_ROOT,
|
|
100
|
+
WORKING_DIR,
|
|
101
|
+
);
|
|
102
|
+
expect(result).toEqual(
|
|
103
|
+
new Set([path.join(PKB_ROOT, "profile/identity.md")]),
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("path-traversal attempt via ../../etc/passwd is excluded", () => {
|
|
108
|
+
const conversation = makeConversation([
|
|
109
|
+
assistantMessageWithBlocks([
|
|
110
|
+
fileReadToolUse("../../etc/passwd"),
|
|
111
|
+
fileReadToolUse("notes/../../../etc/shadow"),
|
|
112
|
+
]),
|
|
113
|
+
]);
|
|
114
|
+
const result = getInContextPkbPaths(conversation, [], PKB_ROOT, WORKING_DIR);
|
|
115
|
+
expect(result).toEqual(new Set());
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("relative file_read path outside pkbRoot is excluded", () => {
|
|
119
|
+
// These are resolved against `workingDir` (matching `file_read`'s own
|
|
120
|
+
// rule), land outside `pkbRoot`, and are correctly ignored.
|
|
121
|
+
const conversation = makeConversation([
|
|
122
|
+
assistantMessageWithBlocks([
|
|
123
|
+
fileReadToolUse("notes.md"),
|
|
124
|
+
fileReadToolUse("./deep/subdir/file.md"),
|
|
125
|
+
]),
|
|
126
|
+
]);
|
|
127
|
+
const result = getInContextPkbPaths(conversation, [], PKB_ROOT, WORKING_DIR);
|
|
128
|
+
expect(result).toEqual(new Set());
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("workspace-relative file_read path inside pkb/ is recognized", () => {
|
|
132
|
+
// The model emits workspace-relative paths like `pkb/threads.md`.
|
|
133
|
+
// The tracker resolves them against `workingDir` (matching `file_read`'s
|
|
134
|
+
// own rule) and verifies the result falls inside `pkbRoot`.
|
|
135
|
+
const conversation = makeConversation([
|
|
136
|
+
assistantMessageWithBlocks([fileReadToolUse("pkb/threads.md")]),
|
|
137
|
+
]);
|
|
138
|
+
const result = getInContextPkbPaths(conversation, [], PKB_ROOT, WORKING_DIR);
|
|
139
|
+
expect(result).toEqual(new Set([path.join(PKB_ROOT, "threads.md")]));
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("resolves relative auto-inject paths against pkbRoot", () => {
|
|
143
|
+
const conversation = makeConversation([]);
|
|
144
|
+
const result = getInContextPkbPaths(
|
|
145
|
+
conversation,
|
|
146
|
+
["./notes/relative.md"],
|
|
147
|
+
PKB_ROOT,
|
|
148
|
+
WORKING_DIR,
|
|
149
|
+
);
|
|
150
|
+
expect(result).toEqual(
|
|
151
|
+
new Set([path.join(PKB_ROOT, "notes/relative.md")]),
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("auto-inject and file_read paths union (no duplicates)", () => {
|
|
156
|
+
const insidePath = path.join(PKB_ROOT, "notes/shared.md");
|
|
157
|
+
const conversation = makeConversation([
|
|
158
|
+
assistantMessageWithBlocks([fileReadToolUse(insidePath)]),
|
|
159
|
+
]);
|
|
160
|
+
const result = getInContextPkbPaths(
|
|
161
|
+
conversation,
|
|
162
|
+
["notes/shared.md"],
|
|
163
|
+
PKB_ROOT,
|
|
164
|
+
WORKING_DIR,
|
|
165
|
+
);
|
|
166
|
+
expect(result.size).toBe(1);
|
|
167
|
+
expect(result.has(insidePath)).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pkb-context-tracker
|
|
3
|
+
*
|
|
4
|
+
* Pure helper that reports which PKB file paths are already "in context" for
|
|
5
|
+
* a given conversation. A path is considered in context if either:
|
|
6
|
+
*
|
|
7
|
+
* 1. It was explicitly auto-injected (caller supplies `autoInjectPaths`),
|
|
8
|
+
* typically via a system-reminder that embeds the file contents.
|
|
9
|
+
* 2. The conversation history contains a structured `file_read` tool_use
|
|
10
|
+
* block whose `input.path` — resolved the same way `file_read` itself
|
|
11
|
+
* resolves it (absolute as-is, relative against `workingDir`) — lands
|
|
12
|
+
* inside `pkbRoot`.
|
|
13
|
+
*
|
|
14
|
+
* Used by the PKB system reminder so we don't suggest files the model has
|
|
15
|
+
* already loaded.
|
|
16
|
+
*
|
|
17
|
+
* Post-compaction note: structured `tool_use` blocks get serialized into a
|
|
18
|
+
* plain-text summary and dropped from the live message array. After a
|
|
19
|
+
* compaction, this helper will naturally only see the `autoInjectPaths` —
|
|
20
|
+
* which is the desired semantics.
|
|
21
|
+
*
|
|
22
|
+
* No I/O, no globals, no side effects.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
|
|
27
|
+
import type { ContentBlock, Message } from "../providers/types.js";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Minimal shape this helper needs from a `Conversation`. Defining it as an
|
|
31
|
+
* interface (rather than importing the full `Conversation` class) keeps the
|
|
32
|
+
* helper pure and trivial to unit-test without constructing a real daemon
|
|
33
|
+
* conversation.
|
|
34
|
+
*/
|
|
35
|
+
export interface PkbContextConversation {
|
|
36
|
+
messages: Message[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The structured tool_use block name the assistant emits when reading files
|
|
41
|
+
* from the workspace (see `assistant/src/tools/filesystem/read.ts`).
|
|
42
|
+
*/
|
|
43
|
+
const FILE_READ_TOOL_NAME = "file_read";
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Resolve `candidate` against `pkbRoot` and return the absolute path ONLY if
|
|
47
|
+
* it stays inside `pkbRoot`. Otherwise return `undefined`. Guards against
|
|
48
|
+
* `..`-style path traversal.
|
|
49
|
+
*/
|
|
50
|
+
function resolveInsidePkbRoot(
|
|
51
|
+
candidate: string,
|
|
52
|
+
pkbRoot: string,
|
|
53
|
+
): string | undefined {
|
|
54
|
+
if (typeof candidate !== "string" || candidate.length === 0) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
const resolved = path.resolve(pkbRoot, candidate);
|
|
58
|
+
// `path.resolve` normalizes any `..` segments in `candidate`. We still need
|
|
59
|
+
// to verify the result is inside `pkbRoot`. Comparing with a trailing
|
|
60
|
+
// separator avoids treating `<pkbRoot>somethingElse` as inside the root.
|
|
61
|
+
if (resolved === pkbRoot) {
|
|
62
|
+
return resolved;
|
|
63
|
+
}
|
|
64
|
+
const rootWithSep = pkbRoot.endsWith(path.sep) ? pkbRoot : pkbRoot + path.sep;
|
|
65
|
+
if (resolved.startsWith(rootWithSep)) {
|
|
66
|
+
return resolved;
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns the set of absolute PKB file paths already in the conversation's
|
|
73
|
+
* in-memory context. This is the union of `autoInjectPaths` (resolved into
|
|
74
|
+
* `pkbRoot`) and any `file_read` tool_use block inputs found in
|
|
75
|
+
* `conversation.messages` that resolve inside `pkbRoot`.
|
|
76
|
+
*
|
|
77
|
+
* `file_read` resolves its `path` argument against `workingDir` (the tool's
|
|
78
|
+
* working directory), so this helper mirrors that rule: relative tool paths
|
|
79
|
+
* are resolved against `workingDir`, absolute paths are taken as-is, and the
|
|
80
|
+
* resulting absolute path is then accepted only if it falls inside `pkbRoot`.
|
|
81
|
+
*
|
|
82
|
+
* Paths outside `pkbRoot` (including `..`-traversal attempts) are excluded.
|
|
83
|
+
* Tool uses whose `name` is not `file_read` are ignored.
|
|
84
|
+
*/
|
|
85
|
+
export function getInContextPkbPaths(
|
|
86
|
+
conversation: PkbContextConversation,
|
|
87
|
+
autoInjectPaths: string[],
|
|
88
|
+
pkbRoot: string,
|
|
89
|
+
workingDir: string,
|
|
90
|
+
): Set<string> {
|
|
91
|
+
const normalizedRoot = path.resolve(pkbRoot);
|
|
92
|
+
const normalizedWorkingDir = path.resolve(workingDir);
|
|
93
|
+
const inContext = new Set<string>();
|
|
94
|
+
|
|
95
|
+
for (const candidate of autoInjectPaths) {
|
|
96
|
+
const resolved = resolveInsidePkbRoot(candidate, normalizedRoot);
|
|
97
|
+
if (resolved !== undefined) {
|
|
98
|
+
inContext.add(resolved);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for (const message of conversation.messages) {
|
|
103
|
+
if (!Array.isArray(message.content)) continue;
|
|
104
|
+
for (const block of message.content as ContentBlock[]) {
|
|
105
|
+
if (block.type !== "tool_use") continue;
|
|
106
|
+
if (block.name !== FILE_READ_TOOL_NAME) continue;
|
|
107
|
+
const rawPath = block.input?.path;
|
|
108
|
+
if (typeof rawPath !== "string" || rawPath.length === 0) continue;
|
|
109
|
+
// Mirror `file_read`'s own path resolution: absolute paths are taken
|
|
110
|
+
// as-is; relative paths resolve against the tool's working directory
|
|
111
|
+
// (NOT `pkbRoot`). Resolving relative paths against `pkbRoot` would
|
|
112
|
+
// double-prefix workspace-relative inputs like `pkb/threads.md` into
|
|
113
|
+
// `<pkbRoot>/pkb/threads.md` and miss the actually-loaded file.
|
|
114
|
+
const absolute = path.isAbsolute(rawPath)
|
|
115
|
+
? path.resolve(rawPath)
|
|
116
|
+
: path.resolve(normalizedWorkingDir, rawPath);
|
|
117
|
+
const resolved = resolveInsidePkbRoot(absolute, normalizedRoot);
|
|
118
|
+
if (resolved !== undefined) {
|
|
119
|
+
inContext.add(resolved);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return inContext;
|
|
125
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { buildPkbReminder } from "./pkb-reminder-builder.js";
|
|
4
|
+
|
|
5
|
+
// Byte-for-byte fixture of the original PKB_SYSTEM_REMINDER from
|
|
6
|
+
// conversation-runtime-assembly.ts. If this ever needs to change, the
|
|
7
|
+
// matching string in conversation-runtime-assembly.ts must change too.
|
|
8
|
+
const ORIGINAL_REMINDER =
|
|
9
|
+
"<system_reminder>" +
|
|
10
|
+
"\nRead any unread Personal Knowledge Base files that might be even partially relevant to this conversation" +
|
|
11
|
+
"\nUse `remember` for anything you learn immediately" +
|
|
12
|
+
"\n</system_reminder>";
|
|
13
|
+
|
|
14
|
+
describe("buildPkbReminder", () => {
|
|
15
|
+
test("empty hints returns exact original reminder byte-for-byte", () => {
|
|
16
|
+
expect(buildPkbReminder([])).toBe(ORIGINAL_REMINDER);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("single hint renders one bullet with no duplicates or trailing blank line", () => {
|
|
20
|
+
const out = buildPkbReminder(["projects/alpha.md"]);
|
|
21
|
+
const expected =
|
|
22
|
+
"<system_reminder>" +
|
|
23
|
+
"\nRead any unread Personal Knowledge Base files that might be even partially relevant to this conversation." +
|
|
24
|
+
"\nBased on the current context, these files look especially relevant:" +
|
|
25
|
+
"\n- projects/alpha.md" +
|
|
26
|
+
"\nUse `remember` for anything you learn immediately" +
|
|
27
|
+
"\n</system_reminder>";
|
|
28
|
+
expect(out).toBe(expected);
|
|
29
|
+
|
|
30
|
+
// Exactly one bullet.
|
|
31
|
+
const bulletCount = (out.match(/^- /gm) ?? []).length;
|
|
32
|
+
expect(bulletCount).toBe(1);
|
|
33
|
+
|
|
34
|
+
// No blank line before closing tag.
|
|
35
|
+
expect(out.includes("\n\n</system_reminder>")).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("three hints render all three in order", () => {
|
|
39
|
+
const hints = ["a.md", "sub/b.md", "c/d/e.md"];
|
|
40
|
+
const out = buildPkbReminder(hints);
|
|
41
|
+
const expected =
|
|
42
|
+
"<system_reminder>" +
|
|
43
|
+
"\nRead any unread Personal Knowledge Base files that might be even partially relevant to this conversation." +
|
|
44
|
+
"\nBased on the current context, these files look especially relevant:" +
|
|
45
|
+
"\n- a.md" +
|
|
46
|
+
"\n- sub/b.md" +
|
|
47
|
+
"\n- c/d/e.md" +
|
|
48
|
+
"\nUse `remember` for anything you learn immediately" +
|
|
49
|
+
"\n</system_reminder>";
|
|
50
|
+
expect(out).toBe(expected);
|
|
51
|
+
|
|
52
|
+
// Order check — each should appear after the previous.
|
|
53
|
+
const idxA = out.indexOf("- a.md");
|
|
54
|
+
const idxB = out.indexOf("- sub/b.md");
|
|
55
|
+
const idxC = out.indexOf("- c/d/e.md");
|
|
56
|
+
expect(idxA).toBeGreaterThan(-1);
|
|
57
|
+
expect(idxB).toBeGreaterThan(idxA);
|
|
58
|
+
expect(idxC).toBeGreaterThan(idxB);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("hints with special chars (< and &) are emitted verbatim (no escaping)", () => {
|
|
62
|
+
const hints = ["weird<name>.md", "foo&bar.md"];
|
|
63
|
+
const out = buildPkbReminder(hints);
|
|
64
|
+
expect(out).toContain("- weird<name>.md");
|
|
65
|
+
expect(out).toContain("- foo&bar.md");
|
|
66
|
+
// Ensure no HTML-style escaping happened.
|
|
67
|
+
expect(out).not.toContain("<");
|
|
68
|
+
expect(out).not.toContain("&");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render the PKB system_reminder text, optionally with a bulleted list of
|
|
3
|
+
* hint paths that look especially relevant to the current conversation.
|
|
4
|
+
*
|
|
5
|
+
* When `hints` is empty, returns the legacy two-line reminder byte-for-byte.
|
|
6
|
+
* When `hints` is non-empty, renders an extended reminder with a bullet per
|
|
7
|
+
* hint. Hints are emitted verbatim — they are trusted internal paths, not
|
|
8
|
+
* user input, so no escaping is performed.
|
|
9
|
+
*
|
|
10
|
+
* Caller is responsible for capping the hints array at 3 entries.
|
|
11
|
+
*/
|
|
12
|
+
export function buildPkbReminder(hints: ReadonlyArray<string>): string {
|
|
13
|
+
if (hints.length === 0) {
|
|
14
|
+
return (
|
|
15
|
+
"<system_reminder>" +
|
|
16
|
+
"\nRead any unread Personal Knowledge Base files that might be even partially relevant to this conversation" +
|
|
17
|
+
"\nUse `remember` for anything you learn immediately" +
|
|
18
|
+
"\n</system_reminder>"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const bullets = hints.map((h) => `- ${h}`).join("\n");
|
|
23
|
+
return (
|
|
24
|
+
"<system_reminder>" +
|
|
25
|
+
"\nRead any unread Personal Knowledge Base files that might be even partially relevant to this conversation." +
|
|
26
|
+
"\nBased on the current context, these files look especially relevant:" +
|
|
27
|
+
`\n${bullets}` +
|
|
28
|
+
"\nUse `remember` for anything you learn immediately" +
|
|
29
|
+
"\n</system_reminder>"
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -27,6 +27,12 @@ import { googleCalendarProvider } from "../watcher/providers/google-calendar.js"
|
|
|
27
27
|
import { linearProvider } from "../watcher/providers/linear.js";
|
|
28
28
|
import { outlookProvider } from "../watcher/providers/outlook.js";
|
|
29
29
|
import { outlookCalendarProvider } from "../watcher/providers/outlook-calendar.js";
|
|
30
|
+
|
|
31
|
+
// Side-effect import: runs each bundled first-party skill's tool
|
|
32
|
+
// registration before `initializeTools()` so external tools are visible
|
|
33
|
+
// to the LLM. See `external-skills-bootstrap.ts` for the rationale.
|
|
34
|
+
import "./external-skills-bootstrap.js";
|
|
35
|
+
|
|
30
36
|
const log = getLogger("lifecycle");
|
|
31
37
|
|
|
32
38
|
export async function initializeProvidersAndTools(
|