@akanjs/cli 3.0.0-alpha.9 → 3.0.0-alpha.90

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 (135) hide show
  1. package/.build-stamp +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/{abstractCompactor-e5yq60qz.js → abstractCompactor-cefxzggj.js} +3 -5
  5. package/{agent.command-f0gqkfgz.js → agent.command-r93wmq7m.js} +11 -13
  6. package/{application.command-x903m2qq.js → application.command-5nqfqgdn.js} +62 -38
  7. package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-b21m07fs.js} +23 -20
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-3wh58n2m.js} +8 -9
  9. package/buildBatch.proc.js +12 -14
  10. package/capacitorApp-gzcx6txb.js +12 -0
  11. package/{cloud.command-zs6kyf83.js → cloud.command-g0pk0k60.js} +15 -18
  12. package/commandManifest.json +1 -1
  13. package/{context.command-fmepgjzg.js → context.command-qd8kqrnh.js} +19 -23
  14. package/dependencyScanner-shs82ynp.js +8 -0
  15. package/devTui-2xf0meaq.js +552 -0
  16. package/devTuiView-7jy8f30g.js +9 -0
  17. package/getDirname-dr3jz1xg.js +7 -0
  18. package/{guideline.command-n6sw0a0c.js → guideline.command-f38x8jhw.js} +16 -18
  19. package/guidelines/agentRule/agentRule.generate.json +31 -0
  20. package/guidelines/agentRule/agentRule.instruction.md +533 -0
  21. package/guidelines/conventions/conventions.instruction.md +406 -197
  22. package/guidelines/cssRule/cssRule.instruction.md +7 -0
  23. package/guidelines/framework/framework.generate.json +3 -2
  24. package/guidelines/framework/framework.instruction.md +1 -9
  25. package/guidelines/mcpRule/mcpRule.generate.json +25 -0
  26. package/guidelines/mcpRule/mcpRule.instruction.md +217 -0
  27. package/guidelines/modelStore/modelStore.instruction.md +12 -0
  28. package/guidelines/modelTemplate/modelTemplate.instruction.md +5 -0
  29. package/guidelines/queryRule/queryRule.generate.json +31 -0
  30. package/guidelines/queryRule/queryRule.instruction.md +143 -0
  31. package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
  32. package/guidelines/runtimeRule/runtimeRule.instruction.md +213 -0
  33. package/guidelines/ssrRule/ssrRule.instruction.md +49 -5
  34. package/guidelines/transportRule/transportRule.generate.json +31 -0
  35. package/guidelines/transportRule/transportRule.instruction.md +60 -0
  36. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +51 -760
  37. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
  38. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
  39. package/incrementalBuilder.proc.js +26 -25
  40. package/{index-774gcx29.js → index-0emb9eat.js} +41 -34
  41. package/index-3d9y066c.js +76 -0
  42. package/{index-3vta1tqa.js → index-3vvbv974.js} +32 -32
  43. package/{index-76rn3g2c.js → index-47pj3aee.js} +4 -4
  44. package/{index-y4vkyhvv.js → index-5xdqxbn9.js} +14 -14
  45. package/{index-1577bej2.js → index-6wwzs1bc.js} +2 -2
  46. package/{index-wnp7hwq7.js → index-92zztqy1.js} +7 -7
  47. package/{index-jhpa13zj.js → index-9bwhxrqf.js} +57 -57
  48. package/{index-bjpxzr6s.js → index-9wtbw98m.js} +6 -3
  49. package/{index-fgc8r6dj.js → index-a5vmm6x4.js} +3 -1
  50. package/{index-xys926f2.js → index-by5gpp8x.js} +4 -4
  51. package/{index-kdh76j26.js → index-cezy7yb3.js} +100 -32
  52. package/{index-62955kn5.js → index-d61rcfa2.js} +758 -127
  53. package/{index-82jrh4hj.js → index-deekbtkj.js} +13 -13
  54. package/{index-rxkpk7n4.js → index-e82dyeqy.js} +4 -4
  55. package/{index-qzdjd4ct.js → index-h759vjfa.js} +18 -18
  56. package/{index-j37qq1f2.js → index-h7yw2z9n.js} +7 -7
  57. package/{index-qb61h0k7.js → index-jydtyzva.js} +1098 -1360
  58. package/{index-46tjzh6s.js → index-kcxmv48c.js} +29 -29
  59. package/{index-4m0bphac.js → index-kfnr6c19.js} +31 -30
  60. package/{index-xmmzf150.js → index-mpmyqm1y.js} +1 -1
  61. package/{index-xjd3rqzj.js → index-n68jx79w.js} +6 -15
  62. package/{index-0cj2zxbm.js → index-n85fer99.js} +12 -11
  63. package/{index-779ske1y.js → index-pgsswppj.js} +27 -27
  64. package/index-pvb4vdwr.js +159 -0
  65. package/{index-67546d0j.js → index-q0y2jq9j.js} +14 -2
  66. package/{index-z8ptfkzv.js → index-q8sn827n.js} +969 -240
  67. package/{index-5sn5w2mt.js → index-r50qen0z.js} +94 -61
  68. package/{index-eyyf2149.js → index-rntcdss1.js} +36 -37
  69. package/{index-gcv8ncfh.js → index-sjak5v5b.js} +16 -12
  70. package/{index-j9cxndc0.js → index-w8kmx1b6.js} +20 -11
  71. package/{index-jf2ya7r2.js → index-y74k5anj.js} +8 -8
  72. package/{index-d43t8af2.js → index-zkvpaggp.js} +58 -25
  73. package/index.js +22 -25
  74. package/{library.command-cv9gdbmg.js → library.command-em103wtn.js} +11 -10
  75. package/{localRegistry.command-d8fg36zc.js → localRegistry.command-gz8apn4y.js} +20 -23
  76. package/{module.command-qyr1s9cn.js → module.command-451pztkc.js} +13 -16
  77. package/{package.command-wsjx0k47.js → package.command-rfhyf38t.js} +8 -10
  78. package/package.json +5 -7
  79. package/{page.command-rdzg65rm.js → page.command-kt19da5g.js} +7 -9
  80. package/{primitive.command-89g38b53.js → primitive.command-pgy69ere.js} +13 -16
  81. package/{quality.command-0cs2z92d.js → quality.command-gpe2vqb5.js} +226 -105
  82. package/recipeScanner-fpagtgc1.js +11 -0
  83. package/{repair.command-6fphxfwj.js → repair.command-2sbrz187.js} +12 -14
  84. package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-ze6x894c.js} +0 -2
  85. package/{scalar.command-xfer69s6.js → scalar.command-jcf4e5sv.js} +11 -14
  86. package/subspace.command-kqzqtk0p.js +755 -0
  87. package/templates/app/env/env.client.debug.ts.template +1 -5
  88. package/templates/app/env/env.client.develop.ts.template +1 -5
  89. package/templates/app/env/env.client.local.ts.template +1 -5
  90. package/templates/app/env/env.client.main.ts.template +1 -5
  91. package/templates/app/env/env.client.testing.ts.template +1 -5
  92. package/templates/app/env/env.client.type.ts +2 -6
  93. package/templates/app/env/env.server.debug.ts.template +1 -5
  94. package/templates/app/env/env.server.develop.ts.template +1 -5
  95. package/templates/app/env/env.server.local.ts.template +1 -5
  96. package/templates/app/env/env.server.main.ts.template +1 -5
  97. package/templates/app/main.ts +3 -1
  98. package/templates/appSample/lib/task/task.signal.ts +11 -6
  99. package/templates/appSample/srvkit/AuthGuard.ts +9 -5
  100. package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
  101. package/templates/crudPages/[__model__Id]/edit/page.tsx +5 -5
  102. package/templates/crudPages/[__model__Id]/page.tsx +10 -13
  103. package/templates/crudPages/new/page.tsx +5 -5
  104. package/templates/crudPages/page.tsx +9 -9
  105. package/templates/crudSinglePage/page.tsx +11 -7
  106. package/templates/env/_env.server.type.ts +7 -5
  107. package/templates/lib/db.ts +1 -1
  108. package/templates/lib/dict.ts +1 -1
  109. package/templates/lib/sig.ts +1 -1
  110. package/templates/lib/srv.ts +6 -2
  111. package/templates/module/__model__.dictionary.ts +4 -1
  112. package/templates/module/__model__.signal.ts +2 -3
  113. package/templates/module/__model__.store.ts +1 -2
  114. package/templates/workspaceRoot/.gitignore.template +0 -1
  115. package/templates/workspaceRoot/.husky/pre-commit.template +16 -0
  116. package/templates/workspaceRoot/.vscode/settings.json.template +1 -1
  117. package/templates/workspaceRoot/AGENTS.md.template +4 -0
  118. package/templates/workspaceRoot/CLAUDE.md.template +19 -0
  119. package/templates/workspaceRoot/biome.json.template +2 -1
  120. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
  121. package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
  122. package/templates/workspaceRoot/package.json.template +2 -4
  123. package/typeChecker-3xgrzc2v.js +7 -0
  124. package/typecheck.proc.js +4 -5
  125. package/{workflow.command-2ygfqt4f.js → workflow.command-m4z25a2p.js} +22 -25
  126. package/{workspace.command-88m0zs64.js → workspace.command-dqgj9zbk.js} +96 -81
  127. package/capacitorApp-9xswcgx7.js +0 -61
  128. package/dependencyScanner-f6grrep3.js +0 -9
  129. package/getDirname-m9s0cmhq.js +0 -8
  130. package/index-mxvakhsm.js +0 -66
  131. package/index-r24hmh0q.js +0 -4
  132. package/recipeScanner-tghkzrrt.js +0 -12
  133. package/typeChecker-kravn7ns.js +0 -8
  134. /package/{index-0wae5ebk.js → index-meh558jy.js} +0 -0
  135. /package/{index-ss469dec.js → index-nz8prx9g.js} +0 -0
@@ -0,0 +1,552 @@
1
+ // @bun
2
+ import {
3
+ openBrowser
4
+ } from "./index-d61rcfa2.js";
5
+
6
+ // pkgs/@akanjs/cli/application/devTui.tsx
7
+ import { render } from "ink";
8
+
9
+ // pkgs/@akanjs/cli/ui/DevTuiApp.tsx
10
+ import { Box, Text, useInput } from "ink";
11
+ import { useEffect, useState } from "react";
12
+ import { jsxDEV } from "react/jsx-dev-runtime";
13
+ var stateGlyph = {
14
+ starting: { glyph: "\u25D0", color: "yellow" },
15
+ ready: { glyph: "\u25CF", color: "green" },
16
+ restarting: { glyph: "\u25D0", color: "yellow" },
17
+ recovering: { glyph: "\u25D0", color: "yellow" },
18
+ suspended: { glyph: "\u25CC", color: "blue" },
19
+ failed: { glyph: "\u2717", color: "red" },
20
+ stopped: { glyph: "\u25CB", color: "gray" }
21
+ };
22
+ var Rail = ({ rows, selected, readyCount, appCount, width, height }) => /* @__PURE__ */ jsxDEV(Box, {
23
+ flexDirection: "column",
24
+ width,
25
+ height,
26
+ borderStyle: "round",
27
+ borderColor: "gray",
28
+ paddingX: 1,
29
+ children: [
30
+ /* @__PURE__ */ jsxDEV(Text, {
31
+ dimColor: true,
32
+ children: [
33
+ "apps ",
34
+ readyCount,
35
+ "/",
36
+ appCount
37
+ ]
38
+ }, undefined, true, undefined, this),
39
+ /* @__PURE__ */ jsxDEV(Box, {
40
+ flexDirection: "column",
41
+ flexGrow: 1,
42
+ children: rows.map((row, idx) => {
43
+ const marker = row.state ? stateGlyph[row.state] : null;
44
+ return /* @__PURE__ */ jsxDEV(Text, {
45
+ inverse: idx === selected,
46
+ wrap: "truncate",
47
+ children: [
48
+ marker ? /* @__PURE__ */ jsxDEV(Text, {
49
+ color: marker.color,
50
+ children: marker.glyph
51
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(Text, {
52
+ dimColor: true,
53
+ children: "\u25C7"
54
+ }, undefined, false, undefined, this),
55
+ /* @__PURE__ */ jsxDEV(Text, {
56
+ dimColor: true,
57
+ children: " ".repeat(row.depth * 2 + 1)
58
+ }, undefined, false, undefined, this),
59
+ row.appIndex === null ? null : /* @__PURE__ */ jsxDEV(Text, {
60
+ dimColor: true,
61
+ children: `${row.appIndex} `
62
+ }, undefined, false, undefined, this),
63
+ row.label,
64
+ row.port === null ? null : /* @__PURE__ */ jsxDEV(Text, {
65
+ dimColor: true,
66
+ children: ` ${row.port}`
67
+ }, undefined, false, undefined, this)
68
+ ]
69
+ }, `${row.app ?? "*"}/${row.source ?? "*"}`, true, undefined, this);
70
+ })
71
+ }, undefined, false, undefined, this)
72
+ ]
73
+ }, undefined, true, undefined, this);
74
+ var LogPane = ({ lines, title, above, below, following, prefix, prefixWidth, width, height }) => /* @__PURE__ */ jsxDEV(Box, {
75
+ flexDirection: "column",
76
+ width,
77
+ height,
78
+ borderStyle: "round",
79
+ borderColor: following ? "gray" : "cyan",
80
+ paddingX: 1,
81
+ children: [
82
+ /* @__PURE__ */ jsxDEV(Text, {
83
+ wrap: "truncate",
84
+ children: [
85
+ title,
86
+ following ? null : /* @__PURE__ */ jsxDEV(Text, {
87
+ color: "cyan",
88
+ children: ` \u25B2${above} \u25BC${below} paused`
89
+ }, undefined, false, undefined, this)
90
+ ]
91
+ }, undefined, true, undefined, this),
92
+ /* @__PURE__ */ jsxDEV(Box, {
93
+ flexDirection: "column",
94
+ flexGrow: 1,
95
+ children: lines.map((line) => /* @__PURE__ */ jsxDEV(Text, {
96
+ wrap: "truncate",
97
+ children: [
98
+ prefix === "none" ? null : /* @__PURE__ */ jsxDEV(Text, {
99
+ dimColor: true,
100
+ children: `${(prefix === "app" ? line.app : line.source).padEnd(prefixWidth)} \u2502 `
101
+ }, undefined, false, undefined, this),
102
+ line.text
103
+ ]
104
+ }, line.seq, true, undefined, this))
105
+ }, undefined, false, undefined, this)
106
+ ]
107
+ }, undefined, true, undefined, this);
108
+ var DevTuiApp = ({ actions }) => {
109
+ const [snapshot, setSnapshot] = useState(actions.snapshot);
110
+ useEffect(() => {
111
+ const unsubscribe = actions.subscribe(() => setSnapshot(actions.snapshot()));
112
+ setSnapshot(actions.snapshot());
113
+ return unsubscribe;
114
+ }, [actions]);
115
+ useInput((input, key) => {
116
+ if (snapshot.editingGrep) {
117
+ if (key.escape) {
118
+ actions.setGrep("");
119
+ actions.setEditingGrep(false);
120
+ } else if (key.return)
121
+ actions.setEditingGrep(false);
122
+ else if (key.backspace || key.delete)
123
+ actions.setGrep(snapshot.grep.slice(0, -1));
124
+ else if (input && !key.ctrl && !key.meta)
125
+ actions.setGrep(snapshot.grep + input);
126
+ return;
127
+ }
128
+ const page = Math.max(1, snapshot.logRows - 1);
129
+ if (input === "q" || key.ctrl && input === "c")
130
+ actions.quit();
131
+ else if (key.upArrow)
132
+ actions.scroll(key.shift ? -page : -1);
133
+ else if (key.downArrow)
134
+ actions.scroll(key.shift ? page : 1);
135
+ else if (key.pageUp)
136
+ actions.scroll(-page);
137
+ else if (key.pageDown)
138
+ actions.scroll(page);
139
+ else if (input === "G" || input === "f")
140
+ actions.follow();
141
+ else if (key.tab)
142
+ actions.moveSelection(key.shift ? -1 : 1);
143
+ else if (input === "/")
144
+ actions.setEditingGrep(true);
145
+ else if (input === "e")
146
+ actions.toggleErrorsOnly();
147
+ else if (input === "c")
148
+ actions.clear();
149
+ else if (input === "o")
150
+ actions.openSelected();
151
+ else if (input === "r")
152
+ actions.restartSelected();
153
+ else if (/^[1-9]$/.test(input))
154
+ actions.selectApp(Number(input) - 1);
155
+ });
156
+ return /* @__PURE__ */ jsxDEV(Box, {
157
+ flexDirection: "column",
158
+ width: snapshot.columns,
159
+ height: snapshot.terminalRows,
160
+ children: [
161
+ /* @__PURE__ */ jsxDEV(Box, {
162
+ flexDirection: "row",
163
+ height: snapshot.bodyHeight,
164
+ children: [
165
+ /* @__PURE__ */ jsxDEV(Rail, {
166
+ rows: snapshot.rows,
167
+ selected: snapshot.selected,
168
+ readyCount: snapshot.readyCount,
169
+ appCount: snapshot.appCount,
170
+ width: snapshot.railWidth,
171
+ height: snapshot.bodyHeight
172
+ }, undefined, false, undefined, this),
173
+ /* @__PURE__ */ jsxDEV(LogPane, {
174
+ lines: snapshot.lines,
175
+ title: snapshot.title,
176
+ above: snapshot.above,
177
+ below: snapshot.below,
178
+ following: snapshot.following,
179
+ prefix: snapshot.prefix,
180
+ prefixWidth: snapshot.prefixWidth,
181
+ width: Math.max(20, snapshot.columns - snapshot.railWidth),
182
+ height: snapshot.bodyHeight
183
+ }, undefined, false, undefined, this)
184
+ ]
185
+ }, undefined, true, undefined, this),
186
+ snapshot.editingGrep ? /* @__PURE__ */ jsxDEV(Text, {
187
+ children: [
188
+ /* @__PURE__ */ jsxDEV(Text, {
189
+ color: "cyan",
190
+ children: "grep "
191
+ }, undefined, false, undefined, this),
192
+ snapshot.grep,
193
+ /* @__PURE__ */ jsxDEV(Text, {
194
+ inverse: true,
195
+ children: " "
196
+ }, undefined, false, undefined, this),
197
+ /* @__PURE__ */ jsxDEV(Text, {
198
+ dimColor: true,
199
+ children: " enter to apply \xB7 esc to clear"
200
+ }, undefined, false, undefined, this)
201
+ ]
202
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV(Text, {
203
+ dimColor: true,
204
+ wrap: "truncate",
205
+ children: `Tab next \xB7 1-9 app \xB7 \u2191\u2193 scroll (shift page) \xB7 G follow${snapshot.following ? "" : " (paused)"} \xB7 / grep${snapshot.grep ? ` (${snapshot.grep})` : ""} \xB7 e errors${snapshot.errorsOnly ? " on" : ""} \xB7 c clear \xB7 o open \xB7 r restart \xB7 q quit`
206
+ }, undefined, false, undefined, this)
207
+ ]
208
+ }, undefined, true, undefined, this);
209
+ };
210
+
211
+ // pkgs/@akanjs/cli/application/devLogBuffer.ts
212
+ var ansi = new RegExp(`${String.fromCharCode(27)}(?:[@-Z\\\\-_]|\\[[\\s\\S]*?[@-~])`, "g");
213
+ var stripAnsi = (text) => text.replace(ansi, "");
214
+ var HOST_SOURCE = "host";
215
+ var childPrefix = /^\[child:(\d+) ([a-z-]+)\] \[(?:stdout|stderr)\] /;
216
+ var sourceOf = (text) => {
217
+ const match = childPrefix.exec(text);
218
+ return match ? `#${match[1]} ${match[2]}` : HOST_SOURCE;
219
+ };
220
+
221
+ class DevLogBuffer {
222
+ static defaultLimit = 5000;
223
+ #limit;
224
+ #lines = [];
225
+ #partial = new Map;
226
+ #sources = new Map;
227
+ #seq = 0;
228
+ constructor({ limit = DevLogBuffer.defaultLimit } = {}) {
229
+ this.#limit = Math.max(1, limit);
230
+ }
231
+ get size() {
232
+ return this.#lines.length;
233
+ }
234
+ sourcesOf(app) {
235
+ return [...this.#sources.get(app) ?? []];
236
+ }
237
+ push(app, kind, chunk) {
238
+ const key = `${app}:${kind}`;
239
+ const parts = `${this.#partial.get(key) ?? ""}${chunk}`.split(`
240
+ `);
241
+ this.#partial.set(key, parts.pop() ?? "");
242
+ return this.#append(app, kind, parts);
243
+ }
244
+ flushPartials() {
245
+ const flushed = [];
246
+ for (const [key, remainder] of [...this.#partial]) {
247
+ this.#partial.set(key, "");
248
+ if (!remainder)
249
+ continue;
250
+ const split = key.lastIndexOf(":");
251
+ const app = key.slice(0, split);
252
+ const kind = key.slice(split + 1) === "stderr" ? "stderr" : "stdout";
253
+ flushed.push(...this.#append(app, kind, [remainder]));
254
+ }
255
+ return flushed;
256
+ }
257
+ select({ app = null, source = null, grep, errorsOnly = false } = {}) {
258
+ const needle = grep?.trim().toLowerCase();
259
+ return this.#lines.filter((line) => {
260
+ if (app !== null && line.app !== app)
261
+ return false;
262
+ if (source !== null && line.source !== source)
263
+ return false;
264
+ if (errorsOnly && line.kind !== "stderr")
265
+ return false;
266
+ if (needle && !stripAnsi(line.text).toLowerCase().includes(needle))
267
+ return false;
268
+ return true;
269
+ });
270
+ }
271
+ clear(app = null) {
272
+ const kept = app === null ? [] : this.#lines.filter((line) => line.app !== app);
273
+ this.#lines.length = 0;
274
+ this.#lines.push(...kept);
275
+ }
276
+ #append(app, kind, texts) {
277
+ const known = this.#sources.get(app) ?? new Set;
278
+ this.#sources.set(app, known);
279
+ const added = texts.map((text) => {
280
+ const source = sourceOf(text);
281
+ known.add(source);
282
+ return { seq: ++this.#seq, app, source, kind, text };
283
+ });
284
+ this.#lines.push(...added);
285
+ if (this.#lines.length > this.#limit)
286
+ this.#lines.splice(0, this.#lines.length - this.#limit);
287
+ return added;
288
+ }
289
+ }
290
+
291
+ // pkgs/@akanjs/cli/application/devLogWindow.ts
292
+ var windowOf = (lines, rows, anchor) => {
293
+ const height = Math.max(1, Math.trunc(rows));
294
+ const end = anchor === null ? lines.length : endOf(lines, height, anchor);
295
+ const start = Math.max(0, end - height);
296
+ return {
297
+ lines: lines.slice(start, end),
298
+ above: start,
299
+ below: lines.length - end,
300
+ following: anchor === null
301
+ };
302
+ };
303
+ var scrollAnchor = (lines, rows, anchor, delta) => {
304
+ const height = Math.max(1, Math.trunc(rows));
305
+ if (lines.length <= height)
306
+ return null;
307
+ const end = anchor === null ? lines.length : endOf(lines, height, anchor);
308
+ const next = Math.min(lines.length, Math.max(height, end + Math.trunc(delta)));
309
+ if (next >= lines.length)
310
+ return null;
311
+ return lines[next - 1]?.seq ?? null;
312
+ };
313
+ var endOf = (lines, height, anchor) => {
314
+ for (let idx = lines.length - 1;idx >= 0; idx -= 1) {
315
+ const line = lines[idx];
316
+ if (line && line.seq <= anchor)
317
+ return idx + 1;
318
+ }
319
+ return Math.min(lines.length, height);
320
+ };
321
+
322
+ // pkgs/@akanjs/cli/application/devTui.tsx
323
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
324
+
325
+ class DevTui {
326
+ static frameMs = 34;
327
+ static footerRows = 1;
328
+ static paneChromeRows = 3;
329
+ #buffer = new DevLogBuffer;
330
+ #listeners = new Set;
331
+ #supervisor;
332
+ #instance;
333
+ #statuses = [];
334
+ #target = { app: null, source: null };
335
+ #anchor = null;
336
+ #grep = "";
337
+ #editingGrep = false;
338
+ #errorsOnly = false;
339
+ #frameTimer = null;
340
+ #cachedSnapshot = null;
341
+ constructor(supervisor) {
342
+ this.#supervisor = supervisor;
343
+ this.#statuses = supervisor.statuses;
344
+ process.stdout.on("resize", this.#onResize);
345
+ this.#instance = render(/* @__PURE__ */ jsxDEV2(DevTuiApp, {
346
+ actions: {
347
+ subscribe: this.#subscribe,
348
+ snapshot: this.#snapshot,
349
+ moveSelection: this.#moveSelection,
350
+ selectApp: this.#selectApp,
351
+ scroll: this.#scroll,
352
+ follow: this.#follow,
353
+ setGrep: this.#setGrep,
354
+ setEditingGrep: this.#setEditingGrep,
355
+ toggleErrorsOnly: this.#toggleErrorsOnly,
356
+ clear: this.#clear,
357
+ openSelected: this.#openSelected,
358
+ restartSelected: this.#restartSelected,
359
+ quit: this.#quit
360
+ }
361
+ }, undefined, false, undefined, this), { patchConsole: false });
362
+ }
363
+ onOutput = (app, kind, text) => {
364
+ this.#buffer.push(app, kind, text);
365
+ this.#scheduleFrame();
366
+ };
367
+ onStatus = (statuses) => {
368
+ this.#statuses = statuses;
369
+ this.#scheduleFrame();
370
+ };
371
+ onNote = (text, level) => {
372
+ this.#buffer.push("akan", level === "warn" ? "stderr" : "stdout", `${text}
373
+ `);
374
+ this.#scheduleFrame();
375
+ };
376
+ waitForExit = async () => {
377
+ await this.#instance.waitUntilExit();
378
+ };
379
+ close = () => {
380
+ if (this.#frameTimer)
381
+ clearTimeout(this.#frameTimer);
382
+ this.#frameTimer = null;
383
+ process.stdout.off("resize", this.#onResize);
384
+ this.#instance.unmount();
385
+ for (const line of this.#buffer.flushPartials())
386
+ process.stdout.write(`${line.app} \u2502 ${line.text}
387
+ `);
388
+ for (const status of this.#statuses)
389
+ process.stdout.write(`${status.name} ${status.url} \u2014 ${status.state}
390
+ `);
391
+ };
392
+ #subscribe = (listener) => {
393
+ this.#listeners.add(listener);
394
+ return () => {
395
+ this.#listeners.delete(listener);
396
+ };
397
+ };
398
+ #railRows() {
399
+ const rows = [
400
+ { app: null, source: null, label: "all apps", state: null, port: null, depth: 0, appIndex: null }
401
+ ];
402
+ this.#statuses.forEach((status, idx) => {
403
+ rows.push({
404
+ app: status.name,
405
+ source: null,
406
+ label: status.name,
407
+ state: status.state,
408
+ port: status.port,
409
+ depth: 0,
410
+ appIndex: idx < 9 ? idx + 1 : null
411
+ });
412
+ if (status.name !== this.#target.app)
413
+ return;
414
+ for (const source of this.#buffer.sourcesOf(status.name))
415
+ rows.push({ app: status.name, source, label: source, state: null, port: null, depth: 1, appIndex: null });
416
+ });
417
+ return rows;
418
+ }
419
+ #indexOfTarget(rows) {
420
+ const found = rows.findIndex((row) => row.app === this.#target.app && row.source === this.#target.source);
421
+ return found < 0 ? 0 : found;
422
+ }
423
+ #filtered(target) {
424
+ return this.#buffer.select({
425
+ app: target.app ?? null,
426
+ source: target.source ?? null,
427
+ grep: this.#grep,
428
+ errorsOnly: this.#errorsOnly
429
+ });
430
+ }
431
+ #snapshot = () => {
432
+ if (this.#cachedSnapshot)
433
+ return this.#cachedSnapshot;
434
+ const terminalRows = Math.max(8, process.stdout.rows ?? 24);
435
+ const columns = Math.max(40, process.stdout.columns ?? 80);
436
+ const bodyHeight = Math.max(DevTui.paneChromeRows + 1, terminalRows - DevTui.footerRows);
437
+ const logRows = Math.max(1, bodyHeight - DevTui.paneChromeRows);
438
+ const rows = this.#railRows();
439
+ const view = windowOf(this.#filtered(this.#target), logRows, this.#anchor);
440
+ const status = this.#statuses.find((candidate) => candidate.name === this.#target.app);
441
+ const railLabelWidth = rows.reduce((max, row) => Math.max(max, row.label.length + row.depth * 2), 0);
442
+ this.#cachedSnapshot = {
443
+ rows,
444
+ selected: this.#indexOfTarget(rows),
445
+ title: status ? `${status.name}${this.#target.source ? ` \xB7 ${this.#target.source}` : ""} \xB7 ${status.url} \xB7 ${status.state}${status.detail ? ` (${status.detail})` : ""}` : "all apps",
446
+ lines: view.lines,
447
+ above: view.above,
448
+ below: view.below,
449
+ following: view.following,
450
+ prefix: this.#target.app === null ? "app" : this.#target.source === null ? "source" : "none",
451
+ prefixWidth: this.#target.app === null ? this.#appWidth() : this.#sourceWidth(),
452
+ grep: this.#grep,
453
+ errorsOnly: this.#errorsOnly,
454
+ editingGrep: this.#editingGrep,
455
+ readyCount: this.#statuses.filter((candidate) => candidate.state === "ready").length,
456
+ appCount: this.#statuses.length,
457
+ logRows,
458
+ bodyHeight,
459
+ railWidth: Math.min(34, Math.max(20, railLabelWidth + 10)),
460
+ columns,
461
+ terminalRows
462
+ };
463
+ return this.#cachedSnapshot;
464
+ };
465
+ #appWidth() {
466
+ return this.#statuses.reduce((max, status) => Math.max(max, status.name.length), 0);
467
+ }
468
+ #sourceWidth() {
469
+ let width = HOST_SOURCE.length;
470
+ for (const status of this.#statuses)
471
+ for (const source of this.#buffer.sourcesOf(status.name))
472
+ width = Math.max(width, source.length);
473
+ return width;
474
+ }
475
+ #scheduleFrame() {
476
+ if (this.#frameTimer)
477
+ return;
478
+ this.#frameTimer = setTimeout(() => {
479
+ this.#frameTimer = null;
480
+ this.#renderNow();
481
+ }, DevTui.frameMs);
482
+ }
483
+ #renderNow() {
484
+ this.#cachedSnapshot = null;
485
+ for (const listener of this.#listeners)
486
+ listener();
487
+ }
488
+ #onResize = () => this.#renderNow();
489
+ #moveSelection = (delta) => {
490
+ const rows = this.#railRows();
491
+ const next = ((this.#indexOfTarget(rows) + delta) % rows.length + rows.length) % rows.length;
492
+ const row = rows[next];
493
+ if (row)
494
+ this.#setTarget({ app: row.app, source: row.source });
495
+ };
496
+ #selectApp = (index) => {
497
+ const status = this.#statuses[index];
498
+ if (status)
499
+ this.#setTarget({ app: status.name, source: null });
500
+ };
501
+ #setTarget(target) {
502
+ this.#target = { app: target.app ?? null, source: target.source ?? null };
503
+ this.#anchor = null;
504
+ this.#renderNow();
505
+ }
506
+ #scroll = (delta) => {
507
+ this.#anchor = scrollAnchor(this.#filtered(this.#target), this.#snapshot().logRows, this.#anchor, delta);
508
+ this.#renderNow();
509
+ };
510
+ #follow = () => {
511
+ this.#anchor = null;
512
+ this.#renderNow();
513
+ };
514
+ #setGrep = (grep) => {
515
+ this.#grep = grep;
516
+ this.#anchor = null;
517
+ this.#renderNow();
518
+ };
519
+ #setEditingGrep = (editing) => {
520
+ this.#editingGrep = editing;
521
+ this.#renderNow();
522
+ };
523
+ #toggleErrorsOnly = () => {
524
+ this.#errorsOnly = !this.#errorsOnly;
525
+ this.#anchor = null;
526
+ this.#renderNow();
527
+ };
528
+ #clear = () => {
529
+ this.#buffer.clear(this.#target.app ?? null);
530
+ this.#anchor = null;
531
+ this.#renderNow();
532
+ };
533
+ #openSelected = () => {
534
+ const status = this.#selectedStatus();
535
+ if (status)
536
+ openBrowser(status.url);
537
+ };
538
+ #restartSelected = () => {
539
+ const status = this.#selectedStatus();
540
+ if (status)
541
+ this.#supervisor.restart(status.name);
542
+ };
543
+ #selectedStatus() {
544
+ return this.#statuses.find((candidate) => candidate.name === this.#target.app);
545
+ }
546
+ #quit = () => {
547
+ this.#instance.unmount();
548
+ };
549
+ }
550
+ export {
551
+ DevTui
552
+ };
@@ -0,0 +1,9 @@
1
+ // @bun
2
+ // pkgs/@akanjs/cli/application/devTuiView.ts
3
+ var createDevTuiView = async (supervisor) => {
4
+ const { DevTui } = await import("./devTui-2xf0meaq.js");
5
+ return new DevTui(supervisor);
6
+ };
7
+ export {
8
+ createDevTuiView
9
+ };
@@ -0,0 +1,7 @@
1
+ // @bun
2
+ import {
3
+ getDirname2
4
+ } from "./index-6wwzs1bc.js";
5
+ export {
6
+ getDirname2 as getDirname
7
+ };
@@ -1,25 +1,23 @@
1
1
  // @bun
2
- import {
3
- AiSession
4
- } from "./index-0cj2zxbm.js";
5
- import {
6
- Prompter
7
- } from "./index-j37qq1f2.js";
8
2
  import {
9
3
  Workspace,
10
- command,
11
4
  runner,
12
- script
13
- } from "./index-kdh76j26.js";
14
- import"./index-z8ptfkzv.js";
15
- import"./index-mxvakhsm.js";
16
- import {
17
- getDirname
18
- } from "./index-1577bej2.js";
5
+ script,
6
+ command
7
+ } from "./index-cezy7yb3.js";
19
8
  import {
20
9
  FileSys
21
- } from "./index-67546d0j.js";
22
- import"./index-r24hmh0q.js";
10
+ } from "./index-q0y2jq9j.js";
11
+ import"./index-q8sn827n.js";
12
+ import {
13
+ getDirname2
14
+ } from "./index-6wwzs1bc.js";
15
+ import {
16
+ Prompter
17
+ } from "./index-h7yw2z9n.js";
18
+ import {
19
+ AiSession
20
+ } from "./index-n85fer99.js";
23
21
 
24
22
  // pkgs/@akanjs/cli/guideline/guideline.script.ts
25
23
  import { Logger } from "akanjs/common";
@@ -65,7 +63,7 @@ class GuidelinePrompt extends Prompter {
65
63
  const scanResult = await Promise.all(targetFilePaths.map(async (filePath) => ({ ...scan, ...await this.workspace.getLocalFile(filePath) })));
66
64
  scanFiles.push(...scanResult);
67
65
  }
68
- const resultPath = `${getDirname(import.meta.url)}/../guidelines/${this.name}/${guideJson.update.filePath}`;
66
+ const resultPath = `${getDirname2(import.meta.url)}/../guidelines/${this.name}/${guideJson.update.filePath}`;
69
67
  const writePath = `${this.workspace.workspaceRoot}/pkgs/@akanjs/cli/guidelines/${this.name}/${guideJson.update.filePath}`;
70
68
  const isResultExists = await this.workspace.exists(writePath);
71
69
  const existingResult = isResultExists ? await this.workspace.readFile(resultPath) : null;
@@ -107,7 +105,7 @@ ${guideJson.update.rules.map((rule) => `- ${rule}`).join(`
107
105
  }
108
106
  async requestUpdateInstruction(updateRequest) {
109
107
  const guideJson = await Prompter.getGuideJson(this.name);
110
- const resultPath = `${getDirname(import.meta.url)}/../guidelines/${this.name}/${guideJson.update.filePath}`;
108
+ const resultPath = `${getDirname2(import.meta.url)}/../guidelines/${this.name}/${guideJson.update.filePath}`;
111
109
  const writePath = `${this.workspace.workspaceRoot}/pkgs/@akanjs/cli/guidelines/${this.name}/${guideJson.update.filePath}`;
112
110
  const isResultExists = await this.workspace.exists(writePath);
113
111
  if (!isResultExists)
@@ -0,0 +1,31 @@
1
+ {
2
+ "title": "In-Page Agent Rule",
3
+ "description": "How an akan screen exposes itself to an in-page agent — st.tool, subscribed keys, built-ins, and the chat",
4
+ "group": "core",
5
+ "codegenPriority": 4,
6
+ "deprecated": false,
7
+ "scans": [
8
+ {
9
+ "type": "example",
10
+ "description": "Components publishing an agent tool beside the control that already performs the action",
11
+ "path": "{apps,libs}/*/**/*.tsx",
12
+ "sample": 4
13
+ }
14
+ ],
15
+ "update": {
16
+ "filePath": "./agentRule.instruction.md",
17
+ "contents": [
18
+ "what a declaration publishes",
19
+ "mounting the chat",
20
+ "publishing a tool",
21
+ "forms and reading state",
22
+ "built-in tools"
23
+ ],
24
+ "rules": [
25
+ "Use current Akan APIs only",
26
+ "State the rule before the reason, and keep the reason to one clause",
27
+ "Never describe a store class as an exposure surface — only st.tool and subscribed keys publish",
28
+ "Keep it workspace-neutral — no app or repo names"
29
+ ]
30
+ }
31
+ }