@akanjs/cli 3.0.0-beta.9 → 3.0.0

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 (224) hide show
  1. package/.build-stamp +1 -1
  2. package/CodeAgent-2vmp9qe0.js +9 -0
  3. package/CodeAgentRpcHost-p7h6n2hp.js +7 -0
  4. package/CodeAgentRpcListener-7p7z5dd7.js +97 -0
  5. package/CodeTui-5ed6bg2a.js +1457 -0
  6. package/README.ko.md +83 -28
  7. package/README.md +70 -27
  8. package/TunnelShare-cwh9ezsm.js +9 -0
  9. package/{agent.command-0q17pnrs.js → agent.command-gn73rhe7.js} +8 -9
  10. package/akanCode.js +102 -0
  11. package/application.command-e968t0hw.js +246 -0
  12. package/{applicationBuildRunner-kxwbssgn.js → applicationBuildRunner-64taxseg.js} +121 -77
  13. package/buildBatch.proc.js +120 -32
  14. package/cloud.command-0jm301rr.js +95 -0
  15. package/cloud.script-nemnzjpv.js +20 -0
  16. package/code.command-18kcm7hq.js +154 -0
  17. package/commandManifest.json +1 -1
  18. package/consoleToStderr-h5bryj94.js +7 -0
  19. package/context.command-trd9bn18.js +48 -0
  20. package/context.runner-y5hwh673.js +21 -0
  21. package/{dependencyScanner-shs82ynp.js → dependencyScanner-06z2dmrr.js} +2 -2
  22. package/{devTui-m1atgkc9.js → devTui-q7k7bakd.js} +122 -40
  23. package/fileSys-wzzrntkw.js +9 -0
  24. package/guideline.command-bdmdn2de.js +42 -0
  25. package/guidelines/agentRule/agentRule.instruction.md +154 -26
  26. package/guidelines/conventions/conventions.instruction.md +134 -48
  27. package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
  28. package/guidelines/queryRule/queryRule.instruction.md +21 -7
  29. package/guidelines/runtimeRule/runtimeRule.instruction.md +291 -6
  30. package/guidelines/ssrRule/ssrRule.instruction.md +4 -2
  31. package/guidelines/transportRule/transportRule.instruction.md +10 -8
  32. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +20 -0
  33. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +66 -3
  34. package/incrementalBuilder.proc.js +564 -109
  35. package/index-0wpybxtr.js +2729 -0
  36. package/{index-kcxmv48c.js → index-2ahj896a.js} +45 -79
  37. package/index-2wc41k5w.js +49 -0
  38. package/index-3hx1z96c.js +87 -0
  39. package/{index-2tv3fdx4.js → index-3w94e7n3.js} +1228 -1458
  40. package/{index-hwkygn9s.js → index-48k96p55.js} +325 -36
  41. package/index-4npz05nm.js +187 -0
  42. package/{index-q0y2jq9j.js → index-52w0fvh8.js} +21 -4
  43. package/index-6he6gvfg.js +4300 -0
  44. package/index-7md2g9vw.js +6 -0
  45. package/{index-04bk599g.js → index-93j60em0.js} +10 -17
  46. package/index-94s080qm.js +266 -0
  47. package/index-9dp031by.js +12 -0
  48. package/{index-ktb5njgy.js → index-9z771ptz.js} +49 -99
  49. package/{index-y6n8nmny.js → index-abxpehf8.js} +75 -203
  50. package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
  51. package/{index-9077wzd2.js → index-by9pxkr0.js} +43 -26
  52. package/index-c6eggbee.js +123 -0
  53. package/index-d2242ksy.js +99 -0
  54. package/index-drehwpdt.js +1119 -0
  55. package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
  56. package/{index-ffvk10zz.js → index-f3c78nd6.js} +107 -241
  57. package/index-gbggbqcp.js +1058 -0
  58. package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
  59. package/index-hsmtysz4.js +53 -0
  60. package/{index-j9yhg404.js → index-jmrn54tt.js} +4 -7
  61. package/{index-a64esmtb.js → index-kcdj1z5v.js} +523 -1022
  62. package/{index-d43r08tf.js → index-kqabytj7.js} +77 -150
  63. package/{index-vyvre9en.js → index-mbxbhay5.js} +6 -2
  64. package/{index-vxtad5bd.js → index-mgxpx3f2.js} +5 -8
  65. package/index-p6pbz9n5.js +25 -0
  66. package/{index-sj5vxr8f.js → index-p993efkq.js} +981 -897
  67. package/{index-2xp0kfkt.js → index-pmhqttv3.js} +37 -25
  68. package/index-tqm7jjcn.js +700 -0
  69. package/{index-0g7r8xz3.js → index-vpj42xwt.js} +114 -232
  70. package/index-wa5jbxj1.js +760 -0
  71. package/{index-k2j1hc4r.js → index-wprnsjms.js} +12 -12
  72. package/{index-gyd220p2.js → index-y3mphr1m.js} +554 -577
  73. package/index-yg7jhz8x.js +69 -0
  74. package/{index-h7yw2z9n.js → index-zzvvc845.js} +8 -14
  75. package/index.js +23 -22
  76. package/{library.command-qzzbj6d8.js → library.command-9h749a1x.js} +4 -5
  77. package/{localRegistry.command-vyrgg4xw.js → localRegistry.command-2bqqhxyz.js} +23 -43
  78. package/{module.command-rq5hq3ax.js → module.command-nv8nzgft.js} +8 -12
  79. package/{package.command-d9hd6v9n.js → package.command-mq4bggp6.js} +6 -7
  80. package/package.json +15 -7
  81. package/{page.command-126d56te.js → page.command-j639n707.js} +4 -5
  82. package/{primitive.command-taxd1538.js → primitive.command-kz6849th.js} +9 -23
  83. package/prompter-76k56b37.js +8 -0
  84. package/{quality.command-6gsna0a3.js → quality.command-4hyabwkb.js} +205 -377
  85. package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
  86. package/{repair.command-tq2dgy72.js → repair.command-a9awpbqr.js} +11 -35
  87. package/{routeSourceValidator-apyqw7wk.js → routeSourceValidator-7ycnfz0e.js} +0 -6
  88. package/{scalar.command-3bcmrrkv.js → scalar.command-ma4fpm9m.js} +7 -11
  89. package/skills/akan-code/SKILL.md +130 -0
  90. package/skills/akan-debug/SKILL.md +42 -0
  91. package/skills/akan-deps/SKILL.md +50 -0
  92. package/skills/akan-err/SKILL.md +39 -0
  93. package/skills/akan-module/SKILL.md +45 -0
  94. package/skills/akan-scaffold/SKILL.md +76 -0
  95. package/skills/akan-scalar/SKILL.md +52 -0
  96. package/skills/akan-service/SKILL.md +34 -0
  97. package/skills/akan-store/SKILL.md +67 -0
  98. package/skills/akan-ui/SKILL.md +63 -0
  99. package/skills/akan-validate/SKILL.md +44 -0
  100. package/{subspace.command-eddzqpx3.js → subspace.command-3k2pmrs4.js} +53 -62
  101. package/templates/__scalar/__model__/__model__.abstract.md.template +8 -0
  102. package/templates/app/page/_index.tsx +257 -258
  103. package/templates/app/page/_layout.tsx +5 -1
  104. package/templates/app/page/_overrides.tsx +12 -0
  105. package/templates/app/page/styles.css.template +316 -14
  106. package/templates/app/public/apple-touch-icon.png +0 -0
  107. package/templates/app/public/favicon.ico +0 -0
  108. package/templates/app/public/jelly/cloud.webp +0 -0
  109. package/templates/app/public/jelly/comet.webp +0 -0
  110. package/templates/app/public/jelly/moon.webp +0 -0
  111. package/templates/app/public/jelly/planet.webp +0 -0
  112. package/templates/app/public/jelly/rocket.webp +0 -0
  113. package/templates/app/public/jelly/star.webp +0 -0
  114. package/templates/app/public/jelly/sugar.webp +0 -0
  115. package/templates/app/public/logo.png +0 -0
  116. package/templates/app/ui/Recipe/index.ts +9 -0
  117. package/templates/app/ui/Recipe/jellyButton.ts +63 -0
  118. package/templates/appSample/lib/__scalar/workHistory/workHistory.abstract.ts +8 -39
  119. package/templates/appSample/lib/_noti/noti.abstract.ts +6 -29
  120. package/templates/appSample/lib/task/Task.Unit.tsx +1 -1
  121. package/templates/appSample/lib/task/Task.Util.tsx +10 -13
  122. package/templates/appSample/lib/task/Task.View.tsx +2 -2
  123. package/templates/appSample/lib/task/Task.Zone.tsx +5 -2
  124. package/templates/appSample/lib/task/task.abstract.ts +12 -32
  125. package/templates/appSample/lib/task/task.signal.spec.ts +1 -15
  126. package/templates/appSample/lib/task/task.signal.test.ts +15 -1
  127. package/templates/appSample/lib/task/task.signal.ts +10 -8
  128. package/templates/appSample/page/task/[taskId]/_index.tsx +6 -6
  129. package/templates/appSample/page/task/[taskId]/edit.tsx +5 -4
  130. package/templates/appSample/page/task/_index.tsx +4 -3
  131. package/templates/appSample/page/task/_layout.tsx +1 -1
  132. package/templates/appSample/page/task/new.tsx +5 -4
  133. package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +7 -4
  134. package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +6 -4
  135. package/templates/appSample/ui/GlobalLoading.tsx +2 -1
  136. package/templates/appSample/ui/QuantityControl.tsx +3 -3
  137. package/templates/client.ts +7 -30
  138. package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -1
  139. package/templates/crudPages/[__model__Id]/page.tsx +2 -1
  140. package/templates/crudPages/new/page.tsx +2 -1
  141. package/templates/crudPages/page.tsx +2 -1
  142. package/templates/crudSinglePage/page.tsx +2 -1
  143. package/templates/lib/__lib/lib.dictionary.ts +0 -2
  144. package/templates/lib/__lib/lib.document.ts +0 -2
  145. package/templates/lib/sig.ts +8 -30
  146. package/templates/localDev/docker-compose.yaml.template +3 -14
  147. package/templates/module/__model__.signal.ts +12 -4
  148. package/templates/pkgRoot/tsconfig.json.template +2 -7
  149. package/templates/server.ts +1 -3
  150. package/templates/service/__model__.abstract.md.template +8 -0
  151. package/templates/workspaceRoot/.gitignore.template +0 -1
  152. package/templates/workspaceRoot/AGENTS.md.template +6 -0
  153. package/templates/workspaceRoot/package.json.template +1 -3
  154. package/tunnel.command-xwr46b66.js +129 -0
  155. package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
  156. package/typecheck.proc.js +1 -1
  157. package/workflow.command-t7wqe4h7.js +79 -0
  158. package/{workspace.command-06wvstgr.js → workspace.command-4derhzrh.js} +79 -109
  159. package/abstractCompactor-gmkc0z8j.js +0 -102
  160. package/application.command-18y0s485.js +0 -204
  161. package/applicationReleasePackager-4yasxwv9.js +0 -244
  162. package/capacitorApp-36rbr858.js +0 -12
  163. package/cloud.command-av97ndh6.js +0 -94
  164. package/cloud.script-cm11xjdz.js +0 -20
  165. package/context.command-5v37ef3n.js +0 -81
  166. package/devTuiView-0hc2emhe.js +0 -9
  167. package/getDirname-dr3jz1xg.js +0 -7
  168. package/guideline.command-4pz9g1rt.js +0 -360
  169. package/guidelines/agentRule/agentRule.generate.json +0 -31
  170. package/guidelines/componentRule/componentRule.generate.json +0 -31
  171. package/guidelines/conventions/conventions.generate.json +0 -25
  172. package/guidelines/cssRule/cssRule.generate.json +0 -31
  173. package/guidelines/docPageRule/docPageRule.generate.json +0 -31
  174. package/guidelines/docPageRule/docPageRule.instruction.md +0 -25
  175. package/guidelines/docSyncRule/docSyncRule.generate.json +0 -31
  176. package/guidelines/docSyncRule/docSyncRule.instruction.md +0 -25
  177. package/guidelines/enumConstant/enumConstant.generate.json +0 -31
  178. package/guidelines/enumConstant/enumConstant.instruction.md +0 -28
  179. package/guidelines/fieldRule/fieldRule.generate.json +0 -31
  180. package/guidelines/framework/framework.generate.json +0 -32
  181. package/guidelines/mcpRule/mcpRule.generate.json +0 -35
  182. package/guidelines/modelConstant/modelConstant.generate.json +0 -32
  183. package/guidelines/modelDictionary/modelDictionary.generate.json +0 -32
  184. package/guidelines/modelDocument/modelDocument.generate.json +0 -31
  185. package/guidelines/modelService/modelService.generate.json +0 -31
  186. package/guidelines/modelSignal/modelSignal.generate.json +0 -31
  187. package/guidelines/modelStore/modelStore.generate.json +0 -31
  188. package/guidelines/modelTemplate/modelTemplate.generate.json +0 -31
  189. package/guidelines/modelUnit/modelUnit.generate.json +0 -31
  190. package/guidelines/modelUtil/modelUtil.generate.json +0 -31
  191. package/guidelines/modelView/modelView.generate.json +0 -31
  192. package/guidelines/modelZone/modelZone.generate.json +0 -31
  193. package/guidelines/moduleCodegen/moduleCodegen.generate.json +0 -31
  194. package/guidelines/moduleCodegen/moduleCodegen.instruction.md +0 -28
  195. package/guidelines/moduleOverview/moduleOverview.generate.json +0 -31
  196. package/guidelines/queryRule/queryRule.generate.json +0 -31
  197. package/guidelines/recipeRule/recipeRule.generate.json +0 -31
  198. package/guidelines/runtimeRule/runtimeRule.generate.json +0 -25
  199. package/guidelines/scalarConstant/scalarConstant.generate.json +0 -32
  200. package/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -32
  201. package/guidelines/scalarModule/scalarModule.generate.json +0 -31
  202. package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -31
  203. package/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -25
  204. package/guidelines/ssrRule/ssrRule.generate.json +0 -31
  205. package/guidelines/transportRule/transportRule.generate.json +0 -31
  206. package/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -31
  207. package/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -25
  208. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +0 -24
  209. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +0 -33
  210. package/index-47pj3aee.js +0 -76
  211. package/index-5ystnsd5.js +0 -841
  212. package/index-6wwzs1bc.js +0 -7
  213. package/index-a17x49vg.js +0 -229
  214. package/index-m0xccmmm.js +0 -228
  215. package/index-meh558jy.js +0 -65
  216. package/index-rtxxan88.js +0 -471
  217. package/index-te54x9zm.js +0 -338
  218. package/index-w8kmx1b6.js +0 -2176
  219. package/index-wt7qrtd4.js +0 -1516
  220. package/templates/__scalar/__model__/__model__.abstract.md +0 -28
  221. package/templates/module/__model__.abstract.md +0 -28
  222. package/templates/service/__model__.abstract.md +0 -28
  223. package/templates/workspaceRoot/patches/react-dom@19.2.7.patch.template +0 -62
  224. package/workflow.command-gtdnzvbz.js +0 -108
@@ -0,0 +1,760 @@
1
+ // @bun
2
+ // pkgs/@akanjs/cli/code/CodeTuiLines.ts
3
+ import stringWidth from "string-width";
4
+
5
+ class CodeTuiLines2 {
6
+ static width(text) {
7
+ return stringWidth(text);
8
+ }
9
+ static rows(rows, width, keyBase) {
10
+ const lines = [];
11
+ rows.forEach((row, idx) => {
12
+ for (const line of CodeTuiLines2.#row(row, Math.max(8, width), `${keyBase}:${idx}`))
13
+ lines.push(line);
14
+ });
15
+ return lines;
16
+ }
17
+ static #row(row, width, key) {
18
+ const prefix = row.prefix;
19
+ const head = prefix ? CodeTuiLines2.width(prefix.text) : 0;
20
+ const hang = row.hang ?? " ".repeat(head);
21
+ const body = width - Math.max(head, CodeTuiLines2.width(hang));
22
+ const wrapped = CodeTuiLines2.#wrap(row.spans, Math.max(4, body));
23
+ if (!wrapped.length)
24
+ wrapped.push([]);
25
+ return wrapped.map((spans, at) => ({
26
+ key: `${key}:${at}`,
27
+ spans: [...at === 0 ? prefix ? [prefix] : [] : hang ? [{ text: hang }] : [], ...spans]
28
+ }));
29
+ }
30
+ static #wrap(spans, width) {
31
+ const lines = [];
32
+ let line = [];
33
+ let used = 0;
34
+ let soft = false;
35
+ const push = (fromWrap) => {
36
+ lines.push(line);
37
+ line = [];
38
+ used = 0;
39
+ soft = fromWrap;
40
+ };
41
+ for (const span of spans) {
42
+ const { text, ...style } = span;
43
+ for (const piece of text.split(`
44
+ `).flatMap((part, at) => at ? [null, part] : [part])) {
45
+ if (piece === null) {
46
+ push(false);
47
+ continue;
48
+ }
49
+ for (const word of CodeTuiLines2.#words(piece)) {
50
+ const size = CodeTuiLines2.width(word);
51
+ if (!word.trim() && !used && soft)
52
+ continue;
53
+ if (used && used + size > width)
54
+ push(true);
55
+ if (size > width) {
56
+ for (const chunk of CodeTuiLines2.chunks(word, width)) {
57
+ if (used)
58
+ push(true);
59
+ line.push({ ...style, text: chunk });
60
+ used = CodeTuiLines2.width(chunk);
61
+ if (used >= width)
62
+ push(true);
63
+ }
64
+ continue;
65
+ }
66
+ line.push({ ...style, text: word });
67
+ used += size;
68
+ }
69
+ }
70
+ }
71
+ if (line.length)
72
+ lines.push(line);
73
+ return lines;
74
+ }
75
+ static #words(text) {
76
+ return text.match(/\S+\s*|\s+/g) ?? [];
77
+ }
78
+ static chunks(word, width) {
79
+ const chunks = [];
80
+ let chunk = "";
81
+ for (const char of word) {
82
+ if (CodeTuiLines2.width(chunk + char) > width) {
83
+ chunks.push(chunk);
84
+ chunk = char;
85
+ } else
86
+ chunk += char;
87
+ }
88
+ if (chunk)
89
+ chunks.push(chunk);
90
+ return chunks;
91
+ }
92
+ static text(line) {
93
+ return line.spans.map((span) => span.text).join("");
94
+ }
95
+ }
96
+
97
+ // pkgs/@akanjs/cli/code/CodeTuiAgents.ts
98
+ class CodeTuiAgents2 {
99
+ static markWidth = 4;
100
+ static minDescription = 12;
101
+ static rows(agents, session, width, now = Date.now()) {
102
+ if (!agents.length)
103
+ return [];
104
+ const kindColumn = Math.max(...agents.map((agent) => CodeTuiLines2.width(agent.kind))) + 2;
105
+ return [
106
+ {
107
+ key: "agents:self",
108
+ spans: [{ text: "\u276F ", color: "cyan" }, { text: "\u23FA ", color: "green" }, { text: session }]
109
+ },
110
+ ...agents.map((agent, at) => ({
111
+ key: `agents:${agent.id || at}`,
112
+ spans: CodeTuiAgents2.#row(agent, kindColumn, width, now)
113
+ }))
114
+ ];
115
+ }
116
+ static #row(agent, kindColumn, width, now) {
117
+ const meta = `${CodeTuiAgents2.elapsed(now - agent.startedAt)} \xB7 \u2193 ${CodeTuiAgents2.tokens(agent.tokens)} tokens`;
118
+ const head = CodeTuiAgents2.markWidth + kindColumn;
119
+ const room = width - head - CodeTuiLines2.width(meta) - 2;
120
+ const spans = [{ text: " \u25EF ", color: "yellow" }, { text: agent.kind.padEnd(kindColumn) }];
121
+ if (room < CodeTuiAgents2.minDescription)
122
+ return [...spans, { text: CodeTuiAgents2.#clip(agent.description, Math.max(1, width - head)) }];
123
+ const description = CodeTuiAgents2.#clip(agent.description, room);
124
+ const pad = " ".repeat(Math.max(0, room - CodeTuiLines2.width(description)));
125
+ return [...spans, { text: `${description}${pad}` }, { text: ` ${meta}`, dim: true }];
126
+ }
127
+ static elapsed(ms) {
128
+ const total = Math.max(0, Math.round(ms / 1000));
129
+ const hours = Math.floor(total / 3600);
130
+ const minutes = Math.floor(total % 3600 / 60);
131
+ const seconds = total % 60;
132
+ if (hours)
133
+ return `${hours}h ${minutes}m`;
134
+ if (minutes)
135
+ return `${minutes}m ${seconds}s`;
136
+ return `${seconds}s`;
137
+ }
138
+ static tokens(count) {
139
+ if (count < 1000)
140
+ return `${Math.max(0, Math.round(count))}`;
141
+ if (count < 1e6)
142
+ return `${(count / 1000).toFixed(1)}k`;
143
+ return `${(count / 1e6).toFixed(1)}M`;
144
+ }
145
+ static #clip(text, width) {
146
+ if (CodeTuiLines2.width(text) <= width)
147
+ return text;
148
+ let clipped = "";
149
+ for (const char of text) {
150
+ if (CodeTuiLines2.width(clipped + char) > width - 1)
151
+ break;
152
+ clipped += char;
153
+ }
154
+ return `${clipped}\u2026`;
155
+ }
156
+ }
157
+
158
+ // pkgs/@akanjs/cli/code/CodeTuiClipboard.ts
159
+ import { existsSync } from "fs";
160
+ import { tmpdir } from "os";
161
+ import path from "path";
162
+
163
+ class CodeTuiClipboard2 {
164
+ static imageTypes = [".png", ".jpg", ".jpeg", ".gif", ".webp"];
165
+ static imagePathsIn(text) {
166
+ const pieces = text.split(`
167
+ `).flatMap((line) => line.split(/ (?=\/)/));
168
+ const images = [];
169
+ const rest = [];
170
+ for (const piece of pieces) {
171
+ const file = CodeTuiClipboard2.imagePathIn(piece);
172
+ if (file)
173
+ images.push(file);
174
+ else if (piece.trim())
175
+ rest.push(piece);
176
+ }
177
+ return { images, rest: rest.join(" ") };
178
+ }
179
+ static imagePathIn(text) {
180
+ const file = text.trim().replace(/^['"]|['"]$/g, "").replace(/\\ /g, " ");
181
+ if (!file || file.includes(`
182
+ `))
183
+ return;
184
+ const lower = file.toLowerCase();
185
+ if (!CodeTuiClipboard2.imageTypes.some((ext) => lower.endsWith(ext)))
186
+ return;
187
+ return existsSync(file) ? file : undefined;
188
+ }
189
+ static async image() {
190
+ const png = await CodeTuiClipboard2.#read();
191
+ if (!png?.length)
192
+ return;
193
+ const file = path.join(tmpdir(), `akan-code-${Date.now()}.png`);
194
+ await Bun.write(file, png);
195
+ return file;
196
+ }
197
+ static has() {
198
+ try {
199
+ return Bun.Image.hasClipboardImage();
200
+ } catch {
201
+ return false;
202
+ }
203
+ }
204
+ static async#read() {
205
+ try {
206
+ const image = Bun.Image.fromClipboard();
207
+ if (image)
208
+ return new Uint8Array(await image.png().toBuffer());
209
+ } catch {}
210
+ if (process.platform === "darwin")
211
+ return await CodeTuiClipboard2.#darwin();
212
+ for (const command of [
213
+ ["wl-paste", "--no-newline", "--type", "image/png"],
214
+ ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
215
+ ]) {
216
+ const bytes = await CodeTuiClipboard2.#bytes(command);
217
+ if (bytes?.length)
218
+ return bytes;
219
+ }
220
+ return;
221
+ }
222
+ static async#darwin() {
223
+ const bytes = await CodeTuiClipboard2.#bytes(["osascript", "-e", CodeTuiClipboard2.ask]);
224
+ return CodeTuiClipboard2.fromAppleScript(bytes ? new TextDecoder().decode(bytes) : undefined);
225
+ }
226
+ static ask = "the clipboard as \xABclass PNGf\xBB";
227
+ static fromAppleScript(out) {
228
+ const hex = /\u00ABdata PNGf([0-9A-Fa-f]*)\u00BB/.exec(out ?? "")?.[1];
229
+ if (!hex || hex.length % 2)
230
+ return;
231
+ return Uint8Array.from((hex.match(/../g) ?? []).map((byte) => Number.parseInt(byte, 16)));
232
+ }
233
+ static async#bytes(command) {
234
+ try {
235
+ const proc = Bun.spawn(command, { stdout: "pipe", stderr: "ignore" });
236
+ const bytes = new Uint8Array(await new Response(proc.stdout).arrayBuffer());
237
+ return await proc.exited === 0 ? bytes : undefined;
238
+ } catch {
239
+ return;
240
+ }
241
+ }
242
+ }
243
+
244
+ // pkgs/@akanjs/cli/code/CodeTuiCommands.ts
245
+ class CodeTuiCommands2 {
246
+ static all = [
247
+ { name: "help", desc: "list these commands and the keys" },
248
+ { name: "tools", desc: "what this session can call" },
249
+ { name: "model", desc: "switch model, or list what is available", arg: "[<provider>/<id>]" },
250
+ { name: "effort", desc: "how hard the model thinks before it answers", arg: "<level>" },
251
+ { name: "thinking", desc: "show the model's reasoning, or fold it away again" },
252
+ { name: "compact", desc: "summarise the conversation to free the window", arg: "[notes]" },
253
+ { name: "abort", desc: "stop the running turn" },
254
+ { name: "clear", desc: "wipe the screen; the model keeps the conversation" },
255
+ { name: "name", desc: "name this session", arg: "<text>" },
256
+ { name: "fork", desc: "continue this conversation twice; the copy takes over here", arg: "[name]" },
257
+ { name: "agents", desc: "what a sub-agent may be, and what one may spend" },
258
+ { name: "mcp", desc: "the MCP servers this session reached", arg: "[add|remove|login|reload]" },
259
+ { name: "peers", desc: "the other akan code sessions running here" },
260
+ { name: "msg", desc: "hand a message to another session", arg: "<peer> <text>" },
261
+ { name: "quit", desc: "leave the session" }
262
+ ];
263
+ static prefixOf(text, caret) {
264
+ if (!text.startsWith("/"))
265
+ return;
266
+ const head = text.slice(0, caret);
267
+ if (/\s/.test(head) || head.includes(`
268
+ `))
269
+ return;
270
+ return head.slice(1);
271
+ }
272
+ static matches(prefix) {
273
+ const needle = prefix.toLowerCase();
274
+ return CodeTuiCommands2.all.filter((command) => command.name.startsWith(needle));
275
+ }
276
+ static help() {
277
+ const usage = (command) => `/${command.name}${command.arg ? ` ${command.arg}` : ""}`;
278
+ const column = Math.max(...CodeTuiCommands2.all.map((command) => usage(command).length)) + 2;
279
+ const list = CodeTuiCommands2.all.map((command) => `${usage(command).padEnd(column)}${command.desc}`).join(`
280
+ `);
281
+ return [
282
+ list,
283
+ "",
284
+ "Keys: enter send \xB7 shift+enter newline \xB7 \u2191\u2193 move (history at the edges) \xB7 \u2190\u2192 move",
285
+ "esc interrupt \xB7 pgup/pgdn scroll \xB7 ^c quit",
286
+ "@ completes a file in this repo \xB7 \u2190 at the start of the prompt lists past sessions",
287
+ "",
288
+ "Scroll: the wheel scrolls this transcript \xB7 hold shift to select text with the mouse instead",
289
+ "",
290
+ "Images: cmd+v attaches what is on the clipboard \xB7 ^v does too, without the terminal in the way",
291
+ "",
292
+ 'shift+enter needs a terminal that reports it \u2014 in VS Code bind it to send "\\\\u001b\\r".'
293
+ ].join(`
294
+ `);
295
+ }
296
+ }
297
+
298
+ // pkgs/@akanjs/cli/code/CodeTuiEditor.ts
299
+ class CodeTuiEditor2 {
300
+ #text = "";
301
+ #caret = 0;
302
+ get text() {
303
+ return this.#text;
304
+ }
305
+ get caret() {
306
+ return this.#caret;
307
+ }
308
+ get isEmpty() {
309
+ return !this.#text.length;
310
+ }
311
+ set(text, caret = text.length) {
312
+ this.#text = text;
313
+ this.#caret = Math.max(0, Math.min(caret, text.length));
314
+ }
315
+ clear() {
316
+ this.set("");
317
+ }
318
+ replace(from, to, text) {
319
+ this.set(this.#text.slice(0, from) + text + this.#text.slice(to), from + text.length);
320
+ }
321
+ token() {
322
+ const before = this.#text.slice(0, this.#caret);
323
+ const from = Math.max(before.lastIndexOf(" "), before.lastIndexOf(`
324
+ `)) + 1;
325
+ const after = /\s/.exec(this.#text.slice(this.#caret));
326
+ const to = after ? this.#caret + (after.index ?? 0) : this.#text.length;
327
+ return { from, to, text: this.#text.slice(from, to) };
328
+ }
329
+ insert(text) {
330
+ const clean = text.replace(/\r\n?/g, `
331
+ `);
332
+ this.set(this.#text.slice(0, this.#caret) + clean + this.#text.slice(this.#caret), this.#caret + clean.length);
333
+ }
334
+ newline() {
335
+ if (this.#text.slice(0, this.#caret).endsWith("\\"))
336
+ this.set(this.#text.slice(0, this.#caret - 1) + this.#text.slice(this.#caret), this.#caret - 1);
337
+ this.insert(`
338
+ `);
339
+ }
340
+ backspace() {
341
+ if (!this.#caret)
342
+ return;
343
+ const at = CodeTuiEditor2.#prev(this.#text, this.#caret);
344
+ this.set(this.#text.slice(0, at) + this.#text.slice(this.#caret), at);
345
+ }
346
+ deleteForward() {
347
+ if (this.#caret >= this.#text.length)
348
+ return;
349
+ const at = CodeTuiEditor2.#next(this.#text, this.#caret);
350
+ this.set(this.#text.slice(0, this.#caret) + this.#text.slice(at), this.#caret);
351
+ }
352
+ deleteWord() {
353
+ const before = this.#text.slice(0, this.#caret);
354
+ const at = before.replace(/\s*\S*$/, "").length;
355
+ this.set(before.slice(0, at) + this.#text.slice(this.#caret), at);
356
+ }
357
+ deleteToLineStart() {
358
+ const at = this.#text.lastIndexOf(`
359
+ `, Math.max(0, this.#caret - 1)) + 1;
360
+ this.set(this.#text.slice(0, at) + this.#text.slice(this.#caret), at);
361
+ }
362
+ left() {
363
+ this.#caret = CodeTuiEditor2.#prev(this.#text, this.#caret);
364
+ }
365
+ right() {
366
+ this.#caret = CodeTuiEditor2.#next(this.#text, this.#caret);
367
+ }
368
+ wordLeft() {
369
+ this.#caret = this.#text.slice(0, this.#caret).replace(/\s*\S*$/, "").length;
370
+ }
371
+ wordRight() {
372
+ const rest = /^\s*\S*/.exec(this.#text.slice(this.#caret))?.[0] ?? "";
373
+ this.#caret = Math.min(this.#text.length, this.#caret + rest.length);
374
+ }
375
+ move(direction, width) {
376
+ const { rows, row, col } = this.layout(width);
377
+ const target = rows[row + direction];
378
+ if (!target)
379
+ return false;
380
+ this.#caret = target.at + CodeTuiEditor2.#indexAt(target.text, col);
381
+ return true;
382
+ }
383
+ homeOfRow(width) {
384
+ const { rows, row } = this.layout(width);
385
+ this.#caret = rows[row]?.at ?? 0;
386
+ }
387
+ endOfRow(width) {
388
+ const { rows, row } = this.layout(width);
389
+ const current = rows[row];
390
+ this.#caret = current ? current.at + current.text.length : this.#text.length;
391
+ }
392
+ layout(width) {
393
+ const room = Math.max(4, width);
394
+ const rows = [];
395
+ let at = 0;
396
+ for (const line of this.#text.split(`
397
+ `)) {
398
+ for (const text of line ? CodeTuiLines2.chunks(line, room) : [""]) {
399
+ rows.push({ text, at });
400
+ at += text.length;
401
+ }
402
+ at += 1;
403
+ }
404
+ if (!rows.length)
405
+ rows.push({ text: "", at: 0 });
406
+ let row = 0;
407
+ for (let index = 0;index < rows.length; index += 1)
408
+ if ((rows[index]?.at ?? 0) <= this.#caret)
409
+ row = index;
410
+ const current = rows[row] ?? { text: "", at: 0 };
411
+ return { rows, row, col: CodeTuiLines2.width(current.text.slice(0, Math.max(0, this.#caret - current.at))) };
412
+ }
413
+ static #indexAt(row, col) {
414
+ let at = 0;
415
+ for (const char of row) {
416
+ if (CodeTuiLines2.width(row.slice(0, at + char.length)) > col)
417
+ break;
418
+ at += char.length;
419
+ }
420
+ return at;
421
+ }
422
+ static #prev(text, at) {
423
+ if (at <= 0)
424
+ return 0;
425
+ return at - ([...text.slice(0, at)].at(-1)?.length ?? 1);
426
+ }
427
+ static #next(text, at) {
428
+ if (at >= text.length)
429
+ return text.length;
430
+ return at + ([...text.slice(at)][0]?.length ?? 1);
431
+ }
432
+ }
433
+
434
+ // pkgs/@akanjs/cli/code/CodeTuiFiles.ts
435
+ class CodeTuiFiles2 {
436
+ static limit = 8;
437
+ #root;
438
+ #all = [];
439
+ #loaded = false;
440
+ constructor(root) {
441
+ this.#root = root;
442
+ }
443
+ get ready() {
444
+ return this.#loaded;
445
+ }
446
+ async load() {
447
+ this.#all = await CodeTuiFiles2.#list(this.#root);
448
+ this.#loaded = true;
449
+ }
450
+ match(query, limit = CodeTuiFiles2.limit) {
451
+ const needle = query.toLowerCase();
452
+ if (!needle)
453
+ return this.#all.slice(0, limit);
454
+ const hits = this.#all.filter((file) => file.toLowerCase().includes(needle));
455
+ return hits.sort((left, right) => left.length - right.length).slice(0, limit);
456
+ }
457
+ static async#list(root) {
458
+ try {
459
+ const proc = Bun.spawn(["git", "ls-files", "--cached", "--others", "--exclude-standard"], {
460
+ cwd: root,
461
+ stdout: "pipe",
462
+ stderr: "ignore"
463
+ });
464
+ const text = await new Response(proc.stdout).text();
465
+ if (await proc.exited !== 0)
466
+ return [];
467
+ return text.split(`
468
+ `).filter((line) => !!line.trim());
469
+ } catch {
470
+ return [];
471
+ }
472
+ }
473
+ }
474
+
475
+ // pkgs/@akanjs/cli/code/CodeTuiMarkdown.ts
476
+ import { MarkdownBlocks, MarkdownSpans } from "akanjs/common";
477
+ class CodeTuiMarkdown2 {
478
+ static bullet = "\u2022";
479
+ static minColumn = 6;
480
+ static rows(source, width = 80) {
481
+ const rows = [];
482
+ const blocks = MarkdownBlocks.of(source);
483
+ blocks.forEach((block, at) => {
484
+ if (at)
485
+ rows.push({ spans: [] });
486
+ for (const row of CodeTuiMarkdown2.#block(block, width))
487
+ rows.push(row);
488
+ });
489
+ return rows;
490
+ }
491
+ static #block(block, width) {
492
+ switch (block.kind) {
493
+ case "heading":
494
+ return [
495
+ {
496
+ spans: CodeTuiMarkdown2.spans(block.text, { bold: true, ...block.level <= 2 ? { color: "cyan" } : {} })
497
+ }
498
+ ];
499
+ case "code":
500
+ return CodeTuiMarkdown2.#code(block.lang, block.text);
501
+ case "quote":
502
+ return block.text.split(`
503
+ `).map((line) => ({
504
+ prefix: { text: "\u258C ", dim: true },
505
+ spans: CodeTuiMarkdown2.spans(line, { dim: true })
506
+ }));
507
+ case "rule":
508
+ return [{ spans: [{ text: "\u2500".repeat(24), dim: true }] }];
509
+ case "list":
510
+ return block.items.map((item) => {
511
+ const indent = " ".repeat(item.depth);
512
+ const marker = item.ordered ? `${item.num}. ` : `${CodeTuiMarkdown2.bullet} `;
513
+ return {
514
+ prefix: { text: `${indent}${marker}`, dim: true },
515
+ spans: CodeTuiMarkdown2.spans(item.text)
516
+ };
517
+ });
518
+ case "table":
519
+ return CodeTuiMarkdown2.#table(block, width);
520
+ default:
521
+ return [{ spans: CodeTuiMarkdown2.spans(block.text) }];
522
+ }
523
+ }
524
+ static #code(lang, text) {
525
+ const label = lang?.trim();
526
+ const bar = { text: "\u2502 ", dim: true };
527
+ return [
528
+ ...label ? [{ spans: [{ text: label, dim: true, italic: true }] }] : [],
529
+ ...text.split(`
530
+ `).map((line) => ({ prefix: bar, hang: "\u2502 ", spans: [{ text: line, color: "green" }] }))
531
+ ];
532
+ }
533
+ static #table(block, width) {
534
+ const columns = block.head.length;
535
+ const grid = [block.head, ...block.rows].map((row) => Array.from({ length: columns }, (_, col) => MarkdownSpans.plain(row[col] ?? "")));
536
+ const widths = CodeTuiMarkdown2.#columns(grid, columns, width);
537
+ const rule = { spans: [{ text: widths.map((size) => "\u2500".repeat(size)).join(" "), dim: true }] };
538
+ const [head, ...body] = grid;
539
+ return [
540
+ ...CodeTuiMarkdown2.#gridRow(head ?? [], widths, block.aligns, { bold: true }),
541
+ rule,
542
+ ...body.flatMap((row) => CodeTuiMarkdown2.#gridRow(row, widths, block.aligns, {}))
543
+ ];
544
+ }
545
+ static #columns(grid, columns, width) {
546
+ const natural = Array.from({ length: columns }, (_, col) => Math.max(1, ...grid.map((row) => CodeTuiLines2.width(row[col] ?? ""))));
547
+ const gaps = 2 * Math.max(0, columns - 1);
548
+ const room = Math.max(columns * CodeTuiMarkdown2.minColumn, width - gaps);
549
+ const total = natural.reduce((sum, size) => sum + size, 0);
550
+ if (total <= width - gaps)
551
+ return natural;
552
+ const floors = natural.map((size, col) => Math.min(size, Math.max(CodeTuiMarkdown2.minColumn, CodeTuiMarkdown2.#longestWord(grid, col))));
553
+ const held = floors.reduce((sum, size) => sum + size, 0);
554
+ if (held > room)
555
+ return natural.map((size) => Math.max(1, Math.floor(size * room / total)));
556
+ const want = natural.map((size, col) => size - (floors[col] ?? 0));
557
+ const wanted = want.reduce((sum, size) => sum + size, 0) || 1;
558
+ const slack = room - held;
559
+ return floors.map((size, col) => size + Math.floor(slack * (want[col] ?? 0) / wanted));
560
+ }
561
+ static #longestWord(grid, col) {
562
+ return Math.max(1, ...grid.flatMap((row) => (row[col] ?? "").split(/\s+/).map((word) => CodeTuiLines2.width(word))));
563
+ }
564
+ static #gridRow(cells, widths, aligns, style) {
565
+ const wrapped = widths.map((size, col) => CodeTuiMarkdown2.#cell(cells[col] ?? "", size));
566
+ const height = Math.max(1, ...wrapped.map((lines) => lines.length));
567
+ return Array.from({ length: height }, (_, line) => ({
568
+ spans: widths.flatMap((size, col) => {
569
+ const text = wrapped[col]?.[line] ?? "";
570
+ const fill = " ".repeat(Math.max(0, size - CodeTuiLines2.width(text)));
571
+ const align = aligns[col];
572
+ const lead = align === "right" ? fill : align === "center" ? " ".repeat(Math.floor(fill.length / 2)) : "";
573
+ const tail = fill.slice(lead.length);
574
+ return [{ text: lead }, { ...style, text }, { text: `${tail}${col === widths.length - 1 ? "" : " "}` }];
575
+ })
576
+ }));
577
+ }
578
+ static #cell(text, width) {
579
+ const lines = [];
580
+ let line = "";
581
+ for (const word of text.split(/(\s+)/)) {
582
+ if (!word)
583
+ continue;
584
+ if (line && CodeTuiLines2.width(line + word) > width) {
585
+ lines.push(line.trimEnd());
586
+ line = word.trim() ? word : "";
587
+ continue;
588
+ }
589
+ line += word;
590
+ }
591
+ if (line.trim() || !lines.length)
592
+ lines.push(line.trimEnd());
593
+ return lines.flatMap((entry) => CodeTuiLines2.width(entry) <= width ? [entry] : CodeTuiLines2.chunks(entry, width));
594
+ }
595
+ static spans(text, base = {}) {
596
+ return MarkdownSpans.of(text).flatMap((span) => {
597
+ if (span.kind === "link")
598
+ return [
599
+ { ...base, underline: true, text: span.text },
600
+ { ...base, dim: true, text: ` (${span.href})` }
601
+ ];
602
+ return [{ ...base, ...CodeTuiMarkdown2.#span(span), text: span.text }];
603
+ });
604
+ }
605
+ static #span(span) {
606
+ switch (span.kind) {
607
+ case "code":
608
+ return { color: "yellow" };
609
+ case "strong":
610
+ return { bold: true };
611
+ case "em":
612
+ return { italic: true };
613
+ case "del":
614
+ return { strikethrough: true };
615
+ default:
616
+ return {};
617
+ }
618
+ }
619
+ }
620
+
621
+ // pkgs/@akanjs/cli/code/CodeTuiParts.ts
622
+ import { codeAgentClip } from "akanjs/common";
623
+ class CodeTuiParts2 {
624
+ static thinkingLines = 6;
625
+ static outputLines = 4;
626
+ static lines(parts, width, options = {}) {
627
+ const lines = [];
628
+ parts.forEach((part, at) => {
629
+ const rows = CodeTuiParts2.rows(part, width, options);
630
+ for (const line of CodeTuiLines2.rows(rows, width, `${part.id}:${at}`))
631
+ lines.push(line);
632
+ });
633
+ return lines;
634
+ }
635
+ static rows(part, width = 80, options = {}) {
636
+ switch (part.kind) {
637
+ case "user":
638
+ return [
639
+ { prefix: { text: "\u203A ", color: "cyan", bold: true }, spans: [{ text: part.text, color: "cyan" }] },
640
+ ...part.images ? [
641
+ {
642
+ prefix: { text: " ", dim: true },
643
+ spans: [{ text: `\u29C9 ${part.images} image${part.images > 1 ? "s" : ""}`, dim: true }]
644
+ }
645
+ ] : []
646
+ ];
647
+ case "assistant":
648
+ return CodeTuiParts2.#assistant(part, width);
649
+ case "thinking":
650
+ return options.thinking ? CodeTuiParts2.#thinking(part.text) : CodeTuiParts2.#folded(part.text);
651
+ case "tool":
652
+ return CodeTuiParts2.#tool(part);
653
+ case "notice":
654
+ return part.text.split(`
655
+ `).map((line, at) => ({
656
+ prefix: { text: at === 0 && part.level !== "info" ? "! " : " ", ...CodeTuiParts2.#noticeStyle(part.level) },
657
+ spans: CodeTuiMarkdown2.spans(line, CodeTuiParts2.#noticeStyle(part.level))
658
+ }));
659
+ case "question":
660
+ return CodeTuiParts2.#question(part);
661
+ case "approval":
662
+ return [
663
+ { prefix: { text: "? ", color: "yellow" }, spans: [{ text: part.request.summary, color: "yellow" }] },
664
+ ...part.approved === undefined ? [] : [{ prefix: { text: " " }, spans: [{ text: part.approved ? "approved" : "denied", dim: true }] }]
665
+ ];
666
+ case "host":
667
+ return [{ prefix: { text: " ", dim: true }, spans: [{ text: `${part.hostKind} ${part.text}`, dim: true }] }];
668
+ default:
669
+ return [];
670
+ }
671
+ }
672
+ static #assistant(part, width) {
673
+ const rows = CodeTuiMarkdown2.rows(part.text, width);
674
+ if (!part.truncated)
675
+ return rows;
676
+ return [
677
+ ...rows,
678
+ { spans: [{ text: "\u2026 the answer stopped at the model's output limit \u2014 ask it to continue", color: "yellow" }] }
679
+ ];
680
+ }
681
+ static #folded(text) {
682
+ const count = text.split(`
683
+ `).filter((line) => line.trim()).length;
684
+ return [
685
+ {
686
+ prefix: { text: "\u273B ", dim: true },
687
+ spans: [{ text: `thinking \xB7 ${count} line${count === 1 ? "" : "s"} \xB7 /thinking to show`, dim: true }]
688
+ }
689
+ ];
690
+ }
691
+ static #thinking(text) {
692
+ const all = text.split(`
693
+ `).filter((line) => line.trim());
694
+ const shown = all.slice(-CodeTuiParts2.thinkingLines);
695
+ const hidden = all.length - shown.length;
696
+ return [
697
+ ...hidden ? [{ prefix: { text: "\xB7 ", dim: true }, spans: [{ text: `(${hidden} earlier lines)`, dim: true }] }] : [],
698
+ ...shown.map((line) => ({
699
+ prefix: { text: "\xB7 ", dim: true },
700
+ spans: [{ text: line, dim: true, italic: true }]
701
+ }))
702
+ ];
703
+ }
704
+ static #tool(part) {
705
+ const running = part.outcome === undefined;
706
+ const mark = running ? "\u25D0" : part.outcome === "ok" ? "\u23FA" : part.outcome === "blocked" ? "\u29B8" : "\u23FA";
707
+ const color = running ? "cyan" : part.outcome === "ok" ? "green" : part.outcome === "blocked" ? "yellow" : "red";
708
+ const head = {
709
+ prefix: { text: `${mark} `, color },
710
+ hang: " ",
711
+ spans: CodeTuiParts2.#title(part.tool.name, part.tool.title)
712
+ };
713
+ const detail = CodeTuiParts2.#detail(part);
714
+ if (!detail.length)
715
+ return [head];
716
+ return [
717
+ head,
718
+ ...detail.map((line, at) => ({
719
+ prefix: { text: at === 0 ? " \u23BF " : " ", dim: true },
720
+ hang: " ",
721
+ spans: [{ text: line, dim: true }]
722
+ }))
723
+ ];
724
+ }
725
+ static #title(name, title) {
726
+ if (!title.startsWith(name))
727
+ return [{ text: title, bold: true }];
728
+ return [
729
+ { text: name, bold: true },
730
+ { text: title.slice(name.length), dim: true }
731
+ ];
732
+ }
733
+ static #detail(part) {
734
+ if (part.outcome === undefined)
735
+ return part.progress ? [part.progress] : [];
736
+ if (part.outcome === "ok")
737
+ return [];
738
+ return (part.output ?? "").split(`
739
+ `).filter((line) => line.trim()).slice(0, CodeTuiParts2.outputLines).map((line) => codeAgentClip(line.trim(), 200));
740
+ }
741
+ static #question(part) {
742
+ return [
743
+ { prefix: { text: "? ", color: "yellow" }, spans: [{ text: part.question.prompt, color: "yellow" }] },
744
+ ...(part.question.options ?? []).map((option) => ({
745
+ prefix: { text: " \xB7 ", dim: true },
746
+ spans: [{ text: `${option.label}${option.recommended ? " (recommended)" : ""}`, dim: true }]
747
+ })),
748
+ ...part.rendered === undefined ? [] : [{ prefix: { text: " = ", color: "green" }, spans: [{ text: part.rendered, color: "green" }] }]
749
+ ];
750
+ }
751
+ static #noticeStyle(level) {
752
+ if (level === "error")
753
+ return { color: "red" };
754
+ if (level === "warning")
755
+ return { color: "yellow" };
756
+ return { dim: true };
757
+ }
758
+ }
759
+
760
+ export { CodeTuiLines2, CodeTuiAgents2, CodeTuiClipboard2, CodeTuiCommands2, CodeTuiEditor2, CodeTuiFiles2, CodeTuiMarkdown2, CodeTuiParts2 };