@cursor/july 0.1.96 → 0.1.99
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/AGENTS.md +1 -1
- package/README.md +3 -2
- package/dist/bin/agent-serve.js +13 -3
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +16 -0
- package/dist/channels/origin/api.d.ts +15 -4
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +19 -3
- package/dist/channels/origin/binding.d.ts +11 -0
- package/dist/channels/origin/binding.d.ts.map +1 -1
- package/dist/channels/origin/binding.js +41 -25
- package/dist/channels/origin/index.d.ts +1 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +1 -0
- package/dist/channels/origin/origin-channel.d.ts +2 -0
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +40 -4
- package/dist/channels/origin/reactions.d.ts +56 -0
- package/dist/channels/origin/reactions.d.ts.map +1 -0
- package/dist/channels/origin/reactions.js +67 -0
- package/dist/channels/origin/types.d.ts +11 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/approvals.d.ts +16 -0
- package/dist/channels/slack/approvals.d.ts.map +1 -1
- package/dist/channels/slack/approvals.js +86 -0
- package/dist/channels/slack/cli-project.d.ts +19 -0
- package/dist/channels/slack/cli-project.d.ts.map +1 -0
- package/dist/channels/slack/cli-project.js +234 -0
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +142 -63
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/init.d.ts +3 -2
- package/dist/channels/slack/init.d.ts.map +1 -1
- package/dist/channels/slack/init.js +5 -5
- package/dist/channels/slack/interactive.d.ts +2 -1
- package/dist/channels/slack/interactive.d.ts.map +1 -1
- package/dist/channels/slack/interactive.js +15 -4
- package/dist/channels/slack/live-delivery.d.ts +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +4 -2
- package/dist/channels/slack/manifest.d.ts +1 -1
- package/dist/channels/slack/manifest.js +1 -1
- package/dist/channels/slack/progress-delivery.d.ts +28 -0
- package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
- package/dist/channels/slack/progress-delivery.js +115 -0
- package/dist/channels/slack/setup.d.ts +1 -1
- package/dist/channels/slack/setup.d.ts.map +1 -1
- package/dist/channels/slack/setup.js +10 -6
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +1 -0
- package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
- package/dist/channels/slack/tool-approval-events.js +91 -1
- package/dist/channels/slack/types.d.ts +9 -1
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.jXleCmOc.js → app.BplEAZ3S.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.8LhyglIT.js → VPLocalSearchBox.CHXyv4wP.js} +1 -1
- package/dist/docs/assets/chunks/{theme.9ged-pr2.js → theme.BTcsZmjQ.js} +2 -2
- package/dist/docs/assets/{deployment.md.D9msOFOW.js → deployment.md.MFPKqsqI.js} +2 -2
- package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.js → guides_mcp-oauth.md.CN-6YmTJ.js} +4 -4
- package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.lean.js → guides_mcp-oauth.md.CN-6YmTJ.lean.js} +1 -1
- package/dist/docs/assets/guides_slack.md.VDXQV3ja.js +22 -0
- package/dist/docs/assets/guides_slack.md.VDXQV3ja.lean.js +1 -0
- package/dist/docs/assets/index.md.CVeRUOeZ.js +5 -0
- package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.js → reference_cli.md.DfoeyvL0.js} +9 -6
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.js → reference_connections.md.DxldvyIB.js} +4 -3
- package/dist/docs/assets/{reference_http-api.md.D89k1mdm.js → reference_http-api.md.BEJx9XVj.js} +2 -2
- package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
- package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.CvAHsdSp.js} +10 -2
- package/dist/docs/assets/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.CvAHsdSp.lean.js} +1 -1
- package/dist/docs/assets/templates_agents-md.md.CXSMZljE.js +2 -0
- package/dist/docs/assets/templates_agents-md.md.CXSMZljE.lean.js +1 -0
- package/dist/docs/assets/troubleshooting.md.DCiPBhYs.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +7 -7
- package/dist/docs/deployment.md +5 -4
- package/dist/docs/design/runtime-abstraction.md +1757 -0
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +8 -8
- package/dist/docs/guides/mcp-oauth.md +26 -8
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +17 -33
- package/dist/docs/guides/slack.md +92 -201
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +5 -3
- package/dist/docs/llms-full.txt +2065 -637
- package/dist/docs/llms.txt +3 -2
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/agent-config.md +2 -2
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +13 -10
- package/dist/docs/reference/cli.md +32 -16
- package/dist/docs/reference/connections.html +9 -8
- package/dist/docs/reference/connections.md +6 -3
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +7 -7
- package/dist/docs/reference/http-api.md +3 -1
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/sessions.md +4 -2
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +15 -7
- package/dist/docs/reference/tools.md +34 -2
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +28 -0
- package/dist/docs/templates/agents-md.md +105 -0
- package/dist/docs/templates/code-wiki.html +5 -5
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +5 -5
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +2 -2
- package/dist/evals/run-facts.d.ts.map +1 -1
- package/dist/evals/run-facts.js +27 -0
- package/dist/files-backends/cursor-hosted.d.ts +3 -2
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +15 -9
- package/dist/internal/approval-gate.d.ts +12 -13
- package/dist/internal/approval-gate.d.ts.map +1 -1
- package/dist/internal/approval-gate.js +16 -21
- package/dist/internal/as-of.d.ts +19 -0
- package/dist/internal/as-of.d.ts.map +1 -0
- package/dist/internal/as-of.js +82 -0
- package/dist/internal/chat-client.js +10 -0
- package/dist/internal/cli-deploy.d.ts +6 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +149 -21
- package/dist/internal/cli-mcp-oauth.js +8 -18
- package/dist/internal/cli-slack-manual.d.ts +24 -2
- package/dist/internal/cli-slack-manual.d.ts.map +1 -1
- package/dist/internal/cli-slack-manual.js +251 -20
- package/dist/internal/cli-slack.d.ts +9 -2
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +29 -82
- package/dist/internal/cursor/account-mcp.d.ts +1 -0
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +17 -0
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +5 -6
- package/dist/internal/deploy-client.d.ts +17 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +31 -10
- package/dist/internal/env-file.d.ts +19 -0
- package/dist/internal/env-file.d.ts.map +1 -0
- package/dist/internal/env-file.js +90 -0
- package/dist/internal/framework-file-storage.d.ts +11 -17
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +17 -40
- package/dist/internal/framework-storage-selection.d.ts +13 -11
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +37 -26
- package/dist/internal/hosted-admission-adapter.d.ts +28 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
- package/dist/internal/hosted-admission-adapter.js +7 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +13 -1
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +8 -1
- package/dist/internal/hosted-delivery.d.ts +21 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +101 -34
- package/dist/internal/hosted-execution-diag.d.ts +59 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
- package/dist/internal/hosted-execution-diag.js +187 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +85 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +2 -0
- package/dist/internal/logs-client.d.ts +5 -0
- package/dist/internal/logs-client.d.ts.map +1 -1
- package/dist/internal/logs-client.js +5 -0
- package/dist/internal/mcp-endpoint.js +2 -3
- package/dist/internal/mcp-host.d.ts +10 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +57 -8
- package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
- package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-on-demand.js +287 -0
- package/dist/internal/mcp-oauth-persist.d.ts +42 -0
- package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-persist.js +92 -0
- package/dist/internal/mcp-oauth.d.ts +1 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +10 -2
- package/dist/internal/null-kv-storage.d.ts +48 -0
- package/dist/internal/null-kv-storage.d.ts.map +1 -0
- package/dist/internal/null-kv-storage.js +58 -0
- package/dist/internal/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +22 -9
- package/dist/internal/server.d.ts +6 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +123 -33
- package/dist/internal/session-engine.d.ts +88 -3
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +538 -46
- package/dist/internal/session-run-log.d.ts +120 -0
- package/dist/internal/session-run-log.d.ts.map +1 -0
- package/dist/internal/session-run-log.js +359 -0
- package/dist/internal/sessions-client.d.ts +9 -7
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +3 -1
- package/dist/internal/storage-coordinator.d.ts +13 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +37 -6
- package/dist/internal/storage-roles.d.ts +5 -0
- package/dist/internal/storage-roles.d.ts.map +1 -1
- package/dist/internal/stream-progress.d.ts.map +1 -1
- package/dist/internal/stream-progress.js +10 -0
- package/dist/internal/tool-policy.d.ts +29 -9
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +24 -0
- package/dist/internal/trajectory.d.ts.map +1 -1
- package/dist/internal/trajectory.js +10 -0
- package/dist/internal/turn-outbox.d.ts +24 -0
- package/dist/internal/turn-outbox.d.ts.map +1 -0
- package/dist/internal/turn-outbox.js +80 -0
- package/dist/playground/assets/index-D7rGZNjy.css +1 -0
- package/dist/playground/assets/index-jzNbJENa.js +69 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +1 -1
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +12 -0
- package/dist/storage-protocol.d.ts +8 -0
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +8 -0
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/tools.d.ts +12 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/types.d.ts +88 -7
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +5 -3
- package/docs/deployment.md +5 -4
- package/docs/design/runtime-abstraction.md +1757 -0
- package/docs/guides/mcp-oauth.md +26 -8
- package/docs/guides/slack.md +93 -202
- package/docs/reference/agent-config.md +2 -2
- package/docs/reference/cli.md +32 -16
- package/docs/reference/connections.md +6 -3
- package/docs/reference/http-api.md +3 -1
- package/docs/reference/sessions.md +4 -2
- package/docs/reference/tools.md +34 -2
- package/docs/templates/agents-md.md +110 -0
- package/docs/troubleshooting.md +2 -2
- package/package.json +1 -1
- package/skills/create-agent/SKILL.md +2 -1
- package/skills/mcp-auth/SKILL.md +6 -3
- package/skills/setup-slack/SKILL.md +23 -13
- package/src/bin/agent-serve.ts +12 -1
- package/src/channels/github/github-channel.ts +17 -0
- package/src/channels/origin/api.ts +24 -5
- package/src/channels/origin/binding.ts +55 -26
- package/src/channels/origin/index.ts +1 -0
- package/src/channels/origin/origin-channel.ts +78 -10
- package/src/channels/origin/reactions.ts +82 -0
- package/src/channels/origin/types.ts +11 -0
- package/src/channels/slack/approvals.ts +105 -0
- package/src/channels/slack/cli-project.ts +267 -0
- package/src/channels/slack/defaults.ts +165 -74
- package/src/channels/slack/dispatch.ts +2 -0
- package/src/channels/slack/init.ts +10 -5
- package/src/channels/slack/interactive.ts +35 -9
- package/src/channels/slack/live-delivery.ts +5 -3
- package/src/channels/slack/manifest.ts +1 -1
- package/src/channels/slack/progress-delivery.ts +133 -0
- package/src/channels/slack/setup.ts +10 -6
- package/src/channels/slack/slack-channel.ts +1 -0
- package/src/channels/slack/tool-approval-events.ts +93 -0
- package/src/channels/slack/types.ts +9 -1
- package/src/evals/run-facts.ts +32 -0
- package/src/files-backends/cursor-hosted.ts +3 -2
- package/src/index.ts +4 -0
- package/src/internal/advertise-tools.ts +31 -10
- package/src/internal/approval-gate.ts +20 -29
- package/src/internal/as-of.ts +107 -0
- package/src/internal/chat-client.ts +19 -0
- package/src/internal/cli-deploy.ts +203 -13
- package/src/internal/cli-mcp-oauth.ts +7 -21
- package/src/internal/cli-slack-manual.ts +350 -18
- package/src/internal/cli-slack.ts +40 -84
- package/src/internal/cursor/account-mcp.ts +21 -0
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/cursor-event-relay.ts +5 -6
- package/src/internal/deploy-client.ts +43 -0
- package/src/internal/env-file.ts +84 -0
- package/src/internal/framework-file-storage.ts +18 -46
- package/src/internal/framework-storage-selection.ts +41 -25
- package/src/internal/hosted-admission-adapter.ts +42 -0
- package/src/internal/hosted-delivery-protocol.ts +14 -2
- package/src/internal/hosted-delivery.ts +169 -44
- package/src/internal/hosted-execution-diag.ts +252 -0
- package/src/internal/http-channel.ts +107 -0
- package/src/internal/init-project.ts +2 -0
- package/src/internal/logs-client.ts +5 -0
- package/src/internal/mcp-endpoint.ts +13 -4
- package/src/internal/mcp-host.ts +77 -11
- package/src/internal/mcp-oauth-on-demand.ts +352 -0
- package/src/internal/mcp-oauth-persist.ts +127 -0
- package/src/internal/mcp-oauth.ts +17 -1
- package/src/internal/null-kv-storage.ts +74 -0
- package/src/internal/otel/collector.ts +30 -0
- package/src/internal/server.ts +159 -11
- package/src/internal/session-engine.ts +691 -57
- package/src/internal/session-run-log.ts +584 -0
- package/src/internal/sessions-client.ts +17 -8
- package/src/internal/storage-coordinator.ts +49 -9
- package/src/internal/storage-roles.ts +7 -0
- package/src/internal/stream-progress.ts +19 -0
- package/src/internal/tool-policy.ts +49 -9
- package/src/internal/trajectory.ts +10 -0
- package/src/internal/turn-outbox.ts +85 -0
- package/src/storage-backends/cursor-hosted.ts +13 -1
- package/src/storage-protocol.ts +10 -0
- package/src/storage.ts +12 -0
- package/src/tools.ts +12 -2
- package/src/types.ts +93 -8
- package/templates/agents-md/README.md +39 -0
- package/templates/agents-md/agent/agent.ts +8 -0
- package/templates/agents-md/agent/channels/github.ts +10 -0
- package/templates/agents-md/agent/channels/queue.ts +28 -0
- package/templates/agents-md/agent/channels/slack.ts +9 -0
- package/templates/agents-md/agent/instructions.md +39 -0
- package/templates/agents-md/agent/lib/collect.ts +439 -0
- package/templates/agents-md/agent/lib/config.ts +8 -0
- package/templates/agents-md/agent/lib/paths.ts +51 -0
- package/templates/agents-md/agent/schedules/weekly.ts +17 -0
- package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
- package/templates/agents-md/evals/agents.eval.ts +135 -0
- package/templates/agents-md/evals/evals.config.ts +5 -0
- package/templates/agents-md/init.json +38 -0
- package/templates/agents-md/package.json +18 -0
- package/templates/agents-md/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +0 -1
- package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
- package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
- package/dist/docs/assets/index.md.CI93Ltlb.js +0 -5
- package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
- package/dist/docs/design/agsh.md +0 -406
- package/dist/playground/assets/index-B1DDvBeC.css +0 -1
- package/dist/playground/assets/index-Cx9CclK_.js +0 -88
- package/docs/design/agsh.md +0 -406
- /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CI93Ltlb.lean.js → index.md.CVeRUOeZ.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.BEJx9XVj.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.D0mIh4KK.lean.js → reference_sessions.md.NxFP_CAC.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Default inbound handlers and stream-event sinks for the Slack channel.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { ChannelEventHandlers } from "../../types.js";
|
|
5
|
+
import type { ChannelEventContext, ChannelEventHandlers } from "../../types.js";
|
|
6
6
|
import {
|
|
7
7
|
appendChatStream,
|
|
8
8
|
postMessage,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "./constants.js";
|
|
19
19
|
import { createStreamDeliveryStrategy } from "./live-delivery.js";
|
|
20
20
|
import { defaultSlackLog, type SlackLog } from "./log.js";
|
|
21
|
+
import { createProgressDelivery } from "./progress-delivery.js";
|
|
21
22
|
import { buildTaskChunkForResult, buildTaskChunksForCalls } from "./stream.js";
|
|
22
23
|
import type {
|
|
23
24
|
SlackAccessPolicy,
|
|
@@ -154,6 +155,10 @@ export function buildDefaultEvents(
|
|
|
154
155
|
const botToken = credentials?.botToken;
|
|
155
156
|
const getLog = options.getLog ?? (() => defaultSlackLog);
|
|
156
157
|
const strategy = createStreamDeliveryStrategy({ botToken, getLog });
|
|
158
|
+
const progress = createProgressDelivery({ botToken, getLog });
|
|
159
|
+
|
|
160
|
+
const streamLive = (state: SlackChannelState): boolean =>
|
|
161
|
+
streaming && !state.streamingUnavailable;
|
|
157
162
|
|
|
158
163
|
const clearWorkingStatus = async (
|
|
159
164
|
channelId: string,
|
|
@@ -174,15 +179,126 @@ export function buildDefaultEvents(
|
|
|
174
179
|
}
|
|
175
180
|
};
|
|
176
181
|
|
|
182
|
+
const finishProgress = async (args: {
|
|
183
|
+
channel: ChannelEventContext<SlackChannelState>;
|
|
184
|
+
text: string;
|
|
185
|
+
sessionId: string;
|
|
186
|
+
}): Promise<boolean> => {
|
|
187
|
+
const log = getLog();
|
|
188
|
+
const state = args.channel.state;
|
|
189
|
+
if (
|
|
190
|
+
state.channelId === null ||
|
|
191
|
+
state.threadTs === null ||
|
|
192
|
+
args.text === ""
|
|
193
|
+
) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
if (await progress.replace({ channel: args.channel, text: args.text })) {
|
|
197
|
+
log.info("reply delivered via progress update", {
|
|
198
|
+
channel: state.channelId,
|
|
199
|
+
thread_ts: state.threadTs,
|
|
200
|
+
session: args.sessionId,
|
|
201
|
+
chars: args.text.length,
|
|
202
|
+
});
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
await progress.clear({ channel: args.channel });
|
|
206
|
+
try {
|
|
207
|
+
const posted = await postMessage({
|
|
208
|
+
botToken,
|
|
209
|
+
channel: state.channelId,
|
|
210
|
+
text: args.text,
|
|
211
|
+
threadTs: state.threadTs,
|
|
212
|
+
});
|
|
213
|
+
state.lastPostedText = args.text;
|
|
214
|
+
state.lastBotMessageTs = posted.ts;
|
|
215
|
+
log.info("reply delivered via postMessage", {
|
|
216
|
+
channel: state.channelId,
|
|
217
|
+
thread_ts: state.threadTs,
|
|
218
|
+
message_ts: posted.ts,
|
|
219
|
+
session: args.sessionId,
|
|
220
|
+
chars: args.text.length,
|
|
221
|
+
});
|
|
222
|
+
return true;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
log.error(
|
|
225
|
+
`postMessage failed: ${
|
|
226
|
+
error instanceof Error ? error.message : String(error)
|
|
227
|
+
}`,
|
|
228
|
+
{
|
|
229
|
+
channel: state.channelId,
|
|
230
|
+
thread_ts: state.threadTs,
|
|
231
|
+
session: args.sessionId,
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Deliver assistant text to the bound Slack thread. Used by a stop-reason
|
|
240
|
+
* `message.completed` and by `turn.completed` when the last assistant
|
|
241
|
+
* block was `finishReason: "tool_call"` (answer then `tag_artifact`,
|
|
242
|
+
* etc.) so the playground result still reaches Slack.
|
|
243
|
+
*/
|
|
244
|
+
const deliverReplyText = async (args: {
|
|
245
|
+
channel: ChannelEventContext<SlackChannelState>;
|
|
246
|
+
text: string;
|
|
247
|
+
sessionId: string;
|
|
248
|
+
}): Promise<boolean> => {
|
|
249
|
+
const state = args.channel.state;
|
|
250
|
+
if (
|
|
251
|
+
state.channelId === null ||
|
|
252
|
+
state.threadTs === null ||
|
|
253
|
+
args.text === ""
|
|
254
|
+
) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (state.lastPostedText === args.text) {
|
|
258
|
+
// Stream append sets this watermark while chat.stopStream is still
|
|
259
|
+
// pending. Treat a match as "already on Slack", not "already finalized".
|
|
260
|
+
const streamTs = state.streamTs;
|
|
261
|
+
if (streamTs !== null && streamTs !== "") {
|
|
262
|
+
if (streamLive(state)) {
|
|
263
|
+
await strategy.finalize({
|
|
264
|
+
channel: args.channel,
|
|
265
|
+
channelId: state.streamChannelId ?? state.channelId,
|
|
266
|
+
text: args.text,
|
|
267
|
+
sessionId: args.sessionId,
|
|
268
|
+
});
|
|
269
|
+
} else {
|
|
270
|
+
await strategy.cleanupOrphan({ channel: args.channel });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (streamLive(state)) {
|
|
277
|
+
const { delivered } = await strategy.finalize({
|
|
278
|
+
channel: args.channel,
|
|
279
|
+
channelId: state.streamChannelId ?? state.channelId,
|
|
280
|
+
text: args.text,
|
|
281
|
+
sessionId: args.sessionId,
|
|
282
|
+
});
|
|
283
|
+
if (delivered) {
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return finishProgress(args);
|
|
289
|
+
};
|
|
290
|
+
|
|
177
291
|
return {
|
|
178
292
|
async "turn.started"(event, channel) {
|
|
179
293
|
const log = getLog();
|
|
294
|
+
await progress.clear({ channel });
|
|
180
295
|
channel.state.pendingToolCallMessage = null;
|
|
181
296
|
channel.state.lastReasoningTypingAtMs = null;
|
|
182
297
|
channel.state.lastReasoningTypingStatus = null;
|
|
183
298
|
channel.state.streamTs = null;
|
|
184
299
|
channel.state.streamChannelId = null;
|
|
185
300
|
channel.state.lastPostedText = null;
|
|
301
|
+
channel.state.streamBlockText = null;
|
|
186
302
|
// Keep lastBotMessageTs across turns — warm delta watermark.
|
|
187
303
|
channel.state.approvalMessageByCallId = {};
|
|
188
304
|
|
|
@@ -208,7 +324,7 @@ export function buildDefaultEvents(
|
|
|
208
324
|
},
|
|
209
325
|
|
|
210
326
|
async "message.appended"(event, channel) {
|
|
211
|
-
if (!
|
|
327
|
+
if (!streamLive(channel.state)) {
|
|
212
328
|
return;
|
|
213
329
|
}
|
|
214
330
|
const channelId =
|
|
@@ -277,8 +393,7 @@ export function buildDefaultEvents(
|
|
|
277
393
|
if (
|
|
278
394
|
strategy.inlineToolSteps &&
|
|
279
395
|
thinkingSteps &&
|
|
280
|
-
|
|
281
|
-
channel.state.streamingUnavailable !== true
|
|
396
|
+
streamLive(channel.state)
|
|
282
397
|
) {
|
|
283
398
|
const channelId =
|
|
284
399
|
channel.state.streamChannelId ?? channel.state.channelId;
|
|
@@ -318,17 +433,24 @@ export function buildDefaultEvents(
|
|
|
318
433
|
threadTs: channel.state.threadTs,
|
|
319
434
|
status: statusText,
|
|
320
435
|
});
|
|
436
|
+
if (
|
|
437
|
+
thinkingSteps &&
|
|
438
|
+
channel.state.streamingUnavailable === true &&
|
|
439
|
+
(channel.state.streamTs === null || channel.state.streamTs === "")
|
|
440
|
+
) {
|
|
441
|
+
await progress.upsert({ channel, text: statusText });
|
|
442
|
+
}
|
|
321
443
|
}
|
|
322
444
|
},
|
|
323
445
|
|
|
324
446
|
async "action.result"(event, channel) {
|
|
447
|
+
const streamTs = channel.state.streamTs;
|
|
325
448
|
if (
|
|
326
449
|
!strategy.inlineToolSteps ||
|
|
327
450
|
!thinkingSteps ||
|
|
328
|
-
!
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
channel.state.streamTs === ""
|
|
451
|
+
!streamLive(channel.state) ||
|
|
452
|
+
streamTs === null ||
|
|
453
|
+
streamTs === ""
|
|
332
454
|
) {
|
|
333
455
|
return;
|
|
334
456
|
}
|
|
@@ -345,16 +467,18 @@ export function buildDefaultEvents(
|
|
|
345
467
|
await appendChatStream({
|
|
346
468
|
botToken,
|
|
347
469
|
channel: channelId,
|
|
348
|
-
ts:
|
|
470
|
+
ts: streamTs,
|
|
349
471
|
chunks: [chunk],
|
|
350
472
|
});
|
|
351
473
|
},
|
|
352
474
|
|
|
353
475
|
async "message.completed"(event, channel) {
|
|
354
|
-
const log = getLog();
|
|
355
476
|
if (event.data.finishReason === "tool_call") {
|
|
356
477
|
channel.state.pendingToolCallMessage =
|
|
357
478
|
firstNonEmptyLine(event.data.text) ?? null;
|
|
479
|
+
// The harness restarts its cumulative text after a tool call, so the
|
|
480
|
+
// next block appends in full instead of diffing against this one.
|
|
481
|
+
channel.state.streamBlockText = null;
|
|
358
482
|
return;
|
|
359
483
|
}
|
|
360
484
|
channel.state.pendingToolCallMessage = null;
|
|
@@ -368,54 +492,16 @@ export function buildDefaultEvents(
|
|
|
368
492
|
// and clear typing.
|
|
369
493
|
if (event.data.text === "") {
|
|
370
494
|
await strategy.finalizeEmpty({ channel });
|
|
495
|
+
await progress.clear({ channel });
|
|
371
496
|
await clearWorkingStatus(state.channelId, state.threadTs);
|
|
372
497
|
return;
|
|
373
498
|
}
|
|
374
499
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
channelId: state.streamChannelId ?? state.channelId,
|
|
381
|
-
text: event.data.text,
|
|
382
|
-
sessionId: event.sessionId,
|
|
383
|
-
});
|
|
384
|
-
if (delivered) {
|
|
385
|
-
await clearWorkingStatus(state.channelId, state.threadTs);
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
try {
|
|
391
|
-
const posted = await postMessage({
|
|
392
|
-
botToken,
|
|
393
|
-
channel: state.channelId,
|
|
394
|
-
text: event.data.text,
|
|
395
|
-
threadTs: state.threadTs,
|
|
396
|
-
});
|
|
397
|
-
channel.state.lastPostedText = event.data.text;
|
|
398
|
-
channel.state.lastBotMessageTs = posted.ts;
|
|
399
|
-
log.info("reply delivered via postMessage", {
|
|
400
|
-
channel: state.channelId,
|
|
401
|
-
thread_ts: state.threadTs,
|
|
402
|
-
message_ts: posted.ts,
|
|
403
|
-
session: event.sessionId,
|
|
404
|
-
chars: event.data.text.length,
|
|
405
|
-
});
|
|
406
|
-
} catch (error) {
|
|
407
|
-
log.error(
|
|
408
|
-
`postMessage failed: ${
|
|
409
|
-
error instanceof Error ? error.message : String(error)
|
|
410
|
-
}`,
|
|
411
|
-
{
|
|
412
|
-
channel: state.channelId,
|
|
413
|
-
thread_ts: state.threadTs,
|
|
414
|
-
session: event.sessionId,
|
|
415
|
-
}
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
|
|
500
|
+
await deliverReplyText({
|
|
501
|
+
channel,
|
|
502
|
+
text: event.data.text,
|
|
503
|
+
sessionId: event.sessionId,
|
|
504
|
+
});
|
|
419
505
|
await clearWorkingStatus(state.channelId, state.threadTs);
|
|
420
506
|
},
|
|
421
507
|
|
|
@@ -428,7 +514,26 @@ export function buildDefaultEvents(
|
|
|
428
514
|
thread_ts: channel.state.threadTs,
|
|
429
515
|
});
|
|
430
516
|
|
|
517
|
+
// Mid-turn `tool_call` text is held as status, not posted. If the
|
|
518
|
+
// turn ends without a later `finishReason: "stop"` block, the
|
|
519
|
+
// playground still has `result` (last assistant text) and Slack
|
|
520
|
+
// would otherwise stay silent.
|
|
521
|
+
const result = event.data.result;
|
|
522
|
+
const unpublished =
|
|
523
|
+
typeof result === "string" &&
|
|
524
|
+
result !== "" &&
|
|
525
|
+
result !== channel.state.lastPostedText;
|
|
526
|
+
if (unpublished) {
|
|
527
|
+
await deliverReplyText({
|
|
528
|
+
channel,
|
|
529
|
+
text: result,
|
|
530
|
+
sessionId: event.sessionId,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
// Always close leftovers. deliverReplyText may fall through to
|
|
534
|
+
// postMessage when streaming is unavailable and leave streamTs open.
|
|
431
535
|
await strategy.cleanupOrphan({ channel });
|
|
536
|
+
await progress.clear({ channel });
|
|
432
537
|
|
|
433
538
|
// Always drop the assistant chip. message.completed already clears
|
|
434
539
|
// after a normal reply, but a tool-call-only finish (or a missed
|
|
@@ -476,7 +581,7 @@ export function buildDefaultEvents(
|
|
|
476
581
|
const errorText = formatSlackTurnFailureMessage(event.data.message);
|
|
477
582
|
|
|
478
583
|
let delivered = false;
|
|
479
|
-
if (
|
|
584
|
+
if (streamLive(state)) {
|
|
480
585
|
({ delivered } = await strategy.fail({
|
|
481
586
|
channel,
|
|
482
587
|
channelId: state.streamChannelId ?? state.channelId,
|
|
@@ -485,25 +590,11 @@ export function buildDefaultEvents(
|
|
|
485
590
|
}));
|
|
486
591
|
}
|
|
487
592
|
if (!delivered) {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
threadTs: state.threadTs,
|
|
494
|
-
});
|
|
495
|
-
} catch (error) {
|
|
496
|
-
log.error(
|
|
497
|
-
`turn.failed postMessage failed: ${
|
|
498
|
-
error instanceof Error ? error.message : String(error)
|
|
499
|
-
}`,
|
|
500
|
-
{
|
|
501
|
-
channel: state.channelId,
|
|
502
|
-
thread_ts: state.threadTs,
|
|
503
|
-
session: event.sessionId,
|
|
504
|
-
}
|
|
505
|
-
);
|
|
506
|
-
}
|
|
593
|
+
await finishProgress({
|
|
594
|
+
channel,
|
|
595
|
+
text: errorText,
|
|
596
|
+
sessionId: event.sessionId,
|
|
597
|
+
});
|
|
507
598
|
}
|
|
508
599
|
await clearWorkingStatus(state.channelId, state.threadTs);
|
|
509
600
|
},
|
|
@@ -126,8 +126,10 @@ export function emptySlackChannelState(
|
|
|
126
126
|
streamTs: null,
|
|
127
127
|
streamChannelId: null,
|
|
128
128
|
lastPostedText: null,
|
|
129
|
+
streamBlockText: null,
|
|
129
130
|
lastBotMessageTs: null,
|
|
130
131
|
streamingUnavailable: false,
|
|
132
|
+
progressTs: null,
|
|
131
133
|
approvalMessageByCallId: {},
|
|
132
134
|
...patch,
|
|
133
135
|
};
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
* Scaffold a Slack channel into an agent-serve project.
|
|
3
3
|
*
|
|
4
4
|
* `initSlackChannel` is the create-safe writer: `agent/channels/slack.ts`
|
|
5
|
-
* only. DIY manifests
|
|
5
|
+
* only. DIY manifests + Slack CLI `.slack/` live in
|
|
6
6
|
* {@link initSlackManual} so `slack create` cannot reach them.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
10
10
|
import { basename, join, resolve } from "node:path";
|
|
11
11
|
import { PACKAGE_NAME } from "../../internal/distribution.js";
|
|
12
|
+
import { writeSlackCliProject } from "./cli-project.js";
|
|
12
13
|
import { envPrefixFromName, slackEnvKeys } from "./credentials.js";
|
|
13
14
|
import {
|
|
14
15
|
buildSlackManifestPair,
|
|
@@ -131,7 +132,8 @@ export async function initSlackChannel(
|
|
|
131
132
|
|
|
132
133
|
/**
|
|
133
134
|
* `slack init --manual`: channel file plus DIY manifests
|
|
134
|
-
* (`managedByCursor: false`), env.example,
|
|
135
|
+
* (`managedByCursor: false`), Slack CLI `.slack/` project, env.example,
|
|
136
|
+
* and setup-status.json.
|
|
135
137
|
*/
|
|
136
138
|
export async function initSlackManual(
|
|
137
139
|
options: InitSlackManualOptions
|
|
@@ -151,9 +153,6 @@ export async function initSlackManual(
|
|
|
151
153
|
description: options.description,
|
|
152
154
|
channelPosts: options.channelPosts,
|
|
153
155
|
});
|
|
154
|
-
for (const file of slackManifestFileEntries(pair)) {
|
|
155
|
-
await write(`.agent-serve/slack/${file.name}`, file.contents);
|
|
156
|
-
}
|
|
157
156
|
await write(
|
|
158
157
|
".agent-serve/slack/env.example",
|
|
159
158
|
`# Copy to .env.local (or export in your shell). Use the *dev* Slack app
|
|
@@ -176,6 +175,12 @@ ${target.envKeys.app}=xapp-...
|
|
|
176
175
|
2
|
|
177
176
|
)}\n`
|
|
178
177
|
);
|
|
178
|
+
files.push(
|
|
179
|
+
...(await writeSlackCliProject(
|
|
180
|
+
target.rootDir,
|
|
181
|
+
slackManifestFileEntries(pair)
|
|
182
|
+
))
|
|
183
|
+
);
|
|
179
184
|
|
|
180
185
|
return {
|
|
181
186
|
rootDir: target.rootDir,
|
|
@@ -15,10 +15,15 @@ import type {
|
|
|
15
15
|
ChannelSession,
|
|
16
16
|
HostContext,
|
|
17
17
|
PendingApproval,
|
|
18
|
+
PendingAuth,
|
|
18
19
|
SendMessageFn,
|
|
19
20
|
} from "../../types.js";
|
|
20
21
|
import { updateMessage } from "./api.js";
|
|
21
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
decisionFromActionId,
|
|
24
|
+
decisionFromAuthActionId,
|
|
25
|
+
parseApprovalActionValue,
|
|
26
|
+
} from "./approvals.js";
|
|
22
27
|
import { buildSlackInteractiveApprovalAuth } from "./auth.js";
|
|
23
28
|
import { dispatchInboundMessage } from "./dispatch.js";
|
|
24
29
|
import { isExternalSlackSender } from "./external-policy.js";
|
|
@@ -41,6 +46,12 @@ export interface SlackInteractiveDispatchDeps {
|
|
|
41
46
|
decision: ApprovalDecision,
|
|
42
47
|
auth: AuthContext | null
|
|
43
48
|
) => Promise<PendingApproval>;
|
|
49
|
+
resolveAuth: (
|
|
50
|
+
sessionId: string,
|
|
51
|
+
callId: string,
|
|
52
|
+
decision: ApprovalDecision,
|
|
53
|
+
auth: AuthContext | null
|
|
54
|
+
) => Promise<PendingAuth>;
|
|
44
55
|
waitUntil: (promise: Promise<unknown>) => void;
|
|
45
56
|
log?: SlackLog;
|
|
46
57
|
/** Defaults to true. */
|
|
@@ -61,11 +72,17 @@ export async function dispatchInteractiveFromPayload(
|
|
|
61
72
|
return false;
|
|
62
73
|
}
|
|
63
74
|
|
|
64
|
-
const
|
|
75
|
+
const approvalDecision = decisionFromActionId(parsed.actionId);
|
|
76
|
+
const authDecision = decisionFromAuthActionId(parsed.actionId);
|
|
65
77
|
const value = parseApprovalActionValue(parsed.value);
|
|
66
|
-
if (
|
|
78
|
+
if (value === null || (approvalDecision === null && authDecision === null)) {
|
|
67
79
|
return false;
|
|
68
80
|
}
|
|
81
|
+
const decision = approvalDecision ?? authDecision;
|
|
82
|
+
if (decision === null) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const kind = approvalDecision !== null ? "approval" : "auth";
|
|
69
86
|
|
|
70
87
|
log.info("interactive approval", {
|
|
71
88
|
decision,
|
|
@@ -153,12 +170,21 @@ export async function dispatchInteractiveFromPayload(
|
|
|
153
170
|
});
|
|
154
171
|
|
|
155
172
|
try {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
173
|
+
if (kind === "auth") {
|
|
174
|
+
await deps.resolveAuth(
|
|
175
|
+
value.sessionId,
|
|
176
|
+
value.callId,
|
|
177
|
+
decision,
|
|
178
|
+
clickingAuth
|
|
179
|
+
);
|
|
180
|
+
} else {
|
|
181
|
+
await deps.resolveApproval(
|
|
182
|
+
value.sessionId,
|
|
183
|
+
value.callId,
|
|
184
|
+
decision,
|
|
185
|
+
clickingAuth
|
|
186
|
+
);
|
|
187
|
+
}
|
|
162
188
|
} catch (error) {
|
|
163
189
|
log.warn("interactive approval resolve failed", {
|
|
164
190
|
session: value.sessionId,
|
|
@@ -41,7 +41,7 @@ type StreamArgs = {
|
|
|
41
41
|
/**
|
|
42
42
|
* How the default handlers deliver an in-progress reply. Methods write live
|
|
43
43
|
* delivery state (`streamTs`, `streamChannelId`, `lastPostedText`,
|
|
44
|
-
* `streamingUnavailable`) on `channel.state` directly.
|
|
44
|
+
* `streamBlockText`, `streamingUnavailable`) on `channel.state` directly.
|
|
45
45
|
*/
|
|
46
46
|
export interface LiveDeliveryStrategy {
|
|
47
47
|
readonly inlineToolSteps: boolean;
|
|
@@ -127,6 +127,7 @@ export function createStreamDeliveryStrategy(
|
|
|
127
127
|
channel.state.streamTs = started.ts;
|
|
128
128
|
channel.state.streamChannelId = started.channel;
|
|
129
129
|
channel.state.lastPostedText = hasMarkdown ? (markdown_text ?? "") : "";
|
|
130
|
+
channel.state.streamBlockText = channel.state.lastPostedText;
|
|
130
131
|
log.info("chat.startStream ok", {
|
|
131
132
|
channel: started.channel,
|
|
132
133
|
stream_ts: started.ts,
|
|
@@ -167,7 +168,7 @@ export function createStreamDeliveryStrategy(
|
|
|
167
168
|
text: string;
|
|
168
169
|
}): Promise<{ ok: boolean; error?: string }> => {
|
|
169
170
|
const appendText = computeStreamAppend(
|
|
170
|
-
args.channel.state.
|
|
171
|
+
args.channel.state.streamBlockText,
|
|
171
172
|
args.text
|
|
172
173
|
);
|
|
173
174
|
const stopped = await stopChatStream({
|
|
@@ -213,7 +214,7 @@ export function createStreamDeliveryStrategy(
|
|
|
213
214
|
return;
|
|
214
215
|
}
|
|
215
216
|
const appendText = computeStreamAppend(
|
|
216
|
-
channel.state.
|
|
217
|
+
channel.state.streamBlockText,
|
|
217
218
|
text
|
|
218
219
|
);
|
|
219
220
|
if (appendText === "") {
|
|
@@ -238,6 +239,7 @@ export function createStreamDeliveryStrategy(
|
|
|
238
239
|
return;
|
|
239
240
|
}
|
|
240
241
|
channel.state.lastPostedText = text;
|
|
242
|
+
channel.state.streamBlockText = text;
|
|
241
243
|
},
|
|
242
244
|
|
|
243
245
|
async appendChunks({ channel, channelId, chunks, sessionId }) {
|
|
@@ -222,7 +222,7 @@ export function buildSlackManifestPair(
|
|
|
222
222
|
};
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
/**
|
|
225
|
+
/** Manifest filenames written under `.slack/`. */
|
|
226
226
|
export function slackManifestFileEntries(
|
|
227
227
|
pair: { dev: SlackAppManifest; prod: SlackAppManifest },
|
|
228
228
|
env: "dev" | "prod" | "both" = "both"
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mid-turn thread progress when `chat.startStream` is unavailable.
|
|
3
|
+
* One editable message; `setThreadStatus` stays on the caller.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ChannelEventContext } from "../../types.js";
|
|
7
|
+
import { deleteMessage, postMessage, updateMessage } from "./api.js";
|
|
8
|
+
import type { SlackLog } from "./log.js";
|
|
9
|
+
import type { SlackBotToken, SlackChannelState } from "./types.js";
|
|
10
|
+
|
|
11
|
+
type SlackChannel = ChannelEventContext<SlackChannelState>;
|
|
12
|
+
|
|
13
|
+
export interface ProgressDeliveryDeps {
|
|
14
|
+
botToken: SlackBotToken | undefined;
|
|
15
|
+
getLog: () => SlackLog;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function activeProgressTs(state: SlackChannelState): string | null {
|
|
19
|
+
const ts = state.progressTs;
|
|
20
|
+
return ts == null || ts === "" ? null : ts;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ProgressDelivery {
|
|
24
|
+
upsert(args: { channel: SlackChannel; text: string }): Promise<void>;
|
|
25
|
+
replace(args: { channel: SlackChannel; text: string }): Promise<boolean>;
|
|
26
|
+
clear(args: { channel: SlackChannel }): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function createProgressDelivery(
|
|
30
|
+
deps: ProgressDeliveryDeps
|
|
31
|
+
): ProgressDelivery {
|
|
32
|
+
const { botToken, getLog } = deps;
|
|
33
|
+
|
|
34
|
+
const clear: ProgressDelivery["clear"] = async (args) => {
|
|
35
|
+
const state = args.channel.state;
|
|
36
|
+
const ts = activeProgressTs(state);
|
|
37
|
+
state.progressTs = null;
|
|
38
|
+
if (ts === null || state.channelId === null) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const deleted = await deleteMessage({
|
|
42
|
+
botToken,
|
|
43
|
+
channel: state.channelId,
|
|
44
|
+
ts,
|
|
45
|
+
});
|
|
46
|
+
if (!deleted.ok) {
|
|
47
|
+
getLog().warn("progress delete failed", {
|
|
48
|
+
error: deleted.error,
|
|
49
|
+
channel: state.channelId,
|
|
50
|
+
progress_ts: ts,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
async upsert(args) {
|
|
57
|
+
const state = args.channel.state;
|
|
58
|
+
if (
|
|
59
|
+
state.channelId === null ||
|
|
60
|
+
state.threadTs === null ||
|
|
61
|
+
args.text === ""
|
|
62
|
+
) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const existing = activeProgressTs(state);
|
|
66
|
+
if (existing !== null) {
|
|
67
|
+
const updated = await updateMessage({
|
|
68
|
+
botToken,
|
|
69
|
+
channel: state.channelId,
|
|
70
|
+
ts: existing,
|
|
71
|
+
text: args.text,
|
|
72
|
+
});
|
|
73
|
+
if (updated.ok) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
getLog().warn("progress update failed; posting a new message", {
|
|
77
|
+
error: updated.error,
|
|
78
|
+
channel: state.channelId,
|
|
79
|
+
thread_ts: state.threadTs,
|
|
80
|
+
progress_ts: existing,
|
|
81
|
+
});
|
|
82
|
+
await clear({ channel: args.channel });
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const posted = await postMessage({
|
|
86
|
+
botToken,
|
|
87
|
+
channel: state.channelId,
|
|
88
|
+
threadTs: state.threadTs,
|
|
89
|
+
text: args.text,
|
|
90
|
+
});
|
|
91
|
+
state.progressTs = posted.ts;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
getLog().warn(
|
|
94
|
+
`progress post failed: ${
|
|
95
|
+
error instanceof Error ? error.message : String(error)
|
|
96
|
+
}`,
|
|
97
|
+
{
|
|
98
|
+
channel: state.channelId,
|
|
99
|
+
thread_ts: state.threadTs,
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
async replace(args) {
|
|
106
|
+
const state = args.channel.state;
|
|
107
|
+
const ts = activeProgressTs(state);
|
|
108
|
+
if (ts === null || state.channelId === null || args.text === "") {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const updated = await updateMessage({
|
|
112
|
+
botToken,
|
|
113
|
+
channel: state.channelId,
|
|
114
|
+
ts,
|
|
115
|
+
text: args.text,
|
|
116
|
+
});
|
|
117
|
+
if (!updated.ok) {
|
|
118
|
+
getLog().warn("progress replace failed", {
|
|
119
|
+
error: updated.error,
|
|
120
|
+
channel: state.channelId,
|
|
121
|
+
progress_ts: ts,
|
|
122
|
+
});
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
state.lastPostedText = args.text;
|
|
126
|
+
state.lastBotMessageTs = ts;
|
|
127
|
+
state.progressTs = null;
|
|
128
|
+
return true;
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
clear,
|
|
132
|
+
};
|
|
133
|
+
}
|