@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
|
@@ -23,6 +23,12 @@ const log = getLogger("slack-backfill");
|
|
|
23
23
|
|
|
24
24
|
const DEFAULT_LIMIT = 50;
|
|
25
25
|
|
|
26
|
+
export interface SlackBackfillWindowPage {
|
|
27
|
+
messages: Message[];
|
|
28
|
+
hasMore: boolean;
|
|
29
|
+
nextCursor?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
function isChannelNotFound(err: unknown): boolean {
|
|
27
33
|
const msg = err instanceof Error ? err.message : String(err);
|
|
28
34
|
return /channel_not_found/i.test(msg);
|
|
@@ -41,31 +47,103 @@ export async function backfillThread(
|
|
|
41
47
|
threadTs: string,
|
|
42
48
|
opts?: { limit?: number; account?: string },
|
|
43
49
|
): Promise<Message[]> {
|
|
50
|
+
return backfillThreadWindow(channelId, threadTs, opts);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Fetch a bounded window of messages in a Slack thread.
|
|
55
|
+
*
|
|
56
|
+
* `after` and `before` are passed through to Slack as `oldest` and `latest`;
|
|
57
|
+
* callers can also pass a Slack pagination cursor when continuing a bounded
|
|
58
|
+
* scan. Returns `[]` on transient errors; rethrows `channel_not_found`.
|
|
59
|
+
*/
|
|
60
|
+
export async function backfillThreadWindow(
|
|
61
|
+
channelId: string,
|
|
62
|
+
threadTs: string,
|
|
63
|
+
opts?: {
|
|
64
|
+
limit?: number;
|
|
65
|
+
after?: string;
|
|
66
|
+
before?: string;
|
|
67
|
+
cursor?: string;
|
|
68
|
+
account?: string;
|
|
69
|
+
},
|
|
70
|
+
): Promise<Message[]> {
|
|
71
|
+
const page = await backfillThreadWindowPage(channelId, threadTs, opts);
|
|
72
|
+
return page.messages;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Fetch a bounded Slack thread page and preserve Slack pagination metadata.
|
|
77
|
+
*
|
|
78
|
+
* This is the preferred helper for callers that need to know whether a
|
|
79
|
+
* bounded window fully covered the requested range. The older
|
|
80
|
+
* `backfillThreadWindow` wrapper intentionally returns only messages for
|
|
81
|
+
* existing consumers.
|
|
82
|
+
*/
|
|
83
|
+
export async function backfillThreadWindowPage(
|
|
84
|
+
channelId: string,
|
|
85
|
+
threadTs: string,
|
|
86
|
+
opts?: {
|
|
87
|
+
limit?: number;
|
|
88
|
+
after?: string;
|
|
89
|
+
before?: string;
|
|
90
|
+
cursor?: string;
|
|
91
|
+
account?: string;
|
|
92
|
+
},
|
|
93
|
+
): Promise<SlackBackfillWindowPage> {
|
|
44
94
|
const limit = opts?.limit ?? DEFAULT_LIMIT;
|
|
45
95
|
try {
|
|
46
96
|
const connection = await slackProvider.resolveConnection?.(opts?.account);
|
|
47
|
-
if (
|
|
97
|
+
if (
|
|
98
|
+
!slackProvider.getThreadRepliesPage &&
|
|
99
|
+
!slackProvider.getThreadReplies
|
|
100
|
+
) {
|
|
48
101
|
log.warn(
|
|
49
102
|
{ channelId, threadTs },
|
|
50
|
-
"Slack provider does not implement
|
|
103
|
+
"Slack provider does not implement thread reply reads — returning []",
|
|
51
104
|
);
|
|
52
|
-
return [];
|
|
105
|
+
return { messages: [], hasMore: false };
|
|
53
106
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
|
|
107
|
+
const historyOptions = {
|
|
108
|
+
limit,
|
|
109
|
+
...(opts?.after !== undefined ? { after: opts.after } : {}),
|
|
110
|
+
...(opts?.before !== undefined ? { before: opts.before } : {}),
|
|
111
|
+
...(opts?.cursor !== undefined ? { cursor: opts.cursor } : {}),
|
|
112
|
+
};
|
|
113
|
+
if (slackProvider.getThreadRepliesPage) {
|
|
114
|
+
return await slackProvider.getThreadRepliesPage(
|
|
115
|
+
connection,
|
|
116
|
+
channelId,
|
|
117
|
+
threadTs,
|
|
118
|
+
historyOptions,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
messages: await slackProvider.getThreadReplies!(
|
|
123
|
+
connection,
|
|
124
|
+
channelId,
|
|
125
|
+
threadTs,
|
|
126
|
+
historyOptions,
|
|
127
|
+
),
|
|
128
|
+
hasMore: false,
|
|
129
|
+
};
|
|
60
130
|
} catch (err) {
|
|
61
131
|
if (isChannelNotFound(err)) {
|
|
62
132
|
throw err;
|
|
63
133
|
}
|
|
64
134
|
log.warn(
|
|
65
|
-
{
|
|
135
|
+
{
|
|
136
|
+
channelId,
|
|
137
|
+
threadTs,
|
|
138
|
+
after: opts?.after,
|
|
139
|
+
before: opts?.before,
|
|
140
|
+
cursor: opts?.cursor,
|
|
141
|
+
account: opts?.account,
|
|
142
|
+
err,
|
|
143
|
+
},
|
|
66
144
|
"Slack thread backfill failed — returning []",
|
|
67
145
|
);
|
|
68
|
-
return [];
|
|
146
|
+
return { messages: [], hasMore: false };
|
|
69
147
|
}
|
|
70
148
|
}
|
|
71
149
|
|
|
@@ -14,19 +14,12 @@ import type { OAuthConnection } from "../../../oauth/connection.js";
|
|
|
14
14
|
import type {
|
|
15
15
|
SlackApiResponse,
|
|
16
16
|
SlackAuthTestResponse,
|
|
17
|
-
SlackChatDeleteResponse,
|
|
18
|
-
SlackChatUpdateResponse,
|
|
19
17
|
SlackConversationHistoryResponse,
|
|
20
|
-
SlackConversationInfoResponse,
|
|
21
|
-
SlackConversationJoinResponse,
|
|
22
|
-
SlackConversationLeaveResponse,
|
|
23
18
|
SlackConversationMarkResponse,
|
|
24
19
|
SlackConversationRepliesResponse,
|
|
25
20
|
SlackConversationsListResponse,
|
|
26
21
|
SlackConversationsOpenResponse,
|
|
27
|
-
SlackPostEphemeralResponse,
|
|
28
22
|
SlackPostMessageResponse,
|
|
29
|
-
SlackReactionAddResponse,
|
|
30
23
|
SlackSearchMessagesResponse,
|
|
31
24
|
SlackUserInfoResponse,
|
|
32
25
|
} from "./types.js";
|
|
@@ -310,19 +303,6 @@ export async function listConversations(
|
|
|
310
303
|
);
|
|
311
304
|
}
|
|
312
305
|
|
|
313
|
-
export async function conversationInfo(
|
|
314
|
-
connectionOrToken: OAuthConnection | string,
|
|
315
|
-
channel: string,
|
|
316
|
-
): Promise<SlackConversationInfoResponse> {
|
|
317
|
-
return request<SlackConversationInfoResponse>(
|
|
318
|
-
connectionOrToken,
|
|
319
|
-
"conversations.info",
|
|
320
|
-
{
|
|
321
|
-
channel,
|
|
322
|
-
},
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
306
|
export async function conversationHistory(
|
|
327
307
|
connectionOrToken: OAuthConnection | string,
|
|
328
308
|
channel: string,
|
|
@@ -330,6 +310,7 @@ export async function conversationHistory(
|
|
|
330
310
|
latest?: string,
|
|
331
311
|
oldest?: string,
|
|
332
312
|
cursor?: string,
|
|
313
|
+
inclusive?: boolean,
|
|
333
314
|
): Promise<SlackConversationHistoryResponse> {
|
|
334
315
|
return request<SlackConversationHistoryResponse>(
|
|
335
316
|
connectionOrToken,
|
|
@@ -340,6 +321,7 @@ export async function conversationHistory(
|
|
|
340
321
|
latest,
|
|
341
322
|
oldest,
|
|
342
323
|
cursor,
|
|
324
|
+
inclusive: inclusive === undefined ? undefined : String(inclusive),
|
|
343
325
|
},
|
|
344
326
|
);
|
|
345
327
|
}
|
|
@@ -349,6 +331,10 @@ export async function conversationReplies(
|
|
|
349
331
|
channel: string,
|
|
350
332
|
ts: string,
|
|
351
333
|
limit = 50,
|
|
334
|
+
latest?: string,
|
|
335
|
+
oldest?: string,
|
|
336
|
+
inclusive?: boolean,
|
|
337
|
+
cursor?: string,
|
|
352
338
|
): Promise<SlackConversationRepliesResponse> {
|
|
353
339
|
return request<SlackConversationRepliesResponse>(
|
|
354
340
|
connectionOrToken,
|
|
@@ -357,6 +343,10 @@ export async function conversationReplies(
|
|
|
357
343
|
channel,
|
|
358
344
|
ts,
|
|
359
345
|
limit: String(limit),
|
|
346
|
+
latest,
|
|
347
|
+
oldest,
|
|
348
|
+
inclusive: inclusive === undefined ? undefined : String(inclusive),
|
|
349
|
+
cursor,
|
|
360
350
|
},
|
|
361
351
|
);
|
|
362
352
|
}
|
|
@@ -426,29 +416,6 @@ export async function postMessage(
|
|
|
426
416
|
);
|
|
427
417
|
}
|
|
428
418
|
|
|
429
|
-
/**
|
|
430
|
-
* Post an ephemeral message visible only to the specified user.
|
|
431
|
-
*
|
|
432
|
-
* Ephemeral messages are fire-and-forget: they cannot be edited or deleted
|
|
433
|
-
* after posting, and they disappear when the user reloads the Slack client.
|
|
434
|
-
*/
|
|
435
|
-
export async function postEphemeral(
|
|
436
|
-
connectionOrToken: OAuthConnection | string,
|
|
437
|
-
channel: string,
|
|
438
|
-
user: string,
|
|
439
|
-
text: string,
|
|
440
|
-
threadTs?: string,
|
|
441
|
-
): Promise<SlackPostEphemeralResponse> {
|
|
442
|
-
const body: Record<string, unknown> = { channel, user, text };
|
|
443
|
-
if (threadTs) body.thread_ts = threadTs;
|
|
444
|
-
return request<SlackPostEphemeralResponse>(
|
|
445
|
-
connectionOrToken,
|
|
446
|
-
"chat.postEphemeral",
|
|
447
|
-
undefined,
|
|
448
|
-
body,
|
|
449
|
-
);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
419
|
export async function searchMessages(
|
|
453
420
|
connectionOrToken: OAuthConnection | string,
|
|
454
421
|
query: string,
|
|
@@ -465,84 +432,3 @@ export async function searchMessages(
|
|
|
465
432
|
},
|
|
466
433
|
);
|
|
467
434
|
}
|
|
468
|
-
|
|
469
|
-
export async function addReaction(
|
|
470
|
-
connectionOrToken: OAuthConnection | string,
|
|
471
|
-
channel: string,
|
|
472
|
-
timestamp: string,
|
|
473
|
-
name: string,
|
|
474
|
-
): Promise<SlackReactionAddResponse> {
|
|
475
|
-
return request<SlackReactionAddResponse>(
|
|
476
|
-
connectionOrToken,
|
|
477
|
-
"reactions.add",
|
|
478
|
-
undefined,
|
|
479
|
-
{
|
|
480
|
-
channel,
|
|
481
|
-
timestamp,
|
|
482
|
-
name,
|
|
483
|
-
},
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
export async function updateMessage(
|
|
488
|
-
connectionOrToken: OAuthConnection | string,
|
|
489
|
-
channel: string,
|
|
490
|
-
ts: string,
|
|
491
|
-
text: string,
|
|
492
|
-
): Promise<SlackChatUpdateResponse> {
|
|
493
|
-
return request<SlackChatUpdateResponse>(
|
|
494
|
-
connectionOrToken,
|
|
495
|
-
"chat.update",
|
|
496
|
-
undefined,
|
|
497
|
-
{
|
|
498
|
-
channel,
|
|
499
|
-
ts,
|
|
500
|
-
text,
|
|
501
|
-
},
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
export async function deleteMessage(
|
|
506
|
-
connectionOrToken: OAuthConnection | string,
|
|
507
|
-
channel: string,
|
|
508
|
-
ts: string,
|
|
509
|
-
): Promise<SlackChatDeleteResponse> {
|
|
510
|
-
return request<SlackChatDeleteResponse>(
|
|
511
|
-
connectionOrToken,
|
|
512
|
-
"chat.delete",
|
|
513
|
-
undefined,
|
|
514
|
-
{
|
|
515
|
-
channel,
|
|
516
|
-
ts,
|
|
517
|
-
},
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
export async function joinConversation(
|
|
522
|
-
connectionOrToken: OAuthConnection | string,
|
|
523
|
-
channel: string,
|
|
524
|
-
): Promise<SlackConversationJoinResponse> {
|
|
525
|
-
return request<SlackConversationJoinResponse>(
|
|
526
|
-
connectionOrToken,
|
|
527
|
-
"conversations.join",
|
|
528
|
-
undefined,
|
|
529
|
-
{
|
|
530
|
-
channel,
|
|
531
|
-
},
|
|
532
|
-
);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
export async function leaveConversation(
|
|
536
|
-
connectionOrToken: OAuthConnection | string,
|
|
537
|
-
channel: string,
|
|
538
|
-
): Promise<SlackConversationLeaveResponse> {
|
|
539
|
-
return request<SlackConversationLeaveResponse>(
|
|
540
|
-
connectionOrToken,
|
|
541
|
-
"conversations.leave",
|
|
542
|
-
undefined,
|
|
543
|
-
{
|
|
544
|
-
channel,
|
|
545
|
-
},
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
@@ -11,8 +11,10 @@ import { z } from "zod";
|
|
|
11
11
|
* Slack-only blob for fresh writes; `mergeSlackMetadata` patches Slack fields
|
|
12
12
|
* while preserving unrelated keys on the existing JSON.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Slack transcript rendering and backfill paths persist and read this metadata
|
|
15
|
+
* to reconstruct thread order, reactions, edits, deletes, and lightweight
|
|
16
|
+
* Slack file markers. Transient late-join notices are current-turn runtime
|
|
17
|
+
* context only and do not become durable message metadata.
|
|
16
18
|
*/
|
|
17
19
|
|
|
18
20
|
export type SlackEventKind = "message" | "reaction";
|
|
@@ -24,6 +26,12 @@ const slackReactionMetadataSchema = z.object({
|
|
|
24
26
|
op: z.enum(["added", "removed"]),
|
|
25
27
|
});
|
|
26
28
|
|
|
29
|
+
const slackFileMetadataSchema = z.object({
|
|
30
|
+
id: z.string().optional(),
|
|
31
|
+
name: z.string(),
|
|
32
|
+
mimetype: z.string().optional(),
|
|
33
|
+
});
|
|
34
|
+
|
|
27
35
|
export const slackMessageMetadataSchema = z.object({
|
|
28
36
|
source: z.literal("slack"),
|
|
29
37
|
channelId: z.string(),
|
|
@@ -34,9 +42,11 @@ export const slackMessageMetadataSchema = z.object({
|
|
|
34
42
|
reaction: slackReactionMetadataSchema.optional(),
|
|
35
43
|
editedAt: z.number().optional(),
|
|
36
44
|
deletedAt: z.number().optional(),
|
|
45
|
+
slackFiles: z.array(slackFileMetadataSchema).optional(),
|
|
37
46
|
});
|
|
38
47
|
|
|
39
48
|
export type SlackReactionMetadata = z.infer<typeof slackReactionMetadataSchema>;
|
|
49
|
+
export type SlackFileMetadata = z.infer<typeof slackFileMetadataSchema>;
|
|
40
50
|
export type SlackMessageMetadata = z.infer<typeof slackMessageMetadataSchema>;
|
|
41
51
|
|
|
42
52
|
/**
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
parentAlias,
|
|
17
17
|
type RenderableSlackMessage,
|
|
18
18
|
renderSlackTranscript,
|
|
19
|
+
renderSlackTranscriptWithProvenance,
|
|
19
20
|
} from "./render-transcript.js";
|
|
20
21
|
|
|
21
22
|
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
@@ -44,6 +45,7 @@ function userMsg(
|
|
|
44
45
|
deletedAt?: number;
|
|
45
46
|
role?: "user" | "assistant";
|
|
46
47
|
createdAt?: number;
|
|
48
|
+
slackFiles?: Array<{ id?: string; name: string; mimetype?: string }>;
|
|
47
49
|
} = {},
|
|
48
50
|
): RenderableSlackMessage {
|
|
49
51
|
return {
|
|
@@ -59,6 +61,7 @@ function userMsg(
|
|
|
59
61
|
eventKind: "message",
|
|
60
62
|
editedAt: opts.editedAt,
|
|
61
63
|
deletedAt: opts.deletedAt,
|
|
64
|
+
slackFiles: opts.slackFiles,
|
|
62
65
|
},
|
|
63
66
|
};
|
|
64
67
|
}
|
|
@@ -242,6 +245,59 @@ describe("renderSlackTranscript — basics", () => {
|
|
|
242
245
|
expect(out).toEqual([textMsg("assistant", "yo 👋")]);
|
|
243
246
|
});
|
|
244
247
|
|
|
248
|
+
test("backfilled Slack file metadata renders as concise attachment markers", () => {
|
|
249
|
+
const out = renderSlackTranscript([
|
|
250
|
+
userMsg(TS_14_25, "@alice", "shared the draft", {
|
|
251
|
+
slackFiles: [
|
|
252
|
+
{ id: "F123", name: "requirements.txt", mimetype: "text/plain" },
|
|
253
|
+
],
|
|
254
|
+
}),
|
|
255
|
+
userMsg(TS_14_26, "@bob", "", {
|
|
256
|
+
slackFiles: [{ name: "diagram.png", mimetype: "image/png" }],
|
|
257
|
+
}),
|
|
258
|
+
]);
|
|
259
|
+
|
|
260
|
+
expect(out).toEqual([
|
|
261
|
+
textMsg(
|
|
262
|
+
"user",
|
|
263
|
+
"[11/14/23 14:25 @alice]: shared the draft [attached file: requirements.txt, text/plain]",
|
|
264
|
+
),
|
|
265
|
+
textMsg(
|
|
266
|
+
"user",
|
|
267
|
+
"[11/14/23 14:26 @bob]: [attached file: diagram.png, image/png]",
|
|
268
|
+
),
|
|
269
|
+
]);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("provenance follows the rendered sequence after orphan filtering", () => {
|
|
273
|
+
const out = renderSlackTranscriptWithProvenance([
|
|
274
|
+
userMsg(TS_14_25, "@alice", "kept"),
|
|
275
|
+
{
|
|
276
|
+
...userMsg(TS_14_26, null, "", { role: "assistant" }),
|
|
277
|
+
contentBlocks: [
|
|
278
|
+
{ type: "tool_use", id: "tool-1", name: "lookup", input: {} },
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
userMsg(TS_14_28, "@bob", "also kept"),
|
|
282
|
+
]);
|
|
283
|
+
|
|
284
|
+
expect(extractTagLineTexts(out.messages)).toEqual([
|
|
285
|
+
"[11/14/23 14:25 @alice]: kept",
|
|
286
|
+
"[11/14/23 14:28 @bob]: also kept",
|
|
287
|
+
]);
|
|
288
|
+
expect(out.renderedMessages.map((entry) => entry.message)).toEqual(
|
|
289
|
+
out.messages,
|
|
290
|
+
);
|
|
291
|
+
expect(out.renderedMessages.map((entry) => entry.sourceChannelTs)).toEqual([
|
|
292
|
+
TS_14_25,
|
|
293
|
+
TS_14_28,
|
|
294
|
+
]);
|
|
295
|
+
expect(out.renderedMessages.map((entry) => entry.sourceChannelTs)).toEqual([
|
|
296
|
+
TS_14_25,
|
|
297
|
+
TS_14_28,
|
|
298
|
+
]);
|
|
299
|
+
});
|
|
300
|
+
|
|
245
301
|
test("omits sender label for user-role message with null senderLabel (no displayName)", () => {
|
|
246
302
|
const out = renderSlackTranscript([userMsg(TS_14_25, null, "yo")]);
|
|
247
303
|
expect(out).toEqual([textMsg("user", "[11/14/23 14:25]: yo")]);
|
|
@@ -58,6 +58,18 @@ export interface RenderOptions {
|
|
|
58
58
|
|
|
59
59
|
const DEFAULT_MAX_REACTIONS = 5;
|
|
60
60
|
|
|
61
|
+
export interface RenderedSlackTranscript {
|
|
62
|
+
/** Rendered messages paired with the Slack source timestamp they represent. */
|
|
63
|
+
readonly renderedMessages: readonly RenderedSlackTranscriptMessage[];
|
|
64
|
+
/** Convenience projection of `renderedMessages[].message`. */
|
|
65
|
+
readonly messages: Message[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface RenderedSlackTranscriptMessage {
|
|
69
|
+
readonly message: Message;
|
|
70
|
+
readonly sourceChannelTs: string | null;
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
/**
|
|
62
74
|
* Replayable Anthropic content-block types that we preserve verbatim from a
|
|
63
75
|
* persisted row when rendering the Slack chronological transcript.
|
|
@@ -146,6 +158,30 @@ function formatEpochMs(ms: number): string {
|
|
|
146
158
|
return `${mo}/${da}/${yy} ${hh}:${mm}`;
|
|
147
159
|
}
|
|
148
160
|
|
|
161
|
+
function renderSlackFileMarkers(
|
|
162
|
+
files: SlackMessageMetadata["slackFiles"],
|
|
163
|
+
): string {
|
|
164
|
+
if (!files || files.length === 0) return "";
|
|
165
|
+
return files
|
|
166
|
+
.map((file) => {
|
|
167
|
+
const name = file.name.replace(/\s+/g, " ").trim();
|
|
168
|
+
const mime = file.mimetype?.replace(/\s+/g, " ").trim();
|
|
169
|
+
return mime
|
|
170
|
+
? `[attached file: ${name}, ${mime}]`
|
|
171
|
+
: `[attached file: ${name}]`;
|
|
172
|
+
})
|
|
173
|
+
.join(" ");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function appendSlackFileMarkers(
|
|
177
|
+
content: string,
|
|
178
|
+
files: SlackMessageMetadata["slackFiles"],
|
|
179
|
+
): string {
|
|
180
|
+
const markers = renderSlackFileMarkers(files);
|
|
181
|
+
if (!markers) return content;
|
|
182
|
+
return content.length > 0 ? `${content} ${markers}` : markers;
|
|
183
|
+
}
|
|
184
|
+
|
|
149
185
|
/**
|
|
150
186
|
* Sort key for chronological ordering.
|
|
151
187
|
*
|
|
@@ -162,6 +198,25 @@ function sortKey(msg: RenderableSlackMessage): number {
|
|
|
162
198
|
return msg.createdAt / 1000;
|
|
163
199
|
}
|
|
164
200
|
|
|
201
|
+
export function compareSlackTs(a: string, b: string): number {
|
|
202
|
+
const aNum = Number.parseFloat(a);
|
|
203
|
+
const bNum = Number.parseFloat(b);
|
|
204
|
+
if (Number.isFinite(aNum) && Number.isFinite(bNum) && aNum !== bNum) {
|
|
205
|
+
return aNum - bNum;
|
|
206
|
+
}
|
|
207
|
+
return a.localeCompare(b);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function isSlackTsAfter(ts: string, watermarkTs: string): boolean {
|
|
211
|
+
return compareSlackTs(ts, watermarkTs) > 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function maxNullableSlackTs(a: string | null, b: string | null): string | null {
|
|
215
|
+
if (a === null) return b;
|
|
216
|
+
if (b === null) return a;
|
|
217
|
+
return compareSlackTs(a, b) >= 0 ? a : b;
|
|
218
|
+
}
|
|
219
|
+
|
|
165
220
|
/**
|
|
166
221
|
* Render a single non-reaction message (post-upgrade or legacy) as one
|
|
167
222
|
* tagged line.
|
|
@@ -197,7 +252,7 @@ function sortKey(msg: RenderableSlackMessage): number {
|
|
|
197
252
|
function renderMessage(msg: RenderableSlackMessage): string {
|
|
198
253
|
if (msg.role === "assistant") {
|
|
199
254
|
if (msg.metadata?.deletedAt !== undefined) return "[deleted]";
|
|
200
|
-
return msg.content;
|
|
255
|
+
return appendSlackFileMarkers(msg.content, msg.metadata?.slackFiles);
|
|
201
256
|
}
|
|
202
257
|
|
|
203
258
|
const meta = msg.metadata;
|
|
@@ -222,7 +277,7 @@ function renderMessage(msg: RenderableSlackMessage): string {
|
|
|
222
277
|
if (meta.editedAt !== undefined) {
|
|
223
278
|
head += `, edited ${formatEpochMs(meta.editedAt)}`;
|
|
224
279
|
}
|
|
225
|
-
head += `]: ${msg.content}`;
|
|
280
|
+
head += `]: ${appendSlackFileMarkers(msg.content, meta.slackFiles)}`;
|
|
226
281
|
return head;
|
|
227
282
|
}
|
|
228
283
|
|
|
@@ -342,7 +397,16 @@ export function renderSlackTranscript(
|
|
|
342
397
|
messages: RenderableSlackMessage[],
|
|
343
398
|
opts?: RenderOptions,
|
|
344
399
|
): Message[] {
|
|
345
|
-
|
|
400
|
+
return renderSlackTranscriptWithProvenance(messages, opts).messages;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function renderSlackTranscriptWithProvenance(
|
|
404
|
+
messages: RenderableSlackMessage[],
|
|
405
|
+
opts?: RenderOptions,
|
|
406
|
+
): RenderedSlackTranscript {
|
|
407
|
+
if (messages.length === 0) {
|
|
408
|
+
return { renderedMessages: [], messages: [] };
|
|
409
|
+
}
|
|
346
410
|
|
|
347
411
|
const maxReactions = Math.max(
|
|
348
412
|
1,
|
|
@@ -364,23 +428,37 @@ export function renderSlackTranscript(
|
|
|
364
428
|
// reaches an event that is not an overflowing reaction for that target.
|
|
365
429
|
const overflowAccumulator = new Map<
|
|
366
430
|
string,
|
|
367
|
-
{
|
|
431
|
+
{
|
|
432
|
+
excess: number;
|
|
433
|
+
role: "user" | "assistant";
|
|
434
|
+
sourceChannelTs: string | null;
|
|
435
|
+
}
|
|
368
436
|
>();
|
|
369
437
|
|
|
370
438
|
const trailerMessage = (
|
|
371
439
|
target: string,
|
|
372
|
-
acc: {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
440
|
+
acc: {
|
|
441
|
+
excess: number;
|
|
442
|
+
role: "user" | "assistant";
|
|
443
|
+
sourceChannelTs: string | null;
|
|
444
|
+
},
|
|
445
|
+
): RenderedSlackTranscriptMessage => ({
|
|
446
|
+
message: {
|
|
447
|
+
role: acc.role,
|
|
448
|
+
content: [
|
|
449
|
+
{
|
|
450
|
+
type: "text" as const,
|
|
451
|
+
text: `[…and ${acc.excess} more ${acc.excess === 1 ? "reaction" : "reactions"} to ${parentAlias(target)}]`,
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
},
|
|
455
|
+
sourceChannelTs: acc.sourceChannelTs,
|
|
381
456
|
});
|
|
382
457
|
|
|
383
|
-
const flushOverflowExcept = (
|
|
458
|
+
const flushOverflowExcept = (
|
|
459
|
+
out: RenderedSlackTranscriptMessage[],
|
|
460
|
+
keepTarget: string | null,
|
|
461
|
+
) => {
|
|
384
462
|
for (const target of Array.from(overflowAccumulator.keys())) {
|
|
385
463
|
if (target === keepTarget) continue;
|
|
386
464
|
const acc = overflowAccumulator.get(target)!;
|
|
@@ -389,7 +467,7 @@ export function renderSlackTranscript(
|
|
|
389
467
|
}
|
|
390
468
|
};
|
|
391
469
|
|
|
392
|
-
const out:
|
|
470
|
+
const out: RenderedSlackTranscriptMessage[] = [];
|
|
393
471
|
for (const m of sorted) {
|
|
394
472
|
const meta = m.metadata;
|
|
395
473
|
if (meta?.eventKind === "reaction" && meta.reaction) {
|
|
@@ -403,8 +481,11 @@ export function renderSlackTranscript(
|
|
|
403
481
|
const line = renderReaction(m);
|
|
404
482
|
if (line !== null) {
|
|
405
483
|
out.push({
|
|
406
|
-
|
|
407
|
-
|
|
484
|
+
message: {
|
|
485
|
+
role: m.role,
|
|
486
|
+
content: [{ type: "text" as const, text: line }],
|
|
487
|
+
},
|
|
488
|
+
sourceChannelTs: meta.channelTs,
|
|
408
489
|
});
|
|
409
490
|
}
|
|
410
491
|
} else {
|
|
@@ -414,8 +495,13 @@ export function renderSlackTranscript(
|
|
|
414
495
|
const acc = overflowAccumulator.get(target) ?? {
|
|
415
496
|
excess: 0,
|
|
416
497
|
role: m.role,
|
|
498
|
+
sourceChannelTs: null,
|
|
417
499
|
};
|
|
418
500
|
acc.excess += 1;
|
|
501
|
+
acc.sourceChannelTs = maxNullableSlackTs(
|
|
502
|
+
acc.sourceChannelTs,
|
|
503
|
+
meta.channelTs,
|
|
504
|
+
);
|
|
419
505
|
overflowAccumulator.set(target, acc);
|
|
420
506
|
}
|
|
421
507
|
continue;
|
|
@@ -426,15 +512,22 @@ export function renderSlackTranscript(
|
|
|
426
512
|
const blocks = buildMessageContentBlocks(m, tagLine);
|
|
427
513
|
if (blocks.length === 0) continue;
|
|
428
514
|
out.push({
|
|
429
|
-
|
|
430
|
-
|
|
515
|
+
message: {
|
|
516
|
+
role: m.role,
|
|
517
|
+
content: blocks,
|
|
518
|
+
},
|
|
519
|
+
sourceChannelTs: meta?.channelTs ?? null,
|
|
431
520
|
});
|
|
432
521
|
}
|
|
433
522
|
|
|
434
523
|
// End of the walk: flush any still-open overflow windows.
|
|
435
524
|
flushOverflowExcept(out, null);
|
|
436
525
|
|
|
437
|
-
|
|
526
|
+
const filtered = filterOrphanToolPairs(out);
|
|
527
|
+
return {
|
|
528
|
+
renderedMessages: filtered,
|
|
529
|
+
messages: filtered.map((entry) => entry.message),
|
|
530
|
+
};
|
|
438
531
|
}
|
|
439
532
|
|
|
440
533
|
/**
|
|
@@ -459,18 +552,21 @@ export function renderSlackTranscript(
|
|
|
459
552
|
* emitted as `{role, content: []}` — empty-content messages are also
|
|
460
553
|
* rejected by the provider.
|
|
461
554
|
*/
|
|
462
|
-
function filterOrphanToolPairs(
|
|
555
|
+
function filterOrphanToolPairs(
|
|
556
|
+
entries: RenderedSlackTranscriptMessage[],
|
|
557
|
+
): RenderedSlackTranscriptMessage[] {
|
|
463
558
|
const produced = new Set<string>();
|
|
464
559
|
const consumed = new Set<string>();
|
|
465
|
-
for (const msg of
|
|
560
|
+
for (const { message: msg } of entries) {
|
|
466
561
|
for (const b of msg.content) {
|
|
467
562
|
if (b.type === "tool_use") produced.add(b.id);
|
|
468
563
|
else if (b.type === "tool_result" || b.type === "web_search_tool_result")
|
|
469
564
|
consumed.add(b.tool_use_id);
|
|
470
565
|
}
|
|
471
566
|
}
|
|
472
|
-
const out:
|
|
473
|
-
for (const
|
|
567
|
+
const out: RenderedSlackTranscriptMessage[] = [];
|
|
568
|
+
for (const entry of entries) {
|
|
569
|
+
const msg = entry.message;
|
|
474
570
|
const kept: ContentBlock[] = [];
|
|
475
571
|
for (const b of msg.content) {
|
|
476
572
|
if (b.type === "tool_use" && !consumed.has(b.id)) continue;
|
|
@@ -481,7 +577,12 @@ function filterOrphanToolPairs(messages: Message[]): Message[] {
|
|
|
481
577
|
continue;
|
|
482
578
|
kept.push(b);
|
|
483
579
|
}
|
|
484
|
-
if (kept.length > 0)
|
|
580
|
+
if (kept.length > 0) {
|
|
581
|
+
out.push({
|
|
582
|
+
message: { role: msg.role, content: kept },
|
|
583
|
+
sourceChannelTs: entry.sourceChannelTs,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
485
586
|
}
|
|
486
587
|
return out;
|
|
487
588
|
}
|
|
@@ -59,6 +59,7 @@ export interface SlackConversationHistoryResponse extends SlackApiResponse {
|
|
|
59
59
|
export interface SlackConversationRepliesResponse extends SlackApiResponse {
|
|
60
60
|
messages: SlackMessage[];
|
|
61
61
|
has_more: boolean;
|
|
62
|
+
response_metadata?: { next_cursor?: string };
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
export interface SlackUser {
|