@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
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default stream-event handlers for the Origin channel: reply delivery.
|
|
3
|
+
*
|
|
4
|
+
* The GitHub channel posts completed assistant messages back to the PR via
|
|
5
|
+
* `buildDefaultGitHubEvents`; this is the Origin analogue. Outbound
|
|
6
|
+
* credentials resolve exactly like `ctx.origin` in hooks (see
|
|
7
|
+
* ./binding.ts): channel app credentials / `ORIGIN_APP_*` env when
|
|
8
|
+
* configured, otherwise — for `cursorAccount` channels — the Cursor-account
|
|
9
|
+
* session exchange, which on hosted v2 acts as the deployment
|
|
10
|
+
* service-account principal. The `agent-serve` SA scope allowlist includes
|
|
11
|
+
* `repository:pull_requests:reviews:write`, the scope
|
|
12
|
+
* `CreatePullRequestComment` checks, so no extra grant is needed.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { ChannelEventHandlers } from "../../types.js";
|
|
16
|
+
import { buildOriginBinding, type OriginHandle } from "./binding.js";
|
|
17
|
+
import type { OriginChannelState } from "./state.js";
|
|
18
|
+
import type { OriginAppOptions } from "./types.js";
|
|
19
|
+
|
|
20
|
+
/** Hidden marker on outbound Origin comments so consumers can spot them. */
|
|
21
|
+
export const ORIGIN_OUTBOUND_MARKER = "<!-- agent-serve-origin -->";
|
|
22
|
+
|
|
23
|
+
export function formatOriginOutboundComment(body: string): string {
|
|
24
|
+
if (body.includes(ORIGIN_OUTBOUND_MARKER)) {
|
|
25
|
+
return body;
|
|
26
|
+
}
|
|
27
|
+
return `${body.trimEnd()}\n\n${ORIGIN_OUTBOUND_MARKER}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface BuildDefaultOriginEventsOptions {
|
|
31
|
+
/** Force the signed-in Cursor account / deployment SA credential path. */
|
|
32
|
+
cursorAccount?: boolean | { repos: readonly string[] };
|
|
33
|
+
/** Channel-authored outbound app credentials / API base. */
|
|
34
|
+
app?: OriginAppOptions;
|
|
35
|
+
/**
|
|
36
|
+
* When false, skip posting completed assistant messages (and failure
|
|
37
|
+
* notices) back to the Origin pull request. Defaults to true.
|
|
38
|
+
*/
|
|
39
|
+
deliverReplies?: boolean;
|
|
40
|
+
/** Injectable binding builder for tests. */
|
|
41
|
+
buildBinding?: typeof buildOriginBinding;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function bindingForState(
|
|
45
|
+
options: BuildDefaultOriginEventsOptions,
|
|
46
|
+
state: OriginChannelState
|
|
47
|
+
): OriginHandle {
|
|
48
|
+
const build = options.buildBinding ?? buildOriginBinding;
|
|
49
|
+
return build({
|
|
50
|
+
repository: {
|
|
51
|
+
owner: state.owner,
|
|
52
|
+
name: state.repo,
|
|
53
|
+
fullName: `${state.owner}/${state.repo}`,
|
|
54
|
+
},
|
|
55
|
+
...(state.installationId === null
|
|
56
|
+
? {}
|
|
57
|
+
: { installationId: state.installationId }),
|
|
58
|
+
cursorAccount:
|
|
59
|
+
options.cursorAccount !== undefined && options.cursorAccount !== false,
|
|
60
|
+
app: options.app,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function postPullRequestComment(
|
|
65
|
+
options: BuildDefaultOriginEventsOptions,
|
|
66
|
+
state: OriginChannelState,
|
|
67
|
+
body: string
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
if (
|
|
70
|
+
state.owner === "" ||
|
|
71
|
+
state.repo === "" ||
|
|
72
|
+
state.pullRequestNumber === null
|
|
73
|
+
) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const origin = bindingForState(options, state);
|
|
77
|
+
await origin.request({
|
|
78
|
+
method: "POST",
|
|
79
|
+
path: `/v1/origin/repos/${encodeURIComponent(state.owner)}/${encodeURIComponent(
|
|
80
|
+
state.repo
|
|
81
|
+
)}/pulls/${state.pullRequestNumber}/comments`,
|
|
82
|
+
body: { body: formatOriginOutboundComment(body) },
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Built-in delivery: post assistant text on `message.completed`, and a
|
|
88
|
+
* short error comment on turn/session failure. Every post soft-fails so a
|
|
89
|
+
* missing outbound credential (or an Origin refusal) never crashes the
|
|
90
|
+
* session — the GitHub defaults' posture.
|
|
91
|
+
*/
|
|
92
|
+
export function buildDefaultOriginEvents(
|
|
93
|
+
options: BuildDefaultOriginEventsOptions = {}
|
|
94
|
+
): ChannelEventHandlers<OriginChannelState> {
|
|
95
|
+
const deliverReplies = options.deliverReplies !== false;
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
async "message.completed"(event, channel) {
|
|
99
|
+
if (!deliverReplies) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (event.data.finishReason === "tool_call" || event.data.text === "") {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
await postPullRequestComment(options, channel.state, event.data.text);
|
|
107
|
+
} catch {
|
|
108
|
+
// Soft-fail delivery so a missing credential does not crash the session.
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
async "turn.failed"(_event, channel) {
|
|
113
|
+
await postFailure(options, channel, deliverReplies);
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
async "session.failed"(_event, channel) {
|
|
117
|
+
await postFailure(options, channel, deliverReplies);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function postFailure(
|
|
123
|
+
options: BuildDefaultOriginEventsOptions,
|
|
124
|
+
channel: { state: OriginChannelState },
|
|
125
|
+
deliverReplies: boolean
|
|
126
|
+
): Promise<void> {
|
|
127
|
+
if (!deliverReplies) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
await postPullRequestComment(
|
|
132
|
+
options,
|
|
133
|
+
channel.state,
|
|
134
|
+
[
|
|
135
|
+
"I hit an error while handling your request.",
|
|
136
|
+
"",
|
|
137
|
+
"Please try again, or reach out if it keeps failing.",
|
|
138
|
+
].join("\n")
|
|
139
|
+
);
|
|
140
|
+
} catch {
|
|
141
|
+
// Soft-fail.
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -26,8 +26,10 @@ export * from "./api.js";
|
|
|
26
26
|
export * from "./binding.js";
|
|
27
27
|
export * from "./checks.js";
|
|
28
28
|
export * from "./cursor-account.js";
|
|
29
|
+
export * from "./defaults.js";
|
|
29
30
|
export * from "./events.js";
|
|
30
31
|
export * from "./origin-channel.js";
|
|
31
32
|
export * from "./origin-webhook.js";
|
|
32
33
|
export * from "./reactions.js";
|
|
34
|
+
export * from "./state.js";
|
|
33
35
|
export * from "./types.js";
|
|
@@ -18,13 +18,16 @@ import type {
|
|
|
18
18
|
AgentCloudOptions,
|
|
19
19
|
AuthContext,
|
|
20
20
|
ChannelDefinition,
|
|
21
|
+
ChannelEventHandlers,
|
|
21
22
|
ChannelHandlerArgs,
|
|
23
|
+
JsonValue,
|
|
22
24
|
} from "../../types.js";
|
|
23
25
|
import { buildOriginBinding } from "./binding.js";
|
|
24
26
|
import {
|
|
25
27
|
parseCursorOriginRepoScope,
|
|
26
28
|
registerOriginCursorAccountRuntime,
|
|
27
29
|
} from "./cursor-account.js";
|
|
30
|
+
import { buildDefaultOriginEvents } from "./defaults.js";
|
|
28
31
|
import { deriveOriginWebhookEvents, ORIGIN_CHANNEL_KIND } from "./events.js";
|
|
29
32
|
import {
|
|
30
33
|
DEFAULT_ORIGIN_API_BASE_URL,
|
|
@@ -32,6 +35,11 @@ import {
|
|
|
32
35
|
type OriginWebhookHeaders,
|
|
33
36
|
verifyOriginWebhook,
|
|
34
37
|
} from "./origin-webhook.js";
|
|
38
|
+
import {
|
|
39
|
+
emptyOriginChannelState,
|
|
40
|
+
type OriginChannelState,
|
|
41
|
+
originChannelStateForEvent,
|
|
42
|
+
} from "./state.js";
|
|
35
43
|
import type {
|
|
36
44
|
OriginActor,
|
|
37
45
|
OriginChannelOptions,
|
|
@@ -432,6 +440,7 @@ function enrichEventContext(input: {
|
|
|
432
440
|
...input.ctx,
|
|
433
441
|
host: input.args.host,
|
|
434
442
|
artifacts: input.args.artifacts,
|
|
443
|
+
send: input.args.send,
|
|
435
444
|
origin: buildOriginBinding({
|
|
436
445
|
repository: input.ctx.repository,
|
|
437
446
|
installationId: input.ctx.installationId,
|
|
@@ -504,6 +513,7 @@ async function startTurn(input: {
|
|
|
504
513
|
message: string;
|
|
505
514
|
dispatch: OriginTurnDispatch;
|
|
506
515
|
cloud?: AgentCloudOptions;
|
|
516
|
+
state: OriginChannelState;
|
|
507
517
|
}): Promise<Response> {
|
|
508
518
|
const source = continuationSource(input.options.continuation, "origin");
|
|
509
519
|
const session = await input.args.send(input.message, {
|
|
@@ -513,6 +523,10 @@ async function startTurn(input: {
|
|
|
513
523
|
: {}),
|
|
514
524
|
title: input.dispatch.title ?? defaultOriginTitle(input.ctx),
|
|
515
525
|
...(input.cloud === undefined ? {} : { cloud: input.cloud }),
|
|
526
|
+
state: input.state as unknown as JsonValue,
|
|
527
|
+
// Resume must refresh the triggering comment / delivery identifiers so
|
|
528
|
+
// reply delivery targets the latest wake, not the session's first.
|
|
529
|
+
refreshState: input.state as unknown as JsonValue,
|
|
516
530
|
});
|
|
517
531
|
if (isDeferredChannelSession(session)) {
|
|
518
532
|
// Hosted admission captured the send; the control plane allocates the
|
|
@@ -569,6 +583,8 @@ async function applyDispatch(input: {
|
|
|
569
583
|
extra: Record<string, unknown>;
|
|
570
584
|
message: string;
|
|
571
585
|
cloud?: AgentCloudOptions;
|
|
586
|
+
/** Comment id that woke this dispatch (comment events only). */
|
|
587
|
+
triggeringCommentId?: string;
|
|
572
588
|
}): Promise<Response> {
|
|
573
589
|
if (input.dispatch === null) {
|
|
574
590
|
return skipped("not_dispatched", input.extra);
|
|
@@ -587,6 +603,14 @@ async function applyDispatch(input: {
|
|
|
587
603
|
message,
|
|
588
604
|
dispatch: input.dispatch,
|
|
589
605
|
cloud: input.cloud,
|
|
606
|
+
state: originChannelStateForEvent({
|
|
607
|
+
repository: input.ctx.repository,
|
|
608
|
+
pullRequestNumber: input.ctx.pullRequestNumber,
|
|
609
|
+
installationId: input.ctx.installationId,
|
|
610
|
+
deliveryId: input.ctx.deliveryId,
|
|
611
|
+
eventType: input.ctx.eventType,
|
|
612
|
+
triggeringCommentId: input.triggeringCommentId,
|
|
613
|
+
}),
|
|
590
614
|
});
|
|
591
615
|
}
|
|
592
616
|
|
|
@@ -654,6 +678,7 @@ export async function dispatchOriginWebhook(input: {
|
|
|
654
678
|
dispatch,
|
|
655
679
|
extra: { event: eventType },
|
|
656
680
|
message: `Origin comment on ${ctx.repository.fullName}#${ctx.pullRequestNumber}`,
|
|
681
|
+
triggeringCommentId: commentId,
|
|
657
682
|
});
|
|
658
683
|
}
|
|
659
684
|
|
|
@@ -798,7 +823,7 @@ export function getOriginChannelOptions(
|
|
|
798
823
|
|
|
799
824
|
export function originChannel(
|
|
800
825
|
options: OriginChannelOptions = {}
|
|
801
|
-
): ChannelDefinition {
|
|
826
|
+
): ChannelDefinition<OriginChannelState> {
|
|
802
827
|
const usesCursorAccount =
|
|
803
828
|
options.cursorAccount === true || typeof options.cursorAccount === "object";
|
|
804
829
|
const cursorScope =
|
|
@@ -833,8 +858,19 @@ export function originChannel(
|
|
|
833
858
|
);
|
|
834
859
|
}
|
|
835
860
|
|
|
861
|
+
const events: ChannelEventHandlers<OriginChannelState> = {
|
|
862
|
+
...buildDefaultOriginEvents({
|
|
863
|
+
cursorAccount: channelOptions.cursorAccount,
|
|
864
|
+
app: channelOptions.app,
|
|
865
|
+
deliverReplies: channelOptions.deliverReplies,
|
|
866
|
+
}),
|
|
867
|
+
...options.events,
|
|
868
|
+
};
|
|
869
|
+
|
|
836
870
|
const definition = defineChannel({
|
|
837
871
|
auth,
|
|
872
|
+
state: emptyOriginChannelState(),
|
|
873
|
+
events,
|
|
838
874
|
onStart: options.onStart,
|
|
839
875
|
onStop: options.onStop,
|
|
840
876
|
meta: {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable per-session Origin channel state.
|
|
3
|
+
*
|
|
4
|
+
* Persisted with the turn (same mechanism as `GitHubChannelState`) so
|
|
5
|
+
* channel stream-event handlers — reply delivery in ./defaults.ts — can
|
|
6
|
+
* rebuild a repo-bound Origin handle without re-parsing the webhook.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface OriginChannelState {
|
|
10
|
+
owner: string;
|
|
11
|
+
repo: string;
|
|
12
|
+
pullRequestNumber: number | null;
|
|
13
|
+
/** Origin app installation id from the delivery envelope, when present. */
|
|
14
|
+
installationId: string | null;
|
|
15
|
+
/** Comment id that woke the turn (comment events only). */
|
|
16
|
+
triggeringCommentId: string | null;
|
|
17
|
+
deliveryId: string | null;
|
|
18
|
+
eventType: string | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function emptyOriginChannelState(
|
|
22
|
+
overrides: Partial<OriginChannelState> = {}
|
|
23
|
+
): OriginChannelState {
|
|
24
|
+
return {
|
|
25
|
+
owner: "",
|
|
26
|
+
repo: "",
|
|
27
|
+
pullRequestNumber: null,
|
|
28
|
+
installationId: null,
|
|
29
|
+
triggeringCommentId: null,
|
|
30
|
+
deliveryId: null,
|
|
31
|
+
eventType: null,
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Build the per-turn channel state from a dispatched event's context. */
|
|
37
|
+
export function originChannelStateForEvent(input: {
|
|
38
|
+
repository: { owner: string; name: string };
|
|
39
|
+
pullRequestNumber: number;
|
|
40
|
+
installationId?: string;
|
|
41
|
+
deliveryId?: string;
|
|
42
|
+
eventType: string;
|
|
43
|
+
triggeringCommentId?: string;
|
|
44
|
+
}): OriginChannelState {
|
|
45
|
+
return emptyOriginChannelState({
|
|
46
|
+
owner: input.repository.owner,
|
|
47
|
+
repo: input.repository.name,
|
|
48
|
+
pullRequestNumber: input.pullRequestNumber,
|
|
49
|
+
installationId: input.installationId ?? null,
|
|
50
|
+
triggeringCommentId: input.triggeringCommentId ?? null,
|
|
51
|
+
deliveryId: input.deliveryId ?? null,
|
|
52
|
+
eventType: input.eventType,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
@@ -4,11 +4,14 @@ import type {
|
|
|
4
4
|
ArtifactsApi,
|
|
5
5
|
AuthContext,
|
|
6
6
|
AuthPolicy,
|
|
7
|
+
ChannelEventHandlers,
|
|
7
8
|
ChannelStartArgs,
|
|
8
9
|
HostContext,
|
|
10
|
+
SendMessageFn,
|
|
9
11
|
} from "../../types.js";
|
|
10
12
|
import type { OriginTokenProvider } from "./api.js";
|
|
11
13
|
import type { OriginHandle } from "./binding.js";
|
|
14
|
+
import type { OriginChannelState } from "./state.js";
|
|
12
15
|
|
|
13
16
|
export interface OriginActor {
|
|
14
17
|
id: string;
|
|
@@ -70,6 +73,12 @@ export interface OriginEventContext {
|
|
|
70
73
|
*/
|
|
71
74
|
payload: Record<string, unknown>;
|
|
72
75
|
sender?: OriginActor;
|
|
76
|
+
/**
|
|
77
|
+
* Channel `send`. Set on every delivery path (HTTP webhook, hosted
|
|
78
|
+
* admission, SCM events) so a hook can start a turn itself instead of
|
|
79
|
+
* returning `{ auth, message }` or a deferred `{ task }`.
|
|
80
|
+
*/
|
|
81
|
+
send?: SendMessageFn;
|
|
73
82
|
host: HostContext;
|
|
74
83
|
artifacts: ArtifactsApi;
|
|
75
84
|
/**
|
|
@@ -242,6 +251,21 @@ export interface OriginChannelOptions {
|
|
|
242
251
|
* pull request URL, or a resolver for custom cloud options.
|
|
243
252
|
*/
|
|
244
253
|
cloud?: boolean | AgentCloudOptions | OriginCloudOptionsResolver;
|
|
254
|
+
/**
|
|
255
|
+
* When false, skip posting completed assistant messages (and failure
|
|
256
|
+
* notices) back to the Origin pull request. Defaults to true — the GitHub
|
|
257
|
+
* channel's reply-delivery posture. Outbound credentials resolve like
|
|
258
|
+
* `ctx.origin`: {@link app} / `ORIGIN_APP_*` env when configured,
|
|
259
|
+
* otherwise the Cursor-account session exchange (hosted v2 deployments
|
|
260
|
+
* post as the deployment service-account principal).
|
|
261
|
+
*/
|
|
262
|
+
deliverReplies?: boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Channel stream-event handlers, merged over the built-in reply-delivery
|
|
265
|
+
* defaults (`buildDefaultOriginEvents`) — same override contract as the
|
|
266
|
+
* GitHub channel's `events`.
|
|
267
|
+
*/
|
|
268
|
+
events?: ChannelEventHandlers<OriginChannelState>;
|
|
245
269
|
/** Called once when the server mounts this channel. */
|
|
246
270
|
onStart?: (args: ChannelStartArgs) => void | Promise<void>;
|
|
247
271
|
/** Called when the server shuts down. */
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { ErrorCode, type WebAPIPlatformError, WebClient } from "@slack/web-api";
|
|
6
6
|
import { slackifyMarkdown } from "slackify-markdown";
|
|
7
7
|
import type { ArtifactsApi, HostContext } from "../../types.js";
|
|
8
|
+
import { highlightCodeFences } from "./code-fences.js";
|
|
8
9
|
import {
|
|
9
10
|
SLACK_DEFAULT_LOADING_MESSAGES,
|
|
10
11
|
SLACK_LOADING_MESSAGE_MAX_LEN,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
} from "./constants.js";
|
|
17
18
|
import { tryResolveAppToken, tryResolveBotToken } from "./credentials.js";
|
|
18
19
|
import { defaultSlackLog, type SlackLog } from "./log.js";
|
|
19
|
-
import type {
|
|
20
|
+
import type { StreamChunk } from "./stream.js";
|
|
20
21
|
import type {
|
|
21
22
|
SlackApiTransport,
|
|
22
23
|
SlackBinding,
|
|
@@ -194,10 +195,18 @@ export function truncateTitle(title: string, max?: number): string {
|
|
|
194
195
|
// ---------------------------------------------------------------------------
|
|
195
196
|
|
|
196
197
|
/**
|
|
197
|
-
* Show or clear the
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
198
|
+
* Show or clear the status chip under the thread.
|
|
199
|
+
*
|
|
200
|
+
* Status text goes through `assistant.threads.setStatus` alone. The agent
|
|
201
|
+
* session is only written when clearing: Agent UX ignores an empty assistant
|
|
202
|
+
* status, so `agents.sessions.setStatus` `active` is what actually drops the
|
|
203
|
+
* chip. That same write must not accompany status text — Slack applies it
|
|
204
|
+
* asynchronously and it blanks the chip when it lands after the text, which
|
|
205
|
+
* reads as flicker between updates. A `processing` write would be worse:
|
|
206
|
+
* Agent UX paints its own generic "is working…" over the assistant text
|
|
207
|
+
* while the session is `processing`. An open `chat.startStream` also flips
|
|
208
|
+
* the session to `processing` on Slack's side, so status text only shows on
|
|
209
|
+
* non-streaming turns. The empty assistant call stays for older workspaces.
|
|
201
210
|
*/
|
|
202
211
|
export async function setThreadStatus(args: {
|
|
203
212
|
botToken: SlackBotToken | undefined;
|
|
@@ -210,21 +219,12 @@ export async function setThreadStatus(args: {
|
|
|
210
219
|
return { ok: false, error: "missing_channel_or_thread" };
|
|
211
220
|
}
|
|
212
221
|
const status = truncateTypingStatus(args.status);
|
|
213
|
-
const sessionResult = await callSlackApiSoft({
|
|
214
|
-
botToken: args.botToken,
|
|
215
|
-
operation: "agents.sessions.setStatus",
|
|
216
|
-
body: {
|
|
217
|
-
channel_id: args.channelId,
|
|
218
|
-
thread_ts: args.threadTs,
|
|
219
|
-
status: status.length > 0 ? "processing" : "active",
|
|
220
|
-
},
|
|
221
|
-
});
|
|
222
|
-
|
|
223
222
|
const body: Record<string, unknown> = {
|
|
224
223
|
channel_id: args.channelId,
|
|
225
224
|
thread_ts: args.threadTs,
|
|
226
225
|
status,
|
|
227
226
|
};
|
|
227
|
+
|
|
228
228
|
if (status.length > 0) {
|
|
229
229
|
const loadingRaw =
|
|
230
230
|
args.loadingMessages !== undefined && args.loadingMessages.length > 0
|
|
@@ -237,7 +237,22 @@ export async function setThreadStatus(args: {
|
|
|
237
237
|
if (loading_messages.length > 0) {
|
|
238
238
|
body.loading_messages = loading_messages;
|
|
239
239
|
}
|
|
240
|
+
return callSlackApiSoft({
|
|
241
|
+
botToken: args.botToken,
|
|
242
|
+
operation: "assistant.threads.setStatus",
|
|
243
|
+
body,
|
|
244
|
+
});
|
|
240
245
|
}
|
|
246
|
+
|
|
247
|
+
const sessionResult = await callSlackApiSoft({
|
|
248
|
+
botToken: args.botToken,
|
|
249
|
+
operation: "agents.sessions.setStatus",
|
|
250
|
+
body: {
|
|
251
|
+
channel_id: args.channelId,
|
|
252
|
+
thread_ts: args.threadTs,
|
|
253
|
+
status: "active",
|
|
254
|
+
},
|
|
255
|
+
});
|
|
241
256
|
const assistantResult = await callSlackApiSoft({
|
|
242
257
|
botToken: args.botToken,
|
|
243
258
|
operation: "assistant.threads.setStatus",
|
|
@@ -300,7 +315,7 @@ export async function startChatStream(args: {
|
|
|
300
315
|
channel: string;
|
|
301
316
|
thread_ts?: string;
|
|
302
317
|
markdown_text?: string;
|
|
303
|
-
chunks?:
|
|
318
|
+
chunks?: StreamChunk[];
|
|
304
319
|
recipient_user_id?: string;
|
|
305
320
|
recipient_team_id?: string;
|
|
306
321
|
}): Promise<SoftSlackResult<{ ts: string; channel: string }>> {
|
|
@@ -346,7 +361,7 @@ export async function appendChatStream(args: {
|
|
|
346
361
|
channel: string;
|
|
347
362
|
ts: string;
|
|
348
363
|
markdown_text?: string;
|
|
349
|
-
chunks?:
|
|
364
|
+
chunks?: StreamChunk[];
|
|
350
365
|
}): Promise<SoftSlackResult> {
|
|
351
366
|
const body: Record<string, unknown> = {
|
|
352
367
|
channel: args.channel,
|
|
@@ -370,6 +385,7 @@ export async function stopChatStream(args: {
|
|
|
370
385
|
channel: string;
|
|
371
386
|
ts: string;
|
|
372
387
|
markdown_text?: string;
|
|
388
|
+
chunks?: StreamChunk[];
|
|
373
389
|
blocks?: unknown[];
|
|
374
390
|
}): Promise<SoftSlackResult> {
|
|
375
391
|
const body: Record<string, unknown> = {
|
|
@@ -379,6 +395,9 @@ export async function stopChatStream(args: {
|
|
|
379
395
|
if (args.markdown_text !== undefined) {
|
|
380
396
|
body.markdown_text = args.markdown_text;
|
|
381
397
|
}
|
|
398
|
+
if (args.chunks !== undefined && args.chunks.length > 0) {
|
|
399
|
+
body.chunks = args.chunks;
|
|
400
|
+
}
|
|
382
401
|
if (args.blocks !== undefined && args.blocks.length > 0) {
|
|
383
402
|
body.blocks = args.blocks;
|
|
384
403
|
}
|
|
@@ -477,7 +496,7 @@ export async function postMessage(args: {
|
|
|
477
496
|
operation: "chat.postMessage",
|
|
478
497
|
body: {
|
|
479
498
|
...base,
|
|
480
|
-
markdown_text: args.text,
|
|
499
|
+
markdown_text: highlightCodeFences(args.text),
|
|
481
500
|
},
|
|
482
501
|
});
|
|
483
502
|
// Older workspaces / scopes may not accept markdown_text — retry with text.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack highlights a fenced code block only when its info string is a
|
|
3
|
+
* language it knows (`ts`, `python`, …). Models on this harness cite code
|
|
4
|
+
* with Cursor's `startLine:endLine:path` form, or a bare path, which Slack
|
|
5
|
+
* shows verbatim as the block's header with no highlighting. The header is
|
|
6
|
+
* the only slot Slack offers, so a block gets colors by moving the reference
|
|
7
|
+
* to a comment on its first line. Files whose language has no comment
|
|
8
|
+
* syntax, or that Slack cannot color anyway, keep the reference as header.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const FENCE = /^(\s*)(`{3,}|~{3,})(.*)$/;
|
|
12
|
+
/** A line that may still grow into a fence. */
|
|
13
|
+
const FENCE_START = /^\s*(`{1,2}|~{1,2})$/;
|
|
14
|
+
const CITATION = /^(\d+):(\d+):(\S+)$/;
|
|
15
|
+
|
|
16
|
+
const LANGUAGE_BY_EXTENSION: Readonly<Record<string, string>> = {
|
|
17
|
+
ts: "ts",
|
|
18
|
+
mts: "ts",
|
|
19
|
+
cts: "ts",
|
|
20
|
+
tsx: "tsx",
|
|
21
|
+
js: "js",
|
|
22
|
+
mjs: "js",
|
|
23
|
+
cjs: "js",
|
|
24
|
+
jsx: "jsx",
|
|
25
|
+
py: "python",
|
|
26
|
+
go: "go",
|
|
27
|
+
rs: "rust",
|
|
28
|
+
java: "java",
|
|
29
|
+
kt: "kotlin",
|
|
30
|
+
swift: "swift",
|
|
31
|
+
rb: "ruby",
|
|
32
|
+
php: "php",
|
|
33
|
+
c: "c",
|
|
34
|
+
h: "c",
|
|
35
|
+
cc: "cpp",
|
|
36
|
+
cpp: "cpp",
|
|
37
|
+
hpp: "cpp",
|
|
38
|
+
cs: "csharp",
|
|
39
|
+
json: "json",
|
|
40
|
+
jsonc: "jsonc",
|
|
41
|
+
yaml: "yaml",
|
|
42
|
+
yml: "yaml",
|
|
43
|
+
toml: "toml",
|
|
44
|
+
xml: "xml",
|
|
45
|
+
html: "html",
|
|
46
|
+
css: "css",
|
|
47
|
+
scss: "scss",
|
|
48
|
+
md: "markdown",
|
|
49
|
+
mdx: "mdx",
|
|
50
|
+
sh: "bash",
|
|
51
|
+
bash: "bash",
|
|
52
|
+
zsh: "bash",
|
|
53
|
+
sql: "sql",
|
|
54
|
+
proto: "protobuf",
|
|
55
|
+
tf: "hcl",
|
|
56
|
+
graphql: "graphql",
|
|
57
|
+
dockerfile: "dockerfile",
|
|
58
|
+
ini: "ini",
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/** `[open, close]` comment delimiters; languages without one (JSON) are absent. */
|
|
62
|
+
const COMMENT_BY_LANGUAGE: Readonly<Record<string, readonly [string, string]>> =
|
|
63
|
+
{
|
|
64
|
+
ts: ["//", ""],
|
|
65
|
+
tsx: ["//", ""],
|
|
66
|
+
js: ["//", ""],
|
|
67
|
+
jsx: ["//", ""],
|
|
68
|
+
go: ["//", ""],
|
|
69
|
+
rust: ["//", ""],
|
|
70
|
+
java: ["//", ""],
|
|
71
|
+
kotlin: ["//", ""],
|
|
72
|
+
swift: ["//", ""],
|
|
73
|
+
php: ["//", ""],
|
|
74
|
+
c: ["//", ""],
|
|
75
|
+
cpp: ["//", ""],
|
|
76
|
+
csharp: ["//", ""],
|
|
77
|
+
jsonc: ["//", ""],
|
|
78
|
+
protobuf: ["//", ""],
|
|
79
|
+
python: ["#", ""],
|
|
80
|
+
ruby: ["#", ""],
|
|
81
|
+
yaml: ["#", ""],
|
|
82
|
+
toml: ["#", ""],
|
|
83
|
+
bash: ["#", ""],
|
|
84
|
+
dockerfile: ["#", ""],
|
|
85
|
+
ini: ["#", ""],
|
|
86
|
+
hcl: ["#", ""],
|
|
87
|
+
graphql: ["#", ""],
|
|
88
|
+
sql: ["--", ""],
|
|
89
|
+
css: ["/*", "*/"],
|
|
90
|
+
scss: ["/*", "*/"],
|
|
91
|
+
html: ["<!--", "-->"],
|
|
92
|
+
xml: ["<!--", "-->"],
|
|
93
|
+
markdown: ["<!--", "-->"],
|
|
94
|
+
mdx: ["<!--", "-->"],
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
function languageForPath(path: string): string | undefined {
|
|
98
|
+
const base = path.slice(path.lastIndexOf("/") + 1).toLowerCase();
|
|
99
|
+
const ext = base.includes(".") ? base.slice(base.lastIndexOf(".") + 1) : base;
|
|
100
|
+
return LANGUAGE_BY_EXTENSION[ext];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function looksLikePath(info: string): boolean {
|
|
104
|
+
return info.includes("/") || languageForPath(info) !== undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Replacement lines for an opening fence whose info string is a citation or
|
|
109
|
+
* a path: the fence tagged with the language, then the reference as a
|
|
110
|
+
* comment. Falls back to the reference as the header when the block cannot
|
|
111
|
+
* carry a comment. `null` when the info string is neither.
|
|
112
|
+
*/
|
|
113
|
+
function rewriteOpening(
|
|
114
|
+
indent: string,
|
|
115
|
+
marks: string,
|
|
116
|
+
info: string
|
|
117
|
+
): string[] | null {
|
|
118
|
+
const token = info.trim().split(/\s+/)[0] ?? "";
|
|
119
|
+
const cited = CITATION.exec(token);
|
|
120
|
+
const path = cited?.[3] ?? (looksLikePath(token) ? token : undefined);
|
|
121
|
+
if (path === undefined) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const reference = cited === null ? path : `${path}:${cited[1]}-${cited[2]}`;
|
|
125
|
+
const language = languageForPath(path);
|
|
126
|
+
const comment =
|
|
127
|
+
language === undefined ? undefined : COMMENT_BY_LANGUAGE[language];
|
|
128
|
+
if (comment === undefined) {
|
|
129
|
+
return [`${indent}${marks}${reference}`];
|
|
130
|
+
}
|
|
131
|
+
const [open, close] = comment;
|
|
132
|
+
const commented =
|
|
133
|
+
close === "" ? `${open} ${reference}` : `${open} ${reference} ${close}`;
|
|
134
|
+
return [`${indent}${marks}${language}`, `${indent}${commented}`];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Rewrite fence info strings so Slack highlights the block. Safe to run on
|
|
139
|
+
* a growing stream: the output for a prefix is a prefix of the output for
|
|
140
|
+
* the full text, because an opening fence whose line has not ended yet is
|
|
141
|
+
* held back rather than emitted half-formed.
|
|
142
|
+
*/
|
|
143
|
+
export function highlightCodeFences(markdown: string): string {
|
|
144
|
+
const complete = markdown.endsWith("\n");
|
|
145
|
+
const lines = markdown.split("\n");
|
|
146
|
+
if (complete) {
|
|
147
|
+
lines.pop();
|
|
148
|
+
}
|
|
149
|
+
const out: string[] = [];
|
|
150
|
+
let open: { marks: string } | null = null;
|
|
151
|
+
const heldBack = (): string =>
|
|
152
|
+
`${out.join("\n")}${out.length > 0 ? "\n" : ""}`;
|
|
153
|
+
for (const [index, line] of lines.entries()) {
|
|
154
|
+
const last = index === lines.length - 1 && !complete;
|
|
155
|
+
const fence = FENCE.exec(line);
|
|
156
|
+
if (fence === null) {
|
|
157
|
+
if (last && open === null && FENCE_START.test(line)) {
|
|
158
|
+
return heldBack();
|
|
159
|
+
}
|
|
160
|
+
out.push(line);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const [, indent = "", marks = "", info = ""] = fence;
|
|
164
|
+
if (open !== null) {
|
|
165
|
+
if (
|
|
166
|
+
marks[0] === open.marks[0] &&
|
|
167
|
+
marks.length >= open.marks.length &&
|
|
168
|
+
info.trim() === ""
|
|
169
|
+
) {
|
|
170
|
+
open = null;
|
|
171
|
+
}
|
|
172
|
+
out.push(line);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (last) {
|
|
176
|
+
// Opening fence still being written: wait for the whole line.
|
|
177
|
+
return heldBack();
|
|
178
|
+
}
|
|
179
|
+
open = { marks };
|
|
180
|
+
out.push(...(rewriteOpening(indent, marks, info) ?? [line]));
|
|
181
|
+
}
|
|
182
|
+
return complete ? `${out.join("\n")}\n` : out.join("\n");
|
|
183
|
+
}
|
|
@@ -13,6 +13,12 @@ export const SLACK_LOADING_MESSAGE_MAX_LEN = 50;
|
|
|
13
13
|
/** Slack `assistant.threads.setStatus` accepts at most 5 `loading_messages`. */
|
|
14
14
|
export const SLACK_LOADING_MESSAGES_MAX = 5;
|
|
15
15
|
export const SLACK_TITLE_MAX_LEN = 80;
|
|
16
|
+
/**
|
|
17
|
+
* `markdown_text` (and so a streamed message, cards included) tops out near
|
|
18
|
+
* 12k characters; past it Slack answers `msg_too_long`. Plain `text` allows
|
|
19
|
+
* about 40k.
|
|
20
|
+
*/
|
|
21
|
+
export const SLACK_MARKDOWN_TEXT_MAX_LEN = 12_000;
|
|
16
22
|
|
|
17
23
|
/** Rotating assistant status lines (Slack `loading_messages`). */
|
|
18
24
|
export const SLACK_DEFAULT_LOADING_MESSAGES = [
|