@vellumai/assistant 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +6 -7
- package/Dockerfile +1 -0
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
- package/bun.lock +3 -0
- package/docs/architecture/security.md +18 -16
- package/knip.json +1 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- package/openapi.yaml +294 -107
- package/package.json +4 -2
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +6 -17
- package/src/__tests__/assistant-event-hub.test.ts +126 -77
- package/src/__tests__/assistant-event.test.ts +0 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/background-shell-host-bash.test.ts +34 -43
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/checker.test.ts +20 -34
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-lifecycle.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
- package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -4
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/cu-unified-flow.test.ts +33 -16
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +4 -1
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +289 -7
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +45 -75
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
- package/src/__tests__/host-cu-proxy.test.ts +56 -111
- package/src/__tests__/host-file-proxy.test.ts +44 -98
- package/src/__tests__/host-file-read-tool.test.ts +42 -21
- package/src/__tests__/host-shell-tool.test.ts +33 -68
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy.test.ts +43 -53
- package/src/__tests__/http-user-message-parity.test.ts +0 -6
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +10 -5
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -66
- package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +66 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -22
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +3 -12
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +0 -4
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +9 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
- package/src/__tests__/tool-executor.test.ts +12 -19
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +150 -0
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/backup-worker.test.ts +36 -8
- package/src/backup/__tests__/paths.test.ts +2 -2
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +36 -2
- package/src/backup/paths.ts +9 -6
- package/src/browser-session/events.ts +0 -9
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +0 -24
- package/src/calls/twilio-rest.ts +0 -38
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +1 -36
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/backup.ts +4 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +63 -5
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +231 -76
- package/src/cli/commands/keys.ts +4 -1
- package/src/cli/commands/memory-v2.ts +24 -52
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +14 -0
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +3 -14
- package/src/config/feature-flag-registry.json +30 -30
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +3 -3
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +1 -1
- package/src/config/schemas/llm.ts +31 -3
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +9 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +6 -6
- package/src/config/schemas/skills.ts +5 -5
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -17
- package/src/contacts/contacts-write.ts +1 -105
- package/src/context/window-manager.ts +44 -5
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
- package/src/daemon/conversation-agent-loop.ts +277 -36
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +83 -163
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +22 -28
- package/src/daemon/conversation-tool-setup.ts +3 -33
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +117 -233
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +23 -71
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-bash-proxy.ts +67 -45
- package/src/daemon/host-browser-proxy.ts +65 -27
- package/src/daemon/host-cu-proxy.ts +40 -39
- package/src/daemon/host-file-proxy.ts +58 -37
- package/src/daemon/host-transfer-proxy.ts +84 -46
- package/src/daemon/lifecycle.ts +49 -15
- package/src/daemon/message-types/conversations.ts +7 -0
- package/src/daemon/message-types/host-bash.ts +1 -0
- package/src/daemon/message-types/host-cu.ts +1 -0
- package/src/daemon/message-types/host-file.ts +1 -0
- package/src/daemon/message-types/host-transfer.ts +1 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +102 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -2
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +3 -1
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
- package/src/heartbeat/heartbeat-service.ts +23 -5
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +16 -3
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +3 -10
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/manager.ts +0 -5
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +29 -4
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +3 -21
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
- package/src/memory/graph/conversation-graph-memory.ts +35 -13
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- package/src/memory/jobs-store.ts +0 -1
- package/src/memory/jobs-worker.ts +2 -16
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +14 -0
- package/src/memory/migrations/registry.ts +24 -0
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +25 -0
- package/src/memory/search/semantic.ts +5 -16
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +289 -90
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +384 -15
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/activation.ts +168 -97
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +14 -12
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +182 -58
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +118 -42
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/skill-store.ts +55 -7
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/types.ts +10 -20
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +122 -21
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +12 -2
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/types.ts +1 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/config.ts +0 -74
- package/src/outbound-proxy/health.ts +0 -44
- package/src/outbound-proxy/index.ts +0 -22
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.ts +4 -1
- package/src/permissions/gateway-threshold-reader.ts +4 -1
- package/src/permissions/prompter.ts +9 -2
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/system-prompt.ts +34 -70
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +1 -6
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -1
- package/src/runtime/auth/route-policy.ts +11 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +22 -82
- package/src/runtime/http-types.ts +5 -0
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
- package/src/runtime/migrations/migration-transport.ts +46 -13
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +133 -79
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +7 -7
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/pending-interactions.ts +13 -4
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +45 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +120 -8
- package/src/runtime/routes/conversation-routes.ts +44 -528
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/documents-routes.ts +53 -18
- package/src/runtime/routes/events-routes.ts +59 -91
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/host-bash-routes.ts +3 -2
- package/src/runtime/routes/host-browser-routes.ts +9 -33
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +3 -2
- package/src/runtime/routes/host-transfer-routes.ts +11 -15
- package/src/runtime/routes/identity-routes.ts +78 -6
- package/src/runtime/routes/inbound-message-handler.ts +580 -137
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/index.ts +4 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/memory-v2-routes.ts +10 -15
- package/src/runtime/routes/migration-routes.ts +188 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +3 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +0 -16
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +6 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
- package/src/telemetry/usage-telemetry-reporter.ts +3 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/executor.ts +44 -31
- package/src/tools/host-filesystem/edit.ts +3 -2
- package/src/tools/host-filesystem/read.ts +3 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +4 -3
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +4 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/types.ts +12 -39
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ContentBlock,
|
|
3
|
-
Message,
|
|
4
|
-
ToolResultContent,
|
|
5
|
-
} from "../providers/types.js";
|
|
6
|
-
import { estimateTextTokens } from "./token-estimator.js";
|
|
7
|
-
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// Constants
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
|
|
12
|
-
/** Default number of recent user-assistant exchanges to keep untouched. */
|
|
13
|
-
const DEFAULT_PROTECT_RECENT_TURNS = 4;
|
|
14
|
-
|
|
15
|
-
/** Default minimum reclaimable tokens required before we commit a pass. */
|
|
16
|
-
const DEFAULT_MIN_GAIN_TOKENS = 2_000;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Default list of tool names whose results are never wholesale-cleared.
|
|
20
|
-
* Matches opencode's `PRUNE_PROTECTED_TOOLS` and Claude Code's equivalent —
|
|
21
|
-
* protects subagent outputs and curated skill results, which are expensive
|
|
22
|
-
* to regenerate and usually load-bearing for the rest of the conversation.
|
|
23
|
-
*
|
|
24
|
-
* Note: ax-tree stripping still applies to protected tool results. Only the
|
|
25
|
-
* full-body replacement is skipped.
|
|
26
|
-
*/
|
|
27
|
-
const DEFAULT_PROTECTED_TOOLS: readonly string[] = [
|
|
28
|
-
"Task",
|
|
29
|
-
"subagent",
|
|
30
|
-
"skill",
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
/** Replacement body for cleared tool-result content. */
|
|
34
|
-
const CLEARED_TOOL_RESULT_TEXT = "[Old tool result content cleared]";
|
|
35
|
-
|
|
36
|
-
/** Replacement text for stubbed image blocks. */
|
|
37
|
-
const CLEARED_IMAGE_TEXT = "[image omitted]";
|
|
38
|
-
|
|
39
|
-
/** Replacement text for stubbed file blocks. */
|
|
40
|
-
const CLEARED_FILE_TEXT = "[file omitted]";
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Regex that matches `<ax-tree>...</ax-tree>` blocks (non-greedy).
|
|
44
|
-
* Kept in sync with `AX_TREE_PATTERN` in `assistant/src/agent/loop.ts`; this
|
|
45
|
-
* module subsumes that function's responsibility for stale tool results.
|
|
46
|
-
*/
|
|
47
|
-
const AX_TREE_PATTERN = /<ax-tree>[\s\S]*?<\/ax-tree>/g;
|
|
48
|
-
|
|
49
|
-
/** Placeholder inserted in place of a stripped ax-tree block. */
|
|
50
|
-
const AX_TREE_PLACEHOLDER = "<ax_tree_omitted />";
|
|
51
|
-
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// Types
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
|
|
56
|
-
export interface MicrocompactOptions {
|
|
57
|
-
/** Preserve the last N user-assistant exchanges verbatim. Default 4. */
|
|
58
|
-
protectRecentTurns?: number;
|
|
59
|
-
/** Tool names whose results are never microcompacted (e.g. "Task", sub-agents). */
|
|
60
|
-
protectedTools?: string[];
|
|
61
|
-
/** Minimum reclaimable tokens required to bother — skip no-op passes. Default 2000. */
|
|
62
|
-
minGainTokens?: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface MicrocompactResult {
|
|
66
|
-
messages: Message[];
|
|
67
|
-
reclaimedTokens: number;
|
|
68
|
-
clearedToolResults: number;
|
|
69
|
-
/** Count of image + file blocks that were replaced with text stubs. */
|
|
70
|
-
clearedMedia: number;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
// Public API
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Deterministically compact stale content in the message history.
|
|
79
|
-
*
|
|
80
|
-
* Walks `messages` from newest to oldest. The most recent
|
|
81
|
-
* `protectRecentTurns` user-assistant exchanges are left untouched. In the
|
|
82
|
-
* older region:
|
|
83
|
-
*
|
|
84
|
-
* - Each `tool_result` whose owning tool is NOT in `protectedTools` has its
|
|
85
|
-
* `content` replaced with a short placeholder.
|
|
86
|
-
* - Every `image` / `file` block is replaced with a text stub.
|
|
87
|
-
* - `<ax-tree>...</ax-tree>` blocks inside any tool_result (including
|
|
88
|
-
* protected ones) are collapsed to a placeholder, subsuming the old
|
|
89
|
-
* `compactAxTreeHistory` in `assistant/src/agent/loop.ts`.
|
|
90
|
-
*
|
|
91
|
-
* The `tool_use` / `tool_result` block structure is preserved — we only
|
|
92
|
-
* mutate block bodies, never the block types or their pairing — so provider
|
|
93
|
-
* serialization remains valid after compaction.
|
|
94
|
-
*
|
|
95
|
-
* If the estimated savings (`reclaimedTokens`) is below `minGainTokens`, the
|
|
96
|
-
* original `messages` reference is returned unchanged. The pass is
|
|
97
|
-
* idempotent: re-invoking on a previously compacted history produces zero
|
|
98
|
-
* incremental reclaim.
|
|
99
|
-
*/
|
|
100
|
-
export function microcompact(
|
|
101
|
-
messages: Message[],
|
|
102
|
-
options?: MicrocompactOptions,
|
|
103
|
-
): MicrocompactResult {
|
|
104
|
-
const protectRecentTurns =
|
|
105
|
-
options?.protectRecentTurns ?? DEFAULT_PROTECT_RECENT_TURNS;
|
|
106
|
-
const minGainTokens = options?.minGainTokens ?? DEFAULT_MIN_GAIN_TOKENS;
|
|
107
|
-
const protectedToolSet = new Set(
|
|
108
|
-
options?.protectedTools ?? DEFAULT_PROTECTED_TOOLS,
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
if (messages.length === 0) {
|
|
112
|
-
return {
|
|
113
|
-
messages,
|
|
114
|
-
reclaimedTokens: 0,
|
|
115
|
-
clearedToolResults: 0,
|
|
116
|
-
clearedMedia: 0,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Build a lookup of tool_use_id -> tool name by scanning every assistant
|
|
121
|
-
// message. Tool_use_ids are globally unique within a conversation so a
|
|
122
|
-
// single map is valid for the whole history.
|
|
123
|
-
const toolNameById = buildToolNameLookup(messages);
|
|
124
|
-
|
|
125
|
-
// Determine the index up to which messages are "protected" (left alone).
|
|
126
|
-
// Anything at index >= firstProtectedIdx is in the protected tail; the
|
|
127
|
-
// older region (indices < firstProtectedIdx) is where we clear.
|
|
128
|
-
const firstProtectedIdx = computeProtectedBoundary(
|
|
129
|
-
messages,
|
|
130
|
-
protectRecentTurns,
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
if (firstProtectedIdx <= 0) {
|
|
134
|
-
// Every message is protected — nothing to clear.
|
|
135
|
-
return {
|
|
136
|
-
messages,
|
|
137
|
-
reclaimedTokens: 0,
|
|
138
|
-
clearedToolResults: 0,
|
|
139
|
-
clearedMedia: 0,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
let reclaimedTokens = 0;
|
|
144
|
-
let clearedToolResults = 0;
|
|
145
|
-
let clearedMedia = 0;
|
|
146
|
-
let anyChange = false;
|
|
147
|
-
|
|
148
|
-
const nextMessages: Message[] = messages.map((msg, idx) => {
|
|
149
|
-
if (idx >= firstProtectedIdx) return msg;
|
|
150
|
-
|
|
151
|
-
let changed = false;
|
|
152
|
-
const nextContent: ContentBlock[] = msg.content.map((block) => {
|
|
153
|
-
// guard:allow-tool-result-only — compaction here operates on locally-
|
|
154
|
-
// executed `tool_result` bodies (string `.content`, possible
|
|
155
|
-
// `.contentBlocks` media). `web_search_tool_result` has an opaque
|
|
156
|
-
// encrypted content shape and is never microcompacted; it's treated as
|
|
157
|
-
// a tool-response only in `isToolResultOnlyUserMessage` above.
|
|
158
|
-
if (block.type === "tool_result") {
|
|
159
|
-
const tr = block as ToolResultContent;
|
|
160
|
-
const toolName = toolNameById.get(tr.tool_use_id);
|
|
161
|
-
const isProtected = toolName != null && protectedToolSet.has(toolName);
|
|
162
|
-
|
|
163
|
-
const { replacement, tokensSaved, didChange, cleared } =
|
|
164
|
-
compactToolResult(tr, isProtected);
|
|
165
|
-
if (didChange) {
|
|
166
|
-
reclaimedTokens += tokensSaved;
|
|
167
|
-
if (cleared) clearedToolResults += 1;
|
|
168
|
-
changed = true;
|
|
169
|
-
return replacement;
|
|
170
|
-
}
|
|
171
|
-
return block;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (block.type === "image") {
|
|
175
|
-
const saved = estimateImageReclaim(block);
|
|
176
|
-
// Only count a reclaim if stubbing actually shrinks the block.
|
|
177
|
-
// The stub is always valid, but avoid double-counting no-op cases.
|
|
178
|
-
reclaimedTokens += saved;
|
|
179
|
-
clearedMedia += 1;
|
|
180
|
-
changed = true;
|
|
181
|
-
return { type: "text", text: CLEARED_IMAGE_TEXT };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (block.type === "file") {
|
|
185
|
-
const saved = estimateFileReclaim(block);
|
|
186
|
-
reclaimedTokens += saved;
|
|
187
|
-
clearedMedia += 1;
|
|
188
|
-
changed = true;
|
|
189
|
-
return { type: "text", text: CLEARED_FILE_TEXT };
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return block;
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
if (!changed) return msg;
|
|
196
|
-
anyChange = true;
|
|
197
|
-
return { ...msg, content: nextContent };
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
if (!anyChange || reclaimedTokens < minGainTokens) {
|
|
201
|
-
return {
|
|
202
|
-
messages,
|
|
203
|
-
reclaimedTokens: 0,
|
|
204
|
-
clearedToolResults: 0,
|
|
205
|
-
clearedMedia: 0,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
messages: nextMessages,
|
|
211
|
-
reclaimedTokens,
|
|
212
|
-
clearedToolResults,
|
|
213
|
-
clearedMedia,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// ---------------------------------------------------------------------------
|
|
218
|
-
// Internals
|
|
219
|
-
// ---------------------------------------------------------------------------
|
|
220
|
-
|
|
221
|
-
function buildToolNameLookup(messages: Message[]): Map<string, string> {
|
|
222
|
-
const map = new Map<string, string>();
|
|
223
|
-
for (const msg of messages) {
|
|
224
|
-
if (msg.role !== "assistant") continue;
|
|
225
|
-
for (const block of msg.content) {
|
|
226
|
-
if (block.type === "tool_use") {
|
|
227
|
-
map.set(block.id, block.name);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return map;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Return the index of the first message that is inside the "protected tail".
|
|
236
|
-
*
|
|
237
|
-
* A user-assistant exchange begins at a user message that carries real user
|
|
238
|
-
* content (i.e. not a tool_result-only follow-up, which is how the provider
|
|
239
|
-
* encodes the tool response turn). We walk newest-to-oldest and, once we've
|
|
240
|
-
* seen `protectRecentTurns` such user-turn starts, return the index of the
|
|
241
|
-
* oldest such start. Everything at or after that index is protected.
|
|
242
|
-
*
|
|
243
|
-
* If the history has fewer than `protectRecentTurns` user turns, protect the
|
|
244
|
-
* entire history by returning 0.
|
|
245
|
-
*/
|
|
246
|
-
function computeProtectedBoundary(
|
|
247
|
-
messages: Message[],
|
|
248
|
-
protectRecentTurns: number,
|
|
249
|
-
): number {
|
|
250
|
-
if (protectRecentTurns <= 0) return messages.length;
|
|
251
|
-
|
|
252
|
-
let seen = 0;
|
|
253
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
254
|
-
const msg = messages[i];
|
|
255
|
-
if (msg.role !== "user") continue;
|
|
256
|
-
if (isToolResultOnlyUserMessage(msg)) continue;
|
|
257
|
-
seen += 1;
|
|
258
|
-
if (seen >= protectRecentTurns) {
|
|
259
|
-
return i;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
// Fewer user turns than the protection budget — protect everything.
|
|
263
|
-
return 0;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* A user message that contains only tool-response blocks (or system-injected
|
|
268
|
-
* metadata) represents the response side of a tool call rather than a fresh
|
|
269
|
-
* user turn.
|
|
270
|
-
*
|
|
271
|
-
* Qualifying blocks:
|
|
272
|
-
* - `tool_result` — locally-executed tool responses.
|
|
273
|
-
* - `web_search_tool_result` — server-side web-search responses. Same
|
|
274
|
-
* semantic as `tool_result` (paired with a prior `server_tool_use`), just
|
|
275
|
-
* a distinct discriminant. Missing this variant would cause these
|
|
276
|
-
* messages to masquerade as real user turns and eat `protectRecentTurns`
|
|
277
|
-
* budget on tool churn.
|
|
278
|
-
* - `text` blocks whose body is wholly inside `<system_notice>...</system_notice>`.
|
|
279
|
-
* Those are system-injected reminders/progress checks, not user-authored.
|
|
280
|
-
*/
|
|
281
|
-
function isToolResultOnlyUserMessage(message: Message): boolean {
|
|
282
|
-
if (message.content.length === 0) return false;
|
|
283
|
-
return message.content.every(isToolResponseOrSystemNoticeBlock);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function isToolResponseOrSystemNoticeBlock(block: ContentBlock): boolean {
|
|
287
|
-
if (block.type === "tool_result" || block.type === "web_search_tool_result") {
|
|
288
|
-
return true;
|
|
289
|
-
}
|
|
290
|
-
if (block.type === "text") {
|
|
291
|
-
const text = block.text;
|
|
292
|
-
return (
|
|
293
|
-
text.startsWith("<system_notice>") && text.endsWith("</system_notice>")
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
return false;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Compact a single tool_result block in the stripped region.
|
|
301
|
-
*
|
|
302
|
-
* - If `isProtected` is true, we keep the body but strip `<ax-tree>` blocks
|
|
303
|
-
* and drop media (image/file) entries from `contentBlocks`, preserving
|
|
304
|
-
* any text entries so meaningful tool output isn't silently removed.
|
|
305
|
-
* - Otherwise we replace the body with a short placeholder and drop
|
|
306
|
-
* `contentBlocks` entirely.
|
|
307
|
-
*
|
|
308
|
-
* `tokensSaved` is the delta between the original and the replacement as
|
|
309
|
-
* measured by `estimateTextTokens`, floored at 0. `cleared` is true only when
|
|
310
|
-
* we fully replaced the body (i.e. counted against `clearedToolResults`).
|
|
311
|
-
*/
|
|
312
|
-
function compactToolResult(
|
|
313
|
-
block: ToolResultContent,
|
|
314
|
-
isProtected: boolean,
|
|
315
|
-
): {
|
|
316
|
-
replacement: ToolResultContent;
|
|
317
|
-
tokensSaved: number;
|
|
318
|
-
didChange: boolean;
|
|
319
|
-
cleared: boolean;
|
|
320
|
-
} {
|
|
321
|
-
const originalContent = block.content;
|
|
322
|
-
const originalContentTokens = estimateTextTokens(originalContent);
|
|
323
|
-
|
|
324
|
-
// Rich contentBlocks may include text (meaningful tool output) alongside
|
|
325
|
-
// media (images/files). For UNPROTECTED results we drop the entire array
|
|
326
|
-
// (the body is being wholesale-replaced). For PROTECTED results we keep
|
|
327
|
-
// text entries but strip media — images aren't the expensive part of a
|
|
328
|
-
// subagent result and are rarely load-bearing once the turn is stale, but
|
|
329
|
-
// text entries can carry real content we must not silently erase.
|
|
330
|
-
const originalContentBlocks = block.contentBlocks;
|
|
331
|
-
const hadContentBlocks =
|
|
332
|
-
originalContentBlocks != null && originalContentBlocks.length > 0;
|
|
333
|
-
|
|
334
|
-
let preservedContentBlocks: ContentBlock[] | undefined;
|
|
335
|
-
let droppedBlocksTokens = 0;
|
|
336
|
-
if (hadContentBlocks) {
|
|
337
|
-
if (isProtected) {
|
|
338
|
-
const kept: ContentBlock[] = [];
|
|
339
|
-
for (const cb of originalContentBlocks) {
|
|
340
|
-
if (cb.type === "text") {
|
|
341
|
-
kept.push(cb);
|
|
342
|
-
} else {
|
|
343
|
-
droppedBlocksTokens += estimateContentBlockTokenCost(cb);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
preservedContentBlocks = kept;
|
|
347
|
-
} else {
|
|
348
|
-
for (const cb of originalContentBlocks) {
|
|
349
|
-
droppedBlocksTokens += estimateContentBlockTokenCost(cb);
|
|
350
|
-
}
|
|
351
|
-
preservedContentBlocks = undefined;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
let newContent: string;
|
|
356
|
-
let cleared: boolean;
|
|
357
|
-
if (isProtected) {
|
|
358
|
-
// Strip ax-tree blocks but keep the rest of the text body.
|
|
359
|
-
newContent = originalContent.replace(AX_TREE_PATTERN, AX_TREE_PLACEHOLDER);
|
|
360
|
-
cleared = false;
|
|
361
|
-
} else {
|
|
362
|
-
newContent = CLEARED_TOOL_RESULT_TEXT;
|
|
363
|
-
cleared = true;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const newContentTokens = estimateTextTokens(newContent);
|
|
367
|
-
const bodyTokensSaved = originalContentTokens - newContentTokens;
|
|
368
|
-
|
|
369
|
-
const bodyChanged = newContent !== originalContent;
|
|
370
|
-
// A protected result with only text contentBlocks would be a no-op — nothing
|
|
371
|
-
// meaningful would be dropped. Only count contentBlocks as a "change" when
|
|
372
|
-
// we actually drop at least one entry.
|
|
373
|
-
const contentBlocksChanged = hadContentBlocks && droppedBlocksTokens > 0;
|
|
374
|
-
const didChange = bodyChanged || contentBlocksChanged;
|
|
375
|
-
|
|
376
|
-
if (!didChange) {
|
|
377
|
-
return {
|
|
378
|
-
replacement: block,
|
|
379
|
-
tokensSaved: 0,
|
|
380
|
-
didChange: false,
|
|
381
|
-
cleared: false,
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const tokensSaved = Math.max(0, bodyTokensSaved + droppedBlocksTokens);
|
|
386
|
-
|
|
387
|
-
const replacement: ToolResultContent = {
|
|
388
|
-
type: "tool_result",
|
|
389
|
-
tool_use_id: block.tool_use_id,
|
|
390
|
-
content: newContent,
|
|
391
|
-
};
|
|
392
|
-
if (block.is_error != null) {
|
|
393
|
-
replacement.is_error = block.is_error;
|
|
394
|
-
}
|
|
395
|
-
if (preservedContentBlocks != null && preservedContentBlocks.length > 0) {
|
|
396
|
-
replacement.contentBlocks = preservedContentBlocks;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return {
|
|
400
|
-
replacement,
|
|
401
|
-
tokensSaved,
|
|
402
|
-
didChange,
|
|
403
|
-
cleared: cleared && bodyChanged,
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function estimateImageReclaim(
|
|
408
|
-
block: Extract<ContentBlock, { type: "image" }>,
|
|
409
|
-
): number {
|
|
410
|
-
// Base64 payloads are the expensive part of image blocks for our naive
|
|
411
|
-
// char/4 heuristic. The Anthropic-aware estimator in `token-estimator.ts`
|
|
412
|
-
// charges per-pixel — we deliberately use the simpler heuristic here so
|
|
413
|
-
// the reclaim number is a conservative lower bound on actual savings.
|
|
414
|
-
const payloadTokens = estimateTextTokens(block.source.data);
|
|
415
|
-
const stubTokens = estimateTextTokens(CLEARED_IMAGE_TEXT);
|
|
416
|
-
return Math.max(0, payloadTokens - stubTokens);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
function estimateFileReclaim(
|
|
420
|
-
block: Extract<ContentBlock, { type: "file" }>,
|
|
421
|
-
): number {
|
|
422
|
-
const payloadTokens =
|
|
423
|
-
estimateTextTokens(block.source.data) +
|
|
424
|
-
estimateTextTokens(block.extracted_text ?? "");
|
|
425
|
-
const stubTokens = estimateTextTokens(CLEARED_FILE_TEXT);
|
|
426
|
-
return Math.max(0, payloadTokens - stubTokens);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
function estimateContentBlockTokenCost(block: ContentBlock): number {
|
|
430
|
-
switch (block.type) {
|
|
431
|
-
case "text":
|
|
432
|
-
return estimateTextTokens(block.text);
|
|
433
|
-
case "image":
|
|
434
|
-
return estimateTextTokens(block.source.data);
|
|
435
|
-
case "file":
|
|
436
|
-
return (
|
|
437
|
-
estimateTextTokens(block.source.data) +
|
|
438
|
-
estimateTextTokens(block.extracted_text ?? "")
|
|
439
|
-
);
|
|
440
|
-
default:
|
|
441
|
-
return 0;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runs an OAuth2 loopback flow to install the user's Slack app and capture
|
|
3
|
-
* bot + user tokens in a single exchange.
|
|
4
|
-
*
|
|
5
|
-
* Prerequisites: client_id, client_secret, and app_token must already be
|
|
6
|
-
* stored in the credential vault (service: slack_channel).
|
|
7
|
-
*
|
|
8
|
-
* The handler reads client credentials from secure storage, starts a
|
|
9
|
-
* loopback OAuth server on port 17322, opens the browser to Slack's
|
|
10
|
-
* authorize URL, and waits for the user to click "Allow". Slack's
|
|
11
|
-
* oauth.v2.access response contains both the bot token (access_token)
|
|
12
|
-
* and user token (authed_user.access_token). Both are stored via
|
|
13
|
-
* setSlackChannelConfig.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { credentialKey } from "../../security/credential-key.js";
|
|
17
|
-
import { startOAuth2Flow } from "../../security/oauth2.js";
|
|
18
|
-
import { getSecureKeyAsync } from "../../security/secure-keys.js";
|
|
19
|
-
import { openInHostBrowser } from "../../util/browser.js";
|
|
20
|
-
import { getLogger } from "../../util/logger.js";
|
|
21
|
-
import { setSlackChannelConfig } from "./config-slack-channel.js";
|
|
22
|
-
|
|
23
|
-
const log = getLogger("slack-channel-oauth-install");
|
|
24
|
-
|
|
25
|
-
/** Port pre-registered for Slack in seed-providers.ts. */
|
|
26
|
-
const SLACK_LOOPBACK_PORT = 17322;
|
|
27
|
-
|
|
28
|
-
/** Bot scopes matching the manifest in SKILL.md. */
|
|
29
|
-
const BOT_SCOPES = [
|
|
30
|
-
"app_mentions:read",
|
|
31
|
-
"assistant:write",
|
|
32
|
-
"channels:history",
|
|
33
|
-
"channels:join",
|
|
34
|
-
"channels:read",
|
|
35
|
-
"chat:write",
|
|
36
|
-
"files:read",
|
|
37
|
-
"files:write",
|
|
38
|
-
"groups:history",
|
|
39
|
-
"groups:read",
|
|
40
|
-
"im:history",
|
|
41
|
-
"im:read",
|
|
42
|
-
"im:write",
|
|
43
|
-
"mpim:history",
|
|
44
|
-
"mpim:read",
|
|
45
|
-
"reactions:read",
|
|
46
|
-
"reactions:write",
|
|
47
|
-
"users:read",
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
/** User scopes matching the manifest in SKILL.md. */
|
|
51
|
-
const USER_SCOPES = [
|
|
52
|
-
"channels:history",
|
|
53
|
-
"channels:read",
|
|
54
|
-
"groups:history",
|
|
55
|
-
"groups:read",
|
|
56
|
-
"im:history",
|
|
57
|
-
"im:read",
|
|
58
|
-
"mpim:history",
|
|
59
|
-
"mpim:read",
|
|
60
|
-
"users:read",
|
|
61
|
-
"search:read",
|
|
62
|
-
"reactions:read",
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
export interface SlackOAuthInstallResult {
|
|
66
|
-
success: boolean;
|
|
67
|
-
hasBotToken: boolean;
|
|
68
|
-
hasUserToken: boolean;
|
|
69
|
-
error?: string;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export async function runSlackChannelOAuthInstall(): Promise<SlackOAuthInstallResult> {
|
|
73
|
-
// Read client credentials from secure storage
|
|
74
|
-
const clientId = await getSecureKeyAsync(
|
|
75
|
-
credentialKey("slack_channel", "client_id"),
|
|
76
|
-
);
|
|
77
|
-
if (!clientId) {
|
|
78
|
-
return {
|
|
79
|
-
success: false,
|
|
80
|
-
hasBotToken: false,
|
|
81
|
-
hasUserToken: false,
|
|
82
|
-
error:
|
|
83
|
-
"Client ID not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: client_id).",
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const clientSecret = await getSecureKeyAsync(
|
|
88
|
-
credentialKey("slack_channel", "client_secret"),
|
|
89
|
-
);
|
|
90
|
-
if (!clientSecret) {
|
|
91
|
-
return {
|
|
92
|
-
success: false,
|
|
93
|
-
hasBotToken: false,
|
|
94
|
-
hasUserToken: false,
|
|
95
|
-
error:
|
|
96
|
-
"Client Secret not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: client_secret).",
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const appToken = await getSecureKeyAsync(
|
|
101
|
-
credentialKey("slack_channel", "app_token"),
|
|
102
|
-
);
|
|
103
|
-
if (!appToken) {
|
|
104
|
-
return {
|
|
105
|
-
success: false,
|
|
106
|
-
hasBotToken: false,
|
|
107
|
-
hasUserToken: false,
|
|
108
|
-
error:
|
|
109
|
-
"App Token not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: app_token).",
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
log.info("Starting Slack OAuth install flow via loopback");
|
|
114
|
-
|
|
115
|
-
let result;
|
|
116
|
-
try {
|
|
117
|
-
result = await startOAuth2Flow(
|
|
118
|
-
{
|
|
119
|
-
authorizeUrl: "https://slack.com/oauth/v2/authorize",
|
|
120
|
-
tokenExchangeUrl: "https://slack.com/api/oauth.v2.access",
|
|
121
|
-
scopes: BOT_SCOPES,
|
|
122
|
-
clientId,
|
|
123
|
-
clientSecret,
|
|
124
|
-
scopeSeparator: ",",
|
|
125
|
-
authorizeParams: {
|
|
126
|
-
user_scope: USER_SCOPES.join(","),
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
openUrl: (url) => openInHostBrowser(url),
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
callbackTransport: "loopback",
|
|
134
|
-
loopbackPort: SLACK_LOOPBACK_PORT,
|
|
135
|
-
},
|
|
136
|
-
);
|
|
137
|
-
} catch (err) {
|
|
138
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
139
|
-
log.error({ err: msg }, "Slack OAuth install flow failed");
|
|
140
|
-
return {
|
|
141
|
-
success: false,
|
|
142
|
-
hasBotToken: false,
|
|
143
|
-
hasUserToken: false,
|
|
144
|
-
error: `OAuth flow failed: ${msg}`,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Slack's oauth.v2.access returns:
|
|
149
|
-
// access_token: "xoxb-..." (bot token)
|
|
150
|
-
// authed_user: { access_token: "xoxp-..." } (user token)
|
|
151
|
-
const raw = result.rawTokenResponse;
|
|
152
|
-
const botToken = raw.access_token as string | undefined;
|
|
153
|
-
const authedUser = raw.authed_user as { access_token?: string } | undefined;
|
|
154
|
-
const userToken = authedUser?.access_token as string | undefined;
|
|
155
|
-
|
|
156
|
-
if (!botToken) {
|
|
157
|
-
log.error(
|
|
158
|
-
{ rawKeys: Object.keys(raw) },
|
|
159
|
-
"Slack OAuth response missing bot access_token",
|
|
160
|
-
);
|
|
161
|
-
return {
|
|
162
|
-
success: false,
|
|
163
|
-
hasBotToken: false,
|
|
164
|
-
hasUserToken: false,
|
|
165
|
-
error:
|
|
166
|
-
"Slack OAuth response did not include a bot token (access_token). The app may not have bot scopes configured.",
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
log.info(
|
|
171
|
-
{ hasBotToken: true, hasUserToken: !!userToken },
|
|
172
|
-
"Slack OAuth tokens received, storing via setSlackChannelConfig",
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
// Store bot token (and user token if present) via the Slack channel handler,
|
|
176
|
-
// which validates tokens and persists workspace metadata.
|
|
177
|
-
const configResult = await setSlackChannelConfig(
|
|
178
|
-
botToken,
|
|
179
|
-
appToken,
|
|
180
|
-
userToken,
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
if (!configResult.success) {
|
|
184
|
-
return {
|
|
185
|
-
success: false,
|
|
186
|
-
hasBotToken: false,
|
|
187
|
-
hasUserToken: false,
|
|
188
|
-
error: configResult.error ?? "Failed to store Slack tokens",
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
success: true,
|
|
194
|
-
hasBotToken: true,
|
|
195
|
-
hasUserToken: !!userToken,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
2
|
-
import type { EventBus, Subscription } from "./bus.js";
|
|
3
|
-
import type { AssistantDomainEvents } from "./domain-events.js";
|
|
4
|
-
|
|
5
|
-
export function registerToolNotificationListener(
|
|
6
|
-
eventBus: EventBus<AssistantDomainEvents>,
|
|
7
|
-
sendToClient: (message: ServerMessage) => void,
|
|
8
|
-
): Subscription {
|
|
9
|
-
return eventBus.on("tool.secret.detected", (event) => {
|
|
10
|
-
sendToClient({
|
|
11
|
-
type: "secret_detected",
|
|
12
|
-
toolName: event.toolName,
|
|
13
|
-
matches: event.matches,
|
|
14
|
-
action: event.action,
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
}
|