@cursor/july 0.1.97 → 0.1.100
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 +5 -3
- package/dist/bin/agent-serve.js +6 -7
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +28 -3
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +16 -0
- package/dist/channels/github/progress.d.ts +7 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.d.ts +2 -0
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +37 -4
- 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 +29 -13
- 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 +221 -122
- 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 +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/live-delivery.d.ts +6 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +110 -20
- package/dist/channels/slack/progress-delivery.d.ts +28 -0
- package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
- package/dist/channels/slack/progress-delivery.js +115 -0
- package/dist/channels/slack/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 +154 -7
- package/dist/channels/slack/types.d.ts.map +1 -1
- 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.B3rWNYE1.js → app.DZ1e0Ycq.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.j70vvPL4.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.C1lhqJJR.js → VPLocalSearchBox.l8omwc6D.js} +1 -1
- package/dist/docs/assets/chunks/{theme.B40_SXuv.js → theme.JVcD6gel.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_cli.md.RyZf5OTE.js → reference_cli.md.DfoeyvL0.js} +4 -4
- package/dist/docs/assets/{reference_cli.md.RyZf5OTE.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.BiGoBAk2.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.5zOAbV86.js → reference_http-api.md.BEJx9XVj.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.B84gw9Ii.js → reference_tools.md.CvAHsdSp.js} +10 -2
- package/dist/docs/assets/{reference_tools.md.B84gw9Ii.lean.js → reference_tools.md.CvAHsdSp.lean.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/design/runtime-abstraction.md +1757 -0
- 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 +2830 -37
- package/dist/docs/llms.txt +15 -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 +7 -7
- package/dist/docs/reference/cli.md +1 -7
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/connections.md +1 -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 -0
- 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 +14 -6
- package/dist/docs/reference/tools.md +25 -0
- 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/files-backends/cursor-hosted.d.ts +9 -2
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +9 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/as-of.d.ts +19 -0
- package/dist/internal/as-of.d.ts.map +1 -0
- package/dist/internal/as-of.js +82 -0
- package/dist/internal/cli-deploy.d.ts +2 -1
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +102 -7
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +3 -4
- 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-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +5 -6
- package/dist/internal/deploy-client.d.ts +6 -6
- package/dist/internal/deploy-client.js +7 -7
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +11 -1
- package/dist/internal/framework-file-storage.d.ts +5 -4
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +6 -4
- package/dist/internal/framework-storage-selection.d.ts +13 -11
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +28 -23
- package/dist/internal/hosted-admission-adapter.d.ts +28 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
- package/dist/internal/hosted-admission-adapter.js +7 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +6 -1
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +1 -1
- package/dist/internal/hosted-delivery.d.ts +15 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +47 -21
- package/dist/internal/hosted-execution-diag.d.ts +11 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +39 -2
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +4 -1
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +82 -19
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +24 -4
- package/dist/internal/session-run-log.d.ts +120 -0
- package/dist/internal/session-run-log.d.ts.map +1 -0
- package/dist/internal/session-run-log.js +358 -0
- package/dist/internal/tool-policy.d.ts +20 -8
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +11 -0
- package/dist/playground/assets/index-BszoQDc6.css +1 -0
- package/dist/playground/assets/index-DVs98vPL.js +69 -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 +8 -0
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +8 -0
- package/dist/tools.d.ts +12 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/ab.md +1 -1
- package/docs/building-with-agents.md +14 -11
- package/docs/design/runtime-abstraction.md +1757 -0
- 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/cli.md +1 -7
- package/docs/reference/connections.md +1 -1
- package/docs/reference/http-api.md +1 -0
- package/docs/reference/tools.md +25 -0
- package/docs/scaffolding-agents.md +3 -3
- package/docs/skills/index.md +26 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +1 -1
- package/src/bin/agent-serve.ts +6 -7
- package/src/channels/github/defaults.ts +36 -3
- package/src/channels/github/github-channel.ts +17 -0
- package/src/channels/github/progress.ts +7 -0
- package/src/channels/origin/origin-channel.ts +74 -10
- package/src/channels/slack/api.ts +35 -17
- package/src/channels/slack/constants.ts +6 -0
- package/src/channels/slack/defaults.ts +253 -144
- package/src/channels/slack/dispatch.ts +10 -1
- package/src/channels/slack/inbound.ts +17 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/live-delivery.ts +135 -22
- package/src/channels/slack/progress-delivery.ts +133 -0
- 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 +168 -7
- package/src/files-backends/cursor-hosted.ts +18 -7
- package/src/index.ts +4 -0
- package/src/internal/as-of.ts +107 -0
- package/src/internal/cli-deploy.ts +130 -10
- package/src/internal/conversation-mirror.ts +3 -8
- package/src/internal/cursor/hosted-store-secrets.ts +72 -0
- package/src/internal/cursor-event-relay.ts +5 -6
- package/src/internal/deploy-client.ts +10 -10
- package/src/internal/discovery.ts +9 -1
- package/src/internal/framework-file-storage.ts +6 -4
- package/src/internal/framework-storage-selection.ts +28 -25
- package/src/internal/hosted-admission-adapter.ts +42 -0
- package/src/internal/hosted-delivery-protocol.ts +7 -2
- package/src/internal/hosted-delivery.ts +88 -36
- package/src/internal/hosted-execution-diag.ts +45 -0
- package/src/internal/http-channel.ts +8 -0
- package/src/internal/server.ts +100 -2
- package/src/internal/session-engine.ts +32 -1
- package/src/internal/session-run-log.ts +579 -0
- package/src/internal/tool-policy.ts +31 -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 +10 -0
- package/src/tools.ts +12 -2
- package/src/types.ts +30 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.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/playground/assets/index-DrkI6y5O.js +0 -88
- package/dist/playground/assets/index-DzNGwm7q.css +0 -1
- /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_connections.md.DxldvyIB.lean.js → reference_connections.md.BiGoBAk2.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.5zOAbV86.lean.js → reference_http-api.md.BEJx9XVj.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,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 ?? {};
|
|
@@ -4,11 +4,36 @@
|
|
|
4
4
|
|
|
5
5
|
export type StreamTaskStatus = "pending" | "in_progress" | "complete" | "error";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* One update to a task card. Slack keeps one card per `id`: `title` and
|
|
9
|
+
* `status` replace the previous values, `details` and `output` are appended
|
|
10
|
+
* to what the card already shows.
|
|
11
|
+
*/
|
|
7
12
|
export interface StreamTaskChunk {
|
|
8
13
|
type: "task_update";
|
|
9
14
|
id: string;
|
|
10
15
|
title: string;
|
|
11
16
|
status: StreamTaskStatus;
|
|
17
|
+
details?: string;
|
|
18
|
+
output?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface StreamMarkdownChunk {
|
|
22
|
+
type: "markdown_text";
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A `chat.*Stream` chunk. Slack fixes a stream's mode at `chat.startStream`:
|
|
28
|
+
* one opened with bare `markdown_text` rejects every later `chunks` append
|
|
29
|
+
* (`streaming_mode_mismatch`), and vice versa. The live-delivery strategy
|
|
30
|
+
* therefore always speaks chunks, wrapping text as `markdown_text` chunks so
|
|
31
|
+
* tool-step `task_update`s can share the same message.
|
|
32
|
+
*/
|
|
33
|
+
export type StreamChunk = StreamMarkdownChunk | StreamTaskChunk;
|
|
34
|
+
|
|
35
|
+
export function markdownChunk(text: string): StreamMarkdownChunk {
|
|
36
|
+
return { type: "markdown_text", text };
|
|
12
37
|
}
|
|
13
38
|
|
|
14
39
|
/**
|
|
@@ -36,28 +61,10 @@ export function computeStreamAppend(
|
|
|
36
61
|
return "";
|
|
37
62
|
}
|
|
38
63
|
|
|
39
|
-
/**
|
|
40
|
-
export function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return
|
|
45
|
-
type: "task_update" as const,
|
|
46
|
-
id: call.callId,
|
|
47
|
-
title: call.toolName,
|
|
48
|
-
status,
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function buildTaskChunkForResult(args: {
|
|
53
|
-
callId: string;
|
|
54
|
-
toolName: string;
|
|
55
|
-
isError: boolean;
|
|
56
|
-
}): StreamTaskChunk {
|
|
57
|
-
return {
|
|
58
|
-
type: "task_update",
|
|
59
|
-
id: args.callId,
|
|
60
|
-
title: args.toolName,
|
|
61
|
-
status: args.isError ? "error" : "complete",
|
|
62
|
-
};
|
|
64
|
+
/** Clamp to `max` characters, ending in an ellipsis when cut. */
|
|
65
|
+
export function truncateCardText(text: string, max: number): string {
|
|
66
|
+
if (text.length <= max) {
|
|
67
|
+
return text;
|
|
68
|
+
}
|
|
69
|
+
return `${text.slice(0, max - 1)}…`;
|
|
63
70
|
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task cards for tool calls inside the streamed reply. One card per key:
|
|
3
|
+
* the call id for `per-call`, the tool name for `per-tool`. A card's title
|
|
4
|
+
* counts its calls and its status follows the whole group; with one call
|
|
5
|
+
* per key that reduces to the plain per-call card.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { redactSecretTokens } from "./redact.js";
|
|
9
|
+
import type { ResolvedSlackToolCards } from "./reply-options.js";
|
|
10
|
+
import { type StreamTaskChunk, truncateCardText } from "./stream.js";
|
|
11
|
+
import type {
|
|
12
|
+
SlackChannelState,
|
|
13
|
+
SlackToolCall,
|
|
14
|
+
SlackToolResult,
|
|
15
|
+
ToolCardCount,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
|
|
18
|
+
/** The argument the playground puts in a built-in tool's header. */
|
|
19
|
+
const TOOL_PRIMARY_ARGS: Readonly<Record<string, readonly string[]>> = {
|
|
20
|
+
grep: ["pattern"],
|
|
21
|
+
glob: ["glob_pattern", "globPattern"],
|
|
22
|
+
read: ["path", "file_path", "target_file"],
|
|
23
|
+
shell: ["command", "cmd"],
|
|
24
|
+
task: ["description", "prompt"],
|
|
25
|
+
};
|
|
26
|
+
/** For other tools: the telling key, if any. */
|
|
27
|
+
const GENERIC_PRIMARY_ARGS = [
|
|
28
|
+
"pattern",
|
|
29
|
+
"query",
|
|
30
|
+
"command",
|
|
31
|
+
"cmd",
|
|
32
|
+
"path",
|
|
33
|
+
"file",
|
|
34
|
+
"file_path",
|
|
35
|
+
"target_file",
|
|
36
|
+
"url",
|
|
37
|
+
"prompt",
|
|
38
|
+
"description",
|
|
39
|
+
"name",
|
|
40
|
+
"message",
|
|
41
|
+
];
|
|
42
|
+
const PATH_ARGS = new Set([
|
|
43
|
+
"path",
|
|
44
|
+
"file",
|
|
45
|
+
"file_path",
|
|
46
|
+
"target_file",
|
|
47
|
+
"target_directory",
|
|
48
|
+
"targetDirectory",
|
|
49
|
+
]);
|
|
50
|
+
const LINE_MAX = 80;
|
|
51
|
+
const JSON_MAX = 120;
|
|
52
|
+
|
|
53
|
+
function oneLine(text: string, max: number): string {
|
|
54
|
+
return truncateCardText(
|
|
55
|
+
redactSecretTokens(text).replace(/\s+/g, " ").trim(),
|
|
56
|
+
max
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Clamp the middle so both ends stay visible; tail-biased to keep filenames. */
|
|
61
|
+
function clampPath(text: string, max: number): string {
|
|
62
|
+
const one = redactSecretTokens(text).replace(/\s+/g, " ").trim();
|
|
63
|
+
if (one.length <= max) {
|
|
64
|
+
return one;
|
|
65
|
+
}
|
|
66
|
+
const budget = max - 1;
|
|
67
|
+
const head = Math.max(1, Math.floor(budget * 0.35));
|
|
68
|
+
const tail = Math.max(1, budget - head);
|
|
69
|
+
return `${one.slice(0, head)}…${one.slice(one.length - tail)}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Default tool-card line for a call, matching the playground's tool header:
|
|
74
|
+
* the grep pattern, the glob pattern, the file path, the shell command. Other
|
|
75
|
+
* tools show a lone string argument bare, else compact JSON. No key labels,
|
|
76
|
+
* no knobs like `headLimit`.
|
|
77
|
+
*/
|
|
78
|
+
export function defaultToolCardDetails(
|
|
79
|
+
call: SlackToolCall
|
|
80
|
+
): string | undefined {
|
|
81
|
+
const args = call.args;
|
|
82
|
+
if (args === undefined || args === null) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
if (typeof args === "string") {
|
|
86
|
+
const line = oneLine(args, LINE_MAX);
|
|
87
|
+
return line === "" ? undefined : line;
|
|
88
|
+
}
|
|
89
|
+
if (typeof args !== "object" || Array.isArray(args)) {
|
|
90
|
+
return oneLine(JSON.stringify(args), JSON_MAX);
|
|
91
|
+
}
|
|
92
|
+
const record = args as Record<string, unknown>;
|
|
93
|
+
for (const key of TOOL_PRIMARY_ARGS[call.toolName] ?? GENERIC_PRIMARY_ARGS) {
|
|
94
|
+
const value = record[key];
|
|
95
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
96
|
+
return PATH_ARGS.has(key)
|
|
97
|
+
? clampPath(value, LINE_MAX)
|
|
98
|
+
: oneLine(value, LINE_MAX);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const entries = Object.entries(record);
|
|
102
|
+
if (entries.length === 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const lone = entries.length === 1 ? entries[0]?.[1] : undefined;
|
|
106
|
+
if (typeof lone === "string" && lone.trim() !== "") {
|
|
107
|
+
return oneLine(lone, LINE_MAX);
|
|
108
|
+
}
|
|
109
|
+
return oneLine(JSON.stringify(record), JSON_MAX);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface ToolCards {
|
|
113
|
+
forCalls(
|
|
114
|
+
state: SlackChannelState,
|
|
115
|
+
calls: readonly SlackToolCall[]
|
|
116
|
+
): StreamTaskChunk[];
|
|
117
|
+
forResult(state: SlackChannelState, result: SlackToolResult): StreamTaskChunk;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function tallyFor(state: SlackChannelState, key: string): ToolCardCount {
|
|
121
|
+
if (state.toolCardCounts === undefined) {
|
|
122
|
+
state.toolCardCounts = {};
|
|
123
|
+
}
|
|
124
|
+
const existing = state.toolCardCounts[key];
|
|
125
|
+
if (existing !== undefined) {
|
|
126
|
+
return existing;
|
|
127
|
+
}
|
|
128
|
+
const created: ToolCardCount = { started: 0, done: 0, errors: 0 };
|
|
129
|
+
state.toolCardCounts[key] = created;
|
|
130
|
+
return created;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Slack appends each update's text to the card verbatim, so a group's later
|
|
135
|
+
* batch of lines brings its own line break.
|
|
136
|
+
*/
|
|
137
|
+
function appendLines(
|
|
138
|
+
tally: ToolCardCount,
|
|
139
|
+
field: "details" | "output",
|
|
140
|
+
lines: readonly string[]
|
|
141
|
+
): string | undefined {
|
|
142
|
+
if (lines.length === 0) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
const already = tally[field] ?? 0;
|
|
146
|
+
tally[field] = already + lines.length;
|
|
147
|
+
return `${already > 0 ? "\n" : ""}${lines.join("\n")}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function present(line: string | undefined): line is string {
|
|
151
|
+
return line !== undefined && line !== "";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function createToolCards(
|
|
155
|
+
cards: ResolvedSlackToolCards,
|
|
156
|
+
toolLabel: (toolName: string) => string
|
|
157
|
+
): ToolCards {
|
|
158
|
+
const keyOf = (call: { callId: string; toolName: string }): string =>
|
|
159
|
+
cards.group === "per-call" ? call.callId : `tool:${call.toolName}`;
|
|
160
|
+
const title = (toolName: string, started: number): string => {
|
|
161
|
+
const label = toolLabel(toolName);
|
|
162
|
+
return started > 1 ? `${label} ×${started}` : label;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
forCalls(state, calls) {
|
|
167
|
+
const groups = new Map<string, SlackToolCall[]>();
|
|
168
|
+
for (const call of calls) {
|
|
169
|
+
const key = keyOf(call);
|
|
170
|
+
groups.set(key, [...(groups.get(key) ?? []), call]);
|
|
171
|
+
}
|
|
172
|
+
return [...groups.entries()].map(([key, group]) => {
|
|
173
|
+
const tally = tallyFor(state, key);
|
|
174
|
+
tally.started += group.length;
|
|
175
|
+
const chunk: StreamTaskChunk = {
|
|
176
|
+
type: "task_update",
|
|
177
|
+
id: key,
|
|
178
|
+
title: title(group[0]!.toolName, tally.started),
|
|
179
|
+
status: "in_progress",
|
|
180
|
+
};
|
|
181
|
+
const details = appendLines(
|
|
182
|
+
tally,
|
|
183
|
+
"details",
|
|
184
|
+
group.map((call) => cards.details?.(call)).filter(present)
|
|
185
|
+
);
|
|
186
|
+
if (details !== undefined) {
|
|
187
|
+
chunk.details = details;
|
|
188
|
+
}
|
|
189
|
+
return chunk;
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
forResult(state, result) {
|
|
194
|
+
const tally = tallyFor(state, keyOf(result));
|
|
195
|
+
tally.done += 1;
|
|
196
|
+
if (result.isError) {
|
|
197
|
+
tally.errors += 1;
|
|
198
|
+
}
|
|
199
|
+
const chunk: StreamTaskChunk = {
|
|
200
|
+
type: "task_update",
|
|
201
|
+
id: keyOf(result),
|
|
202
|
+
title: title(result.toolName, tally.started),
|
|
203
|
+
status:
|
|
204
|
+
tally.done < tally.started
|
|
205
|
+
? "in_progress"
|
|
206
|
+
: tally.errors > 0
|
|
207
|
+
? "error"
|
|
208
|
+
: "complete",
|
|
209
|
+
};
|
|
210
|
+
const output = appendLines(
|
|
211
|
+
tally,
|
|
212
|
+
"output",
|
|
213
|
+
[cards.output?.(result)].filter(present)
|
|
214
|
+
);
|
|
215
|
+
if (output !== undefined) {
|
|
216
|
+
chunk.output = output;
|
|
217
|
+
}
|
|
218
|
+
return chunk;
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|