lark-agent-bridge 0.1.39

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.
Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/README.zh.md +265 -0
  4. package/bin/lark-agent-bridge.mjs +2 -0
  5. package/dist/agent/cursor/cursor-sdk-worker.js +702 -0
  6. package/dist/cli.js +7588 -0
  7. package/dist/index.d.ts +113 -0
  8. package/dist/index.js +721 -0
  9. package/package.json +72 -0
  10. package/vendor/cursor-sdk/LICENSE.md +3 -0
  11. package/vendor/cursor-sdk/README.md +23 -0
  12. package/vendor/cursor-sdk/dist/cjs/642.index.js +1 -0
  13. package/vendor/cursor-sdk/dist/cjs/agent.d.ts +170 -0
  14. package/vendor/cursor-sdk/dist/cjs/agent.d.ts.map +1 -0
  15. package/vendor/cursor-sdk/dist/cjs/analytics.d.ts +98 -0
  16. package/vendor/cursor-sdk/dist/cjs/analytics.d.ts.map +1 -0
  17. package/vendor/cursor-sdk/dist/cjs/artifacts.d.ts +6 -0
  18. package/vendor/cursor-sdk/dist/cjs/artifacts.d.ts.map +1 -0
  19. package/vendor/cursor-sdk/dist/cjs/cloud-agent.d.ts +47 -0
  20. package/vendor/cursor-sdk/dist/cjs/cloud-agent.d.ts.map +1 -0
  21. package/vendor/cursor-sdk/dist/cjs/cloud-api-client.d.ts +197 -0
  22. package/vendor/cursor-sdk/dist/cjs/cloud-api-client.d.ts.map +1 -0
  23. package/vendor/cursor-sdk/dist/cjs/cloud-executor.d.ts +14 -0
  24. package/vendor/cursor-sdk/dist/cjs/cloud-executor.d.ts.map +1 -0
  25. package/vendor/cursor-sdk/dist/cjs/cloud-mcp-utils.d.ts +4 -0
  26. package/vendor/cursor-sdk/dist/cjs/cloud-mcp-utils.d.ts.map +1 -0
  27. package/vendor/cursor-sdk/dist/cjs/core-adapter.d.ts +2 -0
  28. package/vendor/cursor-sdk/dist/cjs/core-adapter.d.ts.map +1 -0
  29. package/vendor/cursor-sdk/dist/cjs/errors.d.ts +135 -0
  30. package/vendor/cursor-sdk/dist/cjs/errors.d.ts.map +1 -0
  31. package/vendor/cursor-sdk/dist/cjs/executor-common.d.ts +16 -0
  32. package/vendor/cursor-sdk/dist/cjs/executor-common.d.ts.map +1 -0
  33. package/vendor/cursor-sdk/dist/cjs/executor-types.d.ts +65 -0
  34. package/vendor/cursor-sdk/dist/cjs/executor-types.d.ts.map +1 -0
  35. package/vendor/cursor-sdk/dist/cjs/index.d.ts +18 -0
  36. package/vendor/cursor-sdk/dist/cjs/index.d.ts.map +1 -0
  37. package/vendor/cursor-sdk/dist/cjs/index.js +8 -0
  38. package/vendor/cursor-sdk/dist/cjs/index.js.LICENSE.txt +285 -0
  39. package/vendor/cursor-sdk/dist/cjs/local-executor.d.ts +18 -0
  40. package/vendor/cursor-sdk/dist/cjs/local-executor.d.ts.map +1 -0
  41. package/vendor/cursor-sdk/dist/cjs/local-model-validation.d.ts +6 -0
  42. package/vendor/cursor-sdk/dist/cjs/local-model-validation.d.ts.map +1 -0
  43. package/vendor/cursor-sdk/dist/cjs/messages.d.ts +110 -0
  44. package/vendor/cursor-sdk/dist/cjs/messages.d.ts.map +1 -0
  45. package/vendor/cursor-sdk/dist/cjs/options.d.ts +145 -0
  46. package/vendor/cursor-sdk/dist/cjs/options.d.ts.map +1 -0
  47. package/vendor/cursor-sdk/dist/cjs/package.json +3 -0
  48. package/vendor/cursor-sdk/dist/cjs/platform.d.ts +71 -0
  49. package/vendor/cursor-sdk/dist/cjs/platform.d.ts.map +1 -0
  50. package/vendor/cursor-sdk/dist/cjs/prefetched-blobs.d.ts +13 -0
  51. package/vendor/cursor-sdk/dist/cjs/prefetched-blobs.d.ts.map +1 -0
  52. package/vendor/cursor-sdk/dist/cjs/public-api.d.ts +12 -0
  53. package/vendor/cursor-sdk/dist/cjs/public-api.d.ts.map +1 -0
  54. package/vendor/cursor-sdk/dist/cjs/run-event-tailer.d.ts +33 -0
  55. package/vendor/cursor-sdk/dist/cjs/run-event-tailer.d.ts.map +1 -0
  56. package/vendor/cursor-sdk/dist/cjs/run-interaction-accumulator.d.ts +33 -0
  57. package/vendor/cursor-sdk/dist/cjs/run-interaction-accumulator.d.ts.map +1 -0
  58. package/vendor/cursor-sdk/dist/cjs/run.d.ts +44 -0
  59. package/vendor/cursor-sdk/dist/cjs/run.d.ts.map +1 -0
  60. package/vendor/cursor-sdk/dist/cjs/sdk-statsig.d.ts +10 -0
  61. package/vendor/cursor-sdk/dist/cjs/sdk-statsig.d.ts.map +1 -0
  62. package/vendor/cursor-sdk/dist/cjs/stubs.d.ts +98 -0
  63. package/vendor/cursor-sdk/dist/cjs/stubs.d.ts.map +1 -0
  64. package/vendor/cursor-sdk/dist/cjs/subagent-conversion.d.ts +22 -0
  65. package/vendor/cursor-sdk/dist/cjs/subagent-conversion.d.ts.map +1 -0
  66. package/vendor/cursor-sdk/dist/cjs/tool-call-utils.d.ts +7 -0
  67. package/vendor/cursor-sdk/dist/cjs/tool-call-utils.d.ts.map +1 -0
  68. package/vendor/cursor-sdk/dist/cjs/types/conversation-types.d.ts +12062 -0
  69. package/vendor/cursor-sdk/dist/cjs/types/conversation-types.d.ts.map +1 -0
  70. package/vendor/cursor-sdk/dist/cjs/types/delta-types.d.ts +2 -0
  71. package/vendor/cursor-sdk/dist/cjs/types/delta-types.d.ts.map +1 -0
  72. package/vendor/cursor-sdk/dist/cjs/types/tool-call-types.d.ts +2 -0
  73. package/vendor/cursor-sdk/dist/cjs/types/tool-call-types.d.ts.map +1 -0
  74. package/vendor/cursor-sdk/dist/cjs/utils/conversation-utils.d.ts +3 -0
  75. package/vendor/cursor-sdk/dist/cjs/utils/conversation-utils.d.ts.map +1 -0
  76. package/vendor/cursor-sdk/dist/cjs/utils/logger.d.ts +12 -0
  77. package/vendor/cursor-sdk/dist/cjs/utils/logger.d.ts.map +1 -0
  78. package/vendor/cursor-sdk/dist/cjs/utils/message-schemas.d.ts +2 -0
  79. package/vendor/cursor-sdk/dist/cjs/utils/message-schemas.d.ts.map +1 -0
  80. package/vendor/cursor-sdk/dist/esm/642.index.js +1 -0
  81. package/vendor/cursor-sdk/dist/esm/agent.d.ts +170 -0
  82. package/vendor/cursor-sdk/dist/esm/agent.d.ts.map +1 -0
  83. package/vendor/cursor-sdk/dist/esm/analytics.d.ts +98 -0
  84. package/vendor/cursor-sdk/dist/esm/analytics.d.ts.map +1 -0
  85. package/vendor/cursor-sdk/dist/esm/artifacts.d.ts +6 -0
  86. package/vendor/cursor-sdk/dist/esm/artifacts.d.ts.map +1 -0
  87. package/vendor/cursor-sdk/dist/esm/cloud-agent.d.ts +47 -0
  88. package/vendor/cursor-sdk/dist/esm/cloud-agent.d.ts.map +1 -0
  89. package/vendor/cursor-sdk/dist/esm/cloud-api-client.d.ts +197 -0
  90. package/vendor/cursor-sdk/dist/esm/cloud-api-client.d.ts.map +1 -0
  91. package/vendor/cursor-sdk/dist/esm/cloud-executor.d.ts +14 -0
  92. package/vendor/cursor-sdk/dist/esm/cloud-executor.d.ts.map +1 -0
  93. package/vendor/cursor-sdk/dist/esm/cloud-mcp-utils.d.ts +4 -0
  94. package/vendor/cursor-sdk/dist/esm/cloud-mcp-utils.d.ts.map +1 -0
  95. package/vendor/cursor-sdk/dist/esm/core-adapter.d.ts +2 -0
  96. package/vendor/cursor-sdk/dist/esm/core-adapter.d.ts.map +1 -0
  97. package/vendor/cursor-sdk/dist/esm/errors.d.ts +135 -0
  98. package/vendor/cursor-sdk/dist/esm/errors.d.ts.map +1 -0
  99. package/vendor/cursor-sdk/dist/esm/executor-common.d.ts +16 -0
  100. package/vendor/cursor-sdk/dist/esm/executor-common.d.ts.map +1 -0
  101. package/vendor/cursor-sdk/dist/esm/executor-types.d.ts +65 -0
  102. package/vendor/cursor-sdk/dist/esm/executor-types.d.ts.map +1 -0
  103. package/vendor/cursor-sdk/dist/esm/index.d.ts +18 -0
  104. package/vendor/cursor-sdk/dist/esm/index.d.ts.map +1 -0
  105. package/vendor/cursor-sdk/dist/esm/index.js +8 -0
  106. package/vendor/cursor-sdk/dist/esm/index.js.LICENSE.txt +285 -0
  107. package/vendor/cursor-sdk/dist/esm/local-executor.d.ts +18 -0
  108. package/vendor/cursor-sdk/dist/esm/local-executor.d.ts.map +1 -0
  109. package/vendor/cursor-sdk/dist/esm/local-model-validation.d.ts +6 -0
  110. package/vendor/cursor-sdk/dist/esm/local-model-validation.d.ts.map +1 -0
  111. package/vendor/cursor-sdk/dist/esm/messages.d.ts +110 -0
  112. package/vendor/cursor-sdk/dist/esm/messages.d.ts.map +1 -0
  113. package/vendor/cursor-sdk/dist/esm/options.d.ts +145 -0
  114. package/vendor/cursor-sdk/dist/esm/options.d.ts.map +1 -0
  115. package/vendor/cursor-sdk/dist/esm/platform.d.ts +71 -0
  116. package/vendor/cursor-sdk/dist/esm/platform.d.ts.map +1 -0
  117. package/vendor/cursor-sdk/dist/esm/prefetched-blobs.d.ts +13 -0
  118. package/vendor/cursor-sdk/dist/esm/prefetched-blobs.d.ts.map +1 -0
  119. package/vendor/cursor-sdk/dist/esm/public-api.d.ts +12 -0
  120. package/vendor/cursor-sdk/dist/esm/public-api.d.ts.map +1 -0
  121. package/vendor/cursor-sdk/dist/esm/run-event-tailer.d.ts +33 -0
  122. package/vendor/cursor-sdk/dist/esm/run-event-tailer.d.ts.map +1 -0
  123. package/vendor/cursor-sdk/dist/esm/run-interaction-accumulator.d.ts +33 -0
  124. package/vendor/cursor-sdk/dist/esm/run-interaction-accumulator.d.ts.map +1 -0
  125. package/vendor/cursor-sdk/dist/esm/run.d.ts +44 -0
  126. package/vendor/cursor-sdk/dist/esm/run.d.ts.map +1 -0
  127. package/vendor/cursor-sdk/dist/esm/sdk-statsig.d.ts +10 -0
  128. package/vendor/cursor-sdk/dist/esm/sdk-statsig.d.ts.map +1 -0
  129. package/vendor/cursor-sdk/dist/esm/stubs.d.ts +98 -0
  130. package/vendor/cursor-sdk/dist/esm/stubs.d.ts.map +1 -0
  131. package/vendor/cursor-sdk/dist/esm/subagent-conversion.d.ts +22 -0
  132. package/vendor/cursor-sdk/dist/esm/subagent-conversion.d.ts.map +1 -0
  133. package/vendor/cursor-sdk/dist/esm/tool-call-utils.d.ts +7 -0
  134. package/vendor/cursor-sdk/dist/esm/tool-call-utils.d.ts.map +1 -0
  135. package/vendor/cursor-sdk/dist/esm/types/conversation-types.d.ts +12062 -0
  136. package/vendor/cursor-sdk/dist/esm/types/conversation-types.d.ts.map +1 -0
  137. package/vendor/cursor-sdk/dist/esm/types/delta-types.d.ts +2 -0
  138. package/vendor/cursor-sdk/dist/esm/types/delta-types.d.ts.map +1 -0
  139. package/vendor/cursor-sdk/dist/esm/types/tool-call-types.d.ts +2 -0
  140. package/vendor/cursor-sdk/dist/esm/types/tool-call-types.d.ts.map +1 -0
  141. package/vendor/cursor-sdk/dist/esm/utils/conversation-utils.d.ts +3 -0
  142. package/vendor/cursor-sdk/dist/esm/utils/conversation-utils.d.ts.map +1 -0
  143. package/vendor/cursor-sdk/dist/esm/utils/logger.d.ts +12 -0
  144. package/vendor/cursor-sdk/dist/esm/utils/logger.d.ts.map +1 -0
  145. package/vendor/cursor-sdk/dist/esm/utils/message-schemas.d.ts +2 -0
  146. package/vendor/cursor-sdk/dist/esm/utils/message-schemas.d.ts.map +1 -0
  147. package/vendor/cursor-sdk/package.json +77 -0
  148. package/vendor/cursor-sdk-linux-x64/README.md +5 -0
  149. package/vendor/cursor-sdk-linux-x64/bin/cursorsandbox +0 -0
  150. package/vendor/cursor-sdk-linux-x64/bin/rg +0 -0
  151. package/vendor/cursor-sdk-linux-x64/package.json +8 -0
  152. package/vendor/package/README.md +5 -0
  153. package/vendor/package/bin/cursorsandbox +0 -0
  154. package/vendor/package/bin/rg +0 -0
  155. package/vendor/package/package.json +25 -0
package/dist/index.js ADDED
@@ -0,0 +1,721 @@
1
+ // src/card/tool-render.ts
2
+ var HEADER_SUMMARY_MAX = 80;
3
+ var BODY_FIELD_MAX = 600;
4
+ var OUTPUT_MAX = 1200;
5
+ var BODY_TOTAL_MAX = 2500;
6
+ function toolHeaderText(tool) {
7
+ const icon = tool.status === "done" ? "\u2705" : tool.status === "error" ? "\u274C" : "\u23F3";
8
+ const summary = summarizeInput(tool.name, tool.input);
9
+ const name = displayName(tool.name);
10
+ return summary ? `${icon} **${name}** \u2014 ${summary}` : `${icon} **${name}**`;
11
+ }
12
+ function isLowSignalTool(tool) {
13
+ if (tool.status === "error") return false;
14
+ const name = canonicalToolName(tool.name);
15
+ if (name === "read" || name === "glob" || name === "grep") return true;
16
+ if (name === "shell") return isContextCommand(tool.input);
17
+ return false;
18
+ }
19
+ function toolBodyMd(tool) {
20
+ const parts = [];
21
+ const inputMd = renderInput(tool);
22
+ if (inputMd) parts.push(inputMd);
23
+ if (tool.output) {
24
+ const truncated = truncate(tool.output, OUTPUT_MAX);
25
+ if (tool.status === "error") {
26
+ parts.push(`**Error**
27
+ \`\`\`
28
+ ${truncated}
29
+ \`\`\``);
30
+ } else if (tool.name === "Bash") {
31
+ parts.push(renderBashOutput(truncated));
32
+ } else {
33
+ parts.push(`**Output**
34
+ \`\`\`
35
+ ${truncated}
36
+ \`\`\``);
37
+ }
38
+ } else if (tool.status === "running") {
39
+ parts.push("_\u8FD0\u884C\u4E2D\u2026_");
40
+ }
41
+ const body = parts.join("\n\n");
42
+ if (body.length <= BODY_TOTAL_MAX) return body;
43
+ return `${body.slice(0, BODY_TOTAL_MAX)}\u2026
44
+
45
+ _\uFF08body \u5DF2\u622A\u65AD,\u5B8C\u6574\u5185\u5BB9\u67E5 \`/doctor\` \u6216\u65E5\u5FD7\uFF09_`;
46
+ }
47
+ function summarizeInput(name, input) {
48
+ if (!input || typeof input !== "object") return "";
49
+ const rec = input;
50
+ const pick = (key, max = HEADER_SUMMARY_MAX) => {
51
+ const v = rec[key];
52
+ if (typeof v !== "string") return "";
53
+ const oneLine2 = v.replace(/\s+/g, " ").trim();
54
+ return oneLine2.length > max ? `${oneLine2.slice(0, max)}\u2026` : oneLine2;
55
+ };
56
+ const path = () => pick("file_path") || pick("path");
57
+ switch (canonicalToolName(name)) {
58
+ case "shell":
59
+ return pick("command");
60
+ case "read":
61
+ case "edit":
62
+ case "write":
63
+ case "notebook_edit":
64
+ return shortenPath(path());
65
+ case "grep": {
66
+ const pat = pick("pattern", 40);
67
+ const where = pick("path", 30);
68
+ return where ? `${pat} in ${shortenPath(where)}` : pat;
69
+ }
70
+ case "glob":
71
+ return pick("pattern") || pick("glob_pattern");
72
+ case "web_fetch":
73
+ return pick("url");
74
+ case "web_search":
75
+ return pick("query", 60) || pick("search_term", 60);
76
+ case "agent":
77
+ case "task":
78
+ return pick("description") || pick("subagent_type");
79
+ default:
80
+ return pick("command") || path() || pick("query") || pick("search_term");
81
+ }
82
+ }
83
+ function renderInput(tool) {
84
+ const input = tool.input;
85
+ if (!input || typeof input !== "object") return "";
86
+ const rec = input;
87
+ const str = (k) => typeof rec[k] === "string" ? rec[k] : "";
88
+ switch (canonicalToolName(tool.name)) {
89
+ case "shell": {
90
+ const cmd = str("command");
91
+ return cmd ? `**Command**
92
+ \`\`\`bash
93
+ ${truncate(cmd, BODY_FIELD_MAX)}
94
+ \`\`\`` : "";
95
+ }
96
+ case "read":
97
+ case "edit":
98
+ case "write":
99
+ case "notebook_edit": {
100
+ const fp = str("file_path") || str("path");
101
+ return fp ? `**File** \`${fp}\`` : "";
102
+ }
103
+ case "grep": {
104
+ const lines = [];
105
+ if (str("pattern")) lines.push(`**Pattern** \`${str("pattern")}\``);
106
+ if (str("path")) lines.push(`**Path** \`${str("path")}\``);
107
+ return lines.join("\n");
108
+ }
109
+ case "web_fetch":
110
+ return str("url") ? `**URL** ${str("url")}` : "";
111
+ case "web_search": {
112
+ const query = str("query") || str("search_term");
113
+ return query ? `**Query** \`${truncate(query, BODY_FIELD_MAX)}\`` : "";
114
+ }
115
+ default:
116
+ return "";
117
+ }
118
+ }
119
+ function renderBashOutput(out) {
120
+ return `**Output**
121
+ \`\`\`
122
+ ${out}
123
+ \`\`\``;
124
+ }
125
+ function shortenPath(p) {
126
+ if (!p) return p;
127
+ const home = process.env.HOME || "";
128
+ if (home && p.startsWith(home)) return `~${p.slice(home.length)}`;
129
+ return p;
130
+ }
131
+ function displayName(name) {
132
+ switch (canonicalToolName(name)) {
133
+ case "shell":
134
+ return "\u7EC8\u7AEF";
135
+ case "read":
136
+ return "\u8BFB\u53D6\u6587\u4EF6";
137
+ case "grep":
138
+ return "\u641C\u7D22";
139
+ case "glob":
140
+ return "\u67E5\u627E\u6587\u4EF6";
141
+ case "edit":
142
+ return "\u7F16\u8F91\u6587\u4EF6";
143
+ case "write":
144
+ return "\u5199\u5165\u6587\u4EF6";
145
+ case "web_search":
146
+ return "\u7F51\u9875\u641C\u7D22";
147
+ case "web_fetch":
148
+ return "\u8BFB\u53D6\u7F51\u9875";
149
+ default:
150
+ return name;
151
+ }
152
+ }
153
+ function canonicalToolName(name) {
154
+ const n = name.replace(/^functions\./, "").replace(/[_\s-]/g, "").toLowerCase();
155
+ if (n === "bash" || n === "shell") return "shell";
156
+ if (n === "read" || n === "readfile") return "read";
157
+ if (n === "grep" || n === "rg" || n === "ripgrep") return "grep";
158
+ if (n === "glob") return "glob";
159
+ if (n === "edit" || n === "applypatch") return "edit";
160
+ if (n === "write") return "write";
161
+ if (n === "notebookedit" || n === "editnotebook") return "notebook_edit";
162
+ if (n === "websearch") return "web_search";
163
+ if (n === "webfetch") return "web_fetch";
164
+ if (n === "agent" || n === "task" || n === "subagent") return "agent";
165
+ return name.toLowerCase();
166
+ }
167
+ function isContextCommand(input) {
168
+ if (!input || typeof input !== "object") return false;
169
+ const command = input.command;
170
+ if (typeof command !== "string") return false;
171
+ const normalized = command.trim().replace(/\s+/g, " ");
172
+ return /^(git (status|log|diff|show)|ls\b|pwd\b|rg\b|npm (run )?typecheck\b)/.test(normalized);
173
+ }
174
+ function truncate(s, max) {
175
+ return s.length > max ? `${s.slice(0, max)}\u2026` : s;
176
+ }
177
+
178
+ // src/card/activity-render.ts
179
+ function activityText(activity, footer) {
180
+ if (activity?.kind === "tool") {
181
+ if (isLowSignalTool(activity.tool)) {
182
+ return footer ? phaseText(footer, "\u6B63\u5728\u51C6\u5907\u4E0A\u4E0B\u6587") : void 0;
183
+ }
184
+ return toolHeaderText(activity.tool);
185
+ }
186
+ if (activity?.kind === "phase") {
187
+ return phaseText(activity.phase, activity.label, activity.detail);
188
+ }
189
+ if (!footer) return void 0;
190
+ return phaseText(footer);
191
+ }
192
+ function phaseText(phase, label, detail) {
193
+ const fallback = phase === "starting" ? "\u6B63\u5728\u542F\u52A8 Agent" : phase === "thinking" ? "\u6B63\u5728\u601D\u8003" : phase === "tool_running" ? "\u6B63\u5728\u8C03\u7528\u5DE5\u5177" : "\u6B63\u5728\u8F93\u51FA\u56DE\u7B54";
194
+ const icon = phase === "starting" ? "\u{1F680}" : phase === "thinking" ? "\u{1F9E0}" : phase === "tool_running" ? "\u{1F9F0}" : "\u270D\uFE0F";
195
+ const main = label || fallback;
196
+ return detail && detail !== main ? `${icon} ${main} \u2014 ${detail}` : `${icon} ${main}`;
197
+ }
198
+
199
+ // src/card/todo-board-render.ts
200
+ var MAX_VISIBLE_TODOS = 6;
201
+ var TODO_CONTENT_MAX = 90;
202
+ function todoSummaryText(todos) {
203
+ if (todos.length === 0) return "";
204
+ const completed = todos.filter((todo) => todo.status === "completed").length;
205
+ const active = todos.find((todo) => todo.status === "in_progress");
206
+ const suffix = active ? ` \xB7 \u5F53\u524D: ${truncate2(oneLine(active.content), 28)}` : "";
207
+ return `${completed}/${todos.length} \u5B8C\u6210${suffix}`;
208
+ }
209
+ function renderTodoBoard(todos, running) {
210
+ if (todos.length === 0) return void 0;
211
+ return {
212
+ tag: "collapsible_panel",
213
+ expanded: running,
214
+ header: panelHeader(`\u{1F4CB} **\u4EFB\u52A1\u770B\u677F** \xB7 ${todoSummaryText(todos)}`),
215
+ border: { color: "blue", corner_radius: "5px" },
216
+ vertical_spacing: "8px",
217
+ padding: "8px 8px 8px 8px",
218
+ elements: [{ tag: "markdown", content: renderTodoMarkdown(todos), text_size: "notation" }]
219
+ };
220
+ }
221
+ function renderTodoMarkdown(todos) {
222
+ const visible = todos.slice(0, MAX_VISIBLE_TODOS);
223
+ const lines = visible.map((todo) => `${statusIcon(todo.status)} ${truncate2(oneLine(todo.content), TODO_CONTENT_MAX)}`);
224
+ const hidden = todos.length - visible.length;
225
+ if (hidden > 0) lines.push(`\u2026\u8FD8\u6709 ${hidden} \u9879`);
226
+ return lines.join("\n");
227
+ }
228
+ function panelHeader(titleMd) {
229
+ return {
230
+ title: { tag: "markdown", content: titleMd },
231
+ vertical_align: "center",
232
+ icon: { tag: "standard_icon", token: "down-small-ccm_outlined", size: "16px 16px" },
233
+ icon_position: "follow_text",
234
+ icon_expanded_angle: -180
235
+ };
236
+ }
237
+ function statusIcon(status) {
238
+ switch (status) {
239
+ case "completed":
240
+ return "\u2705";
241
+ case "in_progress":
242
+ return "\u{1F504}";
243
+ case "cancelled":
244
+ return "\u23F9";
245
+ case "pending":
246
+ return "\u2610";
247
+ }
248
+ }
249
+ function oneLine(value) {
250
+ return value.replace(/\s+/g, " ").trim();
251
+ }
252
+ function truncate2(value, max) {
253
+ return value.length > max ? `${value.slice(0, max)}\u2026` : value;
254
+ }
255
+
256
+ // src/card/run-renderer.ts
257
+ var REASONING_MAX = 1500;
258
+ var COLLAPSE_TOOL_THRESHOLD = 3;
259
+ function renderCard(state) {
260
+ const elements = [];
261
+ if (state.reasoning.content) {
262
+ elements.push(reasoningPanel(state.reasoning.content, state.reasoning.active));
263
+ }
264
+ const todoBoard = renderTodoBoard(state.todos, state.terminal === "running");
265
+ if (todoBoard) elements.push(todoBoard);
266
+ if (state.terminal === "running" && state.runId) {
267
+ elements.push(progressLine(state));
268
+ }
269
+ for (const group of groupBlocks(state.blocks)) {
270
+ if (group.kind === "text") {
271
+ if (group.content.trim()) {
272
+ elements.push(markdown(group.content));
273
+ }
274
+ } else {
275
+ elements.push(...renderToolGroup(group.tools, state.terminal !== "running"));
276
+ }
277
+ }
278
+ if (state.terminal === "interrupted") {
279
+ elements.push(noteMd("_\u23F9 \u5DF2\u88AB\u4E2D\u65AD_"));
280
+ } else if (state.terminal === "idle_timeout") {
281
+ const mins = state.idleTimeoutMinutes ?? 0;
282
+ elements.push(noteMd(`_\u23F1 ${mins} \u5206\u949F\u65E0\u54CD\u5E94,\u5DF2\u81EA\u52A8\u7EC8\u6B62_`));
283
+ } else if (state.terminal === "error" && state.errorMsg) {
284
+ elements.push(noteMd(`\u26A0\uFE0F agent \u5931\u8D25\uFF1A${state.errorMsg}`));
285
+ } else if (state.terminal === "done") {
286
+ if (elements.length === 0) elements.push(noteMd("_\uFF08\u672A\u8FD4\u56DE\u5185\u5BB9\uFF09_"));
287
+ elements.push(noteMd("_\u2705 \u5DF2\u5B8C\u6210_"));
288
+ }
289
+ if (state.terminal === "running") {
290
+ const activity = activityText(state.activity, state.footer);
291
+ if (activity) elements.push(noteMd(activity));
292
+ elements.push(stopButton());
293
+ } else if (state.runId && (state.terminal === "error" || state.terminal === "idle_timeout")) {
294
+ elements.push(retryButton(state.runId));
295
+ }
296
+ return {
297
+ schema: "2.0",
298
+ config: {
299
+ streaming_mode: state.terminal === "running",
300
+ summary: { content: summaryText(state) }
301
+ },
302
+ body: { elements }
303
+ };
304
+ }
305
+ function* groupBlocks(blocks) {
306
+ let toolBuf = [];
307
+ for (const b of blocks) {
308
+ if (b.kind === "tool") {
309
+ toolBuf.push(b.tool);
310
+ } else {
311
+ if (toolBuf.length > 0) {
312
+ yield { kind: "tools", tools: toolBuf };
313
+ toolBuf = [];
314
+ }
315
+ yield { kind: "text", content: b.content };
316
+ }
317
+ }
318
+ if (toolBuf.length > 0) yield { kind: "tools", tools: toolBuf };
319
+ }
320
+ function renderToolGroup(tools, finalized) {
321
+ if (tools.length === 0) return [];
322
+ const visibleTools = tools.filter((tool) => !isLowSignalTool(tool));
323
+ const hiddenCount = tools.length - visibleTools.length;
324
+ if (visibleTools.length === 0) {
325
+ return finalized ? [] : [contextActivity(hiddenCount)];
326
+ }
327
+ if (visibleTools.length < COLLAPSE_TOOL_THRESHOLD) {
328
+ return visibleTools.map((t) => toolPanel(t, false));
329
+ }
330
+ if (finalized) {
331
+ return [collapsedToolSummary(visibleTools, true)];
332
+ }
333
+ const prior = visibleTools.slice(0, -1);
334
+ const latest = visibleTools[visibleTools.length - 1];
335
+ const out = [];
336
+ if (hiddenCount > 0 && visibleTools.length === 0) out.push(contextActivity(hiddenCount));
337
+ if (prior.length > 0) out.push(collapsedToolSummary(prior, false));
338
+ if (latest) out.push(toolPanel(latest, true));
339
+ return out;
340
+ }
341
+ function contextActivity(count) {
342
+ return noteMd(`_\u6B63\u5728\u51C6\u5907\u4E0A\u4E0B\u6587${count > 1 ? `\uFF08${count} \u4E2A\u8BFB\u53D6/\u68C0\u67E5\u6B65\u9AA4\uFF09` : ""}\u2026_`);
343
+ }
344
+ function reasoningPanel(content, active) {
345
+ const title = active ? "\u{1F9E0} **\u601D\u8003\u4E2D**" : "\u{1F9E0} **\u601D\u8003\u5B8C\u6210\uFF0C\u70B9\u51FB\u67E5\u770B**";
346
+ return collapsiblePanel({
347
+ title,
348
+ expanded: active,
349
+ border: "grey",
350
+ body: truncate3(content, REASONING_MAX)
351
+ });
352
+ }
353
+ function toolPanel(tool, expanded) {
354
+ return collapsiblePanel({
355
+ title: toolHeaderText(tool),
356
+ expanded,
357
+ border: tool.status === "error" ? "red" : "grey",
358
+ body: toolBodyMd(tool) || "_\u65E0\u8F93\u51FA_"
359
+ });
360
+ }
361
+ function collapsedToolSummary(tools, finalized) {
362
+ const suffix = finalized ? "\uFF08\u5DF2\u7ED3\u675F\uFF09" : "";
363
+ const title = `\u2615 **${tools.length} \u4E2A\u5DE5\u5177\u8C03\u7528${suffix}**`;
364
+ const headerList = tools.map((t) => `- ${toolHeaderText(t)}`).join("\n");
365
+ return {
366
+ tag: "collapsible_panel",
367
+ expanded: false,
368
+ header: panelHeader2(title),
369
+ border: { color: "blue", corner_radius: "5px" },
370
+ vertical_spacing: "8px",
371
+ padding: "8px 8px 8px 8px",
372
+ elements: [{ tag: "markdown", content: headerList, text_size: "notation" }]
373
+ };
374
+ }
375
+ function collapsiblePanel(opts) {
376
+ return {
377
+ tag: "collapsible_panel",
378
+ expanded: opts.expanded,
379
+ header: panelHeader2(opts.title),
380
+ border: { color: opts.border, corner_radius: "5px" },
381
+ vertical_spacing: "8px",
382
+ padding: "8px 8px 8px 8px",
383
+ elements: [{ tag: "markdown", content: opts.body, text_size: "notation" }]
384
+ };
385
+ }
386
+ function panelHeader2(titleMd) {
387
+ return {
388
+ title: { tag: "markdown", content: titleMd },
389
+ vertical_align: "center",
390
+ icon: { tag: "standard_icon", token: "down-small-ccm_outlined", size: "16px 16px" },
391
+ icon_position: "follow_text",
392
+ icon_expanded_angle: -180
393
+ };
394
+ }
395
+ function markdown(content) {
396
+ return { tag: "markdown", content };
397
+ }
398
+ function noteMd(content) {
399
+ return { tag: "markdown", content, text_size: "notation" };
400
+ }
401
+ function stopButton() {
402
+ return {
403
+ tag: "button",
404
+ text: { tag: "plain_text", content: "\u23F9 \u7EC8\u6B62" },
405
+ type: "danger",
406
+ behaviors: [{ type: "callback", value: { cmd: "stop" } }]
407
+ };
408
+ }
409
+ function retryButton(runId) {
410
+ return {
411
+ tag: "button",
412
+ text: { tag: "plain_text", content: "\u4E00\u952E\u91CD\u8BD5" },
413
+ type: "default",
414
+ behaviors: [{ type: "callback", value: { cmd: "retry", run_id: runId } }]
415
+ };
416
+ }
417
+ function progressLine(state) {
418
+ const started = ageText(Date.now() - state.startedAt);
419
+ const active = ageText(Date.now() - state.lastActivityAt);
420
+ return noteMd(`_\u8FD0\u884C ${started} \xB7 \u6700\u8FD1\u6D3B\u52A8 ${active}\u524D \xB7 \u5361\u7247\u66F4\u65B0 ${timeText(state.updatedAt)}_`);
421
+ }
422
+ function summaryText(state) {
423
+ const todoSummary = todoSummaryText(state.todos);
424
+ const withTodos = (base) => todoSummary ? `${base} \xB7 ${todoSummary}` : base;
425
+ if (state.terminal === "interrupted") return withTodos("\u5DF2\u4E2D\u65AD");
426
+ if (state.terminal === "idle_timeout") return withTodos("\u5DF2\u8D85\u65F6");
427
+ if (state.terminal === "error") return withTodos("\u51FA\u9519");
428
+ if (state.terminal === "done") return withTodos("\u5DF2\u5B8C\u6210");
429
+ if (state.footer === "starting") return withTodos("\u6B63\u5728\u542F\u52A8");
430
+ if (state.footer === "tool_running") return withTodos("\u6B63\u5728\u8C03\u7528\u5DE5\u5177");
431
+ if (state.footer === "streaming") return withTodos("\u6B63\u5728\u8F93\u51FA");
432
+ return withTodos("\u601D\u8003\u4E2D");
433
+ }
434
+ function timeText(ts) {
435
+ return new Date(ts).toLocaleTimeString("zh-CN", { hour12: false });
436
+ }
437
+ function ageText(ms) {
438
+ const seconds = Math.max(0, Math.round(ms / 1e3));
439
+ if (seconds < 60) return `${seconds}s`;
440
+ const minutes = Math.floor(seconds / 60);
441
+ const rest = seconds % 60;
442
+ if (minutes < 60) return rest ? `${minutes}m${rest}s` : `${minutes}m`;
443
+ const hours = Math.floor(minutes / 60);
444
+ const min = minutes % 60;
445
+ return min ? `${hours}h${min}m` : `${hours}h`;
446
+ }
447
+ function truncate3(s, max) {
448
+ return s.length > max ? `${s.slice(0, max)}\u2026` : s;
449
+ }
450
+
451
+ // src/card/text-renderer.ts
452
+ var MAX_TOOL_LINES = 8;
453
+ var MAX_RENDERED_CHARS = 18e3;
454
+ function renderText(state) {
455
+ const parts = [];
456
+ let visibleToolLines = 0;
457
+ let hiddenToolLines = 0;
458
+ for (const block of state.blocks) {
459
+ const piece = renderBlock(block, visibleToolLines < MAX_TOOL_LINES);
460
+ if (piece) parts.push(piece);
461
+ if (block.kind === "tool" && !isLowSignalTool(block.tool)) {
462
+ if (piece) visibleToolLines++;
463
+ else hiddenToolLines++;
464
+ }
465
+ }
466
+ if (hiddenToolLines > 0) {
467
+ parts.push(`_\u5DF2\u6298\u53E0 ${hiddenToolLines} \u4E2A\u5DE5\u5177\u6B65\u9AA4\uFF0C\u5B8C\u6574\u7EC6\u8282\u53EF\u901A\u8FC7 /doctor \u67E5\u770B\u3002_`);
468
+ }
469
+ if (state.todos.length > 0) {
470
+ parts.push(`\u{1F4CB} **\u4EFB\u52A1\u770B\u677F** \xB7 ${todoSummaryText(state.todos)}
471
+ ${renderTodoMarkdown(state.todos)}`);
472
+ }
473
+ if (state.terminal === "running" && state.runId) {
474
+ parts.push(`_\u8FD0\u884C ${ageText2(Date.now() - state.startedAt)} \xB7 \u6700\u8FD1\u6D3B\u52A8 ${ageText2(Date.now() - state.lastActivityAt)}\u524D_`);
475
+ }
476
+ if (state.terminal === "interrupted") {
477
+ parts.push("_\u23F9 \u5DF2\u88AB\u4E2D\u65AD_");
478
+ } else if (state.terminal === "idle_timeout") {
479
+ const mins = state.idleTimeoutMinutes ?? 0;
480
+ parts.push(`_\u23F1 ${mins} \u5206\u949F\u65E0\u54CD\u5E94,\u5DF2\u81EA\u52A8\u7EC8\u6B62_`);
481
+ } else if (state.terminal === "error" && state.errorMsg) {
482
+ parts.push(`\u26A0\uFE0F agent \u5931\u8D25:${state.errorMsg}`);
483
+ } else if (state.terminal === "done") {
484
+ parts.push("_\u2705 \u5DF2\u5B8C\u6210_");
485
+ } else if (state.terminal === "running" && state.footer) {
486
+ const activity = activityText(state.activity, state.footer);
487
+ if (activity) parts.push(`_${activity}_`);
488
+ }
489
+ return truncateRendered(parts.join("\n\n"));
490
+ }
491
+ function renderBlock(block, includeTool) {
492
+ if (block.kind === "text") {
493
+ return block.content.trim();
494
+ }
495
+ if (isLowSignalTool(block.tool)) return "";
496
+ if (!includeTool) return "";
497
+ return toolLine(block.tool);
498
+ }
499
+ function toolLine(tool) {
500
+ return `> ${toolHeaderText(tool)}`;
501
+ }
502
+ function ageText2(ms) {
503
+ const seconds = Math.max(0, Math.round(ms / 1e3));
504
+ if (seconds < 60) return `${seconds}s`;
505
+ const minutes = Math.floor(seconds / 60);
506
+ const rest = seconds % 60;
507
+ if (minutes < 60) return rest ? `${minutes}m${rest}s` : `${minutes}m`;
508
+ const hours = Math.floor(minutes / 60);
509
+ const min = minutes % 60;
510
+ return min ? `${hours}h${min}m` : `${hours}h`;
511
+ }
512
+ function truncateRendered(text) {
513
+ if (text.length <= MAX_RENDERED_CHARS) return text;
514
+ return `${text.slice(0, MAX_RENDERED_CHARS)}
515
+
516
+ _\uFF08\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF1B\u5B8C\u6574\u7EC6\u8282\u53EF\u901A\u8FC7 /doctor \u67E5\u770B\u3002\uFF09_`;
517
+ }
518
+
519
+ // src/card/run-state.ts
520
+ function createInitialState(runId) {
521
+ const now = Date.now();
522
+ return {
523
+ runId,
524
+ blocks: [],
525
+ todos: [],
526
+ reasoning: { content: "", active: false },
527
+ footer: "starting",
528
+ activity: { kind: "phase", phase: "starting" },
529
+ terminal: "running",
530
+ startedAt: now,
531
+ updatedAt: now,
532
+ lastActivityAt: now
533
+ };
534
+ }
535
+ var initialState = createInitialState();
536
+ function closeStreamingText(blocks) {
537
+ return blocks.map(
538
+ (b) => b.kind === "text" && b.streaming ? { ...b, streaming: false } : b
539
+ );
540
+ }
541
+ function reduce(state, evt) {
542
+ switch (evt.type) {
543
+ case "text": {
544
+ const last = state.blocks[state.blocks.length - 1];
545
+ if (last && last.kind === "text" && last.streaming) {
546
+ const next = { ...last, content: last.content + evt.delta };
547
+ return touch({
548
+ ...state,
549
+ blocks: [...state.blocks.slice(0, -1), next],
550
+ reasoning: { ...state.reasoning, active: false },
551
+ footer: "streaming",
552
+ activity: { kind: "phase", phase: "streaming" }
553
+ });
554
+ }
555
+ return touch({
556
+ ...state,
557
+ blocks: [...state.blocks, { kind: "text", content: evt.delta, streaming: true }],
558
+ reasoning: { ...state.reasoning, active: false },
559
+ footer: "streaming",
560
+ activity: { kind: "phase", phase: "streaming" }
561
+ });
562
+ }
563
+ case "thinking": {
564
+ return touch({
565
+ ...state,
566
+ reasoning: { content: state.reasoning.content + evt.delta, active: true },
567
+ footer: "thinking",
568
+ activity: {
569
+ kind: "phase",
570
+ phase: "thinking",
571
+ detail: summarizeActivityText(evt.delta)
572
+ }
573
+ });
574
+ }
575
+ case "progress": {
576
+ const phase = evt.phase ?? state.footer ?? "thinking";
577
+ return touch({
578
+ ...state,
579
+ footer: phase,
580
+ activity: {
581
+ kind: "phase",
582
+ phase,
583
+ label: summarizeActivityText(evt.label),
584
+ detail: summarizeActivityText(evt.detail)
585
+ }
586
+ });
587
+ }
588
+ case "tool_use": {
589
+ const tool = {
590
+ id: evt.id,
591
+ name: evt.name,
592
+ input: evt.input,
593
+ status: "running"
594
+ };
595
+ const todos = readTodoWriteInput(evt.name, evt.input);
596
+ if (todos) {
597
+ return touch({
598
+ ...state,
599
+ todos: applyTodoWrite(state.todos, todos),
600
+ reasoning: { ...state.reasoning, active: false },
601
+ footer: "tool_running",
602
+ activity: { kind: "phase", phase: "tool_running", label: "\u66F4\u65B0\u4EFB\u52A1\u770B\u677F" }
603
+ });
604
+ }
605
+ return touch({
606
+ ...state,
607
+ blocks: [...closeStreamingText(state.blocks), { kind: "tool", tool }],
608
+ reasoning: { ...state.reasoning, active: false },
609
+ footer: "tool_running",
610
+ activity: { kind: "tool", tool }
611
+ });
612
+ }
613
+ case "tool_result": {
614
+ let completedTool;
615
+ const blocks = state.blocks.map((b) => {
616
+ if (b.kind !== "tool" || b.tool.id !== evt.id) return b;
617
+ completedTool = {
618
+ ...b.tool,
619
+ status: evt.isError ? "error" : "done",
620
+ output: evt.output
621
+ };
622
+ return {
623
+ ...b,
624
+ tool: completedTool
625
+ };
626
+ });
627
+ return touch({
628
+ ...state,
629
+ blocks,
630
+ activity: completedTool && state.activity?.kind === "tool" && state.activity.tool.id === evt.id ? { kind: "tool", tool: completedTool } : state.activity
631
+ });
632
+ }
633
+ case "error": {
634
+ return touch({ ...state, terminal: "error", errorMsg: evt.message, footer: null, activity: void 0 });
635
+ }
636
+ case "done": {
637
+ return touch({
638
+ ...state,
639
+ blocks: closeStreamingText(state.blocks),
640
+ reasoning: { ...state.reasoning, active: false },
641
+ terminal: "done",
642
+ footer: null,
643
+ activity: void 0
644
+ });
645
+ }
646
+ default:
647
+ return state;
648
+ }
649
+ }
650
+ function markInterrupted(state) {
651
+ return touch({
652
+ ...state,
653
+ blocks: closeStreamingText(state.blocks),
654
+ reasoning: { ...state.reasoning, active: false },
655
+ terminal: "interrupted",
656
+ footer: null,
657
+ activity: void 0
658
+ });
659
+ }
660
+ function finalizeIfRunning(state) {
661
+ if (state.terminal !== "running") return state;
662
+ return touch({
663
+ ...state,
664
+ blocks: closeStreamingText(state.blocks),
665
+ reasoning: { ...state.reasoning, active: false },
666
+ terminal: "done",
667
+ footer: null,
668
+ activity: void 0
669
+ });
670
+ }
671
+ function touch(state) {
672
+ const now = Date.now();
673
+ return { ...state, updatedAt: now, lastActivityAt: now };
674
+ }
675
+ function readTodoWriteInput(name, input) {
676
+ if (!isTodoWriteTool(name)) return void 0;
677
+ if (!input || typeof input !== "object") return void 0;
678
+ const rec = input;
679
+ if (!Array.isArray(rec.todos)) return void 0;
680
+ const todos = rec.todos.flatMap((raw, idx) => {
681
+ if (!raw || typeof raw !== "object") return [];
682
+ const item = raw;
683
+ const content = typeof item.content === "string" ? item.content.trim() : "";
684
+ if (!content) return [];
685
+ const status = readTodoStatus(item.status);
686
+ if (!status) return [];
687
+ const id = typeof item.id === "string" && item.id.trim() ? item.id.trim() : String(idx + 1);
688
+ return [{ id, content, status }];
689
+ });
690
+ return { todos, merge: rec.merge === true };
691
+ }
692
+ function isTodoWriteTool(name) {
693
+ const normalized = name.replace(/^functions\./, "").replace(/[_\s-]/g, "").toLowerCase();
694
+ return normalized === "todowrite" || normalized === "updatetodos" || normalized === "todoupdate";
695
+ }
696
+ function readTodoStatus(status) {
697
+ return status === "pending" || status === "in_progress" || status === "completed" || status === "cancelled" ? status : void 0;
698
+ }
699
+ function applyTodoWrite(existing, update) {
700
+ if (!update.merge) return update.todos;
701
+ const byId = new Map(existing.map((todo) => [todo.id, todo]));
702
+ for (const todo of update.todos) {
703
+ byId.set(todo.id, todo);
704
+ }
705
+ return Array.from(byId.values());
706
+ }
707
+ function summarizeActivityText(value) {
708
+ if (!value) return void 0;
709
+ const oneLine2 = value.replace(/\s+/g, " ").trim();
710
+ if (!oneLine2) return void 0;
711
+ return oneLine2.length > 140 ? `${oneLine2.slice(0, 140)}\u2026` : oneLine2;
712
+ }
713
+ export {
714
+ createInitialState,
715
+ finalizeIfRunning,
716
+ initialState,
717
+ markInterrupted,
718
+ reduce,
719
+ renderCard,
720
+ renderText
721
+ };