@agent-spaces/server 0.1.2 → 0.2.3

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 (217) hide show
  1. package/dist/adapters/claude-code-runtime/index.js +4 -1
  2. package/dist/adapters/git.js +2 -21
  3. package/dist/agents/issue-agent-runner.js +35 -21
  4. package/dist/agents/issue-task-controller.js +120 -73
  5. package/dist/agents/planner-agent.js +9 -12
  6. package/dist/app.js +12 -1
  7. package/dist/hooks/agent-hooks.js +5 -8
  8. package/dist/package.json +1 -1
  9. package/dist/routes/agent.js +40 -17
  10. package/dist/routes/channel.js +4 -1
  11. package/dist/routes/command.js +108 -0
  12. package/dist/routes/folder.js +44 -7
  13. package/dist/routes/issue.js +57 -23
  14. package/dist/routes/mcp.js +50 -0
  15. package/dist/routes/skill.js +57 -0
  16. package/dist/routes/subscription.js +49 -0
  17. package/dist/routes/task.js +16 -1
  18. package/dist/routes/workflow.js +63 -0
  19. package/dist/routes/workspace.js +2 -21
  20. package/dist/services/agent.js +140 -76
  21. package/dist/services/builtin-tools.js +72 -0
  22. package/dist/services/channel.js +5 -5
  23. package/dist/services/command-process-manager.js +136 -0
  24. package/dist/services/command.js +48 -0
  25. package/dist/services/issue.js +5 -6
  26. package/dist/services/mcp.js +120 -0
  27. package/dist/services/notification-hub/bot-commands.js +48 -16
  28. package/dist/services/notification-hub/helpers.js +12 -0
  29. package/dist/services/pty.js +10 -3
  30. package/dist/services/skill.js +171 -0
  31. package/dist/services/subscription/aicode.js +45 -0
  32. package/dist/services/subscription/base.js +3 -0
  33. package/dist/services/subscription/index.js +20 -0
  34. package/dist/services/subscription/minimax.js +60 -0
  35. package/dist/services/subscription/zhipu.js +39 -0
  36. package/dist/services/workflow.js +203 -0
  37. package/dist/services/workspace.js +0 -1
  38. package/dist/storage/command-store.js +17 -0
  39. package/dist/storage/subscription-store.js +44 -0
  40. package/dist/storage/workflow-store.js +40 -0
  41. package/dist/web/404.html +1 -1
  42. package/dist/web/__next.__PAGE__.txt +4 -4
  43. package/dist/web/__next._full.txt +22 -21
  44. package/dist/web/__next._head.txt +4 -4
  45. package/dist/web/__next._index.txt +9 -8
  46. package/dist/web/__next._tree.txt +2 -2
  47. package/dist/web/_next/static/7UtFGbIZvN_2yiatRc2g3/_buildManifest.js +11 -0
  48. package/dist/web/_next/static/chunks/0-245kun-watp.js +2 -0
  49. package/dist/web/_next/static/chunks/0-ca_fo-yp3~z.js +1 -0
  50. package/dist/web/_next/static/chunks/0-vgd3j-zh3m8.js +2 -0
  51. package/dist/web/_next/static/chunks/0.4.g.8yf4rs0.js +3 -0
  52. package/dist/web/_next/static/chunks/02m_-ngl9w8co.js +1 -0
  53. package/dist/web/_next/static/chunks/03jbh7ud0jw~g.js +1 -0
  54. package/dist/web/_next/static/chunks/07kqxmubf5dua.js +1 -0
  55. package/dist/web/_next/static/chunks/088q-5_51dsrw.js +1 -0
  56. package/dist/web/_next/static/chunks/08fqgb~~a~4ck.js +1 -0
  57. package/dist/web/_next/static/chunks/09_ki3dc5cfwv.css +1 -0
  58. package/dist/web/_next/static/chunks/09jryrjps0vl2.js +1 -0
  59. package/dist/web/_next/static/chunks/0amzlgoqe50tv.js +8 -0
  60. package/dist/web/_next/static/chunks/0b2tump5duj9j.js +1 -0
  61. package/dist/web/_next/static/chunks/0car_w834cbb6.js +1 -0
  62. package/dist/web/_next/static/chunks/0fwvdy-ml8wpk.js +1 -0
  63. package/dist/web/_next/static/chunks/0g4vm6.v0o_lt.js +1 -0
  64. package/dist/web/_next/static/chunks/0g_b4t~000.o~.js +179 -0
  65. package/dist/web/_next/static/chunks/0gyede80jpy3n.js +4 -0
  66. package/dist/web/_next/static/chunks/0h256h-tu4e0r.js +2 -0
  67. package/dist/web/_next/static/chunks/0ib18ul605e~a.js +1 -0
  68. package/dist/web/_next/static/chunks/0j1g_rd9t5ot1.js +1 -0
  69. package/dist/web/_next/static/chunks/0jn~llaqcxo4q.js +1 -0
  70. package/dist/web/_next/static/chunks/0jvmviuftg5e2.css +1 -0
  71. package/dist/web/_next/static/chunks/0lb8l2~6s_owo.js +1 -0
  72. package/dist/web/_next/static/chunks/0o4m39hw4fb_j.js +1 -0
  73. package/dist/web/_next/static/chunks/0pep4mkvt3.rh.js +31 -0
  74. package/dist/web/_next/static/chunks/0pq2670_ezbcj.js +1 -0
  75. package/dist/web/_next/static/chunks/0q_scqkk9.t53.js +2 -0
  76. package/dist/web/_next/static/chunks/0qyjxx0y7rzuu.js +1 -0
  77. package/dist/web/_next/static/chunks/0rrdur.v1a5r7.js +1 -0
  78. package/dist/web/_next/static/chunks/0spo.tmfeas-o.js +1 -0
  79. package/dist/web/_next/static/chunks/0u88ij9dqqh~-.js +1 -0
  80. package/dist/web/_next/static/chunks/0zl19l5tuoppw.js +1 -0
  81. package/dist/web/_next/static/chunks/11n16hogah-5..js +1 -0
  82. package/dist/web/_next/static/chunks/1250wo~-5dgyx.js +1 -0
  83. package/dist/web/_next/static/chunks/14n8i2xz4_y-e.js +1 -0
  84. package/dist/web/_next/static/chunks/160ji-.dfvm20.js +1 -0
  85. package/dist/web/_next/static/chunks/turbopack-0lxiiw.jhevml.js +1 -0
  86. package/dist/web/_next/static/media/favicon.0~ekuj.zhggpa.ico +0 -0
  87. package/dist/web/_not-found/__next._full.txt +26 -19
  88. package/dist/web/_not-found/__next._head.txt +4 -4
  89. package/dist/web/_not-found/__next._index.txt +9 -8
  90. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
  91. package/dist/web/_not-found/__next._not-found.txt +3 -3
  92. package/dist/web/_not-found/__next._tree.txt +2 -2
  93. package/dist/web/_not-found.html +1 -1
  94. package/dist/web/_not-found.txt +26 -19
  95. package/dist/web/apple-touch-icon.png +0 -0
  96. package/dist/web/favicon.ico +0 -0
  97. package/dist/web/icon-192.png +0 -0
  98. package/dist/web/icon-512.png +0 -0
  99. package/dist/web/index.html +1 -1
  100. package/dist/web/index.txt +22 -21
  101. package/dist/web/login/__next._full.txt +25 -23
  102. package/dist/web/login/__next._head.txt +4 -4
  103. package/dist/web/login/__next._index.txt +9 -8
  104. package/dist/web/login/__next._tree.txt +2 -2
  105. package/dist/web/login/__next.login.__PAGE__.txt +4 -4
  106. package/dist/web/login/__next.login.txt +3 -3
  107. package/dist/web/login.html +1 -1
  108. package/dist/web/login.txt +25 -23
  109. package/dist/web/settings/__next._full.txt +36 -0
  110. package/dist/web/settings/__next._head.txt +6 -0
  111. package/dist/web/settings/__next._index.txt +11 -0
  112. package/dist/web/settings/__next._tree.txt +8 -0
  113. package/dist/web/settings/__next.settings.__PAGE__.txt +9 -0
  114. package/dist/web/settings/__next.settings.txt +7 -0
  115. package/dist/web/settings/agents/__next._full.txt +39 -0
  116. package/dist/web/settings/agents/__next._head.txt +6 -0
  117. package/dist/web/settings/agents/__next._index.txt +11 -0
  118. package/dist/web/settings/agents/__next._tree.txt +8 -0
  119. package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +9 -0
  120. package/dist/web/settings/agents/__next.settings.agents.txt +5 -0
  121. package/dist/web/settings/agents/__next.settings.txt +7 -0
  122. package/dist/web/settings/agents.html +1 -0
  123. package/dist/web/settings/agents.txt +39 -0
  124. package/dist/web/settings/mcps/__next._full.txt +39 -0
  125. package/dist/web/settings/mcps/__next._head.txt +6 -0
  126. package/dist/web/settings/mcps/__next._index.txt +11 -0
  127. package/dist/web/settings/mcps/__next._tree.txt +8 -0
  128. package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +9 -0
  129. package/dist/web/settings/mcps/__next.settings.mcps.txt +5 -0
  130. package/dist/web/settings/mcps/__next.settings.txt +7 -0
  131. package/dist/web/settings/mcps.html +1 -0
  132. package/dist/web/settings/mcps.txt +39 -0
  133. package/dist/web/settings/models/__next._full.txt +39 -0
  134. package/dist/web/settings/models/__next._head.txt +6 -0
  135. package/dist/web/settings/models/__next._index.txt +11 -0
  136. package/dist/web/settings/models/__next._tree.txt +8 -0
  137. package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +9 -0
  138. package/dist/web/settings/models/__next.settings.models.txt +5 -0
  139. package/dist/web/settings/models/__next.settings.txt +7 -0
  140. package/dist/web/settings/models.html +1 -0
  141. package/dist/web/settings/models.txt +39 -0
  142. package/dist/web/settings/providers/__next._full.txt +39 -0
  143. package/dist/web/settings/providers/__next._head.txt +6 -0
  144. package/dist/web/settings/providers/__next._index.txt +11 -0
  145. package/dist/web/settings/providers/__next._tree.txt +8 -0
  146. package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +9 -0
  147. package/dist/web/settings/providers/__next.settings.providers.txt +5 -0
  148. package/dist/web/settings/providers/__next.settings.txt +7 -0
  149. package/dist/web/settings/providers.html +1 -0
  150. package/dist/web/settings/providers.txt +39 -0
  151. package/dist/web/settings/skills/__next._full.txt +39 -0
  152. package/dist/web/settings/skills/__next._head.txt +6 -0
  153. package/dist/web/settings/skills/__next._index.txt +11 -0
  154. package/dist/web/settings/skills/__next._tree.txt +8 -0
  155. package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +9 -0
  156. package/dist/web/settings/skills/__next.settings.skills.txt +5 -0
  157. package/dist/web/settings/skills/__next.settings.txt +7 -0
  158. package/dist/web/settings/skills.html +1 -0
  159. package/dist/web/settings/skills.txt +39 -0
  160. package/dist/web/settings.html +1 -0
  161. package/dist/web/settings.txt +36 -0
  162. package/dist/web/workflows/__next._full.txt +35 -0
  163. package/dist/web/workflows/__next._head.txt +6 -0
  164. package/dist/web/workflows/__next._index.txt +11 -0
  165. package/dist/web/workflows/__next._tree.txt +9 -0
  166. package/dist/web/workflows/__next.workflows.__PAGE__.txt +10 -0
  167. package/dist/web/workflows/__next.workflows.txt +5 -0
  168. package/dist/web/workflows.html +1 -0
  169. package/dist/web/workflows.txt +35 -0
  170. package/dist/web/workspace/_/__next._full.txt +25 -20
  171. package/dist/web/workspace/_/__next._head.txt +4 -4
  172. package/dist/web/workspace/_/__next._index.txt +9 -8
  173. package/dist/web/workspace/_/__next._tree.txt +2 -2
  174. package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
  175. package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
  176. package/dist/web/workspace/_/__next.workspace.txt +3 -3
  177. package/dist/web/workspace/_.html +1 -1
  178. package/dist/web/workspace/_.txt +25 -20
  179. package/dist/web/workspaces/__next._full.txt +25 -23
  180. package/dist/web/workspaces/__next._head.txt +4 -4
  181. package/dist/web/workspaces/__next._index.txt +9 -8
  182. package/dist/web/workspaces/__next._tree.txt +2 -2
  183. package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
  184. package/dist/web/workspaces/__next.workspaces.txt +3 -3
  185. package/dist/web/workspaces.html +1 -1
  186. package/dist/web/workspaces.txt +25 -23
  187. package/dist/ws/agent-prompt.js +84 -0
  188. package/dist/ws/agent-runner.js +592 -0
  189. package/dist/ws/handler.js +9 -1200
  190. package/dist/ws/html-utils.js +30 -0
  191. package/dist/ws/message-parts.js +498 -0
  192. package/package.json +12 -10
  193. package/dist/web/_next/static/chunks/038whpa0zpnas.js +0 -1
  194. package/dist/web/_next/static/chunks/06q5go~xoz5a3.js +0 -1
  195. package/dist/web/_next/static/chunks/095.wizobwtyg.js +0 -2
  196. package/dist/web/_next/static/chunks/0bfg.w~u-83h5.js +0 -1
  197. package/dist/web/_next/static/chunks/0ce7i6~sb20rv.js +0 -113
  198. package/dist/web/_next/static/chunks/0d4~pcva1uk-a.js +0 -1
  199. package/dist/web/_next/static/chunks/0iq70n_u75nyu.js +0 -1
  200. package/dist/web/_next/static/chunks/0memz-8zsbxpu.js +0 -1
  201. package/dist/web/_next/static/chunks/0nw~w.3~twebx.js +0 -2
  202. package/dist/web/_next/static/chunks/0pyytgz~5vt0f.js +0 -31
  203. package/dist/web/_next/static/chunks/0ujjcrz~1nq.q.css +0 -1
  204. package/dist/web/_next/static/chunks/0vdnx9n41dyjl.js +0 -1
  205. package/dist/web/_next/static/chunks/0yl4mqmxtll6g.js +0 -1
  206. package/dist/web/_next/static/chunks/0zcbfka5tcle3.js +0 -1
  207. package/dist/web/_next/static/chunks/0~eo58u99i.fr.js +0 -8
  208. package/dist/web/_next/static/chunks/13_2vxyccsv84.js +0 -4
  209. package/dist/web/_next/static/chunks/13wfs~urgxu0w.js +0 -1
  210. package/dist/web/_next/static/chunks/157~3c6wqkt83.js +0 -1
  211. package/dist/web/_next/static/chunks/15jvow_z4uq-..js +0 -1
  212. package/dist/web/_next/static/chunks/15v697nf~r-cy.js +0 -2
  213. package/dist/web/_next/static/chunks/turbopack-164~7ulq9o9yc.js +0 -1
  214. package/dist/web/_next/static/media/favicon.0x3dzn~oxb6tn.ico +0 -0
  215. package/dist/web/_next/static/owMnKmxATbtXK_J_k_uHh/_buildManifest.js +0 -21
  216. /package/dist/web/_next/static/{owMnKmxATbtXK_J_k_uHh → 7UtFGbIZvN_2yiatRc2g3}/_clientMiddlewareManifest.js +0 -0
  217. /package/dist/web/_next/static/{owMnKmxATbtXK_J_k_uHh → 7UtFGbIZvN_2yiatRc2g3}/_ssgManifest.js +0 -0
@@ -0,0 +1,30 @@
1
+ export function stripHtml(content) {
2
+ return content
3
+ .replace(/<span[^>]*data-type=["']mention["'][^>]*data-label=["']([^"']+)["'][^>]*><\/span>/gi, '@$1')
4
+ .replace(/<[^>]+>/g, ' ')
5
+ .replace(/&nbsp;/g, ' ')
6
+ .replace(/&amp;/g, '&')
7
+ .replace(/&lt;/g, '<')
8
+ .replace(/&gt;/g, '>')
9
+ .replace(/\s+/g, ' ')
10
+ .trim();
11
+ }
12
+ export function extractMentionIds(content) {
13
+ const ids = new Set();
14
+ const mentionPattern = /<span[^>]*data-type=["']mention["'][^>]*>/gi;
15
+ for (const match of content.matchAll(mentionPattern)) {
16
+ const id = match[0].match(/\sdata-id=["']([^"']+)["']/i)?.[1];
17
+ if (id)
18
+ ids.add(decodeHtml(id));
19
+ }
20
+ return [...ids];
21
+ }
22
+ function decodeHtml(value) {
23
+ return value
24
+ .replace(/&quot;/g, '"')
25
+ .replace(/&#39;/g, "'")
26
+ .replace(/&amp;/g, '&')
27
+ .replace(/&lt;/g, '<')
28
+ .replace(/&gt;/g, '>');
29
+ }
30
+ //# sourceMappingURL=html-utils.js.map
@@ -0,0 +1,498 @@
1
+ export function buildAgentMessageParts(input) {
2
+ const lines = normalizeOutputLines(input.output);
3
+ const finalTextRange = findFinalTextRange(lines);
4
+ const finalText = finalTextRange
5
+ ? collapseRepeatedTextBlock(lines.slice(finalTextRange.start, finalTextRange.end + 1)).join('\n').trim()
6
+ : '';
7
+ const usage = input.usage ?? extractUsage(lines);
8
+ const parts = [];
9
+ const chainItems = buildChainItems(lines, finalTextRange, finalText, input.workspaceRoot, input.toolDetails);
10
+ const reasoningText = normalizeReasoningText(input.reasoning);
11
+ if (reasoningText) {
12
+ parts.push({
13
+ id: `reasoning-${input.sessionId}`,
14
+ type: 'reasoning',
15
+ text: reasoningText,
16
+ status: input.success ? 'completed' : 'streaming',
17
+ });
18
+ }
19
+ if (chainItems.length > 0) {
20
+ parts.push({
21
+ id: `chain-${input.sessionId}`,
22
+ type: 'chain',
23
+ chains: chainItems,
24
+ });
25
+ }
26
+ for (const subagent of extractSubagentBlocks(lines, input.sessionId, input.toolDetails)) {
27
+ parts.push(subagent);
28
+ }
29
+ for (const question of input.askUserQuestions ?? []) {
30
+ parts.push({
31
+ id: question.id,
32
+ type: 'ask_user_question',
33
+ question: question.question,
34
+ choices: question.choices,
35
+ status: question.answer ? 'answered' : 'requested',
36
+ answer: question.answer,
37
+ toolUseId: question.toolUseId,
38
+ });
39
+ }
40
+ if (hasTokenUsage(usage)) {
41
+ parts.push({
42
+ id: `context-${input.sessionId}`,
43
+ type: 'context',
44
+ usedTokens: getTotalTokens(usage),
45
+ maxTokens: 128_000,
46
+ modelId: input.model,
47
+ usage,
48
+ });
49
+ }
50
+ if (input.error) {
51
+ parts.push({
52
+ id: `terminal-error-${input.sessionId}`,
53
+ type: 'terminal',
54
+ output: input.error,
55
+ status: 'error',
56
+ });
57
+ }
58
+ if (finalText && finalText !== input.error) {
59
+ parts.push({
60
+ id: `text-${input.sessionId}`,
61
+ type: 'text',
62
+ text: finalText,
63
+ });
64
+ }
65
+ return parts;
66
+ }
67
+ export function normalizeOutputLines(output) {
68
+ const lines = output
69
+ .flatMap((line) => line.split(/\r?\n/))
70
+ .map((line) => line.trimEnd())
71
+ .filter((line) => line.trim());
72
+ const seenInitLines = new Set();
73
+ return lines.filter((line) => {
74
+ if (!/^Claude Code initialized\b/i.test(line))
75
+ return true;
76
+ if (seenInitLines.has(line))
77
+ return false;
78
+ seenInitLines.add(line);
79
+ return true;
80
+ });
81
+ }
82
+ export function mergeRuntimeOutput(liveOutput, resultOutput) {
83
+ if (liveOutput.length === 0)
84
+ return resultOutput;
85
+ const finalResult = resultOutput.at(-1)?.trim();
86
+ if (!finalResult)
87
+ return liveOutput;
88
+ if (liveOutput.some((line) => normalizeMessageText(line) === normalizeMessageText(finalResult))) {
89
+ return liveOutput;
90
+ }
91
+ return [...liveOutput, finalResult];
92
+ }
93
+ export function buildToolDetailId(id, line) {
94
+ const key = `${id}:${line}`;
95
+ let hash = 0;
96
+ for (let index = 0; index < key.length; index += 1) {
97
+ hash = ((hash << 5) - hash + key.charCodeAt(index)) | 0;
98
+ }
99
+ return `tool-${Math.abs(hash).toString(36)}`;
100
+ }
101
+ export function summarizeToolLine(line, workspaceRoot) {
102
+ const trimmed = line.trim();
103
+ const toolName = extractToolName(trimmed);
104
+ const inputDescription = extractQuotedField(trimmed, 'description');
105
+ const filePath = toWorkspaceRelativePath(extractQuotedField(trimmed, 'file_path') ?? extractQuotedField(trimmed, 'path'), workspaceRoot);
106
+ const command = extractQuotedField(trimmed, 'command') ?? extractCommand(trimmed, toolName);
107
+ const baseName = filePath?.split(/[\\/]/).filter(Boolean).at(-1);
108
+ if (toolName) {
109
+ if (filePath) {
110
+ return {
111
+ title: `${humanizeToolName(toolName)} ${baseName ?? filePath}`,
112
+ description: inputDescription ?? filePath,
113
+ toolName,
114
+ filePath,
115
+ };
116
+ }
117
+ if (command) {
118
+ return {
119
+ title: `${humanizeToolName(toolName)} command`,
120
+ description: inputDescription,
121
+ toolName,
122
+ command,
123
+ };
124
+ }
125
+ const searchSummary = extractSearchParams(trimmed, toolName, workspaceRoot);
126
+ if (searchSummary) {
127
+ return { ...searchSummary, toolName };
128
+ }
129
+ const todoCount = extractTodoCount(trimmed);
130
+ if (todoCount !== undefined) {
131
+ return {
132
+ title: `Update ${todoCount} ${todoCount === 1 ? 'todo' : 'todos'}`,
133
+ toolName,
134
+ };
135
+ }
136
+ return {
137
+ title: humanizeToolName(toolName),
138
+ toolName,
139
+ };
140
+ }
141
+ return { title: trimmed };
142
+ }
143
+ export function findToolDetailForResult(toolUseId, result, toolUseDetailIds, toolDetails, workspaceRoot) {
144
+ const detailId = toolUseId ? toolUseDetailIds.get(toolUseId) : undefined;
145
+ const byId = detailId ? toolDetails.get(detailId) : undefined;
146
+ if (byId)
147
+ return byId;
148
+ const resultFilePath = extractResultFilePath(result, workspaceRoot);
149
+ if (resultFilePath) {
150
+ const details = Array.from(toolDetails.values()).reverse();
151
+ for (const detail of details) {
152
+ if (detail.output !== undefined)
153
+ continue;
154
+ const inputFilePath = extractInputFilePath(detail.input, workspaceRoot);
155
+ if (inputFilePath === resultFilePath)
156
+ return detail;
157
+ }
158
+ }
159
+ if (isSubagentToolResult(result)) {
160
+ const detail = Array.from(toolDetails.values()).reverse().find((candidate) => {
161
+ return candidate.output === undefined && /^Tool:\s*Task\b/i.test(candidate.raw);
162
+ });
163
+ if (detail)
164
+ return detail;
165
+ }
166
+ return Array.from(toolDetails.values()).reverse().find((detail) => detail.output === undefined);
167
+ }
168
+ function normalizeReasoningText(reasoning) {
169
+ if (!reasoning?.length)
170
+ return '';
171
+ return collapseRepeatedTextBlock(reasoning
172
+ .map((item) => item.text.trim())
173
+ .filter(Boolean)).join('\n\n').trim();
174
+ }
175
+ function hasTokenUsage(usage) {
176
+ return Boolean(usage.totalTokens || usage.inputTokens || usage.outputTokens || usage.cachedInputTokens || usage.reasoningTokens);
177
+ }
178
+ function getTotalTokens(usage) {
179
+ return usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0) + (usage.cachedInputTokens ?? 0) + (usage.reasoningTokens ?? 0);
180
+ }
181
+ function collapseRepeatedTextBlock(lines) {
182
+ let next = [...lines];
183
+ while (next.length > 1 && next.length % 2 === 0) {
184
+ const middle = next.length / 2;
185
+ const first = next.slice(0, middle);
186
+ const second = next.slice(middle);
187
+ if (!sameTextBlock(first, second))
188
+ break;
189
+ next = first;
190
+ }
191
+ return next;
192
+ }
193
+ function sameTextBlock(left, right) {
194
+ if (left.length !== right.length)
195
+ return false;
196
+ return normalizeMessageText(left.join('\n')) === normalizeMessageText(right.join('\n'));
197
+ }
198
+ function findFinalTextRange(lines) {
199
+ let end = -1;
200
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
201
+ if (isFinalAnswerLine(lines[index])) {
202
+ end = index;
203
+ break;
204
+ }
205
+ }
206
+ if (end < 0)
207
+ return null;
208
+ let start = end;
209
+ for (let index = end - 1; index >= 0; index -= 1) {
210
+ if (!isFinalAnswerLine(lines[index]))
211
+ break;
212
+ start = index;
213
+ }
214
+ return { start, end };
215
+ }
216
+ function buildChainItems(lines, finalTextRange, finalText, workspaceRoot, toolDetails) {
217
+ let toolIndex = 0;
218
+ let messageIndex = 0;
219
+ const items = [];
220
+ const toolDetailMatchCounts = new Map();
221
+ let messageBuffer = [];
222
+ const flushMessageBuffer = () => {
223
+ if (messageBuffer.length === 0)
224
+ return;
225
+ const text = messageBuffer.join('\n').trim();
226
+ if (text) {
227
+ items.push({
228
+ id: `message-${messageIndex}`,
229
+ title: summarizeMessageTitle(text),
230
+ text,
231
+ kind: 'message',
232
+ status: 'completed',
233
+ });
234
+ messageIndex += 1;
235
+ }
236
+ messageBuffer = [];
237
+ };
238
+ for (let index = 0; index < lines.length; index += 1) {
239
+ if (finalTextRange && index >= finalTextRange.start && index <= finalTextRange.end)
240
+ continue;
241
+ const line = lines[index];
242
+ if (finalText && isSameMessageText(line, finalText))
243
+ continue;
244
+ if (isSubagentToolLine(line))
245
+ continue;
246
+ if (isToolLikeLine(line)) {
247
+ flushMessageBuffer();
248
+ items.push(buildToolTodo(line, toolIndex, workspaceRoot, toolDetails, toolDetailMatchCounts));
249
+ toolIndex += 1;
250
+ continue;
251
+ }
252
+ if (isFinalAnswerLine(line)) {
253
+ messageBuffer.push(line);
254
+ }
255
+ }
256
+ flushMessageBuffer();
257
+ return items.slice(0, 40);
258
+ }
259
+ function buildToolTodo(line, index, workspaceRoot, toolDetails, toolDetailMatchCounts) {
260
+ const summary = summarizeToolLine(line, workspaceRoot);
261
+ const detailId = findToolDetailId(line, toolDetails, toolDetailMatchCounts);
262
+ return {
263
+ id: `tool-${index}`,
264
+ title: summary.title,
265
+ description: summary.description,
266
+ status: 'completed',
267
+ toolName: summary.toolName,
268
+ filePath: summary.filePath,
269
+ command: summary.command,
270
+ detailId,
271
+ };
272
+ }
273
+ function extractSearchParams(line, toolName, workspaceRoot) {
274
+ if (!/^(Glob|Grep|Search|SemanticSearch|WebSearch|WebFetch|Fetch)$/i.test(toolName))
275
+ return null;
276
+ const pattern = extractQuotedField(line, 'pattern') ?? extractQuotedField(line, 'query');
277
+ const glob = extractQuotedField(line, 'glob');
278
+ const searchPath = toWorkspaceRelativePath(extractQuotedField(line, 'path'), workspaceRoot);
279
+ const url = extractQuotedField(line, 'url');
280
+ const label = humanizeToolName(toolName);
281
+ if (/^(WebSearch|WebFetch|Fetch)$/i.test(toolName)) {
282
+ if (url)
283
+ return { title: `${label} ${truncate(url, 60)}` };
284
+ if (pattern)
285
+ return { title: `${label} ${truncate(pattern, 60)}` };
286
+ return { title: label };
287
+ }
288
+ if (/^Glob$/i.test(toolName)) {
289
+ const parts = [];
290
+ if (pattern)
291
+ parts.push(truncate(pattern, 50));
292
+ else if (glob)
293
+ parts.push(truncate(glob, 50));
294
+ const title = parts.length ? `${label} ${parts.join(' ')}` : label;
295
+ const descParts = [];
296
+ if (pattern && glob)
297
+ descParts.push(`glob: ${glob}`);
298
+ if (searchPath)
299
+ descParts.push(`in ${searchPath}`);
300
+ return { title, description: descParts.length ? descParts.join(', ') : undefined };
301
+ }
302
+ const parts = [];
303
+ if (pattern)
304
+ parts.push(truncate(pattern, 40));
305
+ const title = parts.length ? `${label} ${parts.join(' ')}` : label;
306
+ const descParts = [];
307
+ if (glob)
308
+ descParts.push(`glob: ${glob}`);
309
+ if (searchPath)
310
+ descParts.push(`in ${searchPath}`);
311
+ return { title, description: descParts.length ? descParts.join(', ') : undefined };
312
+ }
313
+ function extractSubagentBlocks(lines, sessionId, toolDetails) {
314
+ const matchCounts = new Map();
315
+ return lines
316
+ .map((line, index) => {
317
+ const match = line.match(/^Tool:\s*Task\b\s*(.*)$/i);
318
+ if (!match)
319
+ return null;
320
+ const name = line.match(/\bdescription=(["'])(.*?)\1/i)?.[2] || `Subagent ${index + 1}`;
321
+ const prompt = line.match(/\bprompt=(["'])(.*?)\1/i)?.[2];
322
+ const detailId = findToolDetailId(line, toolDetails, matchCounts);
323
+ const detail = detailId ? toolDetails?.get(detailId) : undefined;
324
+ const output = stringifySubagentOutput(detail?.output);
325
+ return {
326
+ id: `subagent-${sessionId}-${index}`,
327
+ type: 'subagent',
328
+ name,
329
+ instructions: prompt,
330
+ output,
331
+ };
332
+ })
333
+ .filter((part) => Boolean(part));
334
+ }
335
+ function stringifySubagentOutput(output) {
336
+ if (output === undefined || output === null)
337
+ return undefined;
338
+ if (typeof output === 'string')
339
+ return output.trim() || undefined;
340
+ if (Array.isArray(output)) {
341
+ const text = output.flatMap((item) => {
342
+ if (typeof item === 'string')
343
+ return [item];
344
+ if (!item || typeof item !== 'object')
345
+ return [];
346
+ const record = item;
347
+ return typeof record.text === 'string' ? [record.text] : [];
348
+ }).join('\n').trim();
349
+ return text || undefined;
350
+ }
351
+ if (typeof output === 'object') {
352
+ const record = output;
353
+ if (typeof record.result === 'string' && record.result.trim())
354
+ return record.result.trim();
355
+ if (typeof record.summary === 'string' && record.summary.trim())
356
+ return record.summary.trim();
357
+ if (Array.isArray(record.content))
358
+ return stringifySubagentOutput(record.content);
359
+ }
360
+ return undefined;
361
+ }
362
+ function extractUsage(lines) {
363
+ const usage = {};
364
+ for (const line of lines) {
365
+ const lower = line.toLowerCase();
366
+ if (!lower.includes('token'))
367
+ continue;
368
+ const input = line.match(/\bin(?:put)?[=:\s]+([\d,]+)/i)?.[1];
369
+ const output = line.match(/\bout(?:put)?[=:\s]+([\d,]+)/i)?.[1];
370
+ const total = line.match(/\btokens?[=:\s]+([\d,]+)/i)?.[1];
371
+ if (input)
372
+ usage.inputTokens = Number(input.replace(/,/g, ''));
373
+ if (output)
374
+ usage.outputTokens = Number(output.replace(/,/g, ''));
375
+ if (total)
376
+ usage.totalTokens = Number(total.replace(/,/g, ''));
377
+ }
378
+ return usage;
379
+ }
380
+ function findToolDetailId(line, toolDetails, matchCounts) {
381
+ if (!toolDetails)
382
+ return undefined;
383
+ const targetMatchIndex = matchCounts?.get(line) ?? 0;
384
+ let matchIndex = 0;
385
+ for (const [id, detail] of toolDetails) {
386
+ if (detail.raw !== line)
387
+ continue;
388
+ if (matchIndex === targetMatchIndex) {
389
+ matchCounts?.set(line, targetMatchIndex + 1);
390
+ return id;
391
+ }
392
+ matchIndex += 1;
393
+ }
394
+ return undefined;
395
+ }
396
+ function isSubagentToolResult(result) {
397
+ if (!result || typeof result !== 'object' || Array.isArray(result))
398
+ return false;
399
+ const record = result;
400
+ return (typeof record.agentId === 'string'
401
+ || typeof record.agentType === 'string'
402
+ || (record.status === 'completed' && Array.isArray(record.content)));
403
+ }
404
+ function extractResultFilePath(result, workspaceRoot) {
405
+ if (!result || typeof result !== 'object')
406
+ return undefined;
407
+ const record = result;
408
+ const file = record.file;
409
+ if (file && typeof file === 'object') {
410
+ const filePath = file.filePath;
411
+ if (typeof filePath === 'string')
412
+ return toWorkspaceRelativePath(filePath, workspaceRoot);
413
+ }
414
+ const filePath = record.filePath;
415
+ if (typeof filePath === 'string')
416
+ return toWorkspaceRelativePath(filePath, workspaceRoot);
417
+ return undefined;
418
+ }
419
+ function extractInputFilePath(input, workspaceRoot) {
420
+ if (!input || typeof input !== 'object')
421
+ return undefined;
422
+ const record = input;
423
+ const filePath = record.file_path ?? record.path;
424
+ return typeof filePath === 'string' ? toWorkspaceRelativePath(filePath, workspaceRoot) : undefined;
425
+ }
426
+ function isSameMessageText(left, right) {
427
+ return normalizeMessageText(left) === normalizeMessageText(right);
428
+ }
429
+ function normalizeMessageText(text) {
430
+ return text.trim().replace(/\s+/g, ' ');
431
+ }
432
+ function summarizeMessageTitle(text) {
433
+ const normalized = text.trim().replace(/\s+/g, ' ');
434
+ if (!normalized)
435
+ return 'AI message';
436
+ return normalized.length > 80 ? `${normalized.slice(0, 77)}...` : normalized;
437
+ }
438
+ function isToolLikeLine(line) {
439
+ return /^(Using|Tool:|Read|Write|Edit|MultiEdit|Bash|Search|Grep|Glob|Todo|Task|Web|Fetch|Claude Code initialized|Codex initialized|.+ running \(\d+s\))/i.test(line.trim());
440
+ }
441
+ function isFinalAnswerLine(line) {
442
+ return !isToolLikeLine(line) && !/^(\[.*\]|Agent runtime configuration:|Conversation history:)/.test(line.trim());
443
+ }
444
+ function isSubagentToolLine(line) {
445
+ return /^Tool:\s*Task\b/i.test(line.trim());
446
+ }
447
+ function extractToolName(line) {
448
+ return line.match(/^Tool:\s*([A-Za-z][\w-]*)\b/)?.[1]
449
+ ?? line.match(/^([A-Za-z][\w-]*)\s+running\s+\(\d+s\)/)?.[1]
450
+ ?? line.match(/^([A-Za-z][\w-]*):?\s+/)?.[1];
451
+ }
452
+ function humanizeToolName(toolName) {
453
+ const labels = {
454
+ Read: 'Read',
455
+ Write: 'Write',
456
+ Edit: 'Edit',
457
+ MultiEdit: 'Edit',
458
+ Bash: 'Run',
459
+ TodoWrite: 'Update todos',
460
+ Grep: 'Search',
461
+ Glob: 'Find files',
462
+ Search: 'Search',
463
+ SemanticSearch: 'Semantic search',
464
+ WebSearch: 'Web search',
465
+ WebFetch: 'Fetch',
466
+ Fetch: 'Fetch',
467
+ Task: 'Run subagent',
468
+ };
469
+ return labels[toolName] ?? toolName.replace(/([a-z])([A-Z])/g, '$1 $2');
470
+ }
471
+ function extractQuotedField(line, key) {
472
+ const quoted = line.match(new RegExp(`\\b${key}=(["'])(.*?)\\1`))?.[2];
473
+ if (quoted)
474
+ return quoted;
475
+ const json = line.match(new RegExp(`"${key}"\\s*:\\s*"([^"]+)"`))?.[1];
476
+ return json;
477
+ }
478
+ function extractCommand(line, toolName) {
479
+ if (!toolName || !/^(Bash|Shell|Command)$/i.test(toolName))
480
+ return undefined;
481
+ const command = line.replace(/^Tool:\s*/i, '').replace(new RegExp(`^${toolName}:?\\s*`, 'i'), '').trim();
482
+ return command || undefined;
483
+ }
484
+ function extractTodoCount(line) {
485
+ const matches = line.match(/"content"\s*:/g);
486
+ return matches?.length;
487
+ }
488
+ function toWorkspaceRelativePath(path, workspaceRoot) {
489
+ if (!path)
490
+ return undefined;
491
+ if (!workspaceRoot || !path.startsWith(workspaceRoot))
492
+ return path;
493
+ return path.slice(workspaceRoot.length).replace(/^[/\\]/, '');
494
+ }
495
+ function truncate(str, max) {
496
+ return str.length > max ? `${str.slice(0, max - 3)}...` : str;
497
+ }
498
+ //# sourceMappingURL=message-parts.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-spaces/server",
3
- "version": "0.1.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "agent-spaces-server": "./dist/app.js"
@@ -14,7 +14,15 @@
14
14
  "publishConfig": {
15
15
  "access": "public"
16
16
  },
17
+ "scripts": {
18
+ "dev": "tsx watch src/app.ts",
19
+ "build": "tsc",
20
+ "start": "node dist/app.js",
21
+ "prepublishOnly": "pnpm build",
22
+ "postinstall": "node -e \"try{require('node-pty')}catch(e){if(!require('fs').existsSync('node_modules/node-pty/prebuilds')){process.exit(1)}}\""
23
+ },
17
24
  "dependencies": {
25
+ "@agent-spaces/shared": "workspace:*",
18
26
  "@anthropic-ai/claude-agent-sdk": "^0.2.126",
19
27
  "@codeany/open-agent-sdk": "^0.2.1",
20
28
  "@larksuiteoapi/node-sdk": "^1.62.1",
@@ -26,21 +34,15 @@
26
34
  "simple-git": "^3.36.0",
27
35
  "uuid": "^11.1.0",
28
36
  "ws": "^8.18.2",
29
- "zod": "^4.0.0",
30
- "@agent-spaces/shared": "0.1.0"
37
+ "zod": "^4.0.0"
31
38
  },
32
39
  "devDependencies": {
33
40
  "@types/cors": "^2.8.17",
34
41
  "@types/express": "^5.0.2",
42
+ "@types/node": "^20.19.39",
35
43
  "@types/uuid": "^10.0.0",
36
44
  "@types/ws": "^8.18.1",
37
45
  "tsx": "^4.19.4",
38
46
  "typescript": "^5.8.3"
39
- },
40
- "scripts": {
41
- "dev": "tsx watch src/app.ts",
42
- "build": "tsc",
43
- "start": "node dist/app.js",
44
- "postinstall": "node -e \"try{require('node-pty')}catch(e){if(!require('fs').existsSync('node_modules/node-pty/prebuilds')){process.exit(1)}}\""
45
47
  }
46
- }
48
+ }