@cursor/july 0.1.99 → 0.1.101
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 +4 -2
- package/dist/bin/agent-serve.js +3 -2
- package/dist/channels/deployments/deployments-channel.d.ts +41 -5
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +88 -8
- package/dist/channels/deployments/types.d.ts +4 -3
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +28 -3
- package/dist/channels/github/progress.d.ts +7 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/origin/defaults.d.ts +43 -0
- package/dist/channels/origin/defaults.d.ts.map +1 -0
- package/dist/channels/origin/defaults.js +111 -0
- package/dist/channels/origin/index.d.ts +2 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +2 -0
- package/dist/channels/origin/origin-channel.d.ts +2 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +24 -3
- package/dist/channels/origin/state.d.ts +32 -0
- package/dist/channels/origin/state.d.ts.map +1 -0
- package/dist/channels/origin/state.js +23 -0
- package/dist/channels/origin/types.d.ts +23 -1
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts +16 -7
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +31 -14
- package/dist/channels/slack/code-fences.d.ts +17 -0
- package/dist/channels/slack/code-fences.d.ts.map +1 -0
- package/dist/channels/slack/code-fences.js +168 -0
- package/dist/channels/slack/constants.d.ts +6 -0
- package/dist/channels/slack/constants.d.ts.map +1 -1
- package/dist/channels/slack/constants.js +6 -0
- package/dist/channels/slack/defaults.d.ts +9 -4
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +154 -76
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +3 -3
- package/dist/channels/slack/inbound.d.ts +9 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +14 -0
- package/dist/channels/slack/index.d.ts +2 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +2 -0
- package/dist/channels/slack/live-delivery.d.ts +5 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +116 -21
- package/dist/channels/slack/reasoning-card.d.ts +38 -0
- package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
- package/dist/channels/slack/reasoning-card.js +104 -0
- package/dist/channels/slack/redact.d.ts +2 -0
- package/dist/channels/slack/redact.d.ts.map +1 -0
- package/dist/channels/slack/redact.js +5 -0
- package/dist/channels/slack/reply-options.d.ts +40 -0
- package/dist/channels/slack/reply-options.d.ts.map +1 -0
- package/dist/channels/slack/reply-options.js +150 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +8 -4
- package/dist/channels/slack/stream.d.ts +22 -10
- package/dist/channels/slack/stream.d.ts.map +1 -1
- package/dist/channels/slack/stream.js +9 -16
- package/dist/channels/slack/tool-cards.d.ts +22 -0
- package/dist/channels/slack/tool-cards.d.ts.map +1 -0
- package/dist/channels/slack/tool-cards.js +178 -0
- package/dist/channels/slack/types.d.ts +145 -6
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/connections.d.ts +18 -2
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +18 -2
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +6 -6
- package/dist/docs/ab.md +1 -1
- package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
- package/dist/docs/assets/{app.BplEAZ3S.js → app.BASO9Kih.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.DbFXINq2.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CHXyv4wP.js → VPLocalSearchBox.DwkqxoE0.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BTcsZmjQ.js → theme.CCil_13e.js} +2 -2
- package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
- package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
- package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
- package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.Di6jJAXF.js} +13 -3
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.Di6jJAXF.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.js → reference_http-api.md.oySXBO8o.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/building-with-agents.md +14 -11
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +6 -6
- package/dist/docs/evals.md +1 -1
- 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 +5 -5
- package/dist/docs/guides/github.md +1 -1
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +5 -5
- package/dist/docs/guides/mcp-oauth.md +1 -1
- package/dist/docs/guides/opentelemetry.html +7 -7
- package/dist/docs/guides/opentelemetry.md +2 -2
- package/dist/docs/guides/slack.html +22 -6
- package/dist/docs/guides/slack.md +80 -1
- package/dist/docs/guides/webhooks.html +5 -5
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/hillclimbing.md +5 -5
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +1 -1
- package/dist/docs/llms-full.txt +1073 -31
- package/dist/docs/llms.txt +14 -0
- package/dist/docs/quickstart.html +5 -5
- package/dist/docs/quickstart.md +1 -1
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +4 -4
- package/dist/docs/reference/connections.html +17 -7
- package/dist/docs/reference/connections.md +32 -1
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/http-api.md +1 -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 +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/scaffolding-agents.md +3 -3
- package/dist/docs/skills/ab.html +52 -0
- package/dist/docs/skills/ab.md +50 -0
- package/dist/docs/skills/create-agent.html +34 -0
- package/dist/docs/skills/create-agent.md +160 -0
- package/dist/docs/skills/debug.html +27 -0
- package/dist/docs/skills/debug.md +36 -0
- package/dist/docs/skills/evals.html +51 -0
- package/dist/docs/skills/evals.md +99 -0
- package/dist/docs/skills/framework-map.html +27 -0
- package/dist/docs/skills/framework-map.md +95 -0
- package/dist/docs/skills/github.html +42 -0
- package/dist/docs/skills/github.md +93 -0
- package/dist/docs/skills/hillclimb.html +33 -0
- package/dist/docs/skills/hillclimb.md +55 -0
- package/dist/docs/skills/index.html +27 -0
- package/dist/docs/skills/index.md +21 -0
- package/dist/docs/skills/mcp-auth.html +44 -0
- package/dist/docs/skills/mcp-auth.md +76 -0
- package/dist/docs/skills/otel.html +34 -0
- package/dist/docs/skills/otel.md +48 -0
- package/dist/docs/skills/setup-slack.html +46 -0
- package/dist/docs/skills/setup-slack.md +141 -0
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +4 -4
- 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 +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/extensions/cursor-cloud-agents/extension.d.ts +55 -0
- package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/extension.js +64 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts +30 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.js +45 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts +25 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.js +85 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +15 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.js +55 -0
- package/dist/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.js +37 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.js +83 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.js +36 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.js +41 -0
- package/dist/extensions.d.ts +49 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +75 -0
- package/dist/files-backends/cursor-hosted.d.ts +6 -0
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +6 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/internal/advertise-tools.d.ts +4 -1
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +20 -1
- package/dist/internal/as-of.d.ts +18 -0
- package/dist/internal/as-of.d.ts.map +1 -1
- package/dist/internal/as-of.js +131 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +66 -21
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +3 -1
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +3 -4
- package/dist/internal/cursor/hosted-deployment-secrets.d.ts +16 -0
- package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-deployment-secrets.js +61 -0
- package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
- package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-store-secrets.js +48 -0
- package/dist/internal/cursor-deployment-relay.d.ts +15 -1
- package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
- package/dist/internal/cursor-deployment-relay.js +46 -7
- package/dist/internal/deploy-client.d.ts +29 -6
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +61 -19
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +426 -121
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +5 -0
- package/dist/internal/framework-file-storage.d.ts +15 -8
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +70 -10
- package/dist/internal/framework-storage-selection.d.ts +12 -12
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +33 -39
- package/dist/internal/hosted-delivery.d.ts +3 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +19 -32
- package/dist/internal/hosted-execution-diag.d.ts +5 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +5 -0
- package/dist/internal/hosted-execution-flush.d.ts +46 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -0
- package/dist/internal/hosted-execution-flush.js +81 -0
- package/dist/internal/mcp-endpoint.js +1 -0
- package/dist/internal/mcp-host.d.ts +2 -1
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +35 -15
- package/dist/internal/review-comments.d.ts +1 -1
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +4 -4
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +79 -104
- package/dist/internal/session-engine.d.ts +9 -7
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +45 -34
- package/dist/internal/session-run-log.d.ts +5 -4
- package/dist/internal/session-run-log.d.ts.map +1 -1
- package/dist/internal/session-run-log.js +8 -8
- package/dist/internal/start-log-store.d.ts +60 -0
- package/dist/internal/start-log-store.d.ts.map +1 -0
- package/dist/internal/start-log-store.js +151 -0
- package/dist/internal/storage-coordinator.d.ts +0 -6
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +1 -9
- package/dist/internal/tool-policy.d.ts +8 -0
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +19 -7
- package/dist/playground/assets/{index-jzNbJENa.js → index-BnNN1-EK.js} +45 -45
- package/dist/playground/assets/index-DBQCwFp0.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
- package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
- package/dist/storage-backends/cursor-hosted-v2.js +164 -0
- package/dist/storage-backends/cursor-hosted.d.ts +6 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +6 -1
- package/dist/storage-protocol.d.ts +24 -0
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +33 -0
- package/dist/storage.d.ts +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1 -1
- package/dist/types.d.ts +123 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +29 -1
- package/docs/README.md +1 -1
- package/docs/ab.md +1 -1
- package/docs/building-with-agents.md +14 -11
- package/docs/evals.md +1 -1
- package/docs/guides/github.md +1 -1
- package/docs/guides/mcp-oauth.md +1 -1
- package/docs/guides/opentelemetry.md +2 -2
- package/docs/guides/slack.md +80 -1
- package/docs/hillclimbing.md +5 -5
- package/docs/quickstart.md +1 -1
- package/docs/reference/connections.md +32 -1
- package/docs/reference/http-api.md +1 -1
- package/docs/scaffolding-agents.md +3 -3
- package/docs/skills/index.md +26 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +18 -4
- package/src/bin/agent-serve.ts +11 -2
- package/src/channels/deployments/deployments-channel.ts +117 -8
- package/src/channels/deployments/types.ts +4 -3
- package/src/channels/github/defaults.ts +36 -3
- package/src/channels/github/progress.ts +7 -0
- package/src/channels/origin/defaults.ts +143 -0
- package/src/channels/origin/index.ts +2 -0
- package/src/channels/origin/origin-channel.ts +37 -1
- package/src/channels/origin/state.ts +54 -0
- package/src/channels/origin/types.ts +24 -0
- package/src/channels/slack/api.ts +37 -18
- package/src/channels/slack/code-fences.ts +183 -0
- package/src/channels/slack/constants.ts +6 -0
- package/src/channels/slack/defaults.ts +173 -92
- package/src/channels/slack/dispatch.ts +8 -1
- package/src/channels/slack/inbound.ts +17 -0
- package/src/channels/slack/index.ts +2 -0
- package/src/channels/slack/live-delivery.ts +142 -28
- package/src/channels/slack/reasoning-card.ts +140 -0
- package/src/channels/slack/redact.ts +6 -0
- package/src/channels/slack/reply-options.ts +229 -0
- package/src/channels/slack/slack-channel.ts +7 -2
- package/src/channels/slack/stream.ts +31 -24
- package/src/channels/slack/tool-cards.ts +221 -0
- package/src/channels/slack/types.ts +159 -6
- package/src/connections.ts +18 -1
- package/src/extensions/cursor-cloud-agents/extension.ts +118 -0
- package/src/extensions/cursor-cloud-agents/lib/cloud.ts +79 -0
- package/src/extensions/cursor-cloud-agents/lib/fleet.ts +109 -0
- package/src/extensions/cursor-cloud-agents/lib/repos.ts +81 -0
- package/src/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
- package/src/extensions/cursor-cloud-agents/tools/follow_up.ts +29 -0
- package/src/extensions/cursor-cloud-agents/tools/launch.ts +84 -0
- package/src/extensions/cursor-cloud-agents/tools/list.ts +31 -0
- package/src/extensions/cursor-cloud-agents/tools/status.ts +39 -0
- package/src/extensions.ts +98 -0
- package/src/files-backends/cursor-hosted.ts +15 -5
- package/src/index.ts +2 -0
- package/src/internal/advertise-tools.ts +37 -12
- package/src/internal/as-of.ts +163 -0
- package/src/internal/cli-deploy.ts +88 -25
- package/src/internal/continuation-identity.ts +3 -1
- package/src/internal/conversation-mirror.ts +3 -8
- package/src/internal/cursor/hosted-deployment-secrets.ts +72 -0
- package/src/internal/cursor/hosted-store-secrets.ts +72 -0
- package/src/internal/cursor-deployment-relay.ts +65 -8
- package/src/internal/deploy-client.ts +83 -28
- package/src/internal/discovery.ts +479 -114
- package/src/internal/distribution.ts +5 -0
- package/src/internal/framework-file-storage.ts +80 -10
- package/src/internal/framework-storage-selection.ts +31 -44
- package/src/internal/hosted-delivery.ts +38 -63
- package/src/internal/hosted-execution-diag.ts +6 -0
- package/src/internal/hosted-execution-flush.ts +142 -0
- package/src/internal/mcp-endpoint.ts +1 -0
- package/src/internal/mcp-host.ts +40 -14
- package/src/internal/review-comments.ts +5 -2
- package/src/internal/server.ts +81 -100
- package/src/internal/session-engine.ts +56 -28
- package/src/internal/session-run-log.ts +8 -12
- package/src/internal/start-log-store.ts +177 -0
- package/src/internal/storage-coordinator.ts +1 -11
- package/src/internal/tool-policy.ts +39 -9
- package/src/storage-backends/cursor-hosted-v2.ts +219 -0
- package/src/storage-backends/cursor-hosted.ts +6 -1
- package/src/storage-protocol.ts +37 -0
- package/src/storage.ts +1 -0
- package/src/types.ts +177 -14
- package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +0 -1
- package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
- package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
- package/dist/internal/null-kv-storage.d.ts +0 -48
- package/dist/internal/null-kv-storage.d.ts.map +0 -1
- package/dist/internal/null-kv-storage.js +0 -58
- package/dist/playground/assets/index-D7rGZNjy.css +0 -1
- package/src/internal/null-kv-storage.ts +0 -74
- /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
- /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
- /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
- /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.lean.js → reference_http-api.md.oySXBO8o.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
|
@@ -8,12 +8,29 @@
|
|
|
8
8
|
* Assistant-pane threads only render stream APIs. Start lazily with the
|
|
9
9
|
* first real markdown/chunks plus recipient ids — empty startStream is
|
|
10
10
|
* rejected or never attaches.
|
|
11
|
+
*
|
|
12
|
+
* Every call speaks `chunks`. Slack pins a stream's mode at start: text
|
|
13
|
+
* opened as bare `markdown_text` rejects later `task_update` appends with
|
|
14
|
+
* `streaming_mode_mismatch`, so assistant text goes out as `markdown_text`
|
|
15
|
+
* chunks and tool steps can land in the same message.
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
18
|
import type { ChannelEventContext } from "../../types.js";
|
|
14
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
appendChatStream,
|
|
21
|
+
postMessage,
|
|
22
|
+
startChatStream,
|
|
23
|
+
stopChatStream,
|
|
24
|
+
} from "./api.js";
|
|
25
|
+
import { highlightCodeFences } from "./code-fences.js";
|
|
26
|
+
import { SLACK_MARKDOWN_TEXT_MAX_LEN } from "./constants.js";
|
|
15
27
|
import type { SlackLog } from "./log.js";
|
|
16
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
computeStreamAppend,
|
|
30
|
+
markdownChunk,
|
|
31
|
+
type StreamChunk,
|
|
32
|
+
type StreamTaskChunk,
|
|
33
|
+
} from "./stream.js";
|
|
17
34
|
import type { SlackBotToken, SlackChannelState } from "./types.js";
|
|
18
35
|
|
|
19
36
|
type SlackChannel = ChannelEventContext<SlackChannelState>;
|
|
@@ -98,9 +115,13 @@ export function createStreamDeliveryStrategy(
|
|
|
98
115
|
if (activeStreamTs(channel) !== null) {
|
|
99
116
|
return true;
|
|
100
117
|
}
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
if (
|
|
118
|
+
const openingText = markdown_text ?? "";
|
|
119
|
+
const opening: StreamChunk[] = [];
|
|
120
|
+
if (openingText !== "") {
|
|
121
|
+
opening.push(markdownChunk(highlightCodeFences(openingText)));
|
|
122
|
+
}
|
|
123
|
+
opening.push(...(chunks ?? []));
|
|
124
|
+
if (opening.length === 0) {
|
|
104
125
|
return false;
|
|
105
126
|
}
|
|
106
127
|
const log = getLog();
|
|
@@ -108,8 +129,7 @@ export function createStreamDeliveryStrategy(
|
|
|
108
129
|
botToken,
|
|
109
130
|
channel: channelId,
|
|
110
131
|
thread_ts: threadTs,
|
|
111
|
-
|
|
112
|
-
chunks: hasChunks ? chunks : undefined,
|
|
132
|
+
chunks: opening,
|
|
113
133
|
...streamRecipients(channel),
|
|
114
134
|
});
|
|
115
135
|
if (!started.ok) {
|
|
@@ -126,8 +146,9 @@ export function createStreamDeliveryStrategy(
|
|
|
126
146
|
}
|
|
127
147
|
channel.state.streamTs = started.ts;
|
|
128
148
|
channel.state.streamChannelId = started.channel;
|
|
129
|
-
channel.state.
|
|
130
|
-
channel.state.
|
|
149
|
+
channel.state.streamFull = false;
|
|
150
|
+
channel.state.lastPostedText = openingText;
|
|
151
|
+
channel.state.streamBlockText = openingText;
|
|
131
152
|
log.info("chat.startStream ok", {
|
|
132
153
|
channel: started.channel,
|
|
133
154
|
stream_ts: started.ts,
|
|
@@ -161,21 +182,29 @@ export function createStreamDeliveryStrategy(
|
|
|
161
182
|
return opened ? activeStreamTs(args.channel) : null;
|
|
162
183
|
};
|
|
163
184
|
|
|
185
|
+
/**
|
|
186
|
+
* What to append for the new cumulative text, as Slack should see it: the
|
|
187
|
+
* block text on both sides goes through the same fence rewrite, so the
|
|
188
|
+
* delta lines up with what the stream already holds.
|
|
189
|
+
*/
|
|
190
|
+
const streamDelta = (channel: SlackChannel, text: string): string =>
|
|
191
|
+
computeStreamAppend(
|
|
192
|
+
highlightCodeFences(channel.state.streamBlockText ?? ""),
|
|
193
|
+
highlightCodeFences(text)
|
|
194
|
+
);
|
|
195
|
+
|
|
164
196
|
const stopWithSuffix = async (args: {
|
|
165
197
|
channel: SlackChannel;
|
|
166
198
|
channelId: string;
|
|
167
199
|
ts: string;
|
|
168
200
|
text: string;
|
|
169
201
|
}): Promise<{ ok: boolean; error?: string }> => {
|
|
170
|
-
const appendText =
|
|
171
|
-
args.channel.state.streamBlockText,
|
|
172
|
-
args.text
|
|
173
|
-
);
|
|
202
|
+
const appendText = streamDelta(args.channel, args.text);
|
|
174
203
|
const stopped = await stopChatStream({
|
|
175
204
|
botToken,
|
|
176
205
|
channel: args.channelId,
|
|
177
206
|
ts: args.ts,
|
|
178
|
-
|
|
207
|
+
chunks: appendText === "" ? undefined : [markdownChunk(appendText)],
|
|
179
208
|
});
|
|
180
209
|
args.channel.state.streamTs = null;
|
|
181
210
|
if (stopped.ok) {
|
|
@@ -199,11 +228,77 @@ export function createStreamDeliveryStrategy(
|
|
|
199
228
|
channel.state.streamTs = null;
|
|
200
229
|
};
|
|
201
230
|
|
|
231
|
+
/**
|
|
232
|
+
* `msg_too_long` means the message is full: every further append would
|
|
233
|
+
* fail the same way, so appends stop until `finalize` continues the reply
|
|
234
|
+
* in a new message.
|
|
235
|
+
*/
|
|
236
|
+
const noteAppendFailure = (
|
|
237
|
+
channel: SlackChannel,
|
|
238
|
+
result: { error?: string; unsupported?: boolean }
|
|
239
|
+
): void => {
|
|
240
|
+
if (result.unsupported === true) {
|
|
241
|
+
channel.state.streamingUnavailable = true;
|
|
242
|
+
}
|
|
243
|
+
if (result.error === "msg_too_long") {
|
|
244
|
+
channel.state.streamFull = true;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The streamed message is full. Close it as it stands so it stops spinning
|
|
250
|
+
* and post the rest as a new thread message. Most of the answer is on Slack
|
|
251
|
+
* either way, so the reply counts as delivered even if that post fails: a
|
|
252
|
+
* duplicate would be worse than a lost tail.
|
|
253
|
+
*/
|
|
254
|
+
const continueOverflow = async (args: {
|
|
255
|
+
channel: SlackChannel;
|
|
256
|
+
channelId: string;
|
|
257
|
+
ts: string;
|
|
258
|
+
remainder: string;
|
|
259
|
+
sessionId: string;
|
|
260
|
+
}): Promise<void> => {
|
|
261
|
+
const { channel, channelId, ts, remainder, sessionId } = args;
|
|
262
|
+
const log = getLog();
|
|
263
|
+
await stopChatStream({ botToken, channel: channelId, ts });
|
|
264
|
+
channel.state.streamTs = null;
|
|
265
|
+
const threadTs = channel.state.threadTs;
|
|
266
|
+
if (remainder === "" || threadTs === null || threadTs === "") {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
const posted = await postMessage({
|
|
271
|
+
botToken,
|
|
272
|
+
channel: channelId,
|
|
273
|
+
text: remainder,
|
|
274
|
+
threadTs,
|
|
275
|
+
plainText: remainder.length >= SLACK_MARKDOWN_TEXT_MAX_LEN,
|
|
276
|
+
});
|
|
277
|
+
channel.state.lastBotMessageTs = posted.ts;
|
|
278
|
+
log.info("reply overflowed the stream; continued in a new message", {
|
|
279
|
+
channel: channelId,
|
|
280
|
+
stream_ts: ts,
|
|
281
|
+
session: sessionId,
|
|
282
|
+
continued_chars: remainder.length,
|
|
283
|
+
});
|
|
284
|
+
} catch (error) {
|
|
285
|
+
log.warn("stream overflow continuation failed", {
|
|
286
|
+
error: error instanceof Error ? error.message : String(error),
|
|
287
|
+
channel: channelId,
|
|
288
|
+
stream_ts: ts,
|
|
289
|
+
session: sessionId,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
202
294
|
return {
|
|
203
295
|
inlineToolSteps: true,
|
|
204
296
|
open,
|
|
205
297
|
|
|
206
298
|
async append({ channel, channelId, text, sessionId }) {
|
|
299
|
+
if (channel.state.streamFull === true) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
207
302
|
const ts = await ensureOpen({
|
|
208
303
|
channel,
|
|
209
304
|
channelId,
|
|
@@ -213,10 +308,7 @@ export function createStreamDeliveryStrategy(
|
|
|
213
308
|
if (ts === null) {
|
|
214
309
|
return;
|
|
215
310
|
}
|
|
216
|
-
const appendText =
|
|
217
|
-
channel.state.streamBlockText,
|
|
218
|
-
text
|
|
219
|
-
);
|
|
311
|
+
const appendText = streamDelta(channel, text);
|
|
220
312
|
if (appendText === "") {
|
|
221
313
|
return;
|
|
222
314
|
}
|
|
@@ -224,7 +316,7 @@ export function createStreamDeliveryStrategy(
|
|
|
224
316
|
botToken,
|
|
225
317
|
channel: channelId,
|
|
226
318
|
ts,
|
|
227
|
-
|
|
319
|
+
chunks: [markdownChunk(appendText)],
|
|
228
320
|
});
|
|
229
321
|
if (!result.ok) {
|
|
230
322
|
getLog().warn("appendStream failed", {
|
|
@@ -233,9 +325,7 @@ export function createStreamDeliveryStrategy(
|
|
|
233
325
|
stream_ts: ts,
|
|
234
326
|
session: sessionId,
|
|
235
327
|
});
|
|
236
|
-
|
|
237
|
-
channel.state.streamingUnavailable = true;
|
|
238
|
-
}
|
|
328
|
+
noteAppendFailure(channel, result);
|
|
239
329
|
return;
|
|
240
330
|
}
|
|
241
331
|
channel.state.lastPostedText = text;
|
|
@@ -243,6 +333,9 @@ export function createStreamDeliveryStrategy(
|
|
|
243
333
|
},
|
|
244
334
|
|
|
245
335
|
async appendChunks({ channel, channelId, chunks, sessionId }) {
|
|
336
|
+
if (channel.state.streamFull === true) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
246
339
|
const hadStream = activeStreamTs(channel) !== null;
|
|
247
340
|
const ts = await ensureOpen({
|
|
248
341
|
channel,
|
|
@@ -262,6 +355,16 @@ export function createStreamDeliveryStrategy(
|
|
|
262
355
|
ts,
|
|
263
356
|
chunks,
|
|
264
357
|
});
|
|
358
|
+
if (!result.ok) {
|
|
359
|
+
getLog().warn("appendStream chunks failed", {
|
|
360
|
+
error: result.error,
|
|
361
|
+
channel: channelId,
|
|
362
|
+
stream_ts: ts,
|
|
363
|
+
session: sessionId,
|
|
364
|
+
chunks: chunks.length,
|
|
365
|
+
});
|
|
366
|
+
noteAppendFailure(channel, result);
|
|
367
|
+
}
|
|
265
368
|
return result.ok;
|
|
266
369
|
},
|
|
267
370
|
|
|
@@ -276,12 +379,12 @@ export function createStreamDeliveryStrategy(
|
|
|
276
379
|
if (ts === null) {
|
|
277
380
|
return { delivered: false };
|
|
278
381
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
382
|
+
// Measured before the stop attempt mutates stream state.
|
|
383
|
+
const remainder = streamDelta(channel, text);
|
|
384
|
+
const stopped =
|
|
385
|
+
channel.state.streamFull === true
|
|
386
|
+
? { ok: false, error: "msg_too_long" }
|
|
387
|
+
: await stopWithSuffix({ channel, channelId, ts, text });
|
|
285
388
|
if (stopped.ok) {
|
|
286
389
|
log.info("reply delivered via stream", {
|
|
287
390
|
channel: channelId,
|
|
@@ -291,6 +394,17 @@ export function createStreamDeliveryStrategy(
|
|
|
291
394
|
});
|
|
292
395
|
return { delivered: true };
|
|
293
396
|
}
|
|
397
|
+
if (stopped.error === "msg_too_long") {
|
|
398
|
+
await continueOverflow({
|
|
399
|
+
channel,
|
|
400
|
+
channelId,
|
|
401
|
+
ts,
|
|
402
|
+
remainder,
|
|
403
|
+
sessionId,
|
|
404
|
+
});
|
|
405
|
+
channel.state.lastPostedText = text;
|
|
406
|
+
return { delivered: true };
|
|
407
|
+
}
|
|
294
408
|
log.warn("chat.stopStream failed; falling back to postMessage", {
|
|
295
409
|
error: stopped.error,
|
|
296
410
|
channel: channelId,
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "Thinking" task card that receives the model's reasoning as it streams.
|
|
3
|
+
* Slack appends a card's `details` across updates, so the card is fed
|
|
4
|
+
* deltas: the part of the current reasoning block already on Slack, plus a
|
|
5
|
+
* buffer of what has not gone out yet.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ChannelEventContext } from "../../types.js";
|
|
9
|
+
import type { ResolvedSlackReasoningCard } from "./reply-options.js";
|
|
10
|
+
import { type StreamTaskChunk, truncateCardText } from "./stream.js";
|
|
11
|
+
import type { ReasoningCardState, SlackChannelState } from "./types.js";
|
|
12
|
+
|
|
13
|
+
const FLUSH_MS = 1_000;
|
|
14
|
+
const FLUSH_CHARS = 160;
|
|
15
|
+
const CARD_ID = "reasoning";
|
|
16
|
+
const BLOCK_SEPARATOR = "\n\n";
|
|
17
|
+
|
|
18
|
+
type Channel = ChannelEventContext<SlackChannelState>;
|
|
19
|
+
type CardStatus = "in_progress" | "complete";
|
|
20
|
+
|
|
21
|
+
export interface ReasoningCard {
|
|
22
|
+
/** Buffer the current reasoning block's cumulative text; flushes when due. */
|
|
23
|
+
append(args: {
|
|
24
|
+
channel: Channel;
|
|
25
|
+
sessionId: string;
|
|
26
|
+
text: string;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
/** Send buffered text and set the card status. */
|
|
29
|
+
flush(args: {
|
|
30
|
+
channel: Channel;
|
|
31
|
+
sessionId: string;
|
|
32
|
+
status: CardStatus;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
/** The next reasoning block appends after a blank line. */
|
|
35
|
+
endBlock(channel: Channel): void;
|
|
36
|
+
inProgress(channel: Channel): boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Delivers one chunk into the reply stream; `false` when nothing went out. */
|
|
40
|
+
export type SendCardChunk = (args: {
|
|
41
|
+
channel: Channel;
|
|
42
|
+
sessionId: string;
|
|
43
|
+
chunk: StreamTaskChunk;
|
|
44
|
+
}) => Promise<boolean>;
|
|
45
|
+
|
|
46
|
+
function cardState(state: SlackChannelState): ReasoningCardState {
|
|
47
|
+
if (state.reasoningCard === undefined) {
|
|
48
|
+
state.reasoningCard = {
|
|
49
|
+
status: null,
|
|
50
|
+
blockSent: null,
|
|
51
|
+
pending: "",
|
|
52
|
+
lastFlushMs: null,
|
|
53
|
+
chars: 0,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return state.reasoningCard;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function createReasoningCard(
|
|
60
|
+
card: ResolvedSlackReasoningCard,
|
|
61
|
+
send: SendCardChunk
|
|
62
|
+
): ReasoningCard {
|
|
63
|
+
const flush: ReasoningCard["flush"] = async ({
|
|
64
|
+
channel,
|
|
65
|
+
sessionId,
|
|
66
|
+
status,
|
|
67
|
+
}) => {
|
|
68
|
+
const state = cardState(channel.state);
|
|
69
|
+
if (
|
|
70
|
+
state.pending === "" &&
|
|
71
|
+
(state.status === status || state.status === null)
|
|
72
|
+
) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const chunk: StreamTaskChunk = {
|
|
76
|
+
type: "task_update",
|
|
77
|
+
id: CARD_ID,
|
|
78
|
+
title: card.title,
|
|
79
|
+
status,
|
|
80
|
+
};
|
|
81
|
+
if (state.pending !== "") {
|
|
82
|
+
chunk.details = state.pending;
|
|
83
|
+
}
|
|
84
|
+
// Stamped on the attempt, so a failing stream is retried at most once
|
|
85
|
+
// per flush window instead of once per token.
|
|
86
|
+
state.lastFlushMs = Date.now();
|
|
87
|
+
if (!(await send({ channel, sessionId, chunk }))) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
state.chars += state.pending.length;
|
|
91
|
+
state.pending = "";
|
|
92
|
+
state.status = status;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
flush,
|
|
97
|
+
|
|
98
|
+
async append({ channel, sessionId, text }) {
|
|
99
|
+
const state = cardState(channel.state);
|
|
100
|
+
if (state.chars >= card.maxChars) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const sent = state.blockSent ?? 0;
|
|
104
|
+
let delta: string;
|
|
105
|
+
if (sent > 0 && text.length >= sent) {
|
|
106
|
+
delta = text.slice(sent);
|
|
107
|
+
} else {
|
|
108
|
+
const hasText = state.chars + state.pending.length > 0;
|
|
109
|
+
delta = `${hasText ? BLOCK_SEPARATOR : ""}${text}`;
|
|
110
|
+
}
|
|
111
|
+
state.blockSent = text.length;
|
|
112
|
+
if (delta === "") {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let pending = `${state.pending}${delta}`;
|
|
116
|
+
const room = card.maxChars - state.chars;
|
|
117
|
+
if (pending.length > room) {
|
|
118
|
+
pending = truncateCardText(pending, room);
|
|
119
|
+
state.chars = card.maxChars - pending.length;
|
|
120
|
+
}
|
|
121
|
+
state.pending = pending;
|
|
122
|
+
|
|
123
|
+
const due =
|
|
124
|
+
state.lastFlushMs === null ||
|
|
125
|
+
Date.now() - state.lastFlushMs >= FLUSH_MS ||
|
|
126
|
+
pending.length >= FLUSH_CHARS;
|
|
127
|
+
if (due) {
|
|
128
|
+
await flush({ channel, sessionId, status: "in_progress" });
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
endBlock(channel) {
|
|
133
|
+
cardState(channel.state).blockSent = null;
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
inProgress(channel) {
|
|
137
|
+
return channel.state.reasoningCard?.status === "in_progress";
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve `slackChannel({ reply, toolLabels })` — and the deprecated
|
|
3
|
+
* `streaming` / `thinkingSteps` / `loadingMessages` flags — into one config
|
|
4
|
+
* the default event handlers read.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { SLACK_DEFAULT_LOADING_MESSAGES } from "./constants.js";
|
|
8
|
+
import { defaultToolCardDetails } from "./tool-cards.js";
|
|
9
|
+
import type {
|
|
10
|
+
SlackChannelOptions,
|
|
11
|
+
SlackReasoningCardOptions,
|
|
12
|
+
SlackReplyOptions,
|
|
13
|
+
SlackToolCall,
|
|
14
|
+
SlackToolCardGroup,
|
|
15
|
+
SlackToolLabels,
|
|
16
|
+
SlackToolResult,
|
|
17
|
+
} from "./types.js";
|
|
18
|
+
|
|
19
|
+
export type SlackReplyMode = "post" | "stream";
|
|
20
|
+
|
|
21
|
+
export interface ResolvedSlackStatus {
|
|
22
|
+
reasoning: boolean;
|
|
23
|
+
/** `false`, or the line to show when tool calls start. */
|
|
24
|
+
tools: false | ((calls: readonly SlackToolCall[]) => string);
|
|
25
|
+
idle: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ResolvedSlackToolCards {
|
|
29
|
+
group: SlackToolCardGroup;
|
|
30
|
+
details?: (call: SlackToolCall) => string | undefined;
|
|
31
|
+
output?: (result: SlackToolResult) => string | undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ResolvedSlackReasoningCard {
|
|
35
|
+
title: string;
|
|
36
|
+
maxChars: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ResolvedSlackReply {
|
|
40
|
+
mode: SlackReplyMode;
|
|
41
|
+
status: ResolvedSlackStatus;
|
|
42
|
+
toolCards: false | ResolvedSlackToolCards;
|
|
43
|
+
reasoningCard: false | ResolvedSlackReasoningCard;
|
|
44
|
+
toolLabel: (toolName: string) => string;
|
|
45
|
+
/** Author-facing notices about deprecated options that were honored. */
|
|
46
|
+
deprecations: string[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const DEFAULT_REASONING_CARD_TITLE = "Thinking";
|
|
50
|
+
/** A modest share of `SLACK_MARKDOWN_TEXT_MAX_LEN`, which the whole streamed message shares. */
|
|
51
|
+
export const DEFAULT_REASONING_CARD_MAX_CHARS = 1500;
|
|
52
|
+
|
|
53
|
+
type ReplyInputs = Pick<
|
|
54
|
+
SlackChannelOptions,
|
|
55
|
+
"reply" | "toolLabels" | "streaming" | "thinkingSteps"
|
|
56
|
+
> & { loadingMessages?: readonly string[] };
|
|
57
|
+
|
|
58
|
+
function resolveToolLabel(
|
|
59
|
+
labels: SlackToolLabels | undefined
|
|
60
|
+
): (toolName: string) => string {
|
|
61
|
+
if (labels === undefined) {
|
|
62
|
+
return (toolName) => toolName;
|
|
63
|
+
}
|
|
64
|
+
const lookup =
|
|
65
|
+
typeof labels === "function" ? labels : (name: string) => labels[name];
|
|
66
|
+
return (toolName) => {
|
|
67
|
+
const label = lookup(toolName);
|
|
68
|
+
return label === undefined || label === "" ? toolName : label;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function defaultToolStatusLine(
|
|
73
|
+
toolLabel: (toolName: string) => string
|
|
74
|
+
): (calls: readonly SlackToolCall[]) => string {
|
|
75
|
+
return (calls) => {
|
|
76
|
+
const names = [...new Set(calls.map((call) => toolLabel(call.toolName)))];
|
|
77
|
+
return `Running ${names.join(", ")}…`;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveIdle(idle: readonly string[] | undefined): string[] {
|
|
82
|
+
const cleaned = (idle ?? []).filter((line) => line.trim() !== "");
|
|
83
|
+
return cleaned.length > 0 ? cleaned : [...SLACK_DEFAULT_LOADING_MESSAGES];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resolveReasoningCard(
|
|
87
|
+
option: boolean | SlackReasoningCardOptions | undefined
|
|
88
|
+
): false | ResolvedSlackReasoningCard {
|
|
89
|
+
if (option === undefined || option === false) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
const options = option === true ? {} : option;
|
|
93
|
+
const title = options.title?.trim();
|
|
94
|
+
return {
|
|
95
|
+
title:
|
|
96
|
+
title === undefined || title === ""
|
|
97
|
+
? DEFAULT_REASONING_CARD_TITLE
|
|
98
|
+
: title,
|
|
99
|
+
maxChars:
|
|
100
|
+
options.maxChars !== undefined && options.maxChars > 0
|
|
101
|
+
? options.maxChars
|
|
102
|
+
: DEFAULT_REASONING_CARD_MAX_CHARS,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function resolveToolCards(
|
|
107
|
+
option: SlackReplyOptions & { mode: "stream" }
|
|
108
|
+
): false | ResolvedSlackToolCards {
|
|
109
|
+
const cards = option.toolCards;
|
|
110
|
+
if (cards === undefined || cards === false) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (cards === true) {
|
|
114
|
+
return { group: "per-tool", details: defaultToolCardDetails };
|
|
115
|
+
}
|
|
116
|
+
const group = cards.group ?? "per-tool";
|
|
117
|
+
if (cards.collapsible === false) {
|
|
118
|
+
return { group };
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
group,
|
|
122
|
+
details: cards.details ?? defaultToolCardDetails,
|
|
123
|
+
output: cards.output,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Map the deprecated flags onto a `reply` shape with their old defaults
|
|
129
|
+
* (streaming on, per-call cards on), so a config that only sets these keeps
|
|
130
|
+
* behaving as it did. `null` when none of them is set.
|
|
131
|
+
*/
|
|
132
|
+
function legacyReplyOptions(
|
|
133
|
+
options: ReplyInputs
|
|
134
|
+
): { reply: SlackReplyOptions; deprecations: string[] } | null {
|
|
135
|
+
const idle = options.loadingMessages;
|
|
136
|
+
if (
|
|
137
|
+
options.streaming === undefined &&
|
|
138
|
+
options.thinkingSteps === undefined &&
|
|
139
|
+
idle === undefined
|
|
140
|
+
) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
const deprecations: string[] = [];
|
|
144
|
+
const mode: SlackReplyMode = options.streaming === false ? "post" : "stream";
|
|
145
|
+
// What legacy streaming showed: one title-only card per call.
|
|
146
|
+
const cards = options.thinkingSteps === false ? false : LEGACY_CARDS;
|
|
147
|
+
const replacement =
|
|
148
|
+
mode === "post"
|
|
149
|
+
? 'reply: { mode: "post" }'
|
|
150
|
+
: cards === false
|
|
151
|
+
? 'reply: { mode: "stream" }'
|
|
152
|
+
: 'reply: { mode: "stream", toolCards: { group: "per-call", collapsible: false } }';
|
|
153
|
+
if (idle !== undefined) {
|
|
154
|
+
deprecations.push(
|
|
155
|
+
`slackChannel({ loadingMessages }) is deprecated; use reply: { mode: "${mode}", status: { idle: [...] } }.`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (options.streaming !== undefined) {
|
|
159
|
+
deprecations.push(
|
|
160
|
+
`slackChannel({ streaming: ${String(options.streaming)} }) is deprecated; use ${replacement}.`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (options.thinkingSteps !== undefined) {
|
|
164
|
+
deprecations.push(
|
|
165
|
+
mode === "post"
|
|
166
|
+
? "slackChannel({ thinkingSteps }) has no effect in post mode; remove it."
|
|
167
|
+
: `slackChannel({ thinkingSteps: ${String(options.thinkingSteps)} }) is deprecated; use ${replacement}.`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
const status = { idle };
|
|
171
|
+
if (mode === "post") {
|
|
172
|
+
return { reply: { mode, status }, deprecations };
|
|
173
|
+
}
|
|
174
|
+
return { reply: { mode, status, toolCards: cards }, deprecations };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const LEGACY_CARDS = { group: "per-call", collapsible: false } as const;
|
|
178
|
+
|
|
179
|
+
export function resolveSlackReply(options: ReplyInputs): ResolvedSlackReply {
|
|
180
|
+
const deprecations: string[] = [];
|
|
181
|
+
let reply: SlackReplyOptions = { mode: "post" };
|
|
182
|
+
const legacy = legacyReplyOptions(options);
|
|
183
|
+
if (options.reply !== undefined) {
|
|
184
|
+
reply = options.reply;
|
|
185
|
+
if (legacy !== null) {
|
|
186
|
+
const ignored = (
|
|
187
|
+
["streaming", "thinkingSteps", "loadingMessages"] as const
|
|
188
|
+
).filter((key) => options[key] !== undefined);
|
|
189
|
+
deprecations.push(
|
|
190
|
+
`slackChannel({ ${ignored.join(", ")} }) is ignored because reply is set; remove the deprecated option${ignored.length === 1 ? "" : "s"}.`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
} else if (legacy !== null) {
|
|
194
|
+
reply = legacy.reply;
|
|
195
|
+
deprecations.push(...legacy.deprecations);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const toolLabel = resolveToolLabel(options.toolLabels);
|
|
199
|
+
const statusInput = reply.status ?? {};
|
|
200
|
+
const status: ResolvedSlackStatus = {
|
|
201
|
+
reasoning: statusInput.reasoning !== false,
|
|
202
|
+
tools:
|
|
203
|
+
statusInput.tools === false
|
|
204
|
+
? false
|
|
205
|
+
: typeof statusInput.tools === "function"
|
|
206
|
+
? statusInput.tools
|
|
207
|
+
: defaultToolStatusLine(toolLabel),
|
|
208
|
+
idle: resolveIdle(statusInput.idle),
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
if (reply.mode === "post") {
|
|
212
|
+
return {
|
|
213
|
+
mode: "post",
|
|
214
|
+
status,
|
|
215
|
+
toolCards: false,
|
|
216
|
+
reasoningCard: false,
|
|
217
|
+
toolLabel,
|
|
218
|
+
deprecations,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
mode: "stream",
|
|
223
|
+
status,
|
|
224
|
+
toolCards: resolveToolCards(reply),
|
|
225
|
+
reasoningCard: resolveReasoningCard(reply.reasoningCard),
|
|
226
|
+
toolLabel,
|
|
227
|
+
deprecations,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
dispatchInteractiveFromPayload,
|
|
58
58
|
} from "./interactive.js";
|
|
59
59
|
import { createSlackLogger, type SlackLog } from "./log.js";
|
|
60
|
+
import { resolveSlackReply } from "./reply-options.js";
|
|
60
61
|
import {
|
|
61
62
|
type SlackSocketModeHandle,
|
|
62
63
|
type SlackSocketModeOptions,
|
|
@@ -128,7 +129,8 @@ export function slackChannel(
|
|
|
128
129
|
const credentials =
|
|
129
130
|
options.credentials ?? credentialsFromEnv(options.envPrefix);
|
|
130
131
|
const envKeys = slackEnvKeys(options.envPrefix);
|
|
131
|
-
const
|
|
132
|
+
const reply = resolveSlackReply(options);
|
|
133
|
+
const loadingMessages = reply.status.idle;
|
|
132
134
|
const policy = options.policy;
|
|
133
135
|
const blockExternals = resolveSlackBlockExternals(policy);
|
|
134
136
|
const defaultInbound = createDefaultOnInbound(loadingMessages, policy);
|
|
@@ -174,11 +176,13 @@ export function slackChannel(
|
|
|
174
176
|
events,
|
|
175
177
|
buildDefaultEvents({
|
|
176
178
|
credentials,
|
|
179
|
+
reply: options.reply,
|
|
180
|
+
toolLabels: options.toolLabels,
|
|
177
181
|
streaming: options.streaming,
|
|
178
182
|
thinkingSteps: options.thinkingSteps,
|
|
183
|
+
loadingMessages: options.loadingMessages,
|
|
179
184
|
suggestedPrompts: options.suggestedPrompts,
|
|
180
185
|
suggestedPromptsTitle: options.suggestedPromptsTitle,
|
|
181
|
-
loadingMessages,
|
|
182
186
|
getLog,
|
|
183
187
|
})
|
|
184
188
|
);
|
|
@@ -252,6 +256,7 @@ export function slackChannel(
|
|
|
252
256
|
...(channelPosts === undefined
|
|
253
257
|
? {}
|
|
254
258
|
: { slackChannelPosts: [...channelPosts.allow] }),
|
|
259
|
+
deprecations: reply.deprecations,
|
|
255
260
|
},
|
|
256
261
|
async receive(input: ReceiveInput, { send }) {
|
|
257
262
|
const target = input.target ?? {};
|