@cursor/july 0.1.99 → 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 +4 -2
- 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/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 +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 +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 +5 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +107 -19
- 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/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.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.CHXyv4wP.js → VPLocalSearchBox.l8omwc6D.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BTcsZmjQ.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_connections.md.DxldvyIB.js → reference_connections.md.BiGoBAk2.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 +1041 -30
- 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 +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 +4 -4
- 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/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/internal/cli-deploy.js +2 -2
- 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/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 +12 -5
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +36 -5
- 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/session-run-log.d.ts +3 -3
- package/dist/internal/session-run-log.d.ts.map +1 -1
- package/dist/internal/session-run-log.js +6 -7
- 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/playground/assets/index-BszoQDc6.css +1 -0
- package/dist/playground/assets/{index-jzNbJENa.js → index-DVs98vPL.js} +1 -1
- 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/types.d.ts +5 -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/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 +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 +1 -1
- package/src/channels/github/defaults.ts +36 -3
- package/src/channels/github/progress.ts +7 -0
- package/src/channels/slack/api.ts +35 -17
- 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 +1 -0
- package/src/channels/slack/live-delivery.ts +131 -20
- 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/files-backends/cursor-hosted.ts +15 -5
- package/src/internal/cli-deploy.ts +2 -2
- package/src/internal/conversation-mirror.ts +3 -8
- package/src/internal/cursor/hosted-store-secrets.ts +72 -0
- package/src/internal/deploy-client.ts +10 -10
- package/src/internal/discovery.ts +9 -1
- package/src/internal/framework-file-storage.ts +41 -5
- package/src/internal/framework-storage-selection.ts +31 -44
- package/src/internal/session-run-log.ts +6 -11
- package/src/internal/storage-coordinator.ts +1 -11
- package/src/storage-backends/cursor-hosted-v2.ts +219 -0
- package/src/storage-backends/cursor-hosted.ts +6 -1
- package/src/types.ts +5 -0
- 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_connections.md.DxldvyIB.lean.js → reference_connections.md.BiGoBAk2.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* Assistant-pane threads only render stream APIs. Start lazily with the
|
|
9
9
|
* first real markdown/chunks plus recipient ids — empty startStream is
|
|
10
10
|
* rejected or never attaches.
|
|
11
|
+
*
|
|
12
|
+
* Every call speaks `chunks`. Slack pins a stream's mode at start: text
|
|
13
|
+
* opened as bare `markdown_text` rejects later `task_update` appends with
|
|
14
|
+
* `streaming_mode_mismatch`, so assistant text goes out as `markdown_text`
|
|
15
|
+
* chunks and tool steps can land in the same message.
|
|
11
16
|
*/
|
|
12
17
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
18
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -18,8 +23,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
18
23
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
24
|
});
|
|
20
25
|
};
|
|
21
|
-
import { appendChatStream, startChatStream, stopChatStream } from "./api.js";
|
|
22
|
-
import {
|
|
26
|
+
import { appendChatStream, postMessage, startChatStream, stopChatStream, } from "./api.js";
|
|
27
|
+
import { SLACK_MARKDOWN_TEXT_MAX_LEN } from "./constants.js";
|
|
28
|
+
import { computeStreamAppend, markdownChunk, } from "./stream.js";
|
|
23
29
|
function streamRecipients(channel) {
|
|
24
30
|
const user = channel.state.triggeringUserId;
|
|
25
31
|
const team = channel.state.teamId;
|
|
@@ -38,13 +44,17 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
38
44
|
if (activeStreamTs(channel) !== null) {
|
|
39
45
|
return true;
|
|
40
46
|
}
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
47
|
+
const openingText = markdown_text !== null && markdown_text !== void 0 ? markdown_text : "";
|
|
48
|
+
const opening = [];
|
|
49
|
+
if (openingText !== "") {
|
|
50
|
+
opening.push(markdownChunk(openingText));
|
|
51
|
+
}
|
|
52
|
+
opening.push(...(chunks !== null && chunks !== void 0 ? chunks : []));
|
|
53
|
+
if (opening.length === 0) {
|
|
44
54
|
return false;
|
|
45
55
|
}
|
|
46
56
|
const log = getLog();
|
|
47
|
-
const started = yield startChatStream(Object.assign({ botToken, channel: channelId, thread_ts: threadTs,
|
|
57
|
+
const started = yield startChatStream(Object.assign({ botToken, channel: channelId, thread_ts: threadTs, chunks: opening }, streamRecipients(channel)));
|
|
48
58
|
if (!started.ok) {
|
|
49
59
|
log.warn("chat.startStream unavailable", {
|
|
50
60
|
error: started.error,
|
|
@@ -59,8 +69,9 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
59
69
|
}
|
|
60
70
|
channel.state.streamTs = started.ts;
|
|
61
71
|
channel.state.streamChannelId = started.channel;
|
|
62
|
-
channel.state.
|
|
63
|
-
channel.state.
|
|
72
|
+
channel.state.streamFull = false;
|
|
73
|
+
channel.state.lastPostedText = openingText;
|
|
74
|
+
channel.state.streamBlockText = openingText;
|
|
64
75
|
log.info("chat.startStream ok", {
|
|
65
76
|
channel: started.channel,
|
|
66
77
|
stream_ts: started.ts,
|
|
@@ -93,7 +104,7 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
93
104
|
botToken,
|
|
94
105
|
channel: args.channelId,
|
|
95
106
|
ts: args.ts,
|
|
96
|
-
|
|
107
|
+
chunks: appendText === "" ? undefined : [markdownChunk(appendText)],
|
|
97
108
|
});
|
|
98
109
|
args.channel.state.streamTs = null;
|
|
99
110
|
if (stopped.ok) {
|
|
@@ -116,11 +127,67 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
116
127
|
yield stopChatStream({ botToken, channel: channelId, ts: orphanTs });
|
|
117
128
|
channel.state.streamTs = null;
|
|
118
129
|
});
|
|
130
|
+
/**
|
|
131
|
+
* `msg_too_long` means the message is full: every further append would
|
|
132
|
+
* fail the same way, so appends stop until `finalize` continues the reply
|
|
133
|
+
* in a new message.
|
|
134
|
+
*/
|
|
135
|
+
const noteAppendFailure = (channel, result) => {
|
|
136
|
+
if (result.unsupported === true) {
|
|
137
|
+
channel.state.streamingUnavailable = true;
|
|
138
|
+
}
|
|
139
|
+
if (result.error === "msg_too_long") {
|
|
140
|
+
channel.state.streamFull = true;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* The streamed message is full. Close it as it stands so it stops spinning
|
|
145
|
+
* and post the rest as a new thread message. Most of the answer is on Slack
|
|
146
|
+
* either way, so the reply counts as delivered even if that post fails: a
|
|
147
|
+
* duplicate would be worse than a lost tail.
|
|
148
|
+
*/
|
|
149
|
+
const continueOverflow = (args) => __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
const { channel, channelId, ts, remainder, sessionId } = args;
|
|
151
|
+
const log = getLog();
|
|
152
|
+
yield stopChatStream({ botToken, channel: channelId, ts });
|
|
153
|
+
channel.state.streamTs = null;
|
|
154
|
+
const threadTs = channel.state.threadTs;
|
|
155
|
+
if (remainder === "" || threadTs === null || threadTs === "") {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const posted = yield postMessage({
|
|
160
|
+
botToken,
|
|
161
|
+
channel: channelId,
|
|
162
|
+
text: remainder,
|
|
163
|
+
threadTs,
|
|
164
|
+
plainText: remainder.length >= SLACK_MARKDOWN_TEXT_MAX_LEN,
|
|
165
|
+
});
|
|
166
|
+
channel.state.lastBotMessageTs = posted.ts;
|
|
167
|
+
log.info("reply overflowed the stream; continued in a new message", {
|
|
168
|
+
channel: channelId,
|
|
169
|
+
stream_ts: ts,
|
|
170
|
+
session: sessionId,
|
|
171
|
+
continued_chars: remainder.length,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
log.warn("stream overflow continuation failed", {
|
|
176
|
+
error: error instanceof Error ? error.message : String(error),
|
|
177
|
+
channel: channelId,
|
|
178
|
+
stream_ts: ts,
|
|
179
|
+
session: sessionId,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
119
183
|
return {
|
|
120
184
|
inlineToolSteps: true,
|
|
121
185
|
open,
|
|
122
186
|
append(_a) {
|
|
123
187
|
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, text, sessionId }) {
|
|
188
|
+
if (channel.state.streamFull === true) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
124
191
|
const ts = yield ensureOpen({
|
|
125
192
|
channel,
|
|
126
193
|
channelId,
|
|
@@ -138,7 +205,7 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
138
205
|
botToken,
|
|
139
206
|
channel: channelId,
|
|
140
207
|
ts,
|
|
141
|
-
|
|
208
|
+
chunks: [markdownChunk(appendText)],
|
|
142
209
|
});
|
|
143
210
|
if (!result.ok) {
|
|
144
211
|
getLog().warn("appendStream failed", {
|
|
@@ -147,9 +214,7 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
147
214
|
stream_ts: ts,
|
|
148
215
|
session: sessionId,
|
|
149
216
|
});
|
|
150
|
-
|
|
151
|
-
channel.state.streamingUnavailable = true;
|
|
152
|
-
}
|
|
217
|
+
noteAppendFailure(channel, result);
|
|
153
218
|
return;
|
|
154
219
|
}
|
|
155
220
|
channel.state.lastPostedText = text;
|
|
@@ -158,6 +223,9 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
158
223
|
},
|
|
159
224
|
appendChunks(_a) {
|
|
160
225
|
return __awaiter(this, arguments, void 0, function* ({ channel, channelId, chunks, sessionId }) {
|
|
226
|
+
if (channel.state.streamFull === true) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
161
229
|
const hadStream = activeStreamTs(channel) !== null;
|
|
162
230
|
const ts = yield ensureOpen({
|
|
163
231
|
channel,
|
|
@@ -177,6 +245,16 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
177
245
|
ts,
|
|
178
246
|
chunks,
|
|
179
247
|
});
|
|
248
|
+
if (!result.ok) {
|
|
249
|
+
getLog().warn("appendStream chunks failed", {
|
|
250
|
+
error: result.error,
|
|
251
|
+
channel: channelId,
|
|
252
|
+
stream_ts: ts,
|
|
253
|
+
session: sessionId,
|
|
254
|
+
chunks: chunks.length,
|
|
255
|
+
});
|
|
256
|
+
noteAppendFailure(channel, result);
|
|
257
|
+
}
|
|
180
258
|
return result.ok;
|
|
181
259
|
});
|
|
182
260
|
},
|
|
@@ -192,12 +270,11 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
192
270
|
if (ts === null) {
|
|
193
271
|
return { delivered: false };
|
|
194
272
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
text
|
|
200
|
-
});
|
|
273
|
+
// Measured before the stop attempt mutates stream state.
|
|
274
|
+
const remainder = computeStreamAppend(channel.state.streamBlockText, text);
|
|
275
|
+
const stopped = channel.state.streamFull === true
|
|
276
|
+
? { ok: false, error: "msg_too_long" }
|
|
277
|
+
: yield stopWithSuffix({ channel, channelId, ts, text });
|
|
201
278
|
if (stopped.ok) {
|
|
202
279
|
log.info("reply delivered via stream", {
|
|
203
280
|
channel: channelId,
|
|
@@ -207,6 +284,17 @@ export function createStreamDeliveryStrategy(deps) {
|
|
|
207
284
|
});
|
|
208
285
|
return { delivered: true };
|
|
209
286
|
}
|
|
287
|
+
if (stopped.error === "msg_too_long") {
|
|
288
|
+
yield continueOverflow({
|
|
289
|
+
channel,
|
|
290
|
+
channelId,
|
|
291
|
+
ts,
|
|
292
|
+
remainder,
|
|
293
|
+
sessionId,
|
|
294
|
+
});
|
|
295
|
+
channel.state.lastPostedText = text;
|
|
296
|
+
return { delivered: true };
|
|
297
|
+
}
|
|
210
298
|
log.warn("chat.stopStream failed; falling back to postMessage", {
|
|
211
299
|
error: stopped.error,
|
|
212
300
|
channel: channelId,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "Thinking" task card that receives the model's reasoning as it streams.
|
|
3
|
+
* Slack appends a card's `details` across updates, so the card is fed
|
|
4
|
+
* deltas: the part of the current reasoning block already on Slack, plus a
|
|
5
|
+
* buffer of what has not gone out yet.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChannelEventContext } from "../../types.js";
|
|
8
|
+
import type { ResolvedSlackReasoningCard } from "./reply-options.js";
|
|
9
|
+
import { type StreamTaskChunk } from "./stream.js";
|
|
10
|
+
import type { SlackChannelState } from "./types.js";
|
|
11
|
+
type Channel = ChannelEventContext<SlackChannelState>;
|
|
12
|
+
type CardStatus = "in_progress" | "complete";
|
|
13
|
+
export interface ReasoningCard {
|
|
14
|
+
/** Buffer the current reasoning block's cumulative text; flushes when due. */
|
|
15
|
+
append(args: {
|
|
16
|
+
channel: Channel;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
text: string;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
/** Send buffered text and set the card status. */
|
|
21
|
+
flush(args: {
|
|
22
|
+
channel: Channel;
|
|
23
|
+
sessionId: string;
|
|
24
|
+
status: CardStatus;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
/** The next reasoning block appends after a blank line. */
|
|
27
|
+
endBlock(channel: Channel): void;
|
|
28
|
+
inProgress(channel: Channel): boolean;
|
|
29
|
+
}
|
|
30
|
+
/** Delivers one chunk into the reply stream; `false` when nothing went out. */
|
|
31
|
+
export type SendCardChunk = (args: {
|
|
32
|
+
channel: Channel;
|
|
33
|
+
sessionId: string;
|
|
34
|
+
chunk: StreamTaskChunk;
|
|
35
|
+
}) => Promise<boolean>;
|
|
36
|
+
export declare function createReasoningCard(card: ResolvedSlackReasoningCard, send: SendCardChunk): ReasoningCard;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=reasoning-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-card.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/reasoning-card.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAOxE,KAAK,OAAO,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AACtD,KAAK,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,MAAM,CAAC,IAAI,EAAE;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,kDAAkD;IAClD,KAAK,CAAC,IAAI,EAAE;QACV,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,UAAU,CAAC;KACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;CACvC;AAED,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;CACxB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAevB,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,0BAA0B,EAChC,IAAI,EAAE,aAAa,GAClB,aAAa,CA8Ef"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "Thinking" task card that receives the model's reasoning as it streams.
|
|
3
|
+
* Slack appends a card's `details` across updates, so the card is fed
|
|
4
|
+
* deltas: the part of the current reasoning block already on Slack, plus a
|
|
5
|
+
* buffer of what has not gone out yet.
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
import { truncateCardText } from "./stream.js";
|
|
17
|
+
const FLUSH_MS = 1000;
|
|
18
|
+
const FLUSH_CHARS = 160;
|
|
19
|
+
const CARD_ID = "reasoning";
|
|
20
|
+
const BLOCK_SEPARATOR = "\n\n";
|
|
21
|
+
function cardState(state) {
|
|
22
|
+
if (state.reasoningCard === undefined) {
|
|
23
|
+
state.reasoningCard = {
|
|
24
|
+
status: null,
|
|
25
|
+
blockSent: null,
|
|
26
|
+
pending: "",
|
|
27
|
+
lastFlushMs: null,
|
|
28
|
+
chars: 0,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return state.reasoningCard;
|
|
32
|
+
}
|
|
33
|
+
export function createReasoningCard(card, send) {
|
|
34
|
+
const flush = (_a) => __awaiter(this, [_a], void 0, function* ({ channel, sessionId, status, }) {
|
|
35
|
+
const state = cardState(channel.state);
|
|
36
|
+
if (state.pending === "" &&
|
|
37
|
+
(state.status === status || state.status === null)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const chunk = {
|
|
41
|
+
type: "task_update",
|
|
42
|
+
id: CARD_ID,
|
|
43
|
+
title: card.title,
|
|
44
|
+
status,
|
|
45
|
+
};
|
|
46
|
+
if (state.pending !== "") {
|
|
47
|
+
chunk.details = state.pending;
|
|
48
|
+
}
|
|
49
|
+
// Stamped on the attempt, so a failing stream is retried at most once
|
|
50
|
+
// per flush window instead of once per token.
|
|
51
|
+
state.lastFlushMs = Date.now();
|
|
52
|
+
if (!(yield send({ channel, sessionId, chunk }))) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
state.chars += state.pending.length;
|
|
56
|
+
state.pending = "";
|
|
57
|
+
state.status = status;
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
flush,
|
|
61
|
+
append(_a) {
|
|
62
|
+
return __awaiter(this, arguments, void 0, function* ({ channel, sessionId, text }) {
|
|
63
|
+
var _b;
|
|
64
|
+
const state = cardState(channel.state);
|
|
65
|
+
if (state.chars >= card.maxChars) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const sent = (_b = state.blockSent) !== null && _b !== void 0 ? _b : 0;
|
|
69
|
+
let delta;
|
|
70
|
+
if (sent > 0 && text.length >= sent) {
|
|
71
|
+
delta = text.slice(sent);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const hasText = state.chars + state.pending.length > 0;
|
|
75
|
+
delta = `${hasText ? BLOCK_SEPARATOR : ""}${text}`;
|
|
76
|
+
}
|
|
77
|
+
state.blockSent = text.length;
|
|
78
|
+
if (delta === "") {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
let pending = `${state.pending}${delta}`;
|
|
82
|
+
const room = card.maxChars - state.chars;
|
|
83
|
+
if (pending.length > room) {
|
|
84
|
+
pending = truncateCardText(pending, room);
|
|
85
|
+
state.chars = card.maxChars - pending.length;
|
|
86
|
+
}
|
|
87
|
+
state.pending = pending;
|
|
88
|
+
const due = state.lastFlushMs === null ||
|
|
89
|
+
Date.now() - state.lastFlushMs >= FLUSH_MS ||
|
|
90
|
+
pending.length >= FLUSH_CHARS;
|
|
91
|
+
if (due) {
|
|
92
|
+
yield flush({ channel, sessionId, status: "in_progress" });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
endBlock(channel) {
|
|
97
|
+
cardState(channel.state).blockSent = null;
|
|
98
|
+
},
|
|
99
|
+
inProgress(channel) {
|
|
100
|
+
var _a;
|
|
101
|
+
return ((_a = channel.state.reasoningCard) === null || _a === void 0 ? void 0 : _a.status) === "in_progress";
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/redact.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
import type { SlackChannelOptions, SlackToolCall, SlackToolCardGroup, SlackToolResult } from "./types.js";
|
|
7
|
+
export type SlackReplyMode = "post" | "stream";
|
|
8
|
+
export interface ResolvedSlackStatus {
|
|
9
|
+
reasoning: boolean;
|
|
10
|
+
/** `false`, or the line to show when tool calls start. */
|
|
11
|
+
tools: false | ((calls: readonly SlackToolCall[]) => string);
|
|
12
|
+
idle: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface ResolvedSlackToolCards {
|
|
15
|
+
group: SlackToolCardGroup;
|
|
16
|
+
details?: (call: SlackToolCall) => string | undefined;
|
|
17
|
+
output?: (result: SlackToolResult) => string | undefined;
|
|
18
|
+
}
|
|
19
|
+
export interface ResolvedSlackReasoningCard {
|
|
20
|
+
title: string;
|
|
21
|
+
maxChars: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ResolvedSlackReply {
|
|
24
|
+
mode: SlackReplyMode;
|
|
25
|
+
status: ResolvedSlackStatus;
|
|
26
|
+
toolCards: false | ResolvedSlackToolCards;
|
|
27
|
+
reasoningCard: false | ResolvedSlackReasoningCard;
|
|
28
|
+
toolLabel: (toolName: string) => string;
|
|
29
|
+
/** Author-facing notices about deprecated options that were honored. */
|
|
30
|
+
deprecations: string[];
|
|
31
|
+
}
|
|
32
|
+
export declare const DEFAULT_REASONING_CARD_TITLE = "Thinking";
|
|
33
|
+
/** A modest share of `SLACK_MARKDOWN_TEXT_MAX_LEN`, which the whole streamed message shares. */
|
|
34
|
+
export declare const DEFAULT_REASONING_CARD_MAX_CHARS = 1500;
|
|
35
|
+
type ReplyInputs = Pick<SlackChannelOptions, "reply" | "toolLabels" | "streaming" | "thinkingSteps"> & {
|
|
36
|
+
loadingMessages?: readonly string[];
|
|
37
|
+
};
|
|
38
|
+
export declare function resolveSlackReply(options: ReplyInputs): ResolvedSlackReply;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=reply-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply-options.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/reply-options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,mBAAmB,EAGnB,aAAa,EACb,kBAAkB,EAElB,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,KAAK,MAAM,CAAC,CAAC;IAC7D,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,MAAM,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,KAAK,GAAG,sBAAsB,CAAC;IAC1C,aAAa,EAAE,KAAK,GAAG,0BAA0B,CAAC;IAClD,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,wEAAwE;IACxE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,eAAO,MAAM,4BAA4B,aAAa,CAAC;AACvD,gGAAgG;AAChG,eAAO,MAAM,gCAAgC,OAAO,CAAC;AAErD,KAAK,WAAW,GAAG,IAAI,CACrB,mBAAmB,EACnB,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,eAAe,CACvD,GAAG;IAAE,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AA2H5C,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,kBAAkB,CAkD1E"}
|
|
@@ -0,0 +1,150 @@
|
|
|
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
|
+
import { SLACK_DEFAULT_LOADING_MESSAGES } from "./constants.js";
|
|
7
|
+
import { defaultToolCardDetails } from "./tool-cards.js";
|
|
8
|
+
export const DEFAULT_REASONING_CARD_TITLE = "Thinking";
|
|
9
|
+
/** A modest share of `SLACK_MARKDOWN_TEXT_MAX_LEN`, which the whole streamed message shares. */
|
|
10
|
+
export const DEFAULT_REASONING_CARD_MAX_CHARS = 1500;
|
|
11
|
+
function resolveToolLabel(labels) {
|
|
12
|
+
if (labels === undefined) {
|
|
13
|
+
return (toolName) => toolName;
|
|
14
|
+
}
|
|
15
|
+
const lookup = typeof labels === "function" ? labels : (name) => labels[name];
|
|
16
|
+
return (toolName) => {
|
|
17
|
+
const label = lookup(toolName);
|
|
18
|
+
return label === undefined || label === "" ? toolName : label;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function defaultToolStatusLine(toolLabel) {
|
|
22
|
+
return (calls) => {
|
|
23
|
+
const names = [...new Set(calls.map((call) => toolLabel(call.toolName)))];
|
|
24
|
+
return `Running ${names.join(", ")}…`;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function resolveIdle(idle) {
|
|
28
|
+
const cleaned = (idle !== null && idle !== void 0 ? idle : []).filter((line) => line.trim() !== "");
|
|
29
|
+
return cleaned.length > 0 ? cleaned : [...SLACK_DEFAULT_LOADING_MESSAGES];
|
|
30
|
+
}
|
|
31
|
+
function resolveReasoningCard(option) {
|
|
32
|
+
var _a;
|
|
33
|
+
if (option === undefined || option === false) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const options = option === true ? {} : option;
|
|
37
|
+
const title = (_a = options.title) === null || _a === void 0 ? void 0 : _a.trim();
|
|
38
|
+
return {
|
|
39
|
+
title: title === undefined || title === ""
|
|
40
|
+
? DEFAULT_REASONING_CARD_TITLE
|
|
41
|
+
: title,
|
|
42
|
+
maxChars: options.maxChars !== undefined && options.maxChars > 0
|
|
43
|
+
? options.maxChars
|
|
44
|
+
: DEFAULT_REASONING_CARD_MAX_CHARS,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function resolveToolCards(option) {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const cards = option.toolCards;
|
|
50
|
+
if (cards === undefined || cards === false) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (cards === true) {
|
|
54
|
+
return { group: "per-tool", details: defaultToolCardDetails };
|
|
55
|
+
}
|
|
56
|
+
const group = (_a = cards.group) !== null && _a !== void 0 ? _a : "per-tool";
|
|
57
|
+
if (cards.collapsible === false) {
|
|
58
|
+
return { group };
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
group,
|
|
62
|
+
details: (_b = cards.details) !== null && _b !== void 0 ? _b : defaultToolCardDetails,
|
|
63
|
+
output: cards.output,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Map the deprecated flags onto a `reply` shape with their old defaults
|
|
68
|
+
* (streaming on, per-call cards on), so a config that only sets these keeps
|
|
69
|
+
* behaving as it did. `null` when none of them is set.
|
|
70
|
+
*/
|
|
71
|
+
function legacyReplyOptions(options) {
|
|
72
|
+
const idle = options.loadingMessages;
|
|
73
|
+
if (options.streaming === undefined &&
|
|
74
|
+
options.thinkingSteps === undefined &&
|
|
75
|
+
idle === undefined) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const deprecations = [];
|
|
79
|
+
const mode = options.streaming === false ? "post" : "stream";
|
|
80
|
+
// What legacy streaming showed: one title-only card per call.
|
|
81
|
+
const cards = options.thinkingSteps === false ? false : LEGACY_CARDS;
|
|
82
|
+
const replacement = mode === "post"
|
|
83
|
+
? 'reply: { mode: "post" }'
|
|
84
|
+
: cards === false
|
|
85
|
+
? 'reply: { mode: "stream" }'
|
|
86
|
+
: 'reply: { mode: "stream", toolCards: { group: "per-call", collapsible: false } }';
|
|
87
|
+
if (idle !== undefined) {
|
|
88
|
+
deprecations.push(`slackChannel({ loadingMessages }) is deprecated; use reply: { mode: "${mode}", status: { idle: [...] } }.`);
|
|
89
|
+
}
|
|
90
|
+
if (options.streaming !== undefined) {
|
|
91
|
+
deprecations.push(`slackChannel({ streaming: ${String(options.streaming)} }) is deprecated; use ${replacement}.`);
|
|
92
|
+
}
|
|
93
|
+
if (options.thinkingSteps !== undefined) {
|
|
94
|
+
deprecations.push(mode === "post"
|
|
95
|
+
? "slackChannel({ thinkingSteps }) has no effect in post mode; remove it."
|
|
96
|
+
: `slackChannel({ thinkingSteps: ${String(options.thinkingSteps)} }) is deprecated; use ${replacement}.`);
|
|
97
|
+
}
|
|
98
|
+
const status = { idle };
|
|
99
|
+
if (mode === "post") {
|
|
100
|
+
return { reply: { mode, status }, deprecations };
|
|
101
|
+
}
|
|
102
|
+
return { reply: { mode, status, toolCards: cards }, deprecations };
|
|
103
|
+
}
|
|
104
|
+
const LEGACY_CARDS = { group: "per-call", collapsible: false };
|
|
105
|
+
export function resolveSlackReply(options) {
|
|
106
|
+
var _a;
|
|
107
|
+
const deprecations = [];
|
|
108
|
+
let reply = { mode: "post" };
|
|
109
|
+
const legacy = legacyReplyOptions(options);
|
|
110
|
+
if (options.reply !== undefined) {
|
|
111
|
+
reply = options.reply;
|
|
112
|
+
if (legacy !== null) {
|
|
113
|
+
const ignored = ["streaming", "thinkingSteps", "loadingMessages"].filter((key) => options[key] !== undefined);
|
|
114
|
+
deprecations.push(`slackChannel({ ${ignored.join(", ")} }) is ignored because reply is set; remove the deprecated option${ignored.length === 1 ? "" : "s"}.`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (legacy !== null) {
|
|
118
|
+
reply = legacy.reply;
|
|
119
|
+
deprecations.push(...legacy.deprecations);
|
|
120
|
+
}
|
|
121
|
+
const toolLabel = resolveToolLabel(options.toolLabels);
|
|
122
|
+
const statusInput = (_a = reply.status) !== null && _a !== void 0 ? _a : {};
|
|
123
|
+
const status = {
|
|
124
|
+
reasoning: statusInput.reasoning !== false,
|
|
125
|
+
tools: statusInput.tools === false
|
|
126
|
+
? false
|
|
127
|
+
: typeof statusInput.tools === "function"
|
|
128
|
+
? statusInput.tools
|
|
129
|
+
: defaultToolStatusLine(toolLabel),
|
|
130
|
+
idle: resolveIdle(statusInput.idle),
|
|
131
|
+
};
|
|
132
|
+
if (reply.mode === "post") {
|
|
133
|
+
return {
|
|
134
|
+
mode: "post",
|
|
135
|
+
status,
|
|
136
|
+
toolCards: false,
|
|
137
|
+
reasoningCard: false,
|
|
138
|
+
toolLabel,
|
|
139
|
+
deprecations,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
mode: "stream",
|
|
144
|
+
status,
|
|
145
|
+
toolCards: resolveToolCards(reply),
|
|
146
|
+
reasoningCard: resolveReasoningCard(reply.reasoningCard),
|
|
147
|
+
toolLabel,
|
|
148
|
+
deprecations,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-channel.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/slack-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EAEV,iBAAiB,EAMlB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"slack-channel.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/slack-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EAEV,iBAAiB,EAMlB,MAAM,gBAAgB,CAAC;AA4CxB,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAQpB;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GACjB,mBAAmB,GAAG,SAAS,CAEjC;AAED,0EAA0E;AAC1E,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,aAAa,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9C,uBAAuB,GAAG,SAAS,CAYrC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,GAAE,mBAAwB,GACjC,iBAAiB,CAAC,iBAAiB,CAAC,CAgbtC"}
|
|
@@ -26,6 +26,7 @@ import { dispatchInboundFromEventBody, dispatchInboundMessage, emptySlackChannel
|
|
|
26
26
|
import { createEventIdDedupe } from "./event-id-dedupe.js";
|
|
27
27
|
import { dispatchBlockAction, dispatchInteractiveFromPayload, } from "./interactive.js";
|
|
28
28
|
import { createSlackLogger } from "./log.js";
|
|
29
|
+
import { resolveSlackReply } from "./reply-options.js";
|
|
29
30
|
import { startSlackSocketMode, } from "./socket-mode.js";
|
|
30
31
|
import { buildToolApprovalEvents } from "./tool-approval-events.js";
|
|
31
32
|
/** Options used to construct a slack channel — for host-level credential binding. */
|
|
@@ -70,7 +71,8 @@ export function slackChannel(authored = {}) {
|
|
|
70
71
|
}
|
|
71
72
|
const credentials = (_a = options.credentials) !== null && _a !== void 0 ? _a : credentialsFromEnv(options.envPrefix);
|
|
72
73
|
const envKeys = slackEnvKeys(options.envPrefix);
|
|
73
|
-
const
|
|
74
|
+
const reply = resolveSlackReply(options);
|
|
75
|
+
const loadingMessages = reply.status.idle;
|
|
74
76
|
const policy = options.policy;
|
|
75
77
|
const blockExternals = resolveSlackBlockExternals(policy);
|
|
76
78
|
const defaultInbound = createDefaultOnInbound(loadingMessages, policy);
|
|
@@ -107,11 +109,13 @@ export function slackChannel(authored = {}) {
|
|
|
107
109
|
if (options.deliverDefaults !== false) {
|
|
108
110
|
Object.assign(events, buildDefaultEvents({
|
|
109
111
|
credentials,
|
|
112
|
+
reply: options.reply,
|
|
113
|
+
toolLabels: options.toolLabels,
|
|
110
114
|
streaming: options.streaming,
|
|
111
115
|
thinkingSteps: options.thinkingSteps,
|
|
116
|
+
loadingMessages: options.loadingMessages,
|
|
112
117
|
suggestedPrompts: options.suggestedPrompts,
|
|
113
118
|
suggestedPromptsTitle: options.suggestedPromptsTitle,
|
|
114
|
-
loadingMessages,
|
|
115
119
|
getLog,
|
|
116
120
|
}));
|
|
117
121
|
}
|
|
@@ -145,9 +149,9 @@ export function slackChannel(authored = {}) {
|
|
|
145
149
|
auth: [allowAll()],
|
|
146
150
|
state: emptySlackChannelState(),
|
|
147
151
|
routes: [],
|
|
148
|
-
meta: Object.assign({ kind: "slack" }, (channelPosts === undefined
|
|
152
|
+
meta: Object.assign(Object.assign({ kind: "slack" }, (channelPosts === undefined
|
|
149
153
|
? {}
|
|
150
|
-
: { slackChannelPosts: [...channelPosts.allow] })),
|
|
154
|
+
: { slackChannelPosts: [...channelPosts.allow] })), { deprecations: reply.deprecations }),
|
|
151
155
|
receive(input_1, _a) {
|
|
152
156
|
return __awaiter(this, arguments, void 0, function* (input, { send }) {
|
|
153
157
|
var _b;
|