silvery 0.17.0 → 0.17.2

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 (171) hide show
  1. package/dist/UPNG-AVSMjiFE.mjs +5076 -0
  2. package/dist/UPNG-AVSMjiFE.mjs.map +1 -0
  3. package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs +6 -0
  4. package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs.map +1 -0
  5. package/dist/animation-C_PTO0uH.mjs +304 -0
  6. package/dist/animation-C_PTO0uH.mjs.map +1 -0
  7. package/dist/ansi-CXLE_pt1.mjs +71 -0
  8. package/dist/ansi-CXLE_pt1.mjs.map +1 -0
  9. package/dist/ansi-zmNzgkPB.d.mts +49 -0
  10. package/dist/ansi-zmNzgkPB.d.mts.map +1 -0
  11. package/dist/apng-DCWY913R.mjs +3 -0
  12. package/dist/apng-ENBAJk-H.mjs +70 -0
  13. package/dist/apng-ENBAJk-H.mjs.map +1 -0
  14. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  15. package/dist/backend-CkIkIHR-.mjs +13396 -0
  16. package/dist/backend-CkIkIHR-.mjs.map +1 -0
  17. package/dist/backends-CkvbG3js.mjs +1181 -0
  18. package/dist/backends-CkvbG3js.mjs.map +1 -0
  19. package/dist/backends-CyJqNLeK.mjs +3 -0
  20. package/dist/chunk-BSw8zbkd.mjs +37 -0
  21. package/dist/cli-B-k7Bm56.mjs +4 -0
  22. package/dist/context-QreF3UHr.mjs +64 -0
  23. package/dist/context-QreF3UHr.mjs.map +1 -0
  24. package/dist/derive-D7bFJdfU.d.mts +28 -0
  25. package/dist/derive-D7bFJdfU.d.mts.map +1 -0
  26. package/dist/devtools-CscuKaDK.mjs +89 -0
  27. package/dist/devtools-CscuKaDK.mjs.map +1 -0
  28. package/dist/devtools-D4oGc6LY.mjs +2 -0
  29. package/dist/eta-DLiVPaSD.mjs +110 -0
  30. package/dist/eta-DLiVPaSD.mjs.map +1 -0
  31. package/dist/flexily-zero-adapter-DmG4Ge8t.mjs +3376 -0
  32. package/dist/flexily-zero-adapter-DmG4Ge8t.mjs.map +1 -0
  33. package/dist/flexily-zero-adapter-GHwEW11s.mjs +2 -0
  34. package/dist/gif-BaJNREpP.mjs +3 -0
  35. package/dist/gif-Bp6fIyN3.mjs +73 -0
  36. package/dist/gif-Bp6fIyN3.mjs.map +1 -0
  37. package/dist/gifenc-GiVCZ9-3.mjs +730 -0
  38. package/dist/gifenc-GiVCZ9-3.mjs.map +1 -0
  39. package/dist/image-Dx7gYjkq.mjs +346 -0
  40. package/dist/image-Dx7gYjkq.mjs.map +1 -0
  41. package/dist/index-CBcSpGSM.d.mts +3416 -0
  42. package/dist/index-CBcSpGSM.d.mts.map +1 -0
  43. package/dist/index-DCVL3jHo.d.mts +634 -0
  44. package/dist/index-DCVL3jHo.d.mts.map +1 -0
  45. package/dist/index-p-wBs_wH.d.mts +175 -0
  46. package/dist/index-p-wBs_wH.d.mts.map +1 -0
  47. package/dist/index.d.mts +7296 -0
  48. package/dist/index.d.mts.map +1 -0
  49. package/dist/index.mjs +9399 -0
  50. package/dist/index.mjs.map +1 -0
  51. package/dist/key-mapping-BsUHe_nk.mjs +3 -0
  52. package/dist/key-mapping-DsyfLEdC.mjs +132 -0
  53. package/dist/key-mapping-DsyfLEdC.mjs.map +1 -0
  54. package/dist/layout-engine-B3dsnVLU.mjs +50 -0
  55. package/dist/layout-engine-B3dsnVLU.mjs.map +1 -0
  56. package/dist/layout-engine-D_lSR4i9.mjs +2 -0
  57. package/dist/multi-progress-C0-rkn86.d.mts +180 -0
  58. package/dist/multi-progress-C0-rkn86.d.mts.map +1 -0
  59. package/dist/multi-progress-CQVB9lES.mjs +219 -0
  60. package/dist/multi-progress-CQVB9lES.mjs.map +1 -0
  61. package/dist/node-Dedx-6xF.mjs +1085 -0
  62. package/dist/node-Dedx-6xF.mjs.map +1 -0
  63. package/dist/pipeline-DDOPrjuY.mjs +4387 -0
  64. package/dist/pipeline-DDOPrjuY.mjs.map +1 -0
  65. package/dist/progress-bar-COPSBlT9.mjs +155 -0
  66. package/dist/progress-bar-COPSBlT9.mjs.map +1 -0
  67. package/dist/reconciler-2lp5VXK7.mjs +16506 -0
  68. package/dist/reconciler-2lp5VXK7.mjs.map +1 -0
  69. package/dist/render-string-BXvxTg5P.mjs +201 -0
  70. package/dist/render-string-BXvxTg5P.mjs.map +1 -0
  71. package/dist/render-string-hvfpVtoP.mjs +2 -0
  72. package/dist/resvg-js-V6oMi8CY.mjs +203 -0
  73. package/dist/resvg-js-V6oMi8CY.mjs.map +1 -0
  74. package/dist/runtime-BjDHNTxJ.mjs +8723 -0
  75. package/dist/runtime-BjDHNTxJ.mjs.map +1 -0
  76. package/dist/runtime.d.mts +2 -0
  77. package/dist/runtime.mjs +3 -0
  78. package/dist/spinner-Cgej6Vnb.d.mts +127 -0
  79. package/dist/spinner-Cgej6Vnb.d.mts.map +1 -0
  80. package/dist/spinner-DSByknyx.mjs +298 -0
  81. package/dist/spinner-DSByknyx.mjs.map +1 -0
  82. package/dist/src-9B5k0JmY.mjs +1629 -0
  83. package/dist/src-9B5k0JmY.mjs.map +1 -0
  84. package/dist/src-C9f3hiVG.mjs +3620 -0
  85. package/dist/src-C9f3hiVG.mjs.map +1 -0
  86. package/dist/src-fJVbhdn-.mjs +816 -0
  87. package/dist/src-fJVbhdn-.mjs.map +1 -0
  88. package/dist/theme.d.mts +115 -0
  89. package/dist/theme.d.mts.map +1 -0
  90. package/dist/theme.mjs +8 -0
  91. package/dist/theme.mjs.map +1 -0
  92. package/dist/types-Bhj5QkIQ.mjs +13 -0
  93. package/dist/types-Bhj5QkIQ.mjs.map +1 -0
  94. package/dist/types-CDgkE-Rw.d.mts +241 -0
  95. package/dist/types-CDgkE-Rw.d.mts.map +1 -0
  96. package/dist/ui/animation.d.mts +2 -0
  97. package/dist/ui/animation.mjs +2 -0
  98. package/dist/ui/ansi.d.mts +2 -0
  99. package/dist/ui/ansi.mjs +2 -0
  100. package/dist/ui/cli.d.mts +5 -0
  101. package/dist/ui/cli.mjs +7 -0
  102. package/dist/ui/display.d.mts +35 -0
  103. package/dist/ui/display.d.mts.map +1 -0
  104. package/dist/ui/display.mjs +123 -0
  105. package/dist/ui/display.mjs.map +1 -0
  106. package/dist/ui/image.d.mts +2 -0
  107. package/dist/ui/image.mjs +2 -0
  108. package/dist/ui/input.d.mts +184 -0
  109. package/dist/ui/input.d.mts.map +1 -0
  110. package/dist/ui/input.mjs +285 -0
  111. package/dist/ui/input.mjs.map +1 -0
  112. package/dist/ui/progress.d.mts +249 -0
  113. package/dist/ui/progress.d.mts.map +1 -0
  114. package/dist/ui/progress.mjs +858 -0
  115. package/dist/ui/progress.mjs.map +1 -0
  116. package/dist/ui/react.d.mts +280 -0
  117. package/dist/ui/react.d.mts.map +1 -0
  118. package/dist/ui/react.mjs +413 -0
  119. package/dist/ui/react.mjs.map +1 -0
  120. package/dist/ui/utils.d.mts +86 -0
  121. package/dist/ui/utils.d.mts.map +1 -0
  122. package/dist/ui/utils.mjs +2 -0
  123. package/dist/ui/wrappers.d.mts +3 -0
  124. package/dist/ui/wrappers.mjs +2 -0
  125. package/dist/ui.d.mts +6 -0
  126. package/dist/ui.mjs +7 -0
  127. package/dist/useLatest-BMIYXd6e.d.mts +154 -0
  128. package/dist/useLatest-BMIYXd6e.d.mts.map +1 -0
  129. package/dist/useLayout-BG2cGl15.mjs +139 -0
  130. package/dist/useLayout-BG2cGl15.mjs.map +1 -0
  131. package/dist/with-text-input-CmHf_9d6.d.mts +284 -0
  132. package/dist/with-text-input-CmHf_9d6.d.mts.map +1 -0
  133. package/dist/wrapper-Dqh0zi2W.mjs +3527 -0
  134. package/dist/wrapper-Dqh0zi2W.mjs.map +1 -0
  135. package/dist/wrappers-hhL8EQ_n.mjs +810 -0
  136. package/dist/wrappers-hhL8EQ_n.mjs.map +1 -0
  137. package/dist/yoga-adapter-BJ9SOhTY.mjs +245 -0
  138. package/dist/yoga-adapter-BJ9SOhTY.mjs.map +1 -0
  139. package/dist/yoga-adapter-Daq6-dw1.mjs +2 -0
  140. package/package.json +48 -75
  141. package/CHANGELOG.md +0 -319
  142. package/dist/chalk.js +0 -4
  143. package/dist/index.js +0 -270
  144. package/dist/ink.js +0 -142
  145. package/dist/runtime.js +0 -135
  146. package/dist/theme.js +0 -7
  147. package/dist/ui/animation.js +0 -3
  148. package/dist/ui/ansi.js +0 -3
  149. package/dist/ui/cli.js +0 -9
  150. package/dist/ui/display.js +0 -4
  151. package/dist/ui/image.js +0 -4
  152. package/dist/ui/input.js +0 -3
  153. package/dist/ui/progress.js +0 -9
  154. package/dist/ui/react.js +0 -4
  155. package/dist/ui/utils.js +0 -3
  156. package/dist/ui/wrappers.js +0 -15
  157. package/dist/ui.js +0 -18
  158. package/src/index.ts +0 -73
  159. package/src/runtime.ts +0 -4
  160. package/src/theme.ts +0 -4
  161. package/src/ui/animation.ts +0 -2
  162. package/src/ui/ansi.ts +0 -2
  163. package/src/ui/cli.ts +0 -3
  164. package/src/ui/display.ts +0 -2
  165. package/src/ui/image.ts +0 -2
  166. package/src/ui/input.ts +0 -2
  167. package/src/ui/progress.ts +0 -2
  168. package/src/ui/react.ts +0 -2
  169. package/src/ui/utils.ts +0 -2
  170. package/src/ui/wrappers.ts +0 -2
  171. package/src/ui.ts +0 -4
@@ -0,0 +1,858 @@
1
+ import { i as createSpinner, r as Spinner } from "../spinner-DSByknyx.mjs";
2
+ import { t as ProgressBar } from "../progress-bar-COPSBlT9.mjs";
3
+ import { t as MultiProgress } from "../multi-progress-CQVB9lES.mjs";
4
+ import { AsyncLocalStorage } from "node:async_hooks";
5
+ //#region packages/ag-react/src/ui/progress/als-context.ts
6
+ /**
7
+ * AsyncLocalStorage context for step progress reporting
8
+ *
9
+ * Provides a `step()` function that work functions can call to report progress.
10
+ * Returns a no-op context when called outside of a steps() execution context,
11
+ * so functions work in tests without the progress UI.
12
+ */
13
+ const stepContext = new AsyncLocalStorage();
14
+ /**
15
+ * Get the current step context
16
+ *
17
+ * Safe to call anywhere - returns a no-op context when called outside
18
+ * of a steps() execution context.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * async function processFiles(files: string[]) {
23
+ * for (let i = 0; i < files.length; i++) {
24
+ * step().progress(i + 1, files.length);
25
+ * await process(files[i]);
26
+ * }
27
+ * }
28
+ *
29
+ * // In tests (no steps context)
30
+ * await processFiles(["a.md", "b.md"]); // step() returns no-op, no errors
31
+ *
32
+ * // In production (with steps context)
33
+ * await steps({ process: processFiles }).run(); // Shows progress
34
+ * ```
35
+ */
36
+ function step() {
37
+ return stepContext.getStore() ?? NO_OP_CONTEXT;
38
+ }
39
+ /**
40
+ * Run a function with step context (internal use by runner)
41
+ */
42
+ function runWithStepContext(ctx, fn) {
43
+ return stepContext.run(ctx, fn);
44
+ }
45
+ /**
46
+ * Create an internal step context for the runner
47
+ */
48
+ function createStepContext(label, handle, onSubStep) {
49
+ let currentSubLabel;
50
+ let currentSubHandle = null;
51
+ let subStepStartTime = 0;
52
+ const declaredHandles = /* @__PURE__ */ new Map();
53
+ return {
54
+ get label() {
55
+ return label;
56
+ },
57
+ get handle() {
58
+ return handle;
59
+ },
60
+ progress(current, total) {
61
+ if (currentSubHandle) currentSubHandle.setTitle(`${currentSubLabel} (${current}/${total})`);
62
+ else handle.setTitle(`${label} (${current}/${total})`);
63
+ },
64
+ sub(subLabel) {
65
+ this._completeSubStep();
66
+ currentSubLabel = subLabel;
67
+ subStepStartTime = Date.now();
68
+ if (onSubStep) {
69
+ currentSubHandle = onSubStep(subLabel);
70
+ currentSubHandle.start();
71
+ }
72
+ },
73
+ _addSubHandle(subLabel, subHandle) {
74
+ declaredHandles.set(subLabel, subHandle);
75
+ },
76
+ _getSubHandle(subLabel) {
77
+ return declaredHandles.get(subLabel);
78
+ },
79
+ _setCurrentSubHandle(subLabel, subHandle) {
80
+ currentSubLabel = subLabel;
81
+ currentSubHandle = subHandle;
82
+ subStepStartTime = Date.now();
83
+ },
84
+ _completeSubStep() {
85
+ if (currentSubHandle && currentSubLabel) {
86
+ const elapsed = Date.now() - subStepStartTime;
87
+ currentSubHandle.complete(elapsed);
88
+ currentSubHandle = null;
89
+ currentSubLabel = void 0;
90
+ }
91
+ }
92
+ };
93
+ }
94
+ /**
95
+ * No-op context for when step() is called outside execution context
96
+ */
97
+ const NO_OP_CONTEXT = {
98
+ progress: () => {},
99
+ sub: () => {},
100
+ get label() {
101
+ return "";
102
+ }
103
+ };
104
+ //#endregion
105
+ //#region packages/ag-react/src/ui/progress/step-node.ts
106
+ /**
107
+ * Parse a declarative steps definition into a tree of StepNodes
108
+ *
109
+ * @param def - The declarative structure
110
+ * @param indent - Current indentation level (internal)
111
+ * @returns Array of StepNodes
112
+ */
113
+ function parseStepsDef(def, indent = 0) {
114
+ const nodes = [];
115
+ for (const [key, value] of Object.entries(def)) if (typeof value === "function") nodes.push({
116
+ key,
117
+ label: generateLabel(key),
118
+ work: value,
119
+ indent
120
+ });
121
+ else if (Array.isArray(value) && value.length === 2) {
122
+ const [label, work] = value;
123
+ nodes.push({
124
+ key,
125
+ label,
126
+ work,
127
+ indent
128
+ });
129
+ } else if (typeof value === "object" && value !== null) {
130
+ const children = parseStepsDef(value, indent + 1);
131
+ nodes.push({
132
+ key,
133
+ label: generateLabel(key),
134
+ children,
135
+ indent
136
+ });
137
+ }
138
+ return nodes;
139
+ }
140
+ /**
141
+ * Flatten the tree for sequential execution
142
+ *
143
+ * Returns nodes in depth-first order, with groups followed by their children.
144
+ */
145
+ function flattenStepNodes(nodes) {
146
+ const result = [];
147
+ for (const node of nodes) {
148
+ result.push(node);
149
+ if (node.children) result.push(...flattenStepNodes(node.children));
150
+ }
151
+ return result;
152
+ }
153
+ /**
154
+ * Get only leaf nodes (nodes with work functions)
155
+ */
156
+ function getLeafNodes(nodes) {
157
+ const result = [];
158
+ for (const node of nodes) {
159
+ if (node.work) result.push(node);
160
+ if (node.children) result.push(...getLeafNodes(node.children));
161
+ }
162
+ return result;
163
+ }
164
+ /**
165
+ * Generate a display label from a camelCase function name
166
+ *
167
+ * @example
168
+ * generateLabel("loadModules") // "Load modules"
169
+ * generateLabel("parseMarkdown") // "Parse markdown"
170
+ * generateLabel("initBoardStateGenerator") // "Init board state generator"
171
+ */
172
+ function generateLabel(fnName) {
173
+ return fnName.replace(/([A-Z])/g, " $1").replace(/(\d+)/g, " $1").toLowerCase().trim().replace(/\s+/g, " ").replace(/^./, (s) => s.toUpperCase());
174
+ }
175
+ //#endregion
176
+ //#region packages/ag-react/src/ui/progress/declarative.ts
177
+ /**
178
+ * Declarative steps implementation
179
+ *
180
+ * Provides the declarative overload for steps() that accepts an object
181
+ * structure and shows all steps upfront before execution.
182
+ */
183
+ /**
184
+ * Create a declarative steps runner
185
+ *
186
+ * @param def - Object structure defining steps
187
+ * @returns StepsRunner with run(), pipe(), and done() methods
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * const loader = stepsDeclarative({
192
+ * loadModules, // "Load modules"
193
+ * loadRepo: { // "Load repo" (group)
194
+ * discover, // "Discover"
195
+ * parse, // "Parse"
196
+ * },
197
+ * });
198
+ *
199
+ * const results = await loader.run({ clear: true });
200
+ * ```
201
+ */
202
+ function stepsDeclarative(def) {
203
+ const rootNodes = parseStepsDef(def);
204
+ const allNodes = flattenStepNodes(rootNodes);
205
+ let multi = null;
206
+ const handles = /* @__PURE__ */ new Map();
207
+ const groupLeaves = /* @__PURE__ */ new Map();
208
+ const leafToGroups = /* @__PURE__ */ new Map();
209
+ for (const node of allNodes) if (node.children) {
210
+ const leaves = getLeafNodes([node]);
211
+ groupLeaves.set(node, leaves);
212
+ for (const leaf of leaves) {
213
+ const groups = leafToGroups.get(leaf) ?? [];
214
+ groups.push(node);
215
+ leafToGroups.set(leaf, groups);
216
+ }
217
+ }
218
+ return {
219
+ get _steps() {
220
+ return rootNodes;
221
+ },
222
+ async run(options) {
223
+ multi = new MultiProgress();
224
+ registerAllSteps(allNodes, multi, handles);
225
+ const groupStartTimes = /* @__PURE__ */ new Map();
226
+ const completedLeaves = /* @__PURE__ */ new Set();
227
+ multi.start();
228
+ await new Promise((resolve) => setImmediate(resolve));
229
+ const results = {};
230
+ try {
231
+ for (const node of allNodes) if (node.work) {
232
+ const groups = leafToGroups.get(node) ?? [];
233
+ for (const group of groups) if (!groupStartTimes.has(group)) {
234
+ groupStartTimes.set(group, Date.now());
235
+ handles.get(group)?.start();
236
+ }
237
+ const result = await executeStep(node, handles, multi);
238
+ setNestedResult(results, node.key, result);
239
+ completedLeaves.add(node);
240
+ for (const group of groups) if ((groupLeaves.get(group) ?? []).every((l) => completedLeaves.has(l))) {
241
+ const elapsed = Date.now() - groupStartTimes.get(group);
242
+ handles.get(group)?.complete(elapsed);
243
+ }
244
+ }
245
+ } finally {
246
+ multi.stop(options?.clear ?? false);
247
+ }
248
+ return results;
249
+ },
250
+ async pipe(options) {
251
+ multi = new MultiProgress();
252
+ registerAllSteps(allNodes, multi, handles);
253
+ const groupStartTimes = /* @__PURE__ */ new Map();
254
+ const completedLeaves = /* @__PURE__ */ new Set();
255
+ multi.start();
256
+ await new Promise((resolve) => setImmediate(resolve));
257
+ let previousResult = void 0;
258
+ try {
259
+ for (const node of allNodes) if (node.work) {
260
+ const groups = leafToGroups.get(node) ?? [];
261
+ for (const group of groups) if (!groupStartTimes.has(group)) {
262
+ groupStartTimes.set(group, Date.now());
263
+ handles.get(group)?.start();
264
+ }
265
+ previousResult = await executeStep(node, handles, multi, previousResult);
266
+ completedLeaves.add(node);
267
+ for (const group of groups) if ((groupLeaves.get(group) ?? []).every((l) => completedLeaves.has(l))) {
268
+ const elapsed = Date.now() - groupStartTimes.get(group);
269
+ handles.get(group)?.complete(elapsed);
270
+ }
271
+ }
272
+ } finally {
273
+ multi.stop(options?.clear ?? false);
274
+ }
275
+ return previousResult;
276
+ },
277
+ done(options) {
278
+ if (multi) {
279
+ multi.stop(options?.clear ?? false);
280
+ multi = null;
281
+ }
282
+ }
283
+ };
284
+ }
285
+ /**
286
+ * Register all steps with MultiProgress upfront
287
+ */
288
+ function registerAllSteps(nodes, multi, handles) {
289
+ for (const node of nodes) {
290
+ const isGroup = node.children && !node.work;
291
+ const handle = multi.add(node.label, {
292
+ type: isGroup ? "group" : "spinner",
293
+ indent: node.indent
294
+ });
295
+ handles.set(node, handle);
296
+ }
297
+ }
298
+ /**
299
+ * Execute a single step
300
+ */
301
+ async function executeStep(node, handles, multi, input) {
302
+ const handle = handles.get(node);
303
+ const startTime = Date.now();
304
+ await new Promise((resolve) => setImmediate(resolve));
305
+ const ctx = createStepContext(node.label, handle, (subLabel) => {
306
+ return multi.add(subLabel, {
307
+ type: "spinner",
308
+ indent: node.indent + 1,
309
+ insertAfter: handle.id
310
+ });
311
+ });
312
+ handle.start();
313
+ try {
314
+ const result = await runWithStepContext(ctx, () => {
315
+ if (input !== void 0) return node.work(input);
316
+ return node.work();
317
+ });
318
+ if (isGenerator$2(result)) return await runGenerator$2(result, ctx, node, multi);
319
+ if (isAsyncGenerator$1(result)) return await runAsyncGenerator$1(result, ctx, node, multi);
320
+ ctx._completeSubStep();
321
+ const elapsed = Date.now() - startTime;
322
+ handle.complete(elapsed);
323
+ return result;
324
+ } catch (error) {
325
+ handle.fail();
326
+ throw error;
327
+ }
328
+ }
329
+ /**
330
+ * Run a sync generator step
331
+ */
332
+ async function runGenerator$2(gen, ctx, node, multi) {
333
+ const startTime = Date.now();
334
+ let result = gen.next();
335
+ let hasSubSteps = false;
336
+ let lastInsertedId = ctx.handle.id;
337
+ while (!result.done) {
338
+ const value = result.value;
339
+ if (isDeclareSteps$1(value)) {
340
+ if (!hasSubSteps) {
341
+ hasSubSteps = true;
342
+ ctx.handle.setType("group");
343
+ }
344
+ for (const label of value.declare) {
345
+ const subHandle = multi.add(label, {
346
+ type: "spinner",
347
+ indent: node.indent + 1,
348
+ insertAfter: lastInsertedId
349
+ });
350
+ lastInsertedId = subHandle.id;
351
+ ctx._addSubHandle(label, subHandle);
352
+ }
353
+ } else if (typeof value === "string") {
354
+ ctx._completeSubStep();
355
+ if (!hasSubSteps) {
356
+ hasSubSteps = true;
357
+ ctx.handle.setType("group");
358
+ }
359
+ const existingHandle = ctx._getSubHandle?.(value);
360
+ if (existingHandle) {
361
+ ctx._setCurrentSubHandle(value, existingHandle);
362
+ existingHandle.start();
363
+ } else {
364
+ const subHandle = multi.add(value, {
365
+ type: "spinner",
366
+ indent: node.indent + 1,
367
+ insertAfter: lastInsertedId
368
+ });
369
+ lastInsertedId = subHandle.id;
370
+ ctx._addSubHandle(value, subHandle);
371
+ subHandle.start();
372
+ }
373
+ } else if (isProgressUpdate(value)) ctx.progress(value.current ?? 0, value.total ?? 0);
374
+ await new Promise((resolve) => setTimeout(resolve, 0));
375
+ result = gen.next();
376
+ }
377
+ ctx._completeSubStep();
378
+ const elapsed = Date.now() - startTime;
379
+ ctx.handle.complete(elapsed);
380
+ return result.value;
381
+ }
382
+ /**
383
+ * Run an async generator step
384
+ */
385
+ async function runAsyncGenerator$1(gen, ctx, node, multi) {
386
+ const startTime = Date.now();
387
+ let result = await gen.next();
388
+ let hasSubSteps = false;
389
+ let lastInsertedId = ctx.handle.id;
390
+ while (!result.done) {
391
+ const value = result.value;
392
+ if (isDeclareSteps$1(value)) {
393
+ if (!hasSubSteps) {
394
+ hasSubSteps = true;
395
+ ctx.handle.setType("group");
396
+ }
397
+ for (const label of value.declare) {
398
+ const subHandle = multi.add(label, {
399
+ type: "spinner",
400
+ indent: node.indent + 1,
401
+ insertAfter: lastInsertedId
402
+ });
403
+ lastInsertedId = subHandle.id;
404
+ ctx._addSubHandle(label, subHandle);
405
+ }
406
+ } else if (typeof value === "string") {
407
+ ctx._completeSubStep();
408
+ if (!hasSubSteps) {
409
+ hasSubSteps = true;
410
+ ctx.handle.setType("group");
411
+ }
412
+ const existingHandle = ctx._getSubHandle(value);
413
+ if (existingHandle) {
414
+ ctx._setCurrentSubHandle(value, existingHandle);
415
+ existingHandle.start();
416
+ } else {
417
+ const subHandle = multi.add(value, {
418
+ type: "spinner",
419
+ indent: node.indent + 1,
420
+ insertAfter: lastInsertedId
421
+ });
422
+ lastInsertedId = subHandle.id;
423
+ ctx._addSubHandle(value, subHandle);
424
+ subHandle.start();
425
+ }
426
+ } else if (isProgressUpdate(value)) ctx.progress(value.current ?? 0, value.total ?? 0);
427
+ await new Promise((resolve) => setTimeout(resolve, 0));
428
+ result = await gen.next();
429
+ }
430
+ ctx._completeSubStep();
431
+ const elapsed = Date.now() - startTime;
432
+ ctx.handle.complete(elapsed);
433
+ return result.value;
434
+ }
435
+ /**
436
+ * Set a nested result value by key path
437
+ */
438
+ function setNestedResult(results, key, value) {
439
+ results[key] = value;
440
+ }
441
+ /**
442
+ * Type guards
443
+ */
444
+ function isGenerator$2(value) {
445
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.iterator] === "function";
446
+ }
447
+ function isAsyncGenerator$1(value) {
448
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.asyncIterator] === "function";
449
+ }
450
+ function isProgressUpdate(value) {
451
+ return value !== null && typeof value === "object" && !Array.isArray(value) && ("current" in value || "total" in value);
452
+ }
453
+ function isDeclareSteps$1(value) {
454
+ return value !== null && typeof value === "object" && "declare" in value && Array.isArray(value.declare);
455
+ }
456
+ //#endregion
457
+ //#region packages/ag-react/src/ui/progress/steps.ts
458
+ /**
459
+ * Sequential step runner with progress display
460
+ *
461
+ * Supports two modes:
462
+ *
463
+ * ## Declarative Mode (recommended)
464
+ *
465
+ * Pass an object to declare all steps upfront:
466
+ *
467
+ * ```typescript
468
+ * import { steps, step } from "@silvery/ag-react/ui/progress";
469
+ *
470
+ * const loader = steps({
471
+ * loadModules, // Auto-named: "Load modules"
472
+ * loadRepo: { // Group: "Load repo"
473
+ * discover, // "Discover"
474
+ * parse, // "Parse"
475
+ * },
476
+ * });
477
+ *
478
+ * const results = await loader.run({ clear: true });
479
+ *
480
+ * // Inside work functions, use step() to report progress:
481
+ * async function discover() {
482
+ * const files = await glob("**\/*.md");
483
+ * for (let i = 0; i < files.length; i++) {
484
+ * step().progress(i + 1, files.length);
485
+ * await process(files[i]);
486
+ * }
487
+ * return files;
488
+ * }
489
+ * ```
490
+ *
491
+ * ## Fluent Mode (legacy)
492
+ *
493
+ * Chain steps with `.run()` and execute with `.execute()`:
494
+ *
495
+ * ```typescript
496
+ * await steps()
497
+ * .run("Loading modules", () => import("./app"))
498
+ * .run("Building view", async () => buildView())
499
+ * .execute();
500
+ * ```
501
+ *
502
+ * Generators can yield sub-step progress:
503
+ * - Yield a **string** to create a new sub-step
504
+ * - Yield an **object** `{ current, total }` to update progress on current sub-step
505
+ */
506
+ function steps(def) {
507
+ if (def !== void 0) return stepsDeclarative(def);
508
+ return createFluentBuilder();
509
+ }
510
+ /**
511
+ * Create a no-op StepController for work functions that don't use sub-steps.
512
+ * This satisfies the type union while being harmless if not used.
513
+ */
514
+ function createNoopStepController() {
515
+ const controller = (_label) => {};
516
+ controller.progress = (_current, _total) => {};
517
+ controller.done = () => {};
518
+ return controller;
519
+ }
520
+ /**
521
+ * Create the fluent step builder (legacy mode)
522
+ */
523
+ function createFluentBuilder() {
524
+ const stepList = [];
525
+ const builder = {
526
+ run(title, work) {
527
+ stepList.push({
528
+ title,
529
+ work
530
+ });
531
+ return builder;
532
+ },
533
+ async execute(options) {
534
+ const multi = new MultiProgress();
535
+ const handles = /* @__PURE__ */ new Map();
536
+ const results = {};
537
+ for (const step of stepList) handles.set(step.title, multi.add(step.title, { type: "spinner" }));
538
+ multi.start();
539
+ try {
540
+ for (const step of stepList) {
541
+ const handle = handles.get(step.title);
542
+ await new Promise((resolve) => setImmediate(resolve));
543
+ const result = step.work(createNoopStepController());
544
+ if (isAsyncGenerator(result)) results[step.title] = await runAsyncGenerator(result, handle, step.title, multi);
545
+ else if (isSyncGenerator(result)) results[step.title] = await runSyncGenerator(result, handle, step.title, multi);
546
+ else if (isPromiseLike$2(result)) {
547
+ handle.start();
548
+ results[step.title] = await result;
549
+ handle.complete();
550
+ } else {
551
+ handle.start();
552
+ results[step.title] = result;
553
+ handle.complete();
554
+ }
555
+ }
556
+ } finally {
557
+ multi.stop(options?.clear ?? false);
558
+ }
559
+ return results;
560
+ }
561
+ };
562
+ return builder;
563
+ }
564
+ /**
565
+ * Process a yielded value:
566
+ * - { declare: [...] } = declare all sub-steps upfront (show as pending)
567
+ * - string = start/create a sub-step with that label
568
+ * - { current, total } = update progress on current sub-step
569
+ */
570
+ function processYield(value, state, multi) {
571
+ if (isDeclareSteps(value)) {
572
+ for (const label of value.declare) {
573
+ const handle = multi.add(label, {
574
+ type: "spinner",
575
+ indent: 1,
576
+ insertAfter: state.lastInsertId
577
+ });
578
+ state.lastInsertId = handle.id;
579
+ state.declaredSteps.set(label, handle);
580
+ }
581
+ return;
582
+ }
583
+ if (typeof value === "string") {
584
+ if (state.currentHandle && state.currentLabel) {
585
+ const elapsed = Date.now() - state.subStepStartTime;
586
+ state.currentHandle.complete(elapsed);
587
+ }
588
+ state.currentLabel = value;
589
+ state.subStepStartTime = Date.now();
590
+ const declared = state.declaredSteps.get(value);
591
+ if (declared) {
592
+ state.currentHandle = declared;
593
+ state.currentHandle.start();
594
+ } else {
595
+ state.currentHandle = multi.add(value, {
596
+ type: "spinner",
597
+ indent: 1,
598
+ insertAfter: state.lastInsertId
599
+ });
600
+ state.lastInsertId = state.currentHandle.id;
601
+ state.currentHandle.start();
602
+ }
603
+ } else if (value && typeof value === "object") {
604
+ const { current, total } = value;
605
+ if (state.currentHandle && total && total > 0) state.currentHandle.setTitle(`${state.currentLabel} (${current ?? 0}/${total})`);
606
+ }
607
+ }
608
+ function isDeclareSteps(value) {
609
+ return value !== null && typeof value === "object" && "declare" in value && Array.isArray(value.declare);
610
+ }
611
+ /**
612
+ * Run an async generator step
613
+ */
614
+ async function runAsyncGenerator(gen, parentHandle, parentTitle, multi) {
615
+ const state = {
616
+ currentLabel: void 0,
617
+ currentHandle: null,
618
+ lastInsertId: parentHandle.id,
619
+ subStepStartTime: Date.now(),
620
+ startTime: Date.now(),
621
+ declaredSteps: /* @__PURE__ */ new Map()
622
+ };
623
+ let result = await gen.next();
624
+ while (!result.done) {
625
+ processYield(result.value, state, multi);
626
+ await new Promise((resolve) => setTimeout(resolve, 0));
627
+ result = await gen.next();
628
+ }
629
+ if (state.currentHandle && state.currentLabel) {
630
+ const elapsed = Date.now() - state.subStepStartTime;
631
+ state.currentHandle.complete(elapsed);
632
+ }
633
+ const totalElapsed = Date.now() - state.startTime;
634
+ parentHandle.complete(totalElapsed);
635
+ return result.value;
636
+ }
637
+ /**
638
+ * Run a sync generator step
639
+ */
640
+ async function runSyncGenerator(gen, parentHandle, parentTitle, multi) {
641
+ const state = {
642
+ currentLabel: void 0,
643
+ currentHandle: null,
644
+ lastInsertId: parentHandle.id,
645
+ subStepStartTime: Date.now(),
646
+ startTime: Date.now(),
647
+ declaredSteps: /* @__PURE__ */ new Map()
648
+ };
649
+ let result = gen.next();
650
+ while (!result.done) {
651
+ processYield(result.value, state, multi);
652
+ await new Promise((resolve) => setTimeout(resolve, 0));
653
+ result = gen.next();
654
+ }
655
+ if (state.currentHandle && state.currentLabel) {
656
+ const elapsed = Date.now() - state.subStepStartTime;
657
+ state.currentHandle.complete(elapsed);
658
+ }
659
+ const totalElapsed = Date.now() - state.startTime;
660
+ parentHandle.complete(totalElapsed);
661
+ return result.value;
662
+ }
663
+ function isAsyncGenerator(value) {
664
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.asyncIterator] === "function";
665
+ }
666
+ function isSyncGenerator(value) {
667
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.iterator] === "function";
668
+ }
669
+ function isPromiseLike$2(value) {
670
+ return value !== null && typeof value === "object" && typeof value.then === "function";
671
+ }
672
+ //#endregion
673
+ //#region packages/ag-react/src/ui/progress/task.ts
674
+ /** Phase labels for common operations */
675
+ const PHASE_LABELS$1 = {
676
+ reading: "Reading events",
677
+ applying: "Applying events",
678
+ rules: "Evaluating rules",
679
+ scanning: "Scanning files",
680
+ reconciling: "Reconciling changes",
681
+ board: "Building view"
682
+ };
683
+ /**
684
+ * Create a task wrapper with spinner
685
+ *
686
+ * @param title - Display title for the task
687
+ * @returns TaskWrapper with wrap() method
688
+ */
689
+ function task(title) {
690
+ return { async wrap(work) {
691
+ const spinner = createSpinner();
692
+ spinner(title);
693
+ try {
694
+ if (typeof work === "function") {
695
+ const result = work();
696
+ if (isGenerator$1(result)) return await runGenerator$1(result, spinner, title);
697
+ if (isPromiseLike$1(result)) {
698
+ const value = await result;
699
+ spinner.succeed(title);
700
+ return value;
701
+ }
702
+ spinner.succeed(title);
703
+ return result;
704
+ }
705
+ if (isPromiseLike$1(work)) {
706
+ const value = await work;
707
+ spinner.succeed(title);
708
+ return value;
709
+ }
710
+ spinner.succeed(title);
711
+ return work;
712
+ } catch (error) {
713
+ spinner.fail(title);
714
+ throw error;
715
+ }
716
+ } };
717
+ }
718
+ /**
719
+ * Run a generator with progress updates
720
+ */
721
+ async function runGenerator$1(gen, spinner, baseTitle) {
722
+ let result = gen.next();
723
+ while (!result.done) {
724
+ const info = result.value;
725
+ const phase = info.phase ?? "";
726
+ const phaseLabel = PHASE_LABELS$1[phase] ?? (phase || baseTitle);
727
+ if (info.total && info.total > 0) spinner(`${phaseLabel} (${info.current}/${info.total})`);
728
+ else spinner(phaseLabel);
729
+ await new Promise((resolve) => setImmediate(resolve));
730
+ result = gen.next();
731
+ }
732
+ spinner.succeed(baseTitle);
733
+ return result.value;
734
+ }
735
+ function isGenerator$1(value) {
736
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value.throw === "function";
737
+ }
738
+ function isPromiseLike$1(value) {
739
+ return value !== null && typeof value === "object" && typeof value.then === "function";
740
+ }
741
+ //#endregion
742
+ //#region packages/ag-react/src/ui/progress/tasks.ts
743
+ /** Phase labels for common operations */
744
+ const PHASE_LABELS = {
745
+ discover: "Discovering files",
746
+ parse: "Parsing markdown",
747
+ apply: "Applying changes",
748
+ resolve: "Resolving links",
749
+ materialize: "Evaluating rules",
750
+ board: "Building view",
751
+ reading: "Reading events",
752
+ applying: "Applying events",
753
+ rules: "Evaluating rules",
754
+ scanning: "Scanning files",
755
+ reconciling: "Reconciling changes"
756
+ };
757
+ /**
758
+ * Create a sequential task builder
759
+ *
760
+ * @returns TaskBuilder with add() and run() methods
761
+ */
762
+ function tasks() {
763
+ const taskList = [];
764
+ const builder = {
765
+ add(title, work) {
766
+ taskList.push({
767
+ title,
768
+ work
769
+ });
770
+ return builder;
771
+ },
772
+ async run(options) {
773
+ const multi = new MultiProgress();
774
+ const handles = /* @__PURE__ */ new Map();
775
+ const results = {};
776
+ for (const task of taskList) handles.set(task.title, multi.add(task.title, { type: "spinner" }));
777
+ multi.start();
778
+ try {
779
+ for (const task of taskList) {
780
+ const handle = handles.get(task.title);
781
+ await new Promise((resolve) => setImmediate(resolve));
782
+ const result = task.work();
783
+ if (isGenerator(result)) results[task.title] = await runGenerator(result, handle, task.title, multi);
784
+ else if (isPromiseLike(result)) {
785
+ handle.start();
786
+ results[task.title] = await result;
787
+ handle.complete();
788
+ } else {
789
+ handle.start();
790
+ results[task.title] = result;
791
+ handle.complete();
792
+ }
793
+ }
794
+ } finally {
795
+ multi.stop(options?.clear ?? false);
796
+ }
797
+ return results;
798
+ }
799
+ };
800
+ return builder;
801
+ }
802
+ /**
803
+ * Run a generator task with progress updates
804
+ * Parent task stays visible while sub-phases are indented below
805
+ */
806
+ async function runGenerator(gen, parentHandle, baseTitle, multi) {
807
+ let result = gen.next();
808
+ let currentPhase;
809
+ let currentPhaseHandle = null;
810
+ let lastInsertId = parentHandle.id;
811
+ let phaseStartTime = Date.now();
812
+ const taskStartTime = Date.now();
813
+ while (!result.done) {
814
+ const info = result.value;
815
+ const phase = info.phase ?? "";
816
+ if (phase && phase !== currentPhase) {
817
+ if (currentPhaseHandle && currentPhase) {
818
+ const elapsed = Date.now() - phaseStartTime;
819
+ const prevLabel = PHASE_LABELS[currentPhase] ?? currentPhase;
820
+ currentPhaseHandle.complete(`${prevLabel} (${elapsed}ms)`);
821
+ }
822
+ currentPhase = phase;
823
+ phaseStartTime = Date.now();
824
+ const phaseLabel = PHASE_LABELS[phase] ?? phase;
825
+ currentPhaseHandle = multi.add(phaseLabel, {
826
+ type: "spinner",
827
+ indent: 1,
828
+ insertAfter: lastInsertId
829
+ });
830
+ lastInsertId = currentPhaseHandle.id;
831
+ currentPhaseHandle.start();
832
+ }
833
+ if (currentPhaseHandle && info.total && info.total > 0) {
834
+ const phaseLabel = PHASE_LABELS[phase] ?? phase;
835
+ currentPhaseHandle.setTitle(`${phaseLabel} (${info.current}/${info.total})`);
836
+ }
837
+ await new Promise((resolve) => setTimeout(resolve, 0));
838
+ result = gen.next();
839
+ }
840
+ if (currentPhaseHandle && currentPhase) {
841
+ const elapsed = Date.now() - phaseStartTime;
842
+ const finalLabel = PHASE_LABELS[currentPhase] ?? currentPhase;
843
+ currentPhaseHandle.complete(`${finalLabel} (${elapsed}ms)`);
844
+ }
845
+ const totalElapsed = Date.now() - taskStartTime;
846
+ parentHandle.complete(`${baseTitle} (${totalElapsed}ms)`);
847
+ return result.value;
848
+ }
849
+ function isGenerator(value) {
850
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value.throw === "function";
851
+ }
852
+ function isPromiseLike(value) {
853
+ return value !== null && typeof value === "object" && typeof value.then === "function";
854
+ }
855
+ //#endregion
856
+ export { MultiProgress, ProgressBar, Spinner, createSpinner, step, steps, task, tasks };
857
+
858
+ //# sourceMappingURL=progress.mjs.map