@geminixiang/mikan 1.0.0-beta.28 → 1.0.0-beta.29
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/CHANGELOG.md +28 -0
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/buffered-responder.d.ts +7 -1
- package/dist/adapters/buffered-responder.d.ts.map +1 -1
- package/dist/adapters/buffered-responder.js +6 -0
- package/dist/adapters/buffered-responder.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +108 -152
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +1 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +44 -6
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/progressive-render.d.ts +66 -0
- package/dist/adapters/slack/progressive-render.d.ts.map +1 -0
- package/dist/adapters/slack/progressive-render.js +171 -0
- package/dist/adapters/slack/progressive-render.js.map +1 -0
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +41 -139
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/tool-pack.d.ts +27 -0
- package/dist/adapters/slack/tool-pack.d.ts.map +1 -0
- package/dist/adapters/slack/tool-pack.js +24 -0
- package/dist/adapters/slack/tool-pack.js.map +1 -0
- package/dist/adapters/slack/tools/blockkit.d.ts +28 -0
- package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -0
- package/dist/adapters/slack/tools/blockkit.js +106 -0
- package/dist/adapters/slack/tools/blockkit.js.map +1 -0
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +14 -0
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/agent.d.ts +2 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +227 -40
- package/dist/agent.js.map +1 -1
- package/dist/cli/ext-dev.d.ts +2 -0
- package/dist/cli/ext-dev.d.ts.map +1 -0
- package/dist/cli/ext-dev.js +177 -0
- package/dist/cli/ext-dev.js.map +1 -0
- package/dist/cli/ext.d.ts.map +1 -1
- package/dist/cli/ext.js +7 -0
- package/dist/cli/ext.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -0
- package/dist/config.js.map +1 -1
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +16 -3
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/auth.d.ts +2 -1
- package/dist/harness/auth.d.ts.map +1 -1
- package/dist/harness/auth.js +6 -0
- package/dist/harness/auth.js.map +1 -1
- package/dist/harness/extensions/blockkit.d.ts +19 -0
- package/dist/harness/extensions/blockkit.d.ts.map +1 -0
- package/dist/harness/extensions/blockkit.js +42 -0
- package/dist/harness/extensions/blockkit.js.map +1 -0
- package/dist/harness/extensions/loader.d.ts +13 -1
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +112 -41
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/registry.d.ts +15 -1
- package/dist/harness/extensions/registry.d.ts.map +1 -1
- package/dist/harness/extensions/registry.js +34 -0
- package/dist/harness/extensions/registry.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +64 -0
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +4 -2
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +2 -0
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/runner.d.ts +6 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +37 -8
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/subagent-profiles.d.ts +16 -0
- package/dist/harness/subagent-profiles.d.ts.map +1 -0
- package/dist/harness/subagent-profiles.js +211 -0
- package/dist/harness/subagent-profiles.js.map +1 -0
- package/dist/harness/subagent-runner.d.ts +9 -5
- package/dist/harness/subagent-runner.d.ts.map +1 -1
- package/dist/harness/subagent-runner.js +276 -103
- package/dist/harness/subagent-runner.js.map +1 -1
- package/dist/harness/types.d.ts +38 -1
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/main.js +51 -14
- package/dist/main.js.map +1 -1
- package/dist/packages/admin.d.ts +29 -0
- package/dist/packages/admin.d.ts.map +1 -0
- package/dist/packages/admin.js +96 -0
- package/dist/packages/admin.js.map +1 -0
- package/dist/packages/index.d.ts +6 -0
- package/dist/packages/index.d.ts.map +1 -0
- package/dist/packages/index.js +6 -0
- package/dist/packages/index.js.map +1 -0
- package/dist/packages/inspect.d.ts +36 -0
- package/dist/packages/inspect.d.ts.map +1 -0
- package/dist/packages/inspect.js +100 -0
- package/dist/packages/inspect.js.map +1 -0
- package/dist/packages/materialize.d.ts +41 -0
- package/dist/packages/materialize.d.ts.map +1 -0
- package/dist/packages/materialize.js +190 -0
- package/dist/packages/materialize.js.map +1 -0
- package/dist/packages/resolve.d.ts +60 -0
- package/dist/packages/resolve.d.ts.map +1 -0
- package/dist/packages/resolve.js +212 -0
- package/dist/packages/resolve.js.map +1 -0
- package/dist/packages/source.d.ts +33 -0
- package/dist/packages/source.d.ts.map +1 -0
- package/dist/packages/source.js +177 -0
- package/dist/packages/source.js.map +1 -0
- package/dist/packages/types.d.ts +58 -0
- package/dist/packages/types.d.ts.map +1 -0
- package/dist/packages/types.js +2 -0
- package/dist/packages/types.js.map +1 -0
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +4 -1
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +90 -21
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +3 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/gondolin.d.ts +39 -9
- package/dist/sandbox/gondolin.d.ts.map +1 -1
- package/dist/sandbox/gondolin.js +335 -43
- package/dist/sandbox/gondolin.js.map +1 -1
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +1 -1
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +1 -0
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/subagent-progress.d.ts +43 -0
- package/dist/subagent-progress.d.ts.map +1 -0
- package/dist/subagent-progress.js +220 -0
- package/dist/subagent-progress.js.map +1 -0
- package/dist/tools/read.d.ts +1 -0
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +30 -5
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/subagent.d.ts +12 -9
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +141 -76
- package/dist/tools/subagent.js.map +1 -1
- package/dist/types.d.ts +90 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +268 -1
- package/dist/web/admin/portal.js.map +1 -1
- package/package.json +6 -6
- package/dist/sandbox/gondolin-bootstrap.d.ts +0 -12
- package/dist/sandbox/gondolin-bootstrap.d.ts.map +0 -1
- package/dist/sandbox/gondolin-bootstrap.js +0 -9
- package/dist/sandbox/gondolin-bootstrap.js.map +0 -1
- package/dist/sandbox/gondolin-contract.d.ts +0 -58
- package/dist/sandbox/gondolin-contract.d.ts.map +0 -1
- package/dist/sandbox/gondolin-contract.js +0 -71
- package/dist/sandbox/gondolin-contract.js.map +0 -1
- package/dist/sandbox/gondolin-inventory.d.ts +0 -75
- package/dist/sandbox/gondolin-inventory.d.ts.map +0 -1
- package/dist/sandbox/gondolin-inventory.js +0 -257
- package/dist/sandbox/gondolin-inventory.js.map +0 -1
- package/dist/sandbox/gondolin-recovery.d.ts +0 -20
- package/dist/sandbox/gondolin-recovery.d.ts.map +0 -1
- package/dist/sandbox/gondolin-recovery.js +0 -24
- package/dist/sandbox/gondolin-recovery.js.map +0 -1
- package/dist/sandbox/gondolin-worker-client.d.ts +0 -110
- package/dist/sandbox/gondolin-worker-client.d.ts.map +0 -1
- package/dist/sandbox/gondolin-worker-client.js +0 -322
- package/dist/sandbox/gondolin-worker-client.js.map +0 -1
- package/dist/sandbox/gondolin-worker-main.d.ts +0 -2
- package/dist/sandbox/gondolin-worker-main.d.ts.map +0 -1
- package/dist/sandbox/gondolin-worker-main.js +0 -22
- package/dist/sandbox/gondolin-worker-main.js.map +0 -1
- package/dist/sandbox/gondolin-worker.d.ts +0 -17
- package/dist/sandbox/gondolin-worker.d.ts.map +0 -1
- package/dist/sandbox/gondolin-worker.js +0 -201
- package/dist/sandbox/gondolin-worker.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,34 @@ any release.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [1.0.0-beta.29]
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Add Git-sourced extension packages with global and conversation scopes, package mount resolution, CLI inspection, and admin portal management.
|
|
17
|
+
- Add native Slack markdown-block responses and the `slack_blockkit` tool for interactive Block Kit messages.
|
|
18
|
+
- Add interactive Block Kit APIs for extensions, with a poll extension example.
|
|
19
|
+
- Add named subagent profiles, built-in workflow specialists, per-profile tool grants, and a bounded Slack progress dashboard.
|
|
20
|
+
- Preserve durable memory with Session Dream before biweekly shared-channel session rotation, using the same conversation-scoped maintenance path as `/new`.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Run Gondolin runtimes inside the mikan process instead of detached workers. Restarts now boot fresh VMs on demand, and shutdown closes every VM so projected files sync back first.
|
|
25
|
+
- Remove Gondolin runtime inventories, worker heartbeats, and the `stateDir` argument from `configureGondolinRuntime`.
|
|
26
|
+
- Render standard GFM response prose as native Slack markdown blocks while keeping progressive response updates behind a single lifecycle.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Keep the current session active and preserve saved memory when Session Dream cannot finish.
|
|
31
|
+
- Bound subagent cancellation, invocation modes, profile labels, and Block Kit payloads; clamp long labels with an ellipsis instead of rejecting calls.
|
|
32
|
+
- Show the selected subagent profile and its tool grant consistently in progress output.
|
|
33
|
+
- Render the Slack subagent dashboard as a response source rather than escaped mrkdwn.
|
|
34
|
+
- Isolate Git test fixtures from an ambient `GIT_DIR`.
|
|
35
|
+
|
|
36
|
+
### Tests
|
|
37
|
+
|
|
38
|
+
- Add coverage for extension packages, extension Block Kit APIs, native Slack rendering, subagent profiles and progress, Session Dream rotation, and in-process Gondolin lifecycle behavior.
|
|
39
|
+
|
|
12
40
|
## [1.0.0-beta.28]
|
|
13
41
|
|
|
14
42
|
### Removed
|
package/dist/adapter.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type { MessagingBot, ConversationContext, ConversationEvent, MessagingEventHandler, ChatAdapter, ConversationMessage, ConversationResponder, ChatToolResult, ConversationKind, MessagingInfo, PlatformName, PlatformNotifier, PlatformReactor, PlatformUploader, RunningSession, } from "./types.js";
|
|
1
|
+
export type { MessagingBot, ConversationContext, ConversationEvent, MessagingEventHandler, ChatAdapter, ConversationMessage, ConversationResponder, ChatToolResult, ConversationKind, MessagingInfo, PlatformBlockKit, PlatformName, PlatformNotifier, PlatformReactor, PlatformUploader, RunningSession, SubagentProgressSnapshot, } from "./types.js";
|
|
2
2
|
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
package/dist/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"","sourcesContent":["export type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ChatAdapter,\n ConversationMessage,\n ConversationResponder,\n ChatToolResult,\n ConversationKind,\n MessagingInfo,\n PlatformName,\n PlatformNotifier,\n PlatformReactor,\n PlatformUploader,\n RunningSession,\n} from \"./types.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"","sourcesContent":["export type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ChatAdapter,\n ConversationMessage,\n ConversationResponder,\n ChatToolResult,\n ConversationKind,\n MessagingInfo,\n PlatformBlockKit,\n PlatformName,\n PlatformNotifier,\n PlatformReactor,\n PlatformUploader,\n RunningSession,\n SubagentProgressSnapshot,\n} from \"./types.js\";\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatToolResult, ConversationResponder } from "../adapter.js";
|
|
1
|
+
import type { ChatToolResult, ConversationResponder, SubagentProgressSnapshot } from "../adapter.js";
|
|
2
2
|
import { type ChatResponseErrorOperation } from "./shared.js";
|
|
3
3
|
/**
|
|
4
4
|
* The per-platform verbs and policy behind one buffered responder. Everything
|
|
@@ -26,6 +26,12 @@ export interface BufferedResponderPlatform {
|
|
|
26
26
|
workingIndicator?: string;
|
|
27
27
|
/** Enable appendResponseDelta/finishResponse over a buffered stream. */
|
|
28
28
|
streaming: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Convert the subagent dashboard for a pipeline that is not response-source
|
|
31
|
+
* Markdown (Telegram HTML). Markdown platforms omit this: the harness
|
|
32
|
+
* composes the Markdown dashboard through replaceResponse.
|
|
33
|
+
*/
|
|
34
|
+
formatSubagentProgress?: (progress: SubagentProgressSnapshot) => string;
|
|
29
35
|
typing?: {
|
|
30
36
|
send: () => Promise<unknown>;
|
|
31
37
|
intervalMs: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buffered-responder.d.ts","sourceRoot":"","sources":["../../src/adapters/buffered-responder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"buffered-responder.d.ts","sourceRoot":"","sources":["../../src/adapters/buffered-responder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAA6B,KAAK,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAGzF;;;;;;;;GAQG;AACH,MAAM,WAAW,yBAAyB;IACxC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,wBAAwB,KAAK,MAAM,CAAC;IACxE,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,+DAA+D;QAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,gBAAgB,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,MAAM,CAAC;IACrD,WAAW,EAAE,CACX,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,0BAA0B,EACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC3B,IAAI,CAAC;IACV,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,gEAAgE;IAChE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,0CAA0C;IAC1C,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,gEAAgE;IAChE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,mCAAmC;IACnC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,oFAAoF;AACpF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CASvE;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,yBAAyB,GAAG;IAC5E,SAAS,EAAE,qBAAqB,CAAC;CAClC,CA2PA"}
|
|
@@ -123,6 +123,12 @@ export function createBufferedResponder(platform) {
|
|
|
123
123
|
hadExistingResponse: Boolean(responseId),
|
|
124
124
|
}));
|
|
125
125
|
},
|
|
126
|
+
replaceSubagentProgress: platform.formatSubagentProgress
|
|
127
|
+
? async (progress, finalText) => {
|
|
128
|
+
const dashboard = platform.formatSubagentProgress(progress);
|
|
129
|
+
await responder.replaceResponse(finalText ? `${dashboard}\n\n${finalText}` : dashboard);
|
|
130
|
+
}
|
|
131
|
+
: undefined,
|
|
126
132
|
respondDiagnostic: async (text, options) => {
|
|
127
133
|
await run("respondDiagnostic", "respond_diagnostic", async () => {
|
|
128
134
|
const prefix = options?.style === "error" ? platform.errorPrefix : "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buffered-responder.js","sourceRoot":"","sources":["../../src/adapters/buffered-responder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChatToolResult, ConversationResponder } from \"../adapter.js\";\nimport * as log from \"../log.js\";\nimport { formatToolArgs, splitText, type ChatResponseErrorOperation } from \"./shared.js\";\nimport { BufferedResponseStream, OrderedResponseOperations } from \"./streaming.js\";\n\n/**\n * The per-platform verbs and policy behind one buffered responder. Everything\n * else — the accumulated-text state machine, split-first-then-continuations\n * posting, response-id capture, ordered-queue error choreography, typing\n * interval, working indicator, delete semantics — is owned by\n * {@link createBufferedResponder} and identical on every buffered platform.\n * (Slack keeps its own streaming lifecycle; this covers the platforms that\n * edit one response message in place.)\n */\nexport interface BufferedResponderPlatform {\n /** Log label, e.g. \"Discord\". */\n label: string;\n /** Hard message length; longer responses continue in extra messages. */\n maxLength: number;\n formatContinuation: (partNum: number) => string;\n /** Prefix for respondDiagnostic({style:\"error\"}). */\n errorPrefix: string;\n /** Platform text normalization applied before accumulation (e.g. HTML). */\n sanitize?: (text: string) => string;\n /**\n * Suffix rendered while the run is working (and re-rendered away by\n * setWorking(false)). Platforms without one leave setWorking to typing.\n */\n workingIndicator?: string;\n /** Enable appendResponseDelta/finishResponse over a buffered stream. */\n streaming: boolean;\n typing?: {\n send: () => Promise<unknown>;\n intervalMs: number;\n /** Also stop the indicator when a message is actually sent. */\n stopOnSend?: boolean;\n };\n formatToolResult: (result: ChatToolResult) => string;\n reportError: (\n err: unknown,\n operation: ChatResponseErrorOperation,\n extra: Record<string, unknown>,\n ) => void;\n /** Posted into the conversation after a send fails (e.g. Telegram's ⚠️). */\n notifySendFailure?: (errorMessage: string) => Promise<void>;\n /** Post the first response message; returns its platform id. */\n post: (text: string) => Promise<string>;\n /** Edit the existing response message. */\n update: (id: string, text: string) => Promise<void>;\n /** Post an out-of-band message (continuations, diagnostics). */\n postExtra: (text: string, responseId: string | null) => Promise<unknown>;\n /** Delete the response message. */\n delete?: (id: string) => Promise<void>;\n /** Record a bot response chunk against the response message id. */\n logBotResponse?: (text: string, id: string) => void;\n /** Direct upload; absent platforms fall back to uploadFallbackNote. */\n uploadFile?: (filePath: string, title?: string) => Promise<void>;\n /** Posted (queued) instead of uploading when uploadFile is absent. */\n uploadFallbackNote?: (name: string) => string;\n react?: (emoji: string) => Promise<void>;\n}\n\n/** The tool-result rendering shared by the Markdown platforms (Discord, GitHub). */\nexport function formatMarkdownToolResult(result: ChatToolResult): string {\n const argsFormatted = formatToolArgs(result.args);\n const duration = (result.durationMs / 1000).toFixed(1);\n let text = `**${result.isError ? \"Error\" : \"Done\"} ${result.toolName}**`;\n if (result.label) text += `: ${result.label}`;\n text += ` (${duration}s)\\n`;\n if (argsFormatted) text += `\\`\\`\\`\\n${argsFormatted}\\n\\`\\`\\`\\n`;\n text += `**Result:**\\n\\`\\`\\`\\n${result.result}\\n\\`\\`\\``;\n return text;\n}\n\nexport function createBufferedResponder(platform: BufferedResponderPlatform): {\n responder: ConversationResponder;\n} {\n let responseId: string | null = null;\n let accumulatedText = \"\";\n let isWorking = true;\n const queue = new OrderedResponseOperations();\n let typingInterval: ReturnType<typeof setInterval> | null = null;\n let typingFailureWarned = false;\n\n const sanitize = platform.sanitize ?? ((text: string) => text);\n\n function stopTyping(): void {\n if (typingInterval !== null) {\n clearInterval(typingInterval);\n typingInterval = null;\n }\n }\n\n /** The response text as currently displayed (working indicator applied). */\n function render(text: string): string {\n return platform.workingIndicator && isWorking ? text + platform.workingIndicator : text;\n }\n\n async function postOrUpdate(displayText: string): Promise<void> {\n if (responseId !== null) {\n await platform.update(responseId, displayText);\n return;\n }\n if (platform.typing?.stopOnSend) stopTyping();\n responseId = await platform.post(displayText);\n }\n\n async function postExtra(text: string): Promise<void> {\n if (platform.typing?.stopOnSend) stopTyping();\n await platform.postExtra(text, responseId);\n }\n\n async function postSplit(text: string): Promise<void> {\n const [head, ...tail] = splitText(text, platform.maxLength, platform.formatContinuation);\n await postOrUpdate(head);\n for (const part of tail) {\n await postExtra(part);\n }\n }\n\n const stream = new BufferedResponseStream({\n flush: async (text) => {\n await postSplit(render(text));\n },\n finish: async (text) => {\n isWorking = false;\n stopTyping();\n await postSplit(text);\n },\n });\n\n function run(\n label: string,\n operation: ChatResponseErrorOperation,\n work: () => Promise<void>,\n extra: (err: unknown) => Record<string, unknown>,\n ): Promise<void> {\n return queue.run(work, async (err) => {\n const message = err instanceof Error ? err.message : String(err);\n log.logWarning(`${platform.label} ${label} error`, message);\n platform.reportError(err, operation, extra(err));\n if (platform.notifySendFailure) {\n try {\n await platform.notifySendFailure(message);\n } catch {\n // ignore secondary failure\n }\n }\n });\n }\n\n const responder: ConversationResponder = {\n respond: async (text: string) => {\n await run(\n \"respond\",\n \"respond\",\n async () => {\n const sanitized = sanitize(text);\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${sanitized}` : sanitized;\n stream.setText(accumulatedText);\n await postSplit(render(accumulatedText));\n if (responseId !== null) {\n platform.logBotResponse?.(text, responseId);\n }\n },\n () => ({\n phase: responseId ? \"update\" : \"initial_post\",\n textLength: text.length,\n accumulatedLength: accumulatedText.length,\n }),\n );\n },\n\n ...(platform.streaming\n ? {\n appendResponseDelta: async (delta: string) => {\n await run(\n \"appendResponseDelta\",\n \"respond\",\n async () => {\n await stream.append(sanitize(delta));\n accumulatedText = stream.getText();\n if (responseId !== null) {\n platform.logBotResponse?.(delta, responseId);\n }\n },\n () => ({ textLength: delta.length, accumulatedLength: stream.getText().length }),\n );\n },\n\n finishResponse: async (finalText?: string) => {\n await run(\n \"finishResponse\",\n \"set_working\",\n async () => {\n await stream.finish(finalText === undefined ? undefined : sanitize(finalText));\n accumulatedText = stream.getText();\n },\n () => ({ finalTextLength: finalText?.length }),\n );\n },\n }\n : {}),\n\n replaceResponse: async (text: string) => {\n await run(\n \"replaceResponse\",\n \"replace_response\",\n async () => {\n accumulatedText = sanitize(text);\n stream.setText(accumulatedText);\n await postSplit(accumulatedText);\n },\n () => ({\n textLength: text.length,\n hadExistingResponse: Boolean(responseId),\n }),\n );\n },\n\n respondDiagnostic: async (text: string, options?: { style?: \"muted\" | \"error\" }) => {\n await run(\n \"respondDiagnostic\",\n \"respond_diagnostic\",\n async () => {\n const prefix = options?.style === \"error\" ? platform.errorPrefix : \"\";\n for (const part of splitText(\n sanitize(`${prefix}${text}`),\n platform.maxLength,\n platform.formatContinuation,\n )) {\n await postExtra(part);\n }\n },\n () => ({ textLength: text.length, style: options?.style }),\n );\n },\n\n respondToolResult: async (result: ChatToolResult) => {\n await responder.respondDiagnostic(platform.formatToolResult(result));\n },\n\n setTyping: async (isTyping: boolean) => {\n const typing = platform.typing;\n if (!typing) return;\n const onTypingError = (err: unknown): void => {\n if (typingFailureWarned) return;\n typingFailureWarned = true;\n log.logWarning(\n `${platform.label} sendTyping failed (further occurrences suppressed for this session)`,\n err instanceof Error ? err.message : String(err),\n );\n };\n if (isTyping && typingInterval === null) {\n typing.send().catch(onTypingError);\n typingInterval = setInterval(() => {\n typing.send().catch(onTypingError);\n }, typing.intervalMs);\n } else if (!isTyping) {\n stopTyping();\n }\n },\n\n setWorking: async (working: boolean) => {\n if (!platform.workingIndicator) {\n if (!working) stopTyping();\n return;\n }\n await run(\n \"setWorking\",\n \"set_working\",\n async () => {\n isWorking = working;\n if (!working) stopTyping();\n if (responseId !== null) {\n const [head] = splitText(\n render(accumulatedText),\n platform.maxLength,\n platform.formatContinuation,\n );\n await platform.update(responseId, head);\n }\n },\n () => ({ working }),\n );\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n if (platform.uploadFile) {\n await platform.uploadFile(filePath, title);\n return;\n }\n const note = platform.uploadFallbackNote?.(title ?? filePath);\n if (note === undefined) return;\n await run(\n \"uploadFile\",\n \"respond_diagnostic\",\n () => postExtra(note),\n () => ({ filePath }),\n );\n },\n\n ...(platform.react ? { react: platform.react } : {}),\n\n deleteResponse: async () => {\n await queue.run(async () => {\n stopTyping();\n if (responseId !== null) {\n try {\n await platform.delete?.(responseId);\n } catch {\n // Ignore errors\n }\n responseId = null;\n }\n });\n },\n };\n\n return { responder };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"buffered-responder.js","sourceRoot":"","sources":["../../src/adapters/buffered-responder.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ChatToolResult,\n ConversationResponder,\n SubagentProgressSnapshot,\n} from \"../adapter.js\";\nimport * as log from \"../log.js\";\nimport { formatToolArgs, splitText, type ChatResponseErrorOperation } from \"./shared.js\";\nimport { BufferedResponseStream, OrderedResponseOperations } from \"./streaming.js\";\n\n/**\n * The per-platform verbs and policy behind one buffered responder. Everything\n * else — the accumulated-text state machine, split-first-then-continuations\n * posting, response-id capture, ordered-queue error choreography, typing\n * interval, working indicator, delete semantics — is owned by\n * {@link createBufferedResponder} and identical on every buffered platform.\n * (Slack keeps its own streaming lifecycle; this covers the platforms that\n * edit one response message in place.)\n */\nexport interface BufferedResponderPlatform {\n /** Log label, e.g. \"Discord\". */\n label: string;\n /** Hard message length; longer responses continue in extra messages. */\n maxLength: number;\n formatContinuation: (partNum: number) => string;\n /** Prefix for respondDiagnostic({style:\"error\"}). */\n errorPrefix: string;\n /** Platform text normalization applied before accumulation (e.g. HTML). */\n sanitize?: (text: string) => string;\n /**\n * Suffix rendered while the run is working (and re-rendered away by\n * setWorking(false)). Platforms without one leave setWorking to typing.\n */\n workingIndicator?: string;\n /** Enable appendResponseDelta/finishResponse over a buffered stream. */\n streaming: boolean;\n /**\n * Convert the subagent dashboard for a pipeline that is not response-source\n * Markdown (Telegram HTML). Markdown platforms omit this: the harness\n * composes the Markdown dashboard through replaceResponse.\n */\n formatSubagentProgress?: (progress: SubagentProgressSnapshot) => string;\n typing?: {\n send: () => Promise<unknown>;\n intervalMs: number;\n /** Also stop the indicator when a message is actually sent. */\n stopOnSend?: boolean;\n };\n formatToolResult: (result: ChatToolResult) => string;\n reportError: (\n err: unknown,\n operation: ChatResponseErrorOperation,\n extra: Record<string, unknown>,\n ) => void;\n /** Posted into the conversation after a send fails (e.g. Telegram's ⚠️). */\n notifySendFailure?: (errorMessage: string) => Promise<void>;\n /** Post the first response message; returns its platform id. */\n post: (text: string) => Promise<string>;\n /** Edit the existing response message. */\n update: (id: string, text: string) => Promise<void>;\n /** Post an out-of-band message (continuations, diagnostics). */\n postExtra: (text: string, responseId: string | null) => Promise<unknown>;\n /** Delete the response message. */\n delete?: (id: string) => Promise<void>;\n /** Record a bot response chunk against the response message id. */\n logBotResponse?: (text: string, id: string) => void;\n /** Direct upload; absent platforms fall back to uploadFallbackNote. */\n uploadFile?: (filePath: string, title?: string) => Promise<void>;\n /** Posted (queued) instead of uploading when uploadFile is absent. */\n uploadFallbackNote?: (name: string) => string;\n react?: (emoji: string) => Promise<void>;\n}\n\n/** The tool-result rendering shared by the Markdown platforms (Discord, GitHub). */\nexport function formatMarkdownToolResult(result: ChatToolResult): string {\n const argsFormatted = formatToolArgs(result.args);\n const duration = (result.durationMs / 1000).toFixed(1);\n let text = `**${result.isError ? \"Error\" : \"Done\"} ${result.toolName}**`;\n if (result.label) text += `: ${result.label}`;\n text += ` (${duration}s)\\n`;\n if (argsFormatted) text += `\\`\\`\\`\\n${argsFormatted}\\n\\`\\`\\`\\n`;\n text += `**Result:**\\n\\`\\`\\`\\n${result.result}\\n\\`\\`\\``;\n return text;\n}\n\nexport function createBufferedResponder(platform: BufferedResponderPlatform): {\n responder: ConversationResponder;\n} {\n let responseId: string | null = null;\n let accumulatedText = \"\";\n let isWorking = true;\n const queue = new OrderedResponseOperations();\n let typingInterval: ReturnType<typeof setInterval> | null = null;\n let typingFailureWarned = false;\n\n const sanitize = platform.sanitize ?? ((text: string) => text);\n\n function stopTyping(): void {\n if (typingInterval !== null) {\n clearInterval(typingInterval);\n typingInterval = null;\n }\n }\n\n /** The response text as currently displayed (working indicator applied). */\n function render(text: string): string {\n return platform.workingIndicator && isWorking ? text + platform.workingIndicator : text;\n }\n\n async function postOrUpdate(displayText: string): Promise<void> {\n if (responseId !== null) {\n await platform.update(responseId, displayText);\n return;\n }\n if (platform.typing?.stopOnSend) stopTyping();\n responseId = await platform.post(displayText);\n }\n\n async function postExtra(text: string): Promise<void> {\n if (platform.typing?.stopOnSend) stopTyping();\n await platform.postExtra(text, responseId);\n }\n\n async function postSplit(text: string): Promise<void> {\n const [head, ...tail] = splitText(text, platform.maxLength, platform.formatContinuation);\n await postOrUpdate(head);\n for (const part of tail) {\n await postExtra(part);\n }\n }\n\n const stream = new BufferedResponseStream({\n flush: async (text) => {\n await postSplit(render(text));\n },\n finish: async (text) => {\n isWorking = false;\n stopTyping();\n await postSplit(text);\n },\n });\n\n function run(\n label: string,\n operation: ChatResponseErrorOperation,\n work: () => Promise<void>,\n extra: (err: unknown) => Record<string, unknown>,\n ): Promise<void> {\n return queue.run(work, async (err) => {\n const message = err instanceof Error ? err.message : String(err);\n log.logWarning(`${platform.label} ${label} error`, message);\n platform.reportError(err, operation, extra(err));\n if (platform.notifySendFailure) {\n try {\n await platform.notifySendFailure(message);\n } catch {\n // ignore secondary failure\n }\n }\n });\n }\n\n const responder: ConversationResponder = {\n respond: async (text: string) => {\n await run(\n \"respond\",\n \"respond\",\n async () => {\n const sanitized = sanitize(text);\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${sanitized}` : sanitized;\n stream.setText(accumulatedText);\n await postSplit(render(accumulatedText));\n if (responseId !== null) {\n platform.logBotResponse?.(text, responseId);\n }\n },\n () => ({\n phase: responseId ? \"update\" : \"initial_post\",\n textLength: text.length,\n accumulatedLength: accumulatedText.length,\n }),\n );\n },\n\n ...(platform.streaming\n ? {\n appendResponseDelta: async (delta: string) => {\n await run(\n \"appendResponseDelta\",\n \"respond\",\n async () => {\n await stream.append(sanitize(delta));\n accumulatedText = stream.getText();\n if (responseId !== null) {\n platform.logBotResponse?.(delta, responseId);\n }\n },\n () => ({ textLength: delta.length, accumulatedLength: stream.getText().length }),\n );\n },\n\n finishResponse: async (finalText?: string) => {\n await run(\n \"finishResponse\",\n \"set_working\",\n async () => {\n await stream.finish(finalText === undefined ? undefined : sanitize(finalText));\n accumulatedText = stream.getText();\n },\n () => ({ finalTextLength: finalText?.length }),\n );\n },\n }\n : {}),\n\n replaceResponse: async (text: string) => {\n await run(\n \"replaceResponse\",\n \"replace_response\",\n async () => {\n accumulatedText = sanitize(text);\n stream.setText(accumulatedText);\n await postSplit(accumulatedText);\n },\n () => ({\n textLength: text.length,\n hadExistingResponse: Boolean(responseId),\n }),\n );\n },\n\n replaceSubagentProgress: platform.formatSubagentProgress\n ? async (progress: SubagentProgressSnapshot, finalText?: string) => {\n const dashboard = platform.formatSubagentProgress!(progress);\n await responder.replaceResponse(finalText ? `${dashboard}\\n\\n${finalText}` : dashboard);\n }\n : undefined,\n\n respondDiagnostic: async (text: string, options?: { style?: \"muted\" | \"error\" }) => {\n await run(\n \"respondDiagnostic\",\n \"respond_diagnostic\",\n async () => {\n const prefix = options?.style === \"error\" ? platform.errorPrefix : \"\";\n for (const part of splitText(\n sanitize(`${prefix}${text}`),\n platform.maxLength,\n platform.formatContinuation,\n )) {\n await postExtra(part);\n }\n },\n () => ({ textLength: text.length, style: options?.style }),\n );\n },\n\n respondToolResult: async (result: ChatToolResult) => {\n await responder.respondDiagnostic(platform.formatToolResult(result));\n },\n\n setTyping: async (isTyping: boolean) => {\n const typing = platform.typing;\n if (!typing) return;\n const onTypingError = (err: unknown): void => {\n if (typingFailureWarned) return;\n typingFailureWarned = true;\n log.logWarning(\n `${platform.label} sendTyping failed (further occurrences suppressed for this session)`,\n err instanceof Error ? err.message : String(err),\n );\n };\n if (isTyping && typingInterval === null) {\n typing.send().catch(onTypingError);\n typingInterval = setInterval(() => {\n typing.send().catch(onTypingError);\n }, typing.intervalMs);\n } else if (!isTyping) {\n stopTyping();\n }\n },\n\n setWorking: async (working: boolean) => {\n if (!platform.workingIndicator) {\n if (!working) stopTyping();\n return;\n }\n await run(\n \"setWorking\",\n \"set_working\",\n async () => {\n isWorking = working;\n if (!working) stopTyping();\n if (responseId !== null) {\n const [head] = splitText(\n render(accumulatedText),\n platform.maxLength,\n platform.formatContinuation,\n );\n await platform.update(responseId, head);\n }\n },\n () => ({ working }),\n );\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n if (platform.uploadFile) {\n await platform.uploadFile(filePath, title);\n return;\n }\n const note = platform.uploadFallbackNote?.(title ?? filePath);\n if (note === undefined) return;\n await run(\n \"uploadFile\",\n \"respond_diagnostic\",\n () => postExtra(note),\n () => ({ filePath }),\n );\n },\n\n ...(platform.react ? { react: platform.react } : {}),\n\n deleteResponse: async () => {\n await queue.run(async () => {\n stopTyping();\n if (responseId !== null) {\n try {\n await platform.delete?.(responseId);\n } catch {\n // Ignore errors\n }\n responseId = null;\n }\n });\n },\n };\n\n return { responder };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/blocks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/blocks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA+I/C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,CAmCxF"}
|
|
@@ -1,80 +1,46 @@
|
|
|
1
1
|
import MarkdownIt from "markdown-it";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
});
|
|
2
|
+
// Parser is used only to locate tables and derive plain-text fallback.
|
|
3
|
+
// Prose is never re-serialized from tokens: it is sliced verbatim from the
|
|
4
|
+
// source and handed to Slack as a native `markdown` block, so Slack owns
|
|
5
|
+
// all prose rendering (same renderer as the markdown_text streaming API).
|
|
6
|
+
const markdown = new MarkdownIt({ html: false });
|
|
7
7
|
const MAX_BLOCKS = 50;
|
|
8
|
-
|
|
8
|
+
// Slack rejects messages whose markdown block text exceeds 12k (msg_too_long).
|
|
9
|
+
const MARKDOWN_TEXT_LIMIT = 12000;
|
|
9
10
|
const FIELD_TEXT_LIMIT = 2000;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
// Legacy Slack-style links (<url|label>) predate the standard-GFM response
|
|
12
|
+
// source contract; system producers may still emit them.
|
|
13
|
+
const LEGACY_MRKDWN_LINK_PATTERN = /<(https?:\/\/[^<>|\s]+)\|([^<>\n]+)>/g;
|
|
14
|
+
function convertLegacyMrkdwnLinks(source) {
|
|
15
|
+
return source.replace(LEGACY_MRKDWN_LINK_PATTERN, "[$2]($1)");
|
|
16
|
+
}
|
|
17
|
+
function normalizeMarkdownTables(source) {
|
|
18
|
+
return source
|
|
19
|
+
.split("\n")
|
|
20
|
+
.map((line) => {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (!trimmed.startsWith("|") || !trimmed.endsWith("|"))
|
|
23
|
+
return line;
|
|
24
|
+
if (!/^[|+\-:\s]+$/.test(trimmed) || !trimmed.includes("+"))
|
|
25
|
+
return line;
|
|
26
|
+
return line.replaceAll("+", "|");
|
|
27
|
+
})
|
|
28
|
+
.join("\n");
|
|
20
29
|
}
|
|
21
|
-
function
|
|
30
|
+
function inlinePlainText(tokens) {
|
|
22
31
|
if (!tokens)
|
|
23
32
|
return "";
|
|
24
33
|
let text = "";
|
|
25
|
-
for (
|
|
26
|
-
|
|
27
|
-
const linkText = tokens[i + 1];
|
|
28
|
-
const linkClose = tokens[i + 2];
|
|
29
|
-
if (token.type === "link_open" &&
|
|
30
|
-
token.markup === "autolink" &&
|
|
31
|
-
linkText?.type === "text" &&
|
|
32
|
-
linkText.content.includes("|") &&
|
|
33
|
-
linkClose?.type === "link_close") {
|
|
34
|
-
text += `<${linkText.content}>`;
|
|
35
|
-
i += 2;
|
|
36
|
-
}
|
|
37
|
-
else if (token.type === "text" || token.type === "code_inline")
|
|
34
|
+
for (const token of tokens) {
|
|
35
|
+
if (token.type === "text" || token.type === "code_inline")
|
|
38
36
|
text += token.content;
|
|
39
37
|
else if (token.type === "softbreak" || token.type === "hardbreak")
|
|
40
38
|
text += "\n";
|
|
41
|
-
else if (token.
|
|
42
|
-
text +=
|
|
43
|
-
else if (token.type === "strong_close")
|
|
44
|
-
text += "*";
|
|
45
|
-
else if (token.type === "em_open")
|
|
46
|
-
text += "_";
|
|
47
|
-
else if (token.type === "em_close")
|
|
48
|
-
text += "_";
|
|
49
|
-
else if (token.type === "link_open") {
|
|
50
|
-
const href = token.attrGet("href");
|
|
51
|
-
if (href)
|
|
52
|
-
text += `<${href}|`;
|
|
53
|
-
}
|
|
54
|
-
else if (token.type === "link_close") {
|
|
55
|
-
text += ">";
|
|
56
|
-
}
|
|
57
|
-
else if (token.children) {
|
|
58
|
-
text += renderInline(token.children);
|
|
59
|
-
}
|
|
39
|
+
else if (token.children)
|
|
40
|
+
text += inlinePlainText(token.children);
|
|
60
41
|
}
|
|
61
42
|
return text;
|
|
62
43
|
}
|
|
63
|
-
function collectInlineUntil(tokens, index, endType) {
|
|
64
|
-
let text = "";
|
|
65
|
-
let i = index;
|
|
66
|
-
for (; i < tokens.length && tokens[i].type !== endType; i++) {
|
|
67
|
-
const token = tokens[i];
|
|
68
|
-
if (token.type === "inline")
|
|
69
|
-
text += renderInline(token.children) || token.content;
|
|
70
|
-
else if (token.type === "fence" || token.type === "code_block")
|
|
71
|
-
text += `\n\`\`\`\n${token.content}\n\`\`\``;
|
|
72
|
-
}
|
|
73
|
-
return { text, next: i };
|
|
74
|
-
}
|
|
75
|
-
function isTableAt(tokens, index) {
|
|
76
|
-
return tokens[index]?.type === "table_open";
|
|
77
|
-
}
|
|
78
44
|
function buildTableBlock(headers, rows) {
|
|
79
45
|
const hasIndex = headers[0] === "#";
|
|
80
46
|
const tableHeaders = hasIndex ? headers : ["#", ...headers];
|
|
@@ -88,7 +54,8 @@ function buildTableBlock(headers, rows) {
|
|
|
88
54
|
};
|
|
89
55
|
}
|
|
90
56
|
function parseTable(tokens, index) {
|
|
91
|
-
|
|
57
|
+
const open = tokens[index];
|
|
58
|
+
if (open?.type !== "table_open" || !open.map)
|
|
92
59
|
return null;
|
|
93
60
|
const headers = [];
|
|
94
61
|
const rows = [];
|
|
@@ -111,110 +78,99 @@ function parseTable(tokens, index) {
|
|
|
111
78
|
currentRow = null;
|
|
112
79
|
}
|
|
113
80
|
else if (token.type === "inline" && currentRow) {
|
|
114
|
-
currentRow.push(
|
|
81
|
+
currentRow.push(inlinePlainText(token.children) || token.content);
|
|
115
82
|
}
|
|
116
83
|
}
|
|
117
84
|
if (!headers.length || !rows.length)
|
|
118
85
|
return null;
|
|
119
86
|
const fallback = [headers.join(" | "), ...rows.map((row) => row.join(" | "))].join("\n");
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return line;
|
|
131
|
-
return line.replaceAll("+", "|");
|
|
132
|
-
})
|
|
133
|
-
.join("\n");
|
|
134
|
-
}
|
|
135
|
-
const SLACK_MRKDWN_LINK_PATTERN = /<https?:\/\/[^<>|\s]+\|[^<>\n]+>/g;
|
|
136
|
-
function protectSlackMrkdwnLinks(source) {
|
|
137
|
-
const links = [];
|
|
138
|
-
const protectedSource = source.replace(SLACK_MRKDWN_LINK_PATTERN, (link) => {
|
|
139
|
-
const index = links.push(link) - 1;
|
|
140
|
-
return `MIKANSLACKLINK${index}PLACEHOLDER`;
|
|
141
|
-
});
|
|
142
|
-
return { source: protectedSource, links };
|
|
87
|
+
const endLine = tokens[i]?.map?.[1] ?? open.map[1];
|
|
88
|
+
return {
|
|
89
|
+
table: {
|
|
90
|
+
block: buildTableBlock(headers, rows),
|
|
91
|
+
fallback,
|
|
92
|
+
startLine: open.map[0],
|
|
93
|
+
endLine,
|
|
94
|
+
},
|
|
95
|
+
next: i,
|
|
96
|
+
};
|
|
143
97
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
98
|
+
/** Split prose into chunks under the markdown block limit, preferring
|
|
99
|
+
* paragraph boundaries, then line boundaries, then a hard slice. */
|
|
100
|
+
function splitProse(text) {
|
|
101
|
+
if (text.length <= MARKDOWN_TEXT_LIMIT)
|
|
102
|
+
return [text];
|
|
103
|
+
const chunks = [];
|
|
104
|
+
let rest = text;
|
|
105
|
+
while (rest.length > MARKDOWN_TEXT_LIMIT) {
|
|
106
|
+
const window = rest.slice(0, MARKDOWN_TEXT_LIMIT);
|
|
107
|
+
let cut = window.lastIndexOf("\n\n");
|
|
108
|
+
if (cut <= 0)
|
|
109
|
+
cut = window.lastIndexOf("\n");
|
|
110
|
+
if (cut <= 0)
|
|
111
|
+
cut = MARKDOWN_TEXT_LIMIT;
|
|
112
|
+
chunks.push(rest.slice(0, cut));
|
|
113
|
+
rest = rest.slice(cut);
|
|
114
|
+
}
|
|
115
|
+
if (rest.trim())
|
|
116
|
+
chunks.push(rest);
|
|
117
|
+
return chunks;
|
|
148
118
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
151
|
-
|
|
119
|
+
function pushMarkdown(blocks, prose) {
|
|
120
|
+
const trimmed = prose.trim();
|
|
121
|
+
if (!trimmed)
|
|
122
|
+
return;
|
|
123
|
+
for (const chunk of splitProse(trimmed)) {
|
|
124
|
+
if (blocks.length >= MAX_BLOCKS)
|
|
125
|
+
return;
|
|
126
|
+
const text = chunk.trim();
|
|
127
|
+
if (text)
|
|
128
|
+
blocks.push({ type: "markdown", text });
|
|
152
129
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
130
|
+
}
|
|
131
|
+
function plainTextFallback(tokens) {
|
|
132
|
+
const parts = [];
|
|
133
|
+
for (const token of tokens) {
|
|
134
|
+
if (token.type === "inline")
|
|
135
|
+
parts.push(inlinePlainText(token.children) || token.content);
|
|
136
|
+
else if (token.type === "fence" || token.type === "code_block")
|
|
137
|
+
parts.push(token.content.trimEnd());
|
|
161
138
|
}
|
|
162
|
-
return
|
|
139
|
+
return parts.filter(Boolean).join("\n");
|
|
163
140
|
}
|
|
164
141
|
export function renderSlackBlocks(source) {
|
|
165
|
-
const
|
|
166
|
-
const tokens = markdown.parse(
|
|
142
|
+
const normalized = normalizeMarkdownTables(convertLegacyMrkdwnLinks(source));
|
|
143
|
+
const tokens = markdown.parse(normalized, {});
|
|
144
|
+
const lines = normalized.split("\n");
|
|
145
|
+
const tables = [];
|
|
146
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
147
|
+
const parsed = parseTable(tokens, i);
|
|
148
|
+
if (parsed) {
|
|
149
|
+
tables.push(parsed.table);
|
|
150
|
+
i = parsed.next;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
167
153
|
const blocks = [];
|
|
168
154
|
const fallback = [];
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
155
|
+
let cursor = 0;
|
|
156
|
+
for (const table of tables) {
|
|
157
|
+
const prose = lines.slice(cursor, table.startLine).join("\n");
|
|
158
|
+
pushMarkdown(blocks, prose);
|
|
159
|
+
if (prose.trim())
|
|
160
|
+
fallback.push(plainTextFallback(markdown.parse(prose, {})));
|
|
161
|
+
if (blocks.length < MAX_BLOCKS) {
|
|
162
|
+
blocks.push(table.block);
|
|
174
163
|
fallback.push(table.fallback);
|
|
175
|
-
i = table.next;
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
if (token.type === "heading_open") {
|
|
179
|
-
const collected = collectInlineUntil(tokens, i + 1, "heading_close");
|
|
180
|
-
const text = `*${collected.text}*`;
|
|
181
|
-
pushSection(blocks, text);
|
|
182
|
-
fallback.push(collected.text);
|
|
183
|
-
i = collected.next;
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
if (token.type === "paragraph_open") {
|
|
187
|
-
const collected = collectInlineUntil(tokens, i + 1, "paragraph_close");
|
|
188
|
-
pushSection(blocks, collected.text);
|
|
189
|
-
fallback.push(collected.text);
|
|
190
|
-
i = collected.next;
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
if (token.type === "bullet_list_open" || token.type === "ordered_list_open") {
|
|
194
|
-
const lines = [];
|
|
195
|
-
let item = 1;
|
|
196
|
-
for (i += 1; i < tokens.length && !tokens[i].type.endsWith("list_close"); i++) {
|
|
197
|
-
if (tokens[i].type !== "inline")
|
|
198
|
-
continue;
|
|
199
|
-
const marker = token.type === "ordered_list_open" ? `${item++}.` : "•";
|
|
200
|
-
lines.push(`${marker} ${renderInline(tokens[i].children) || tokens[i].content}`);
|
|
201
|
-
}
|
|
202
|
-
const text = lines.join("\n");
|
|
203
|
-
pushSection(blocks, text);
|
|
204
|
-
fallback.push(text);
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
if (token.type === "fence" || token.type === "code_block") {
|
|
208
|
-
const text = `\`\`\`\n${token.content}\n\`\`\``;
|
|
209
|
-
pushSection(blocks, text);
|
|
210
|
-
fallback.push(token.content);
|
|
211
164
|
}
|
|
165
|
+
cursor = table.endLine;
|
|
212
166
|
}
|
|
213
|
-
|
|
214
|
-
|
|
167
|
+
const trailingProse = lines.slice(cursor).join("\n");
|
|
168
|
+
pushMarkdown(blocks, trailingProse);
|
|
169
|
+
if (trailingProse.trim())
|
|
170
|
+
fallback.push(plainTextFallback(markdown.parse(trailingProse, {})));
|
|
215
171
|
return {
|
|
216
|
-
text:
|
|
217
|
-
blocks
|
|
172
|
+
text: fallback.filter(Boolean).join("\n\n") || normalized,
|
|
173
|
+
blocks,
|
|
218
174
|
};
|
|
219
175
|
}
|
|
220
176
|
//# sourceMappingURL=blocks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../../src/adapters/slack/blocks.ts"],"names":[],"mappings":"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","sourcesContent":["import MarkdownIt from \"markdown-it\";\nimport type Token from \"markdown-it/lib/token.mjs\";\nimport type { KnownBlock } from \"@slack/types\";\n\nconst markdown = new MarkdownIt({\n html: false,\n linkify: true,\n breaks: true,\n});\n\nconst MAX_BLOCKS = 50;\nconst SECTION_TEXT_LIMIT = 3000;\nconst FIELD_TEXT_LIMIT = 2000;\n\nfunction pushSection(blocks: KnownBlock[], text: string): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n for (let i = 0; i < trimmed.length && blocks.length < MAX_BLOCKS; i += SECTION_TEXT_LIMIT) {\n blocks.push({\n type: \"section\",\n text: { type: \"mrkdwn\", text: trimmed.slice(i, i + SECTION_TEXT_LIMIT) },\n } as KnownBlock);\n }\n}\n\nfunction renderInline(tokens: Token[] | null | undefined): string {\n if (!tokens) return \"\";\n let text = \"\";\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n const linkText = tokens[i + 1];\n const linkClose = tokens[i + 2];\n if (\n token.type === \"link_open\" &&\n token.markup === \"autolink\" &&\n linkText?.type === \"text\" &&\n linkText.content.includes(\"|\") &&\n linkClose?.type === \"link_close\"\n ) {\n text += `<${linkText.content}>`;\n i += 2;\n } else if (token.type === \"text\" || token.type === \"code_inline\") text += token.content;\n else if (token.type === \"softbreak\" || token.type === \"hardbreak\") text += \"\\n\";\n else if (token.type === \"strong_open\") text += \"*\";\n else if (token.type === \"strong_close\") text += \"*\";\n else if (token.type === \"em_open\") text += \"_\";\n else if (token.type === \"em_close\") text += \"_\";\n else if (token.type === \"link_open\") {\n const href = token.attrGet(\"href\");\n if (href) text += `<${href}|`;\n } else if (token.type === \"link_close\") {\n text += \">\";\n } else if (token.children) {\n text += renderInline(token.children);\n }\n }\n return text;\n}\n\nfunction collectInlineUntil(\n tokens: Token[],\n index: number,\n endType: string,\n): { text: string; next: number } {\n let text = \"\";\n let i = index;\n for (; i < tokens.length && tokens[i].type !== endType; i++) {\n const token = tokens[i];\n if (token.type === \"inline\") text += renderInline(token.children) || token.content;\n else if (token.type === \"fence\" || token.type === \"code_block\")\n text += `\\n\\`\\`\\`\\n${token.content}\\n\\`\\`\\``;\n }\n return { text, next: i };\n}\n\nfunction isTableAt(tokens: Token[], index: number): boolean {\n return tokens[index]?.type === \"table_open\";\n}\n\nfunction buildTableBlock(headers: string[], rows: string[][]): KnownBlock {\n const hasIndex = headers[0] === \"#\";\n const tableHeaders = hasIndex ? headers : [\"#\", ...headers];\n const tableRows = hasIndex\n ? rows\n : rows.map((row, rowNumber) => [String(rowNumber + 1)].concat(row));\n return {\n type: \"table\",\n rows: [tableHeaders, ...tableRows].map((row) =>\n row.map((cell) => ({ type: \"raw_text\", text: (cell || \" \").slice(0, FIELD_TEXT_LIMIT) })),\n ),\n column_settings: tableHeaders.map(() => ({ is_wrapped: true })),\n } as KnownBlock;\n}\n\nfunction parseTable(\n tokens: Token[],\n index: number,\n): { blocks: KnownBlock[]; fallback: string; next: number } | null {\n if (!isTableAt(tokens, index)) return null;\n\n const headers: string[] = [];\n const rows: string[][] = [];\n let currentRow: string[] | null = null;\n let inHead = false;\n let i = index + 1;\n\n for (; i < tokens.length && tokens[i].type !== \"table_close\"; i++) {\n const token = tokens[i];\n if (token.type === \"thead_open\") inHead = true;\n else if (token.type === \"thead_close\") inHead = false;\n else if (token.type === \"tr_open\") currentRow = [];\n else if (token.type === \"tr_close\" && currentRow) {\n if (inHead) headers.push(...currentRow);\n else rows.push(currentRow);\n currentRow = null;\n } else if (token.type === \"inline\" && currentRow) {\n currentRow.push(renderInline(token.children) || token.content);\n }\n }\n\n if (!headers.length || !rows.length) return null;\n\n const fallback = [headers.join(\" | \"), ...rows.map((row) => row.join(\" | \"))].join(\"\\n\");\n return { blocks: [buildTableBlock(headers, rows)], fallback, next: i };\n}\n\nfunction normalizeMarkdownTables(source: string): string {\n return source\n .split(\"\\n\")\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"|\") || !trimmed.endsWith(\"|\")) return line;\n if (!/^[|+\\-:\\s]+$/.test(trimmed) || !trimmed.includes(\"+\")) return line;\n return line.replaceAll(\"+\", \"|\");\n })\n .join(\"\\n\");\n}\n\nconst SLACK_MRKDWN_LINK_PATTERN = /<https?:\\/\\/[^<>|\\s]+\\|[^<>\\n]+>/g;\n\nfunction protectSlackMrkdwnLinks(source: string): { source: string; links: string[] } {\n const links: string[] = [];\n const protectedSource = source.replace(SLACK_MRKDWN_LINK_PATTERN, (link) => {\n const index = links.push(link) - 1;\n return `MIKANSLACKLINK${index}PLACEHOLDER`;\n });\n return { source: protectedSource, links };\n}\n\nfunction restoreSlackMrkdwnLinks(text: string, links: string[]): string {\n return text.replace(/MIKANSLACKLINK(\\d+)PLACEHOLDER/g, (placeholder, indexText: string) => {\n return links[Number(indexText)] ?? placeholder;\n });\n}\n\nfunction restoreBlockLinks(block: KnownBlock, links: string[]): KnownBlock {\n if (block.type === \"section\" && block.text?.type === \"mrkdwn\") {\n block.text.text = restoreSlackMrkdwnLinks(block.text.text, links);\n } else if (block.type === \"table\") {\n for (const row of block.rows) {\n for (const cell of row) {\n if (\"text\" in cell && typeof cell.text === \"string\") {\n cell.text = restoreSlackMrkdwnLinks(cell.text, links);\n }\n }\n }\n }\n return block;\n}\n\nexport function renderSlackBlocks(source: string): { text: string; blocks: KnownBlock[] } {\n const protectedSource = protectSlackMrkdwnLinks(normalizeMarkdownTables(source));\n const tokens = markdown.parse(protectedSource.source, {});\n const blocks: KnownBlock[] = [];\n const fallback: string[] = [];\n\n for (let i = 0; i < tokens.length && blocks.length < MAX_BLOCKS; i++) {\n const token = tokens[i];\n\n const table = parseTable(tokens, i);\n if (table) {\n blocks.push(...table.blocks.slice(0, MAX_BLOCKS - blocks.length));\n fallback.push(table.fallback);\n i = table.next;\n continue;\n }\n\n if (token.type === \"heading_open\") {\n const collected = collectInlineUntil(tokens, i + 1, \"heading_close\");\n const text = `*${collected.text}*`;\n pushSection(blocks, text);\n fallback.push(collected.text);\n i = collected.next;\n continue;\n }\n\n if (token.type === \"paragraph_open\") {\n const collected = collectInlineUntil(tokens, i + 1, \"paragraph_close\");\n pushSection(blocks, collected.text);\n fallback.push(collected.text);\n i = collected.next;\n continue;\n }\n\n if (token.type === \"bullet_list_open\" || token.type === \"ordered_list_open\") {\n const lines: string[] = [];\n let item = 1;\n for (i += 1; i < tokens.length && !tokens[i].type.endsWith(\"list_close\"); i++) {\n if (tokens[i].type !== \"inline\") continue;\n const marker = token.type === \"ordered_list_open\" ? `${item++}.` : \"•\";\n lines.push(`${marker} ${renderInline(tokens[i].children) || tokens[i].content}`);\n }\n const text = lines.join(\"\\n\");\n pushSection(blocks, text);\n fallback.push(text);\n continue;\n }\n\n if (token.type === \"fence\" || token.type === \"code_block\") {\n const text = `\\`\\`\\`\\n${token.content}\\n\\`\\`\\``;\n pushSection(blocks, text);\n fallback.push(token.content);\n }\n }\n\n if (!blocks.length) pushSection(blocks, protectedSource.source);\n return {\n text: restoreSlackMrkdwnLinks(\n fallback.join(\"\\n\\n\") || protectedSource.source,\n protectedSource.links,\n ),\n blocks: blocks.map((block) => restoreBlockLinks(block, protectedSource.links)),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../../src/adapters/slack/blocks.ts"],"names":[],"mappings":"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","sourcesContent":["import MarkdownIt from \"markdown-it\";\nimport type Token from \"markdown-it/lib/token.mjs\";\nimport type { KnownBlock } from \"@slack/types\";\n\n// Parser is used only to locate tables and derive plain-text fallback.\n// Prose is never re-serialized from tokens: it is sliced verbatim from the\n// source and handed to Slack as a native `markdown` block, so Slack owns\n// all prose rendering (same renderer as the markdown_text streaming API).\nconst markdown = new MarkdownIt({ html: false });\n\nconst MAX_BLOCKS = 50;\n// Slack rejects messages whose markdown block text exceeds 12k (msg_too_long).\nconst MARKDOWN_TEXT_LIMIT = 12000;\nconst FIELD_TEXT_LIMIT = 2000;\n\n// Legacy Slack-style links (<url|label>) predate the standard-GFM response\n// source contract; system producers may still emit them.\nconst LEGACY_MRKDWN_LINK_PATTERN = /<(https?:\\/\\/[^<>|\\s]+)\\|([^<>\\n]+)>/g;\n\nfunction convertLegacyMrkdwnLinks(source: string): string {\n return source.replace(LEGACY_MRKDWN_LINK_PATTERN, \"[$2]($1)\");\n}\n\nfunction normalizeMarkdownTables(source: string): string {\n return source\n .split(\"\\n\")\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"|\") || !trimmed.endsWith(\"|\")) return line;\n if (!/^[|+\\-:\\s]+$/.test(trimmed) || !trimmed.includes(\"+\")) return line;\n return line.replaceAll(\"+\", \"|\");\n })\n .join(\"\\n\");\n}\n\nfunction inlinePlainText(tokens: Token[] | null | undefined): string {\n if (!tokens) return \"\";\n let text = \"\";\n for (const token of tokens) {\n if (token.type === \"text\" || token.type === \"code_inline\") text += token.content;\n else if (token.type === \"softbreak\" || token.type === \"hardbreak\") text += \"\\n\";\n else if (token.children) text += inlinePlainText(token.children);\n }\n return text;\n}\n\nfunction buildTableBlock(headers: string[], rows: string[][]): KnownBlock {\n const hasIndex = headers[0] === \"#\";\n const tableHeaders = hasIndex ? headers : [\"#\", ...headers];\n const tableRows = hasIndex\n ? rows\n : rows.map((row, rowNumber) => [String(rowNumber + 1)].concat(row));\n return {\n type: \"table\",\n rows: [tableHeaders, ...tableRows].map((row) =>\n row.map((cell) => ({ type: \"raw_text\", text: (cell || \" \").slice(0, FIELD_TEXT_LIMIT) })),\n ),\n column_settings: tableHeaders.map(() => ({ is_wrapped: true })),\n } as KnownBlock;\n}\n\ninterface ParsedTable {\n block: KnownBlock;\n fallback: string;\n startLine: number;\n endLine: number;\n}\n\nfunction parseTable(tokens: Token[], index: number): { table: ParsedTable; next: number } | null {\n const open = tokens[index];\n if (open?.type !== \"table_open\" || !open.map) return null;\n\n const headers: string[] = [];\n const rows: string[][] = [];\n let currentRow: string[] | null = null;\n let inHead = false;\n let i = index + 1;\n\n for (; i < tokens.length && tokens[i].type !== \"table_close\"; i++) {\n const token = tokens[i];\n if (token.type === \"thead_open\") inHead = true;\n else if (token.type === \"thead_close\") inHead = false;\n else if (token.type === \"tr_open\") currentRow = [];\n else if (token.type === \"tr_close\" && currentRow) {\n if (inHead) headers.push(...currentRow);\n else rows.push(currentRow);\n currentRow = null;\n } else if (token.type === \"inline\" && currentRow) {\n currentRow.push(inlinePlainText(token.children) || token.content);\n }\n }\n\n if (!headers.length || !rows.length) return null;\n\n const fallback = [headers.join(\" | \"), ...rows.map((row) => row.join(\" | \"))].join(\"\\n\");\n const endLine = tokens[i]?.map?.[1] ?? open.map[1];\n return {\n table: {\n block: buildTableBlock(headers, rows),\n fallback,\n startLine: open.map[0],\n endLine,\n },\n next: i,\n };\n}\n\n/** Split prose into chunks under the markdown block limit, preferring\n * paragraph boundaries, then line boundaries, then a hard slice. */\nfunction splitProse(text: string): string[] {\n if (text.length <= MARKDOWN_TEXT_LIMIT) return [text];\n const chunks: string[] = [];\n let rest = text;\n while (rest.length > MARKDOWN_TEXT_LIMIT) {\n const window = rest.slice(0, MARKDOWN_TEXT_LIMIT);\n let cut = window.lastIndexOf(\"\\n\\n\");\n if (cut <= 0) cut = window.lastIndexOf(\"\\n\");\n if (cut <= 0) cut = MARKDOWN_TEXT_LIMIT;\n chunks.push(rest.slice(0, cut));\n rest = rest.slice(cut);\n }\n if (rest.trim()) chunks.push(rest);\n return chunks;\n}\n\nfunction pushMarkdown(blocks: KnownBlock[], prose: string): void {\n const trimmed = prose.trim();\n if (!trimmed) return;\n for (const chunk of splitProse(trimmed)) {\n if (blocks.length >= MAX_BLOCKS) return;\n const text = chunk.trim();\n if (text) blocks.push({ type: \"markdown\", text } as KnownBlock);\n }\n}\n\nfunction plainTextFallback(tokens: Token[]): string {\n const parts: string[] = [];\n for (const token of tokens) {\n if (token.type === \"inline\") parts.push(inlinePlainText(token.children) || token.content);\n else if (token.type === \"fence\" || token.type === \"code_block\")\n parts.push(token.content.trimEnd());\n }\n return parts.filter(Boolean).join(\"\\n\");\n}\n\nexport function renderSlackBlocks(source: string): { text: string; blocks: KnownBlock[] } {\n const normalized = normalizeMarkdownTables(convertLegacyMrkdwnLinks(source));\n const tokens = markdown.parse(normalized, {});\n const lines = normalized.split(\"\\n\");\n\n const tables: ParsedTable[] = [];\n for (let i = 0; i < tokens.length; i++) {\n const parsed = parseTable(tokens, i);\n if (parsed) {\n tables.push(parsed.table);\n i = parsed.next;\n }\n }\n\n const blocks: KnownBlock[] = [];\n const fallback: string[] = [];\n let cursor = 0;\n for (const table of tables) {\n const prose = lines.slice(cursor, table.startLine).join(\"\\n\");\n pushMarkdown(blocks, prose);\n if (prose.trim()) fallback.push(plainTextFallback(markdown.parse(prose, {})));\n if (blocks.length < MAX_BLOCKS) {\n blocks.push(table.block);\n fallback.push(table.fallback);\n }\n cursor = table.endLine;\n }\n const trailingProse = lines.slice(cursor).join(\"\\n\");\n pushMarkdown(blocks, trailingProse);\n if (trailingProse.trim()) fallback.push(plainTextFallback(markdown.parse(trailingProse, {})));\n\n return {\n text: fallback.filter(Boolean).join(\"\\n\\n\") || normalized,\n blocks,\n };\n}\n"]}
|
|
@@ -42,6 +42,7 @@ export declare class SlackMessagingBot implements MessagingBot {
|
|
|
42
42
|
postEphemeral(channel: string, user: string, text: string, threadTs?: string): Promise<void>;
|
|
43
43
|
postEphemeralBlocks(channel: string, user: string, text: string, blocks: object[], threadTs?: string): Promise<void>;
|
|
44
44
|
postMessageBlocks(channel: string, text: string, blocks: object[]): Promise<string>;
|
|
45
|
+
updateMessageBlocks(channel: string, ts: string, text: string, blocks: object[]): Promise<void>;
|
|
45
46
|
postPrivate(conversationId: string, userId: string, text: string): Promise<void>;
|
|
46
47
|
postPrivateDiagnostic(conversationId: string, userId: string, text: string, options?: {
|
|
47
48
|
style?: "muted" | "error";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/bot.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EAEZ,iBAAiB,EACjB,qBAAqB,EAKrB,aAAa,EACd,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/bot.ts"],"names":[],"mappings":"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"}
|