@chengchenccc/oh-my-agent 0.1.1-rc.1

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 (276) hide show
  1. package/README.md +79 -0
  2. package/dist/cli/args.d.ts +24 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +120 -0
  5. package/dist/cli/initial-input.d.ts +32 -0
  6. package/dist/cli/initial-input.d.ts.map +1 -0
  7. package/dist/cli/initial-input.js +131 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +3 -0
  11. package/dist/core/__fixtures__/echo-model.d.ts +6 -0
  12. package/dist/core/__fixtures__/echo-model.d.ts.map +1 -0
  13. package/dist/core/__fixtures__/echo-model.js +10 -0
  14. package/dist/core/__fixtures__/mcp-echo-server.d.ts +2 -0
  15. package/dist/core/__fixtures__/mcp-echo-server.d.ts.map +1 -0
  16. package/dist/core/__fixtures__/mcp-echo-server.js +54 -0
  17. package/dist/core/agent-runtime.d.ts +21 -0
  18. package/dist/core/agent-runtime.d.ts.map +1 -0
  19. package/dist/core/agent-runtime.js +14 -0
  20. package/dist/core/memory/autonomous-memory.d.ts +21 -0
  21. package/dist/core/memory/autonomous-memory.d.ts.map +1 -0
  22. package/dist/core/memory/autonomous-memory.js +202 -0
  23. package/dist/core/persistence/in-memory-session-store.d.ts +3 -0
  24. package/dist/core/persistence/in-memory-session-store.d.ts.map +1 -0
  25. package/dist/core/persistence/in-memory-session-store.js +109 -0
  26. package/dist/core/persistence/session-store.contract.d.ts +5 -0
  27. package/dist/core/persistence/session-store.contract.d.ts.map +1 -0
  28. package/dist/core/persistence/session-store.contract.js +183 -0
  29. package/dist/core/persistence/session-store.d.ts +33 -0
  30. package/dist/core/persistence/session-store.d.ts.map +1 -0
  31. package/dist/core/persistence/session-store.js +22 -0
  32. package/dist/core/persistence/session-tree.d.ts +49 -0
  33. package/dist/core/persistence/session-tree.d.ts.map +1 -0
  34. package/dist/core/persistence/session-tree.js +1 -0
  35. package/dist/core/plugins/plugin-code.d.ts +13 -0
  36. package/dist/core/plugins/plugin-code.d.ts.map +1 -0
  37. package/dist/core/plugins/plugin-code.js +62 -0
  38. package/dist/core/plugins/plugin-marketplace.d.ts +72 -0
  39. package/dist/core/plugins/plugin-marketplace.d.ts.map +1 -0
  40. package/dist/core/plugins/plugin-marketplace.js +340 -0
  41. package/dist/core/plugins/plugin-resolve.d.ts +32 -0
  42. package/dist/core/plugins/plugin-resolve.d.ts.map +1 -0
  43. package/dist/core/plugins/plugin-resolve.js +101 -0
  44. package/dist/core/plugins/plugin-trust.d.ts +24 -0
  45. package/dist/core/plugins/plugin-trust.d.ts.map +1 -0
  46. package/dist/core/plugins/plugin-trust.js +89 -0
  47. package/dist/core/runtime/agent-event.d.ts +98 -0
  48. package/dist/core/runtime/agent-event.d.ts.map +1 -0
  49. package/dist/core/runtime/agent-event.js +1 -0
  50. package/dist/core/runtime/agent-loop.d.ts +142 -0
  51. package/dist/core/runtime/agent-loop.d.ts.map +1 -0
  52. package/dist/core/runtime/agent-loop.js +1008 -0
  53. package/dist/core/runtime/approval.d.ts +23 -0
  54. package/dist/core/runtime/approval.d.ts.map +1 -0
  55. package/dist/core/runtime/approval.js +25 -0
  56. package/dist/core/runtime/compaction.d.ts +22 -0
  57. package/dist/core/runtime/compaction.d.ts.map +1 -0
  58. package/dist/core/runtime/compaction.js +90 -0
  59. package/dist/core/runtime/context-estimate.d.ts +42 -0
  60. package/dist/core/runtime/context-estimate.d.ts.map +1 -0
  61. package/dist/core/runtime/context-estimate.js +34 -0
  62. package/dist/core/runtime/create-runtime.d.ts +81 -0
  63. package/dist/core/runtime/create-runtime.d.ts.map +1 -0
  64. package/dist/core/runtime/create-runtime.js +250 -0
  65. package/dist/core/runtime/fake-provider.d.ts +3 -0
  66. package/dist/core/runtime/fake-provider.d.ts.map +1 -0
  67. package/dist/core/runtime/fake-provider.js +87 -0
  68. package/dist/core/runtime/logger.d.ts +13 -0
  69. package/dist/core/runtime/logger.d.ts.map +1 -0
  70. package/dist/core/runtime/logger.js +38 -0
  71. package/dist/core/runtime/loop-input.d.ts +39 -0
  72. package/dist/core/runtime/loop-input.d.ts.map +1 -0
  73. package/dist/core/runtime/loop-input.js +38 -0
  74. package/dist/core/runtime/message-cache.d.ts +16 -0
  75. package/dist/core/runtime/message-cache.d.ts.map +1 -0
  76. package/dist/core/runtime/message-cache.js +23 -0
  77. package/dist/core/runtime/model-catalog.d.ts +10 -0
  78. package/dist/core/runtime/model-catalog.d.ts.map +1 -0
  79. package/dist/core/runtime/model-catalog.js +14 -0
  80. package/dist/core/runtime/plugin-runtime.d.ts +41 -0
  81. package/dist/core/runtime/plugin-runtime.d.ts.map +1 -0
  82. package/dist/core/runtime/plugin-runtime.js +1 -0
  83. package/dist/core/runtime/plugin.d.ts +86 -0
  84. package/dist/core/runtime/plugin.d.ts.map +1 -0
  85. package/dist/core/runtime/plugin.js +23 -0
  86. package/dist/core/runtime/process-tree.d.ts +12 -0
  87. package/dist/core/runtime/process-tree.d.ts.map +1 -0
  88. package/dist/core/runtime/process-tree.js +40 -0
  89. package/dist/core/runtime/prompt.d.ts +23 -0
  90. package/dist/core/runtime/prompt.d.ts.map +1 -0
  91. package/dist/core/runtime/prompt.js +29 -0
  92. package/dist/core/runtime/prompts.d.ts +16 -0
  93. package/dist/core/runtime/prompts.d.ts.map +1 -0
  94. package/dist/core/runtime/prompts.js +36 -0
  95. package/dist/core/runtime/retry.d.ts +20 -0
  96. package/dist/core/runtime/retry.d.ts.map +1 -0
  97. package/dist/core/runtime/retry.js +60 -0
  98. package/dist/core/runtime/run-runtime.d.ts +93 -0
  99. package/dist/core/runtime/run-runtime.d.ts.map +1 -0
  100. package/dist/core/runtime/run-runtime.js +664 -0
  101. package/dist/core/runtime/runtime-catalog.d.ts +12 -0
  102. package/dist/core/runtime/runtime-catalog.d.ts.map +1 -0
  103. package/dist/core/runtime/runtime-catalog.js +89 -0
  104. package/dist/core/runtime/stream-rules.d.ts +9 -0
  105. package/dist/core/runtime/stream-rules.d.ts.map +1 -0
  106. package/dist/core/runtime/stream-rules.js +44 -0
  107. package/dist/core/runtime/title.d.ts +7 -0
  108. package/dist/core/runtime/title.d.ts.map +1 -0
  109. package/dist/core/runtime/title.js +114 -0
  110. package/dist/core/runtime/todo.d.ts +16 -0
  111. package/dist/core/runtime/todo.d.ts.map +1 -0
  112. package/dist/core/runtime/todo.js +40 -0
  113. package/dist/core/runtime/tool-filter.d.ts +12 -0
  114. package/dist/core/runtime/tool-filter.d.ts.map +1 -0
  115. package/dist/core/runtime/tool-filter.js +23 -0
  116. package/dist/core/runtime/tool-pruning.d.ts +29 -0
  117. package/dist/core/runtime/tool-pruning.d.ts.map +1 -0
  118. package/dist/core/runtime/tool-pruning.js +105 -0
  119. package/dist/core/session/input-history.d.ts +8 -0
  120. package/dist/core/session/input-history.d.ts.map +1 -0
  121. package/dist/core/session/input-history.js +41 -0
  122. package/dist/core/session/session-file.d.ts +84 -0
  123. package/dist/core/session/session-file.d.ts.map +1 -0
  124. package/dist/core/session/session-file.js +392 -0
  125. package/dist/core/session/session-loop.d.ts +33 -0
  126. package/dist/core/session/session-loop.d.ts.map +1 -0
  127. package/dist/core/session/session-loop.js +30 -0
  128. package/dist/core/settings/project-settings.d.ts +46 -0
  129. package/dist/core/settings/project-settings.d.ts.map +1 -0
  130. package/dist/core/settings/project-settings.js +85 -0
  131. package/dist/core/settings/workspace-context.d.ts +10 -0
  132. package/dist/core/settings/workspace-context.d.ts.map +1 -0
  133. package/dist/core/settings/workspace-context.js +48 -0
  134. package/dist/core/tools/agent-fs-like.d.ts +15 -0
  135. package/dist/core/tools/agent-fs-like.d.ts.map +1 -0
  136. package/dist/core/tools/agent-fs-like.js +4 -0
  137. package/dist/core/tools/ask-question.d.ts +5 -0
  138. package/dist/core/tools/ask-question.d.ts.map +1 -0
  139. package/dist/core/tools/ask-question.js +51 -0
  140. package/dist/core/tools/bash.d.ts +5 -0
  141. package/dist/core/tools/bash.d.ts.map +1 -0
  142. package/dist/core/tools/bash.js +109 -0
  143. package/dist/core/tools/eval.d.ts +10 -0
  144. package/dist/core/tools/eval.d.ts.map +1 -0
  145. package/dist/core/tools/eval.js +83 -0
  146. package/dist/core/tools/file-tools.d.ts +18 -0
  147. package/dist/core/tools/file-tools.d.ts.map +1 -0
  148. package/dist/core/tools/file-tools.js +249 -0
  149. package/dist/core/tools/glob.d.ts +5 -0
  150. package/dist/core/tools/glob.d.ts.map +1 -0
  151. package/dist/core/tools/glob.js +54 -0
  152. package/dist/core/tools/grep.d.ts +5 -0
  153. package/dist/core/tools/grep.d.ts.map +1 -0
  154. package/dist/core/tools/grep.js +61 -0
  155. package/dist/core/tools/index.d.ts +14 -0
  156. package/dist/core/tools/index.d.ts.map +1 -0
  157. package/dist/core/tools/index.js +14 -0
  158. package/dist/core/tools/ls-tree.d.ts +10 -0
  159. package/dist/core/tools/ls-tree.d.ts.map +1 -0
  160. package/dist/core/tools/ls-tree.js +177 -0
  161. package/dist/core/tools/mcp-mount.d.ts +63 -0
  162. package/dist/core/tools/mcp-mount.d.ts.map +1 -0
  163. package/dist/core/tools/mcp-mount.js +287 -0
  164. package/dist/core/tools/read-image.d.ts +6 -0
  165. package/dist/core/tools/read-image.d.ts.map +1 -0
  166. package/dist/core/tools/read-image.js +98 -0
  167. package/dist/core/tools/skill.d.ts +11 -0
  168. package/dist/core/tools/skill.d.ts.map +1 -0
  169. package/dist/core/tools/skill.js +65 -0
  170. package/dist/core/tools/skills.d.ts +10 -0
  171. package/dist/core/tools/skills.d.ts.map +1 -0
  172. package/dist/core/tools/skills.js +116 -0
  173. package/dist/core/tools/todo-store.d.ts +8 -0
  174. package/dist/core/tools/todo-store.d.ts.map +1 -0
  175. package/dist/core/tools/todo-store.js +100 -0
  176. package/dist/core/tools/todo.d.ts +8 -0
  177. package/dist/core/tools/todo.d.ts.map +1 -0
  178. package/dist/core/tools/todo.js +91 -0
  179. package/dist/core/tools/url-guard.d.ts +12 -0
  180. package/dist/core/tools/url-guard.d.ts.map +1 -0
  181. package/dist/core/tools/url-guard.js +58 -0
  182. package/dist/core/tools/web-ports-std.d.ts +6 -0
  183. package/dist/core/tools/web-ports-std.d.ts.map +1 -0
  184. package/dist/core/tools/web-ports-std.js +145 -0
  185. package/dist/core/tools/web-ports.d.ts +56 -0
  186. package/dist/core/tools/web-ports.d.ts.map +1 -0
  187. package/dist/core/tools/web-ports.js +62 -0
  188. package/dist/core/tools/workspace-sandbox.d.ts +20 -0
  189. package/dist/core/tools/workspace-sandbox.d.ts.map +1 -0
  190. package/dist/core/tools/workspace-sandbox.js +84 -0
  191. package/dist/core/workflow/subagent-registry.d.ts +40 -0
  192. package/dist/core/workflow/subagent-registry.d.ts.map +1 -0
  193. package/dist/core/workflow/subagent-registry.js +118 -0
  194. package/dist/core/workflow/workflow-evaluator.d.ts +23 -0
  195. package/dist/core/workflow/workflow-evaluator.d.ts.map +1 -0
  196. package/dist/core/workflow/workflow-evaluator.js +21 -0
  197. package/dist/core/workflow/workflow-executor.d.ts +108 -0
  198. package/dist/core/workflow/workflow-executor.d.ts.map +1 -0
  199. package/dist/core/workflow/workflow-executor.js +549 -0
  200. package/dist/core/workflow/workflow-tools.d.ts +50 -0
  201. package/dist/core/workflow/workflow-tools.d.ts.map +1 -0
  202. package/dist/core/workflow/workflow-tools.js +217 -0
  203. package/dist/index.d.ts +14 -0
  204. package/dist/index.d.ts.map +1 -0
  205. package/dist/index.js +13 -0
  206. package/dist/main.d.ts +9 -0
  207. package/dist/main.d.ts.map +1 -0
  208. package/dist/main.js +97 -0
  209. package/dist/modes/json-mode.d.ts +5 -0
  210. package/dist/modes/json-mode.d.ts.map +1 -0
  211. package/dist/modes/json-mode.js +46 -0
  212. package/dist/modes/print-mode.d.ts +20 -0
  213. package/dist/modes/print-mode.d.ts.map +1 -0
  214. package/dist/modes/print-mode.js +82 -0
  215. package/dist/modes/rpc/jsonl.d.ts +23 -0
  216. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  217. package/dist/modes/rpc/jsonl.js +88 -0
  218. package/dist/modes/rpc/rpc-mode.d.ts +18 -0
  219. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  220. package/dist/modes/rpc/rpc-mode.js +326 -0
  221. package/dist/modes/tui/settings-overlay.d.ts +23 -0
  222. package/dist/modes/tui/settings-overlay.d.ts.map +1 -0
  223. package/dist/modes/tui/settings-overlay.js +136 -0
  224. package/dist/modes/tui/tui-commands-session.d.ts +3 -0
  225. package/dist/modes/tui/tui-commands-session.d.ts.map +1 -0
  226. package/dist/modes/tui/tui-commands-session.js +191 -0
  227. package/dist/modes/tui/tui-commands.d.ts +52 -0
  228. package/dist/modes/tui/tui-commands.d.ts.map +1 -0
  229. package/dist/modes/tui/tui-commands.js +373 -0
  230. package/dist/modes/tui/tui-components.d.ts +81 -0
  231. package/dist/modes/tui/tui-components.d.ts.map +1 -0
  232. package/dist/modes/tui/tui-components.js +248 -0
  233. package/dist/modes/tui/tui-format.d.ts +65 -0
  234. package/dist/modes/tui/tui-format.d.ts.map +1 -0
  235. package/dist/modes/tui/tui-format.js +246 -0
  236. package/dist/modes/tui/tui-frame-provider.d.ts +16 -0
  237. package/dist/modes/tui/tui-frame-provider.d.ts.map +1 -0
  238. package/dist/modes/tui/tui-frame-provider.js +31 -0
  239. package/dist/modes/tui/tui-interactive.d.ts +16 -0
  240. package/dist/modes/tui/tui-interactive.d.ts.map +1 -0
  241. package/dist/modes/tui/tui-interactive.js +123 -0
  242. package/dist/modes/tui/tui-io.d.ts +12 -0
  243. package/dist/modes/tui/tui-io.d.ts.map +1 -0
  244. package/dist/modes/tui/tui-io.js +620 -0
  245. package/dist/modes/tui/tui-mode.d.ts +120 -0
  246. package/dist/modes/tui/tui-mode.d.ts.map +1 -0
  247. package/dist/modes/tui/tui-mode.js +391 -0
  248. package/dist/modes/tui/tui-render.d.ts +54 -0
  249. package/dist/modes/tui/tui-render.d.ts.map +1 -0
  250. package/dist/modes/tui/tui-render.js +399 -0
  251. package/dist/modes/tui/tui-slash.d.ts +12 -0
  252. package/dist/modes/tui/tui-slash.d.ts.map +1 -0
  253. package/dist/modes/tui/tui-slash.js +64 -0
  254. package/dist/modes/tui/tui-tool-render.d.ts +6 -0
  255. package/dist/modes/tui/tui-tool-render.d.ts.map +1 -0
  256. package/dist/modes/tui/tui-tool-render.js +79 -0
  257. package/dist/modes/tui/tui-transcript-reconciler.d.ts +25 -0
  258. package/dist/modes/tui/tui-transcript-reconciler.d.ts.map +1 -0
  259. package/dist/modes/tui/tui-transcript-reconciler.js +97 -0
  260. package/dist/modes/tui/view-state.d.ts +67 -0
  261. package/dist/modes/tui/view-state.d.ts.map +1 -0
  262. package/dist/modes/tui/view-state.js +353 -0
  263. package/dist/prompts/agents/subagent.md +26 -0
  264. package/dist/prompts/system/base.md +20 -0
  265. package/dist/prompts/system/memory.md +23 -0
  266. package/dist/prompts/system/safety.md +12 -0
  267. package/dist/protocol/index.d.ts +5 -0
  268. package/dist/protocol/index.d.ts.map +1 -0
  269. package/dist/protocol/index.js +2 -0
  270. package/dist/protocol/mapping.d.ts +25 -0
  271. package/dist/protocol/mapping.d.ts.map +1 -0
  272. package/dist/protocol/mapping.js +115 -0
  273. package/dist/protocol/transport.d.ts +1396 -0
  274. package/dist/protocol/transport.d.ts.map +1 -0
  275. package/dist/protocol/transport.js +170 -0
  276. package/package.json +49 -0
@@ -0,0 +1,399 @@
1
+ import { CachedOutputBlock, Card, Markdown, renderStatusBar, renderToolHeader, Text, truncateToWidth, wrapTextWithAnsi, } from "@chengchenccc/tui";
2
+ import { cleanHeaderTitle, contextColor, formatWorkspace, gitStatus, MARKDOWN_THEME, MAX_DIFF_LINES, prettyJson, renderGitSegment, summarizeResult, summarizeToolArgs, USER_TEXT_STYLE, } from "./tui-format.js";
3
+ import { renderTaskTool, renderTodoTool } from "./tui-tool-render.js";
4
+ import { TuiTranscriptReconciler } from "./tui-transcript-reconciler.js";
5
+ /** Renders transcript items to display lines, memoizing markdown/tool blocks.
6
+ * Extracted from tui-io.ts to keep the io assembly file under 500 lines. */
7
+ export class TuiItemRenderer {
8
+ tui;
9
+ markdownCache = new WeakMap();
10
+ itemLineCache = new WeakMap();
11
+ toolBlockCache = new WeakMap();
12
+ constructor(tui) {
13
+ this.tui = tui;
14
+ }
15
+ renderItem(item, state) {
16
+ const cached = this.itemLineCache.get(item);
17
+ if (cached &&
18
+ !item.streaming &&
19
+ cached.showThinking === state.showThinking &&
20
+ cached.showToolDetail === state.showToolDetail &&
21
+ cached.width === this.tui.terminal.columns) {
22
+ return cached.lines;
23
+ }
24
+ const lines = this.computeRenderItem(item, state);
25
+ if (!item.streaming) {
26
+ this.itemLineCache.set(item, {
27
+ lines,
28
+ showThinking: state.showThinking,
29
+ showToolDetail: state.showToolDetail,
30
+ width: this.tui.terminal.columns,
31
+ });
32
+ }
33
+ return lines;
34
+ }
35
+ computeRenderItem(item, state) {
36
+ switch (item.kind) {
37
+ case "user":
38
+ if (!item.text)
39
+ return [];
40
+ if (item.pending) {
41
+ return [`\u001b[2m » ${item.text.replace(/\r?\n/g, " ↵ ")}\u001b[0m`];
42
+ }
43
+ return this.markdownLines(item, 1, 1, USER_TEXT_STYLE);
44
+ case "assistant": {
45
+ const lines = [];
46
+ if (item.thinking)
47
+ lines.push(...this.renderThinking(item.thinking, state.showThinking));
48
+ if (item.text)
49
+ lines.push(...this.markdownLines(item, 1, 0));
50
+ return lines;
51
+ }
52
+ case "thinking":
53
+ return this.renderThinking(item.text, state.showThinking);
54
+ case "tool":
55
+ return this.renderTool(item, state.showToolDetail);
56
+ case "status":
57
+ return [`\u001b[2m [${item.text}]\u001b[0m`];
58
+ case "error":
59
+ return [`\u001b[31m error: ${item.text}\u001b[0m`];
60
+ }
61
+ }
62
+ markdownLines(item, paddingX, paddingY, style) {
63
+ let md = this.markdownCache.get(item);
64
+ if (!md) {
65
+ md = new Markdown(item.text, paddingX, paddingY, MARKDOWN_THEME, style);
66
+ this.markdownCache.set(item, md);
67
+ }
68
+ else {
69
+ md.setText(item.text);
70
+ }
71
+ return md.render(this.tui.terminal.columns);
72
+ }
73
+ renderThinking(text, expanded) {
74
+ if (!text)
75
+ return [];
76
+ const firstLine = text.split("\n", 1)[0] ?? "";
77
+ const dim = (s) => `\u001b[2m${s}\u001b[0m`;
78
+ if (!expanded) {
79
+ if (text.length === firstLine.length)
80
+ return [dim(` ~ ${firstLine}`)];
81
+ return [dim(` ~ ${firstLine} … (ctrl+t)`)];
82
+ }
83
+ const wrapWidth = Math.max(20, this.tui.terminal.columns - 6);
84
+ return wrapTextWithAnsi(text, wrapWidth).map((line) => dim(` ~ ${line}`));
85
+ }
86
+ renderTool(item, expanded) {
87
+ const toolName = item.text.replace(/…$/, "");
88
+ if (toolName === "todo" || toolName === "todo_read" || toolName === "todo_write") {
89
+ return renderTodoTool(item, expanded);
90
+ }
91
+ if (toolName === "task" || toolName === "task_list" || toolName === "task_output") {
92
+ return renderTaskTool(item, expanded);
93
+ }
94
+ const failed = item.result !== undefined &&
95
+ (item.result.isError === true || item.result.error !== undefined);
96
+ const running = item.streaming;
97
+ const mark = running ? "\u27f3" : failed ? "\u2718" : "\u2714";
98
+ const state = running ? "running" : failed ? "error" : "success";
99
+ const titleColor = state === "running" ? "\u001b[33m" : state === "error" ? "\u001b[31m" : "\u001b[32m";
100
+ const wallMs = item.durationMs ??
101
+ (item.streaming && item.startedAt !== undefined ? Date.now() - item.startedAt : undefined);
102
+ const wall = wallMs === undefined ? "—" : `${(wallMs / 1000).toFixed(2)}s`;
103
+ const timeoutMs = item.timeoutMs;
104
+ const timeout = timeoutMs === undefined ? "—" : `${(timeoutMs / 1000).toFixed(0)}s`;
105
+ const header = renderToolHeader({
106
+ icon: mark,
107
+ title: toolName,
108
+ meta: [`\u001b[2m⟦Wall: ${wall} | Timeout: ${timeout}⟧\u001b[0m`],
109
+ titleColor,
110
+ });
111
+ const sections = [];
112
+ if (item.input !== undefined) {
113
+ const lines = [];
114
+ if (expanded) {
115
+ for (const line of prettyJson(item.input).split("\n")) {
116
+ lines.push(`\u001b[2m${line}\u001b[0m`);
117
+ }
118
+ }
119
+ else {
120
+ lines.push(`\u001b[2m└ ${summarizeToolArgs(toolName, item.input)}\u001b[0m`);
121
+ }
122
+ sections.push({ lines });
123
+ }
124
+ if (toolName === "edit" && item.input !== undefined) {
125
+ const str = (v) => (typeof v === "string" ? v : "");
126
+ const lines = [];
127
+ for (const line of str(item.input.old_string).split("\n").slice(0, MAX_DIFF_LINES)) {
128
+ lines.push(`\u001b[31m- ${line.slice(0, 90)}\u001b[0m`);
129
+ }
130
+ for (const line of str(item.input.new_string).split("\n").slice(0, MAX_DIFF_LINES)) {
131
+ lines.push(`\u001b[32m+ ${line.slice(0, 90)}\u001b[0m`);
132
+ }
133
+ sections.push({ lines });
134
+ }
135
+ if (item.output && item.streaming) {
136
+ const tail = item.output.slice(-600);
137
+ const lines = [];
138
+ for (const line of tail.split("\n").slice(-4)) {
139
+ if (line.trim())
140
+ lines.push(`\u001b[2m${line}\u001b[0m`);
141
+ }
142
+ sections.push({ lines });
143
+ }
144
+ if (item.result !== undefined) {
145
+ const content = typeof item.result.content === "string" ? item.result.content : null;
146
+ const resultColor = failed ? "\u001b[31m" : "\u001b[2m";
147
+ const lines = [];
148
+ if (content !== null) {
149
+ let textContent = content.trimEnd();
150
+ const trimmed = textContent.trimStart();
151
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
152
+ try {
153
+ textContent = prettyJson(JSON.parse(textContent));
154
+ }
155
+ catch {
156
+ // non-JSON that merely starts with a bracket: keep raw text
157
+ }
158
+ }
159
+ const outputLines = textContent
160
+ .split("\n")
161
+ .filter((line) => !(!failed && /\[exit: \d+\]/.test(line)));
162
+ const maxOut = expanded ? 12 : 4;
163
+ const display = outputLines.slice(0, maxOut);
164
+ const isCodeResult = toolName === "read" || toolName === "write";
165
+ for (const line of display) {
166
+ const truncated = truncateToWidth(line, this.tui.terminal.columns - 6);
167
+ lines.push(isCodeResult && !failed
168
+ ? MARKDOWN_THEME.codeBlock(truncated)
169
+ : `${resultColor}${truncated}\u001b[0m`);
170
+ }
171
+ if (outputLines.length > maxOut) {
172
+ lines.push(`\u001b[2m… ${outputLines.length - maxOut} more lines · (ctrl+o)\u001b[0m`);
173
+ }
174
+ else if (!expanded) {
175
+ lines.push(`\u001b[2m· (ctrl+o)\u001b[0m`);
176
+ }
177
+ }
178
+ else {
179
+ const summary = summarizeResult(item.result);
180
+ if (summary)
181
+ lines.push(`${resultColor}${summary}\u001b[0m`);
182
+ }
183
+ if (content !== null || Object.keys(item.result).length > 0) {
184
+ sections.push({ label: "Output", lines });
185
+ }
186
+ }
187
+ let block = this.toolBlockCache.get(item);
188
+ if (!block) {
189
+ block = new CachedOutputBlock();
190
+ this.toolBlockCache.set(item, block);
191
+ }
192
+ return [
193
+ ...block.render({
194
+ header,
195
+ state,
196
+ sections,
197
+ width: this.tui.terminal.columns,
198
+ bg: (line) => `\u001b[48;5;234m${line}\u001b[0m`,
199
+ }),
200
+ ];
201
+ }
202
+ }
203
+ /** Header/status/transcript render shell for createTerminalIo. Owns the
204
+ * display-only mutable state (header fields, busy, status line) so the io
205
+ * assembly file stays small. */
206
+ export class TuiRenderShell {
207
+ tui;
208
+ headerContainer;
209
+ transcript;
210
+ statusContainer;
211
+ workspaceRoot;
212
+ welcomeTip;
213
+ headerInfo = "oma";
214
+ headerModel = "";
215
+ headerSession = "";
216
+ headerTitle = "";
217
+ headerContext = "";
218
+ busy = false;
219
+ loader = null;
220
+ busySeconds = 0;
221
+ currentState = null;
222
+ statusLineText = "";
223
+ itemRenderer;
224
+ reconciler;
225
+ lastLiveStartRow = 0;
226
+ lastTotalRows = 0;
227
+ constructor(tui, headerContainer, transcript, statusContainer, workspaceRoot, welcomeTip) {
228
+ this.tui = tui;
229
+ this.headerContainer = headerContainer;
230
+ this.transcript = transcript;
231
+ this.statusContainer = statusContainer;
232
+ this.workspaceRoot = workspaceRoot;
233
+ this.welcomeTip = welcomeTip;
234
+ this.itemRenderer = new TuiItemRenderer(tui);
235
+ this.reconciler = new TuiTranscriptReconciler();
236
+ }
237
+ setHeader(model, session, title, context) {
238
+ this.headerModel = model;
239
+ this.headerSession = session;
240
+ this.headerTitle = title;
241
+ if (context !== undefined)
242
+ this.headerContext = context;
243
+ this.renderHeader();
244
+ if (!this.busy) {
245
+ this.statusContainer.clear();
246
+ this.renderIdleFooter();
247
+ }
248
+ this.tui.requestRender();
249
+ }
250
+ setBusy(busy, loader, busySeconds) {
251
+ this.busy = busy;
252
+ this.loader = loader;
253
+ this.busySeconds = busySeconds;
254
+ }
255
+ setBusySeconds(busySeconds) {
256
+ this.busySeconds = busySeconds;
257
+ }
258
+ setCurrentState(state) {
259
+ this.currentState = state;
260
+ }
261
+ renderHeader() {
262
+ this.headerContainer.clear();
263
+ const banner = [
264
+ "\u001b[36m ██████╗ ███╗ ███╗ █████╗ \u001b[0m",
265
+ "\u001b[36m ██╔═══██╗████╗ ████║██╔══██╗\u001b[0m",
266
+ "\u001b[36m ██║ ██║██╔████╔██║███████║\u001b[0m",
267
+ "\u001b[36m ██║ ██║██║╚██╔╝██║██╔══██║\u001b[0m",
268
+ "\u001b[36m ╚██████╔╝██║ ╚═╝ ██║██║ ██║\u001b[0m",
269
+ "\u001b[36m ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝\u001b[0m",
270
+ ];
271
+ const infoLines = [];
272
+ infoLines.push(`\u001b[1m ${this.headerInfo}\u001b[0m`);
273
+ const hTitle = cleanHeaderTitle(this.headerTitle);
274
+ if (hTitle)
275
+ infoLines.push(`\u001b[2m ${hTitle}\u001b[0m`);
276
+ if (this.headerModel) {
277
+ infoLines.push(`\u001b[2m model:\u001b[0m \u001b[36m${this.headerModel}\u001b[0m`);
278
+ }
279
+ infoLines.push(`\u001b[2m workspace:\u001b[0m \u001b[38;5;39m${formatWorkspace(this.workspaceRoot)}\u001b[0m`);
280
+ const hGit = gitStatus(this.workspaceRoot);
281
+ if (hGit)
282
+ infoLines.push(`\u001b[2m git:\u001b[0m ${renderGitSegment(hGit)}`);
283
+ if (this.headerSession)
284
+ infoLines.push(`\u001b[2m session:\u001b[0m ${this.headerSession.slice(0, 8)}`);
285
+ if (this.headerContext)
286
+ infoLines.push(`\u001b[2m context:\u001b[0m ${this.headerContext}`);
287
+ const combined = [];
288
+ const rows = Math.max(banner.length, infoLines.length);
289
+ for (let i = 0; i < rows; i++) {
290
+ const left = banner[i] ?? "";
291
+ const right = infoLines[i] ?? "";
292
+ combined.push(`${left}${left ? " " : ""}${right}`);
293
+ }
294
+ const headerCard = new Card(combined.map((line) => new Text(truncateToWidth(line, this.tui.terminal.columns - 2), 0, 0)), {
295
+ paddingX: 0,
296
+ paddingY: 0,
297
+ border: { color: (s) => `\u001b[2m${s}\u001b[0m` },
298
+ });
299
+ const infoLinesRendered = headerCard.render(this.tui.terminal.columns);
300
+ for (const line of infoLinesRendered) {
301
+ this.headerContainer.addChild(new Text(truncateToWidth(line, this.tui.terminal.columns), 0, 0));
302
+ }
303
+ }
304
+ currentActivitySummary() {
305
+ if (!this.currentState)
306
+ return undefined;
307
+ for (let r = this.currentState.runs.length - 1; r >= 0; r--) {
308
+ const run = this.currentState.runs[r];
309
+ for (let i = run.items.length - 1; i >= 0; i--) {
310
+ const item = run.items[i];
311
+ if (item.kind === "tool" && item.streaming) {
312
+ const name = item.text.replace(/…$/, "");
313
+ const intent = typeof item.input?.intent === "string"
314
+ ? item.input.intent.trim()
315
+ : typeof item.input?.description === "string"
316
+ ? item.input.description.trim()
317
+ : "";
318
+ const summary = intent
319
+ ? intent
320
+ : item.input !== undefined
321
+ ? summarizeToolArgs(name, item.input)
322
+ : "";
323
+ return summary.trim() ? `${name} · ${summary}` : name;
324
+ }
325
+ if (item.kind === "assistant" && item.streaming) {
326
+ const source = `${item.thinking ?? ""}
327
+ ${item.text ?? ""}`;
328
+ const first = source.split("\n", 1)[0]?.trim() ?? "";
329
+ if (first)
330
+ return first.length > 80 ? `${first.slice(0, 80)}…` : first;
331
+ }
332
+ }
333
+ }
334
+ // Fallback: a busy run with a tool item (even if the streaming flag is
335
+ // lost) should never read as a bare "working…".
336
+ for (let r = this.currentState.runs.length - 1; r >= 0; r--) {
337
+ const run = this.currentState.runs[r];
338
+ for (let i = run.items.length - 1; i >= 0; i--) {
339
+ const item = run.items[i];
340
+ if (item.kind === "tool" && item.text)
341
+ return item.text.replace(/…$/, "");
342
+ }
343
+ }
344
+ return undefined;
345
+ }
346
+ updateWorkingMessage() {
347
+ if (!this.busy || !this.loader)
348
+ return;
349
+ const summary = this.currentActivitySummary();
350
+ const seconds = this.busySeconds > 0 ? ` · ${this.busySeconds}s` : "";
351
+ const msg = summary
352
+ ? `${summary}${seconds} (esc to abort)`
353
+ : `working…${seconds} (esc to abort)`;
354
+ this.loader.setMessage(msg);
355
+ }
356
+ addStatusBar() {
357
+ const git = gitStatus(this.workspaceRoot);
358
+ const segs = [];
359
+ if (this.headerModel) {
360
+ segs.push({ text: this.headerModel, chip: true, bg: "\u001b[48;5;25m" });
361
+ }
362
+ segs.push({ text: formatWorkspace(this.workspaceRoot), fg: "\u001b[38;5;39m" });
363
+ if (git)
364
+ segs.push({ text: renderGitSegment(git) });
365
+ if (this.headerSession)
366
+ segs.push({ text: this.headerSession.slice(0, 8), fg: "\u001b[2m" });
367
+ if (this.headerContext)
368
+ segs.push({ text: this.headerContext, fg: contextColor(this.headerContext) });
369
+ if (segs.length > 0) {
370
+ this.statusLineText = renderStatusBar(segs);
371
+ }
372
+ }
373
+ renderIdleFooter() {
374
+ if (this.busy || this.statusContainer.children.length > 0)
375
+ return;
376
+ this.addStatusBar();
377
+ }
378
+ render(state) {
379
+ this.setCurrentState(state);
380
+ this.transcript.setDeferCommit(state.runs.some((r) => r.running &&
381
+ r.items.some((i) => i.kind === "assistant" &&
382
+ (i.text.includes("```mermaid") || i.text.includes("~~~mermaid")))));
383
+ if (this.busy)
384
+ this.updateWorkingMessage();
385
+ const result = this.reconciler.reconcile(this.transcript, state.runs, state, (item) => this.itemRenderer.renderItem(item, state));
386
+ this.lastLiveStartRow = result.liveStartRow;
387
+ this.lastTotalRows = result.totalRows;
388
+ if (state.runs.length === 0 && this.welcomeTip && this.transcript.children.length === 0) {
389
+ this.transcript.addChild(new Text(`\u001b[33m ${this.welcomeTip}\u001b[0m`, 0, 0));
390
+ }
391
+ this.renderIdleFooter();
392
+ if (result.didReset) {
393
+ this.tui.requestRender(true);
394
+ }
395
+ else {
396
+ this.tui.requestRender();
397
+ }
398
+ }
399
+ }
@@ -0,0 +1,12 @@
1
+ import type { SlashCommand } from "@chengchenccc/tui";
2
+ import type { CommandDef, TuiSessionContext } from "./tui-commands.js";
3
+ export interface SlashSystem {
4
+ commandsWithSkills: CommandDef[];
5
+ slashCommands: SlashCommand[];
6
+ runCommandText: (text: string) => Promise<void>;
7
+ }
8
+ /** Auto-registered skill commands (pi's /skill:<name> pattern): every
9
+ * discovered skill becomes a slash command that submits a prompt pointing
10
+ * the model at the skill. */
11
+ export declare function buildSlashSystem(ctx: TuiSessionContext, commands: CommandDef[]): SlashSystem;
12
+ //# sourceMappingURL=tui-slash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-slash.d.ts","sourceRoot":"","sources":["../../../src/modes/tui/tui-slash.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,UAAU,EAAE,CAAC;IACjC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED;;8BAE8B;AAC9B,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,WAAW,CAsE5F"}
@@ -0,0 +1,64 @@
1
+ import { resolveStandaloneSkillRoots } from "../../cli/initial-input.js";
2
+ import { buildSkillIndex } from "../../core/tools/index.js";
3
+ /** Auto-registered skill commands (pi's /skill:<name> pattern): every
4
+ * discovered skill becomes a slash command that submits a prompt pointing
5
+ * the model at the skill. */
6
+ export function buildSlashSystem(ctx, commands) {
7
+ const skillCommands = buildSkillIndex(resolveStandaloneSkillRoots(ctx.opts.workspaceRoot)).map((sk) => ({
8
+ name: `skill:${sk.name}`,
9
+ description: sk.description || `invoke the ${sk.name} skill`,
10
+ group: "skill",
11
+ run: (args) => {
12
+ ctx.pendingPrompt = args
13
+ ? `${args}\n\n(follow the "${sk.name}" skill — skill_load "${sk.name}" first)`
14
+ : `Follow the "${sk.name}" skill (skill_load "${sk.name}" first).`;
15
+ },
16
+ }));
17
+ const commandsWithSkills = [...commands, ...skillCommands];
18
+ ctx.commandsWithSkills = commandsWithSkills;
19
+ // Autocomplete: the editor already triggers on "/" — hand it the table
20
+ // (static commands + auto-registered skill commands).
21
+ const slashCommands = commandsWithSkills.map((c) => {
22
+ const command = { name: c.name, description: c.description };
23
+ if (c.argumentHint)
24
+ command.argumentHint = c.argumentHint;
25
+ if (c.name === "model") {
26
+ command.getArgumentCompletions = async (prefix) => {
27
+ const models = await ctx.listModels();
28
+ return models.filter((m) => m.startsWith(prefix)).map((m) => ({ value: m, label: m }));
29
+ };
30
+ }
31
+ if (c.name === "resume") {
32
+ command.getArgumentCompletions = (prefix) => ctx
33
+ .listSessions()
34
+ .filter((s) => s.id.startsWith(prefix))
35
+ .slice(0, 20)
36
+ .map((s) => ({
37
+ value: s.id,
38
+ label: s.id,
39
+ description: s.title ?? (s.preview || undefined),
40
+ }));
41
+ }
42
+ return command;
43
+ });
44
+ /** Slash-command dispatch shared by the idle loop and live submissions
45
+ * (pi's LiveCommandController: /commands execute even mid-run instead of
46
+ * being steered into the model as literal text). */
47
+ async function runCommandText(text) {
48
+ const space = text.indexOf(" ");
49
+ const name = space === -1 ? text.slice(1) : text.slice(1, space);
50
+ const args = space === -1 ? "" : text.slice(space + 1).trim();
51
+ const command = commandsWithSkills.find((c) => c.name === name) ??
52
+ commandsWithSkills.find((c) => c.aliases?.includes(name));
53
+ if (!command) {
54
+ ctx.pushStatus(`unknown command /${name} — try /help`);
55
+ return;
56
+ }
57
+ if (ctx.liveRuntime && !command.live) {
58
+ ctx.pushStatus(`/${name} is not available while a run is live`);
59
+ return;
60
+ }
61
+ await command.run(args);
62
+ }
63
+ return { commandsWithSkills, slashCommands, runCommandText };
64
+ }
@@ -0,0 +1,6 @@
1
+ import type { TranscriptItem } from "./view-state.js";
2
+ /** omp-style plain-list todo rendering (no card/box). */
3
+ export declare function renderTodoTool(item: TranscriptItem, expanded: boolean): string[];
4
+ /** omp-style plain-list task rendering (no card/box). */
5
+ export declare function renderTaskTool(item: TranscriptItem, expanded: boolean): string[];
6
+ //# sourceMappingURL=tui-tool-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-tool-render.d.ts","sourceRoot":"","sources":["../../../src/modes/tui/tui-tool-render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CAoBhF;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CAoBhF"}
@@ -0,0 +1,79 @@
1
+ /** omp-style plain-list todo rendering (no card/box). */
2
+ export function renderTodoTool(item, expanded) {
3
+ const lines = ["\u001b[36m todo\u001b[0m"];
4
+ const items = todoItems(item);
5
+ if (items.length === 0)
6
+ return ["\u001b[36m todo\u001b[0m", "\u001b[2m (no items)\u001b[0m"];
7
+ for (const it of items) {
8
+ const mark = it.status === "done"
9
+ ? "\u001b[32m✓\u001b[0m"
10
+ : it.status === "in_progress"
11
+ ? "\u001b[33m●\u001b[0m"
12
+ : it.status === "cancelled"
13
+ ? "\u001b[31m✗\u001b[0m"
14
+ : "\u001b[2m☐\u001b[0m";
15
+ lines.push(` ${mark} ${it.text}`);
16
+ }
17
+ if (!expanded) {
18
+ const open = items.filter((i) => i.status !== "done" && i.status !== "cancelled").length;
19
+ if (open > 0)
20
+ lines.push(`\u001b[2m ${open} open — (ctrl+o for full list)\u001b[0m`);
21
+ }
22
+ return lines;
23
+ }
24
+ /** omp-style plain-list task rendering (no card/box). */
25
+ export function renderTaskTool(item, expanded) {
26
+ const label = typeof item.input?.label === "string" ? item.input.label : "";
27
+ const lines = [`\u001b[36m task${label ? ` · ${label}` : ""}\u001b[0m`];
28
+ const result = item.result;
29
+ if (result && typeof result === "object" && "status" in result) {
30
+ const st = String(result.status);
31
+ lines.push(`\u001b[2m status: ${st}\u001b[0m`);
32
+ }
33
+ const content = typeof result?.content === "string"
34
+ ? result.content
35
+ : typeof result?.text === "string"
36
+ ? result.text
37
+ : "";
38
+ if (content) {
39
+ const text = content.trim();
40
+ if (text)
41
+ lines.push(`\u001b[2m ${text.slice(0, expanded ? 400 : 160)}\u001b[0m`);
42
+ }
43
+ if (lines.length === 1)
44
+ lines.push(`\u001b[2m (done)\u001b[0m`);
45
+ return lines;
46
+ }
47
+ function todoItems(item) {
48
+ const candidates = [];
49
+ const result = item.result;
50
+ if (result) {
51
+ if (Array.isArray(result.items))
52
+ candidates.push(...result.items);
53
+ const content = typeof result.content === "string" ? result.content : "";
54
+ if (content) {
55
+ try {
56
+ const parsed = JSON.parse(content);
57
+ if (Array.isArray(parsed.items))
58
+ candidates.push(...parsed.items);
59
+ }
60
+ catch {
61
+ // keep raw string path below
62
+ }
63
+ }
64
+ }
65
+ if (item.input && Array.isArray(item.input.items))
66
+ candidates.push(...item.input.items);
67
+ return candidates
68
+ .filter((v) => typeof v === "object" &&
69
+ v !== null &&
70
+ "text" in v &&
71
+ typeof v.text === "string" &&
72
+ "status" in v &&
73
+ typeof v.status === "string")
74
+ .map((v) => ({
75
+ id: "id" in v && typeof v.id === "string" ? v.id : "",
76
+ text: v.text,
77
+ status: v.status,
78
+ }));
79
+ }
@@ -0,0 +1,25 @@
1
+ import type { OmaTranscriptContainer } from "./tui-components.js";
2
+ import type { RunViewState, TranscriptItem, TuiViewState } from "./view-state.js";
3
+ export interface ReconcileResult {
4
+ /** Row index of the first streaming item (or totalRows when none stream). */
5
+ liveStartRow: number;
6
+ /** Total rendered rows in the transcript container. */
7
+ totalRows: number;
8
+ /** True when a full rebuild was forced (flag toggle or item removal). */
9
+ didReset: boolean;
10
+ }
11
+ /** Incrementally reconciles transcript children with the current view state.
12
+ * Items are matched by `runIndex:itemIndex` because the view-state objects
13
+ * are rebuilt every turn; keying by object identity would force a full reset
14
+ * (and a scrollback clear) on every render. */
15
+ export declare class TuiTranscriptReconciler {
16
+ private readonly orderKeys;
17
+ private readonly groups;
18
+ private lastShowThinking;
19
+ private lastShowToolDetail;
20
+ reconcile(transcript: OmaTranscriptContainer, runs: readonly RunViewState[], state: TuiViewState, renderItem: (item: TranscriptItem) => string[]): ReconcileResult;
21
+ /** Force a full rebuild (display flag toggle or item removal). */
22
+ reset(transcript: OmaTranscriptContainer): void;
23
+ private updateGroup;
24
+ }
25
+ //# sourceMappingURL=tui-transcript-reconciler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-transcript-reconciler.d.ts","sourceRoot":"","sources":["../../../src/modes/tui/tui-transcript-reconciler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;gDAGgD;AAChD,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,kBAAkB,CAAS;IAEnC,SAAS,CACP,UAAU,EAAE,sBAAsB,EAClC,IAAI,EAAE,SAAS,YAAY,EAAE,EAC7B,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,EAAE,GAC7C,eAAe;IAiElB,kEAAkE;IAClE,KAAK,CAAC,UAAU,EAAE,sBAAsB,GAAG,IAAI;IAM/C,OAAO,CAAC,WAAW;CAiBpB"}