@vellumai/assistant 0.6.4 → 0.6.5
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/ARCHITECTURE.md +32 -36
- package/Dockerfile +12 -0
- package/README.md +3 -4
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +1 -20
- package/docs/architecture/security.md +16 -16
- package/docs/error-handling.md +111 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- 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/openapi.yaml +123 -11
- 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__/approval-cascade.test.ts +31 -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__/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__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +27 -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 +428 -501
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-circuit-breaker.test.ts +336 -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-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +427 -114
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +530 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
- package/src/__tests__/conversation-agent-loop.test.ts +412 -82
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
- package/src/__tests__/conversation-process-callsite.test.ts +306 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
- package/src/__tests__/conversation-queue.test.ts +41 -26
- package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
- package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +34 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
- package/src/__tests__/conversation-speed-override.test.ts +30 -11
- 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 +2 -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 +3 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
- package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- 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__/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__/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 +26 -7
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- 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__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/intent-routing.test.ts +1 -40
- 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__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +684 -0
- package/src/__tests__/model-intents.test.ts +9 -83
- 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__/oauth-store.test.ts +10 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -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__/permission-checker-host-gate.test.ts +1 -1
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/pricing.test.ts +50 -3
- 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 +0 -1
- package/src/__tests__/reaction-persistence.test.ts +560 -0
- 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__/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-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 +160 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor.test.ts +60 -94
- 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__/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-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +1 -13
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +209 -17
- 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/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/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/cli/AGENTS.md +1 -1
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- 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 +666 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +451 -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 +594 -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/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +14 -1
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +300 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- 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/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 +23 -4
- package/src/cli.ts +0 -37
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -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 +11 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -175
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +25 -9
- 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 +30 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/calls.ts +0 -4
- 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 +318 -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 +53 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skills.ts +2 -2
- package/src/context/__tests__/compact-prompt.test.ts +45 -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 +12 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/window-manager.ts +229 -25
- 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/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 -1
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
- package/src/daemon/conversation-agent-loop.ts +462 -80
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-lifecycle.ts +30 -6
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-process.ts +10 -4
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +760 -29
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +10 -5
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +118 -30
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- 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 +54 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +2 -2
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +76 -14
- package/src/daemon/message-types/conversations.ts +14 -0
- package/src/daemon/message-types/messages.ts +9 -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 +117 -9
- package/src/daemon/tool-side-effects.ts +0 -9
- package/src/daemon/watch-handler.ts +4 -4
- 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/heartbeat-service.ts +76 -28
- 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 +4 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +56 -2
- package/src/home/relationship-state-writer.ts +2 -2
- 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 +73 -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 +4 -4
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +61 -0
- package/src/ipc/routes/browser.ts +96 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/index.ts +17 -1
- 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/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +100 -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 +103 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-title-service.ts +7 -4
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-backend.ts +1 -1
- 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 +173 -51
- package/src/memory/graph/graph-search.test.ts +92 -0
- package/src/memory/graph/graph-search.ts +4 -1
- 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 +230 -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/140-backfill-usage-cache-accounting.ts +1 -1
- 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/index.ts +1 -0
- package/src/memory/pkb/pkb-index.test.ts +368 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +438 -0
- package/src/memory/pkb/pkb-search.ts +137 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.ts +122 -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 +1373 -0
- package/src/messaging/providers/slack/render-transcript.ts +443 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/oauth/oauth-store.ts +1 -0
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/seed-providers.ts +4 -2
- package/src/permissions/approval-policy.test.ts +948 -0
- package/src/permissions/approval-policy.ts +257 -0
- package/src/permissions/bash-risk-classifier.test.ts +1208 -0
- package/src/permissions/bash-risk-classifier.ts +707 -0
- package/src/permissions/checker.ts +217 -708
- package/src/permissions/command-registry.test.ts +535 -0
- package/src/permissions/command-registry.ts +825 -0
- package/src/permissions/defaults.ts +26 -78
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/risk-types.ts +205 -0
- package/src/permissions/secret-prompter.ts +53 -2
- 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 +23 -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 +1 -16
- package/src/platform/client.ts +19 -1
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- 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 +501 -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 +76 -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/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 +578 -0
- package/src/providers/speech-to-text/xai-realtime.ts +796 -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 +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- 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/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 +52 -1
- package/src/runtime/http-types.ts +23 -1
- 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-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 +58 -0
- package/src/runtime/routes/approval-routes.ts +12 -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/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +133 -27
- 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 +912 -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/migration-routes.ts +720 -124
- 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 +28 -6
- package/src/schedule/scheduler.ts +8 -0
- 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 +26 -7
- 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 +45 -2
- package/src/tools/browser/browser-execution.ts +65 -38
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +4 -0
- 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/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +36 -15
- package/src/tools/policy-context.ts +25 -8
- package/src/tools/registry.ts +55 -3
- 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/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 +12 -3
- 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 +2 -2
- package/src/util/pricing.ts +15 -5
- 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/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 +57 -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/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- 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__/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__/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/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/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/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/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/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/shared/provider-env-vars.ts +0 -19
- 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
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
1
4
|
import type { ContextWindowConfig } from "../config/types.js";
|
|
2
5
|
import type {
|
|
3
6
|
ContentBlock,
|
|
@@ -5,6 +8,7 @@ import type {
|
|
|
5
8
|
Message,
|
|
6
9
|
Provider,
|
|
7
10
|
} from "../providers/types.js";
|
|
11
|
+
import { resolveBundledDir } from "../util/bundled-asset.js";
|
|
8
12
|
import { getLogger } from "../util/logger.js";
|
|
9
13
|
import { safeStringSlice } from "../util/unicode.js";
|
|
10
14
|
import {
|
|
@@ -26,11 +30,38 @@ const COMPACTION_TOOL_RESULT_MAX_CHARS = 6_000;
|
|
|
26
30
|
const MIN_COMPACTABLE_PERSISTED_MESSAGES = 2;
|
|
27
31
|
const INTERNAL_CONTEXT_SUMMARY_MESSAGES = new WeakSet<Message>();
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Load the compaction summary system prompt from the bundled markdown asset.
|
|
35
|
+
*
|
|
36
|
+
* `resolveBundledDir` handles the compiled-binary case where the caller path
|
|
37
|
+
* points to `/$bunfs/` and the asset lives next to the executable (macOS app
|
|
38
|
+
* bundle `Contents/Resources/` or sibling dir). In source mode it falls back
|
|
39
|
+
* to the sibling `prompts/` directory.
|
|
40
|
+
*/
|
|
41
|
+
export function loadCompactPrompt(): string {
|
|
42
|
+
const callerDir = import.meta.dirname ?? __dirname;
|
|
43
|
+
const promptsDir = resolveBundledDir(callerDir, "prompts", "compact-prompts");
|
|
44
|
+
const promptPath = join(promptsDir, "compact.md");
|
|
45
|
+
const contents = readFileSync(promptPath, "utf-8");
|
|
46
|
+
if (contents.length === 0) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`compact.md at ${promptPath} is empty — compaction summary prompt missing`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return contents;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Hardcoded fallback prompt used when the bundled `compact.md` asset is
|
|
56
|
+
* missing or unreadable, so the daemon can still compact conversations
|
|
57
|
+
* rather than failing module import at startup.
|
|
58
|
+
*/
|
|
59
|
+
const SUMMARY_PROMPT_FALLBACK = [
|
|
30
60
|
"You compress long assistant conversations into durable working memory.",
|
|
31
61
|
"Focus on actionable state, not prose.",
|
|
32
62
|
"Preserve concrete facts: goals, constraints, decisions, pending questions, file paths, commands, errors, and TODOs.",
|
|
33
63
|
"Remove repetition and stale details that were superseded.",
|
|
64
|
+
'Thread anchors: when a "Retained Thread References" section is present, each listed reply cites its parent via `→ Mxxxxxx`. If that parent appears in the Transcript, preserve its text verbatim (reactions may be aggregated as "N users reacted"). Omit when the section is absent.',
|
|
34
65
|
"Return concise markdown using these section headers exactly:",
|
|
35
66
|
"## Goals",
|
|
36
67
|
"## Constraints",
|
|
@@ -40,6 +71,42 @@ const SUMMARY_SYSTEM_PROMPT = [
|
|
|
40
71
|
"## Recent Progress",
|
|
41
72
|
].join("\n");
|
|
42
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Load the compact prompt with graceful fallback. If `loader` throws (missing
|
|
76
|
+
* or unreadable bundled asset, partial deployment, filesystem corruption),
|
|
77
|
+
* logs a warning and returns the hardcoded fallback string so module import
|
|
78
|
+
* never fails. The loader is injectable for testability.
|
|
79
|
+
*/
|
|
80
|
+
export function loadCompactPromptOrFallback(
|
|
81
|
+
loader: () => string = loadCompactPrompt,
|
|
82
|
+
): string {
|
|
83
|
+
try {
|
|
84
|
+
return loader();
|
|
85
|
+
} catch (err) {
|
|
86
|
+
log.warn(
|
|
87
|
+
{ err },
|
|
88
|
+
"Failed to load compact.md from bundle; using inline fallback prompt. The bundled asset may be missing or unreadable.",
|
|
89
|
+
);
|
|
90
|
+
return SUMMARY_PROMPT_FALLBACK;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const SUMMARY_SYSTEM_PROMPT = loadCompactPromptOrFallback();
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Pattern matching a Slack-style reply tag-line's parent-alias reference.
|
|
98
|
+
* The chronological renderer emits reply lines as
|
|
99
|
+
* `[MM/DD/YY HH:MM @sender → Mxxxxxx]: body`, or, for edited replies,
|
|
100
|
+
* `[MM/DD/YY HH:MM @sender → Mxxxxxx, edited MM/DD/YY HH:MM]: body`. The
|
|
101
|
+
* character after the 6-hex parent alias is therefore `]` for a plain reply
|
|
102
|
+
* or `,` for an edited one — the regex accepts either. `Mxxxxxx` is the
|
|
103
|
+
* first 6 hex chars of sha256(threadTs). A retained-tail text block that
|
|
104
|
+
* contains this pattern is carrying a live reference to a parent that may
|
|
105
|
+
* still live in the compactable region — the summarizer needs to know about
|
|
106
|
+
* it to act on the Thread-anchors clause of SUMMARY_SYSTEM_PROMPT.
|
|
107
|
+
*/
|
|
108
|
+
const THREAD_REPLY_REFERENCE_PATTERN = /→ M[0-9a-f]{6}[,\]]/;
|
|
109
|
+
|
|
43
110
|
export interface ContextWindowResult {
|
|
44
111
|
messages: Message[];
|
|
45
112
|
compacted: boolean;
|
|
@@ -58,6 +125,13 @@ export interface ContextWindowResult {
|
|
|
58
125
|
summaryRawResponses?: unknown[];
|
|
59
126
|
summaryText: string;
|
|
60
127
|
reason?: string;
|
|
128
|
+
/**
|
|
129
|
+
* True when the summary LLM call threw and the local fallback produced the
|
|
130
|
+
* summary. Callers use this to distinguish provider-side summary failures
|
|
131
|
+
* from successful compactions so they can apply circuit-breaker logic
|
|
132
|
+
* without losing the fallback-compacted messages.
|
|
133
|
+
*/
|
|
134
|
+
summaryFailed?: boolean;
|
|
61
135
|
}
|
|
62
136
|
|
|
63
137
|
export interface ShouldCompactResult {
|
|
@@ -73,13 +147,22 @@ export interface ContextWindowCompactOptions {
|
|
|
73
147
|
* Override the minimum number of recent user turns to preserve.
|
|
74
148
|
* Set to `0` for emergency recovery that can compact the entire history
|
|
75
149
|
* (except the summary message itself). When omitted, the default floor
|
|
76
|
-
*
|
|
150
|
+
* is `1` (or `8` when `conversationOriginChannel === "slack"`).
|
|
77
151
|
*/
|
|
78
152
|
minKeepRecentUserTurns?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Origin channel hint used when `minKeepRecentUserTurns` is omitted.
|
|
155
|
+
* Slack-originated conversations bump the default keep floor so multi-turn
|
|
156
|
+
* thread context (replies, quoted messages) is not summarized away too
|
|
157
|
+
* aggressively. Explicit `minKeepRecentUserTurns` overrides this hint.
|
|
158
|
+
*/
|
|
159
|
+
conversationOriginChannel?: string;
|
|
79
160
|
/**
|
|
80
161
|
* Override the target input token budget used for keep-boundary
|
|
81
|
-
* projected-fit checks.
|
|
82
|
-
*
|
|
162
|
+
* projected-fit checks. Clamped to no looser than `config.targetInputTokens`
|
|
163
|
+
* — i.e. the override may only demand a *stricter* fit. Passing a looser
|
|
164
|
+
* value has no effect. Intended for forced recovery paths that need a
|
|
165
|
+
* tighter target than the default.
|
|
83
166
|
*/
|
|
84
167
|
targetInputTokensOverride?: number;
|
|
85
168
|
/**
|
|
@@ -274,6 +357,8 @@ export class ContextWindowManager {
|
|
|
274
357
|
const keepPlan = this.pickKeepBoundary(messages, userTurnStarts, {
|
|
275
358
|
minKeepRecentUserTurns: options?.minKeepRecentUserTurns,
|
|
276
359
|
targetInputTokensOverride: options?.targetInputTokensOverride,
|
|
360
|
+
conversationOriginChannel: options?.conversationOriginChannel,
|
|
361
|
+
force: options?.force,
|
|
277
362
|
});
|
|
278
363
|
if (keepPlan.keepFromIndex <= summaryOffset) {
|
|
279
364
|
// All turns fit after truncation projection, but the real in-memory
|
|
@@ -447,13 +532,18 @@ export class ContextWindowManager {
|
|
|
447
532
|
};
|
|
448
533
|
}
|
|
449
534
|
|
|
535
|
+
const retainedThreadRefs = collectRetainedThreadReferences(
|
|
536
|
+
messages.slice(keepPlan.keepFromIndex),
|
|
537
|
+
);
|
|
450
538
|
const transcriptBlocks = this.capTranscriptBlocksToTokenBudget(
|
|
451
539
|
serializeMessagesToContentBlocks(compactableMessages),
|
|
452
540
|
existingSummary ?? "No previous summary.",
|
|
541
|
+
retainedThreadRefs,
|
|
453
542
|
);
|
|
454
543
|
const summaryUpdate = await this.updateSummary(
|
|
455
544
|
existingSummary ?? "No previous summary.",
|
|
456
545
|
transcriptBlocks,
|
|
546
|
+
retainedThreadRefs,
|
|
457
547
|
signal,
|
|
458
548
|
);
|
|
459
549
|
const summary = summaryUpdate.summary;
|
|
@@ -463,6 +553,7 @@ export class ContextWindowManager {
|
|
|
463
553
|
const summaryCacheCreationInputTokens =
|
|
464
554
|
summaryUpdate.cacheCreationInputTokens;
|
|
465
555
|
const summaryCacheReadInputTokens = summaryUpdate.cacheReadInputTokens;
|
|
556
|
+
const summaryFailed = summaryUpdate.failed;
|
|
466
557
|
const summaryRawResponses: unknown[] = [];
|
|
467
558
|
if (Array.isArray(summaryUpdate.rawResponse)) {
|
|
468
559
|
summaryRawResponses.push(...summaryUpdate.rawResponse);
|
|
@@ -499,7 +590,9 @@ export class ContextWindowManager {
|
|
|
499
590
|
// the summary at index 0 as child-owned.
|
|
500
591
|
this.nonPersistedPrefixCount = Math.max(
|
|
501
592
|
0,
|
|
502
|
-
this.nonPersistedPrefixCount -
|
|
593
|
+
this.nonPersistedPrefixCount -
|
|
594
|
+
injectedInCompactable -
|
|
595
|
+
injectedSummaryOffset,
|
|
503
596
|
);
|
|
504
597
|
this.summaryIsInjected = false;
|
|
505
598
|
|
|
@@ -532,6 +625,7 @@ export class ContextWindowManager {
|
|
|
532
625
|
summaryCacheReadInputTokens,
|
|
533
626
|
summaryRawResponses,
|
|
534
627
|
summaryText: summary,
|
|
628
|
+
summaryFailed,
|
|
535
629
|
};
|
|
536
630
|
}
|
|
537
631
|
|
|
@@ -548,14 +642,24 @@ export class ContextWindowManager {
|
|
|
548
642
|
opts?: {
|
|
549
643
|
minKeepRecentUserTurns?: number;
|
|
550
644
|
targetInputTokensOverride?: number;
|
|
645
|
+
conversationOriginChannel?: string;
|
|
646
|
+
force?: boolean;
|
|
551
647
|
},
|
|
552
648
|
): { keepFromIndex: number; keepTurns: number } {
|
|
649
|
+
// Slack-originated conversations rely on multi-turn thread context
|
|
650
|
+
// (reply chains, quoted messages, contextual references). Bump the
|
|
651
|
+
// default keep floor for them so compaction does not summarize away
|
|
652
|
+
// recent turns that the next reply may directly cite. Explicit
|
|
653
|
+
// `minKeepRecentUserTurns` (including emergency `0`) wins.
|
|
654
|
+
const defaultTurns = opts?.conversationOriginChannel === "slack" ? 8 : 1;
|
|
553
655
|
const minFloor = Math.min(
|
|
554
|
-
Math.max(0, Math.floor(opts?.minKeepRecentUserTurns ??
|
|
656
|
+
Math.max(0, Math.floor(opts?.minKeepRecentUserTurns ?? defaultTurns)),
|
|
555
657
|
userTurnStarts.length,
|
|
556
658
|
);
|
|
557
|
-
const targetTokens =
|
|
558
|
-
opts?.targetInputTokensOverride ?? this.targetInputTokens
|
|
659
|
+
const targetTokens = Math.min(
|
|
660
|
+
opts?.targetInputTokensOverride ?? this.targetInputTokens,
|
|
661
|
+
this.targetInputTokens,
|
|
662
|
+
);
|
|
559
663
|
|
|
560
664
|
// Binary search for the maximum keepTurns whose projected tokens fit
|
|
561
665
|
// within the budget. Token count is monotonically non-decreasing with
|
|
@@ -597,6 +701,32 @@ export class ContextWindowManager {
|
|
|
597
701
|
lo = hi;
|
|
598
702
|
}
|
|
599
703
|
|
|
704
|
+
// Under forced compaction with only the implicit default floor in play,
|
|
705
|
+
// that floor stops being an absolute override when the kept region still
|
|
706
|
+
// exceeds the target. Walk keepTurns below the floor — down to 0 if
|
|
707
|
+
// needed — so /compact can always drive the conversation toward target,
|
|
708
|
+
// even when the floor turn itself is oversized (e.g. a huge paste in the
|
|
709
|
+
// last user message). Exceptions that still treat the floor as hard:
|
|
710
|
+
// - Explicit `minKeepRecentUserTurns` (the caller opted in to that
|
|
711
|
+
// floor; emergency recovery already passes 0 when it wants to go all
|
|
712
|
+
// the way down).
|
|
713
|
+
// - Slack origin (the bumped 8-turn floor protects thread reply chains
|
|
714
|
+
// and quoted-message context that the next reply may directly cite).
|
|
715
|
+
// Automatic mid-loop compaction (force !== true) always honors the floor
|
|
716
|
+
// so the in-flight agent turn isn't summarized away.
|
|
717
|
+
const floorIsImplicitDefault =
|
|
718
|
+
opts?.minKeepRecentUserTurns === undefined &&
|
|
719
|
+
opts?.conversationOriginChannel !== "slack";
|
|
720
|
+
if (
|
|
721
|
+
opts?.force &&
|
|
722
|
+
floorIsImplicitDefault &&
|
|
723
|
+
projectedTokensForKeep(lo) > targetTokens
|
|
724
|
+
) {
|
|
725
|
+
while (lo > 0 && projectedTokensForKeep(lo) > targetTokens) {
|
|
726
|
+
lo--;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
600
730
|
const keepTurns = lo;
|
|
601
731
|
const rawKeepFromIndex =
|
|
602
732
|
keepTurns === 0
|
|
@@ -628,10 +758,13 @@ export class ContextWindowManager {
|
|
|
628
758
|
private capTranscriptBlocksToTokenBudget(
|
|
629
759
|
blocks: ContentBlock[],
|
|
630
760
|
currentSummary: string,
|
|
761
|
+
retainedThreadRefs: string[],
|
|
631
762
|
): ContentBlock[] {
|
|
763
|
+
const retainedRefsText = retainedThreadRefs.join("\n");
|
|
632
764
|
const overheadTokens =
|
|
633
765
|
estimateTextTokens(SUMMARY_SYSTEM_PROMPT) +
|
|
634
766
|
estimateTextTokens(currentSummary) +
|
|
767
|
+
estimateTextTokens(retainedRefsText) +
|
|
635
768
|
// Scaffolding text in buildSummaryContentBlocks ("Update the summary...",
|
|
636
769
|
// section headers, etc.) — generous fixed estimate.
|
|
637
770
|
200 +
|
|
@@ -643,7 +776,9 @@ export class ContextWindowManager {
|
|
|
643
776
|
);
|
|
644
777
|
|
|
645
778
|
const estimateBlockTokens = (b: ContentBlock): number =>
|
|
646
|
-
estimateContentBlockTokens(b, {
|
|
779
|
+
estimateContentBlockTokens(b, {
|
|
780
|
+
providerName: this.estimationProviderName,
|
|
781
|
+
});
|
|
647
782
|
|
|
648
783
|
let totalTokens = 0;
|
|
649
784
|
for (const block of blocks) {
|
|
@@ -656,7 +791,11 @@ export class ContextWindowManager {
|
|
|
656
791
|
// images to drop. Images are high-cost and their text context (message
|
|
657
792
|
// headers, surrounding tool_use/tool_result serializations) is preserved.
|
|
658
793
|
const result = [...blocks];
|
|
659
|
-
for (
|
|
794
|
+
for (
|
|
795
|
+
let i = 0;
|
|
796
|
+
i < result.length && totalTokens > maxTranscriptTokens;
|
|
797
|
+
i++
|
|
798
|
+
) {
|
|
660
799
|
if (result[i].type === "image") {
|
|
661
800
|
totalTokens -= estimateBlockTokens(result[i]);
|
|
662
801
|
const stub: ContentBlock = {
|
|
@@ -674,7 +813,11 @@ export class ContextWindowManager {
|
|
|
674
813
|
// than dropping it entirely so the summarizer always has content to work with.
|
|
675
814
|
let dropUntil = 0;
|
|
676
815
|
let droppedTokens = 0;
|
|
677
|
-
for (
|
|
816
|
+
for (
|
|
817
|
+
let i = 0;
|
|
818
|
+
i < result.length && totalTokens > maxTranscriptTokens;
|
|
819
|
+
i++
|
|
820
|
+
) {
|
|
678
821
|
const blockTokens = estimateBlockTokens(result[i]);
|
|
679
822
|
const excess = totalTokens - maxTranscriptTokens;
|
|
680
823
|
if (blockTokens > excess && result[i].type === "text") {
|
|
@@ -722,6 +865,7 @@ export class ContextWindowManager {
|
|
|
722
865
|
private async updateSummary(
|
|
723
866
|
currentSummary: string,
|
|
724
867
|
transcriptBlocks: ContentBlock[],
|
|
868
|
+
retainedThreadRefs: string[],
|
|
725
869
|
signal?: AbortSignal,
|
|
726
870
|
): Promise<{
|
|
727
871
|
summary: string;
|
|
@@ -731,12 +875,20 @@ export class ContextWindowManager {
|
|
|
731
875
|
cacheCreationInputTokens: number;
|
|
732
876
|
cacheReadInputTokens: number;
|
|
733
877
|
rawResponse?: unknown;
|
|
878
|
+
/**
|
|
879
|
+
* True when the provider.sendMessage call threw and the local fallback
|
|
880
|
+
* was used. Callers (the agent loop) use this to drive circuit-breaker
|
|
881
|
+
* state without having to reimplement the fallback themselves.
|
|
882
|
+
*/
|
|
883
|
+
failed: boolean;
|
|
734
884
|
}> {
|
|
735
885
|
const contentBlocks = buildSummaryContentBlocks(
|
|
736
886
|
currentSummary,
|
|
737
887
|
transcriptBlocks,
|
|
888
|
+
retainedThreadRefs,
|
|
738
889
|
);
|
|
739
890
|
const summaryMessage: Message = { role: "user", content: contentBlocks };
|
|
891
|
+
let failed = false;
|
|
740
892
|
try {
|
|
741
893
|
const response = await this.provider.sendMessage(
|
|
742
894
|
[summaryMessage],
|
|
@@ -759,15 +911,19 @@ export class ContextWindowManager {
|
|
|
759
911
|
response.usage.cacheCreationInputTokens ?? 0,
|
|
760
912
|
cacheReadInputTokens: response.usage.cacheReadInputTokens ?? 0,
|
|
761
913
|
rawResponse: response.rawResponse,
|
|
914
|
+
failed: false,
|
|
762
915
|
};
|
|
763
916
|
}
|
|
764
917
|
} catch (err) {
|
|
918
|
+
failed = true;
|
|
765
919
|
log.warn({ err }, "Summary generation failed, using local fallback");
|
|
766
920
|
}
|
|
767
921
|
|
|
768
922
|
// Fallback: extract text-only transcript for local summary generation.
|
|
769
923
|
const textTranscript = transcriptBlocks
|
|
770
|
-
.filter(
|
|
924
|
+
.filter(
|
|
925
|
+
(b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text",
|
|
926
|
+
)
|
|
771
927
|
.map((b) => b.text)
|
|
772
928
|
.join("\n\n");
|
|
773
929
|
|
|
@@ -778,6 +934,7 @@ export class ContextWindowManager {
|
|
|
778
934
|
model: "",
|
|
779
935
|
cacheCreationInputTokens: 0,
|
|
780
936
|
cacheReadInputTokens: 0,
|
|
937
|
+
failed,
|
|
781
938
|
};
|
|
782
939
|
}
|
|
783
940
|
|
|
@@ -854,7 +1011,11 @@ function adjustForToolPairs(
|
|
|
854
1011
|
// Collect tool_use_ids referenced by tool_results in this user message
|
|
855
1012
|
const referencedIds = new Set<string>();
|
|
856
1013
|
for (const block of msg.content) {
|
|
857
|
-
if (
|
|
1014
|
+
if (
|
|
1015
|
+
(block.type === "tool_result" ||
|
|
1016
|
+
block.type === "web_search_tool_result") &&
|
|
1017
|
+
"tool_use_id" in block
|
|
1018
|
+
) {
|
|
858
1019
|
referencedIds.add((block as { tool_use_id: string }).tool_use_id);
|
|
859
1020
|
}
|
|
860
1021
|
}
|
|
@@ -930,26 +1091,68 @@ export function createContextSummaryMessage(summary: string): Message {
|
|
|
930
1091
|
function buildSummaryContentBlocks(
|
|
931
1092
|
currentSummary: string,
|
|
932
1093
|
transcriptBlocks: ContentBlock[],
|
|
1094
|
+
retainedThreadRefs: string[],
|
|
933
1095
|
): ContentBlock[] {
|
|
1096
|
+
const lines = [
|
|
1097
|
+
"Update the summary with new transcript data.",
|
|
1098
|
+
"If new information conflicts with older notes, keep the most recent and explicit detail.",
|
|
1099
|
+
"Keep all unresolved asks and next steps.",
|
|
1100
|
+
"For any images included below, describe their visual content in the summary so the information is preserved after compaction.",
|
|
1101
|
+
"",
|
|
1102
|
+
"### Existing Summary",
|
|
1103
|
+
currentSummary.trim().length > 0 ? currentSummary.trim() : "None.",
|
|
1104
|
+
"",
|
|
1105
|
+
];
|
|
1106
|
+
if (retainedThreadRefs.length > 0) {
|
|
1107
|
+
lines.push(
|
|
1108
|
+
"### Retained Thread References",
|
|
1109
|
+
"These reply tag lines remain in the live context after compaction. Each `→ Mxxxxxx` cites a parent message by alias; if that parent appears in the Transcript below, preserve its text verbatim.",
|
|
1110
|
+
...retainedThreadRefs.map((ref) => `- ${ref}`),
|
|
1111
|
+
"",
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
lines.push("### Transcript");
|
|
934
1115
|
return [
|
|
935
1116
|
{
|
|
936
1117
|
type: "text",
|
|
937
|
-
text:
|
|
938
|
-
"Update the summary with new transcript data.",
|
|
939
|
-
"If new information conflicts with older notes, keep the most recent and explicit detail.",
|
|
940
|
-
"Keep all unresolved asks and next steps.",
|
|
941
|
-
"For any images included below, describe their visual content in the summary so the information is preserved after compaction.",
|
|
942
|
-
"",
|
|
943
|
-
"### Existing Summary",
|
|
944
|
-
currentSummary.trim().length > 0 ? currentSummary.trim() : "None.",
|
|
945
|
-
"",
|
|
946
|
-
"### Transcript",
|
|
947
|
-
].join("\n"),
|
|
1118
|
+
text: lines.join("\n"),
|
|
948
1119
|
} as ContentBlock,
|
|
949
1120
|
...transcriptBlocks,
|
|
950
1121
|
];
|
|
951
1122
|
}
|
|
952
1123
|
|
|
1124
|
+
/**
|
|
1125
|
+
* Scan retained-tail messages for Slack-style reply tag lines that cite a
|
|
1126
|
+
* thread parent via the `→ Mxxxxxx` alias convention. Returns the full tag
|
|
1127
|
+
* line for each match (de-duplicated, order-preserved) so the summarizer
|
|
1128
|
+
* has a concrete list of parents whose text must be preserved verbatim.
|
|
1129
|
+
*
|
|
1130
|
+
* Non-slack conversations and retained tails without any reply markers
|
|
1131
|
+
* produce an empty list — in that case the summarizer is told explicitly
|
|
1132
|
+
* that no verbatim preservation is required.
|
|
1133
|
+
*/
|
|
1134
|
+
function collectRetainedThreadReferences(
|
|
1135
|
+
retainedMessages: Message[],
|
|
1136
|
+
): string[] {
|
|
1137
|
+
const seen = new Set<string>();
|
|
1138
|
+
const out: string[] = [];
|
|
1139
|
+
for (const msg of retainedMessages) {
|
|
1140
|
+
for (const block of msg.content) {
|
|
1141
|
+
if (block.type !== "text") continue;
|
|
1142
|
+
const text = (block as { text: string }).text;
|
|
1143
|
+
for (const line of text.split("\n")) {
|
|
1144
|
+
if (!THREAD_REPLY_REFERENCE_PATTERN.test(line)) continue;
|
|
1145
|
+
const trimmed = line.trim();
|
|
1146
|
+
if (trimmed.length === 0) continue;
|
|
1147
|
+
if (seen.has(trimmed)) continue;
|
|
1148
|
+
seen.add(trimmed);
|
|
1149
|
+
out.push(trimmed);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return out;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
953
1156
|
/**
|
|
954
1157
|
* Serialize messages into a sequence of content blocks. Text-based content
|
|
955
1158
|
* (tool calls, tool results, thinking, etc.) is serialized into text blocks.
|
|
@@ -970,7 +1173,8 @@ function serializeMessagesToContentBlocks(messages: Message[]): ContentBlock[] {
|
|
|
970
1173
|
textLines.length = 0;
|
|
971
1174
|
}
|
|
972
1175
|
blocks.push(block);
|
|
973
|
-
} else if (block.type === "tool_result") {
|
|
1176
|
+
} else if (block.type === "tool_result") {
|
|
1177
|
+
// guard:allow-tool-result-only — web_search_tool_result handled by serializeBlock via else branch
|
|
974
1178
|
// Extract images from tool_result contentBlocks before serializing.
|
|
975
1179
|
const collectedImages: ImageContent[] = [];
|
|
976
1180
|
textLines.push(serializeToolResultBlock(block, collectedImages));
|
|
@@ -67,17 +67,28 @@ function getManagedBootstrapSocketPath(): string {
|
|
|
67
67
|
* a malicious binary there. Removed to close the sandbox-escape vector.
|
|
68
68
|
*
|
|
69
69
|
* Search order:
|
|
70
|
-
* 1. Alongside the running executable
|
|
71
|
-
* `<App>.app/Contents/MacOS/credential-executor`).
|
|
72
|
-
*
|
|
73
|
-
*
|
|
70
|
+
* 1. Alongside the running executable, but ONLY when running from a
|
|
71
|
+
* packaged macOS app bundle (`<App>.app/Contents/MacOS/credential-executor`).
|
|
72
|
+
* In dev mode, `process.execPath` points at the bun/node install dir
|
|
73
|
+
* (e.g. `~/.bun/bin`), where an unrelated file named `credential-executor`
|
|
74
|
+
* could be picked up by accident.
|
|
74
75
|
* 2. `<binDir>/credential-executor` — user-installed override (dev flow).
|
|
75
76
|
*/
|
|
76
77
|
function getLocalBinarySearchPaths(): string[] {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
const paths: string[] = [];
|
|
79
|
+
|
|
80
|
+
// Only check the sibling of process.execPath when running from a packaged
|
|
81
|
+
// app bundle — the .app/Contents/MacOS directory is a controlled location.
|
|
82
|
+
// In dev mode, process.execPath is the bun/node binary (e.g. ~/.bun/bin/bun)
|
|
83
|
+
// and a sibling lookup there could discover an unrelated or untrusted
|
|
84
|
+
// executable.
|
|
85
|
+
const execDir = dirname(process.execPath);
|
|
86
|
+
if (execDir.includes(".app/Contents/MacOS")) {
|
|
87
|
+
paths.push(join(execDir, "credential-executor"));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
paths.push(join(getBinDir(), "credential-executor"));
|
|
91
|
+
return paths;
|
|
81
92
|
}
|
|
82
93
|
|
|
83
94
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { logCesLine } from "./process-manager.js";
|
|
4
|
+
|
|
5
|
+
function makeLogger() {
|
|
6
|
+
return {
|
|
7
|
+
debug: mock((_obj: object, _msg: string) => {}),
|
|
8
|
+
info: mock((_obj: object, _msg: string) => {}),
|
|
9
|
+
warn: mock((_obj: object, _msg: string) => {}),
|
|
10
|
+
error: mock((_obj: object, _msg: string) => {}),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe("logCesLine", () => {
|
|
15
|
+
test("pino JSON INFO line routes to log.info (not log.error)", () => {
|
|
16
|
+
const logger = makeLogger();
|
|
17
|
+
const line = JSON.stringify({
|
|
18
|
+
level: 30,
|
|
19
|
+
msg: "CES ready",
|
|
20
|
+
time: Date.now(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
logCesLine(line, 42, logger);
|
|
24
|
+
|
|
25
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
26
|
+
expect(logger.error).not.toHaveBeenCalled();
|
|
27
|
+
expect(logger.warn).not.toHaveBeenCalled();
|
|
28
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
29
|
+
|
|
30
|
+
const [meta, msg] = logger.info.mock.calls[0] as [object, string];
|
|
31
|
+
expect(meta).toEqual({ pid: 42 });
|
|
32
|
+
expect(msg).toBe(`[ces-stderr] ${line}`);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("pino JSON ERROR line routes to log.error", () => {
|
|
36
|
+
const logger = makeLogger();
|
|
37
|
+
const line = JSON.stringify({
|
|
38
|
+
level: 50,
|
|
39
|
+
msg: "credential store failed",
|
|
40
|
+
time: Date.now(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
logCesLine(line, 42, logger);
|
|
44
|
+
|
|
45
|
+
expect(logger.error).toHaveBeenCalledTimes(1);
|
|
46
|
+
expect(logger.info).not.toHaveBeenCalled();
|
|
47
|
+
expect(logger.warn).not.toHaveBeenCalled();
|
|
48
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("non-JSON fragment like 'args: []' routes to log.info", () => {
|
|
52
|
+
const logger = makeLogger();
|
|
53
|
+
|
|
54
|
+
logCesLine("args: []", 42, logger);
|
|
55
|
+
|
|
56
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
57
|
+
expect(logger.error).not.toHaveBeenCalled();
|
|
58
|
+
expect(logger.warn).not.toHaveBeenCalled();
|
|
59
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
60
|
+
|
|
61
|
+
const [meta, msg] = logger.info.mock.calls[0] as [object, string];
|
|
62
|
+
expect(meta).toEqual({ pid: 42 });
|
|
63
|
+
expect(msg).toBe("[ces-stderr] args: []");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("non-JSON line starting with 'ERROR:' routes to log.error", () => {
|
|
67
|
+
const logger = makeLogger();
|
|
68
|
+
|
|
69
|
+
logCesLine("ERROR: bad thing happened", 42, logger);
|
|
70
|
+
|
|
71
|
+
expect(logger.error).toHaveBeenCalledTimes(1);
|
|
72
|
+
expect(logger.info).not.toHaveBeenCalled();
|
|
73
|
+
expect(logger.warn).not.toHaveBeenCalled();
|
|
74
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("pino-pretty timestamped ERROR line routes to log.error", () => {
|
|
78
|
+
const logger = makeLogger();
|
|
79
|
+
|
|
80
|
+
logCesLine("[12:07:37.467] ERROR oh no", 42, logger);
|
|
81
|
+
|
|
82
|
+
expect(logger.error).toHaveBeenCalledTimes(1);
|
|
83
|
+
expect(logger.info).not.toHaveBeenCalled();
|
|
84
|
+
expect(logger.warn).not.toHaveBeenCalled();
|
|
85
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("pino-pretty timestamped WARN line routes to log.warn", () => {
|
|
89
|
+
const logger = makeLogger();
|
|
90
|
+
|
|
91
|
+
logCesLine("[12:07:37.467] WARN wat", 42, logger);
|
|
92
|
+
|
|
93
|
+
expect(logger.warn).toHaveBeenCalledTimes(1);
|
|
94
|
+
expect(logger.error).not.toHaveBeenCalled();
|
|
95
|
+
expect(logger.info).not.toHaveBeenCalled();
|
|
96
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("pino-pretty timestamped INFO line routes to log.info", () => {
|
|
100
|
+
const logger = makeLogger();
|
|
101
|
+
|
|
102
|
+
logCesLine("[12:07:37.467] INFO starting", 42, logger);
|
|
103
|
+
|
|
104
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(logger.error).not.toHaveBeenCalled();
|
|
106
|
+
expect(logger.warn).not.toHaveBeenCalled();
|
|
107
|
+
expect(logger.debug).not.toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
});
|