@zr-ovo/devforge 0.1.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 (77) hide show
  1. package/dist/ai/analyze.d.ts +25 -0
  2. package/dist/ai/analyze.d.ts.map +1 -0
  3. package/dist/ai/analyze.js +198 -0
  4. package/dist/ai/analyze.js.map +1 -0
  5. package/dist/commands/config.d.ts +6 -0
  6. package/dist/commands/config.d.ts.map +1 -0
  7. package/dist/commands/config.js +246 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/create.d.ts +2 -0
  10. package/dist/commands/create.d.ts.map +1 -0
  11. package/dist/commands/create.js +397 -0
  12. package/dist/commands/create.js.map +1 -0
  13. package/dist/commands/install.d.ts +2 -0
  14. package/dist/commands/install.d.ts.map +1 -0
  15. package/dist/commands/install.js +127 -0
  16. package/dist/commands/install.js.map +1 -0
  17. package/dist/commands/search.d.ts +2 -0
  18. package/dist/commands/search.d.ts.map +1 -0
  19. package/dist/commands/search.js +137 -0
  20. package/dist/commands/search.js.map +1 -0
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +87 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/ui/badge.d.ts +15 -0
  26. package/dist/ui/badge.d.ts.map +1 -0
  27. package/dist/ui/badge.js +35 -0
  28. package/dist/ui/badge.js.map +1 -0
  29. package/dist/ui/box.d.ts +33 -0
  30. package/dist/ui/box.d.ts.map +1 -0
  31. package/dist/ui/box.js +76 -0
  32. package/dist/ui/box.js.map +1 -0
  33. package/dist/ui/card.d.ts +39 -0
  34. package/dist/ui/card.d.ts.map +1 -0
  35. package/dist/ui/card.js +81 -0
  36. package/dist/ui/card.js.map +1 -0
  37. package/dist/ui/divider.d.ts +32 -0
  38. package/dist/ui/divider.d.ts.map +1 -0
  39. package/dist/ui/divider.js +53 -0
  40. package/dist/ui/divider.js.map +1 -0
  41. package/dist/ui/format.d.ts +28 -0
  42. package/dist/ui/format.d.ts.map +1 -0
  43. package/dist/ui/format.js +93 -0
  44. package/dist/ui/format.js.map +1 -0
  45. package/dist/ui/index.d.ts +11 -0
  46. package/dist/ui/index.d.ts.map +1 -0
  47. package/dist/ui/index.js +27 -0
  48. package/dist/ui/index.js.map +1 -0
  49. package/dist/ui/progress.d.ts +47 -0
  50. package/dist/ui/progress.d.ts.map +1 -0
  51. package/dist/ui/progress.js +114 -0
  52. package/dist/ui/progress.js.map +1 -0
  53. package/dist/ui/screen.d.ts +37 -0
  54. package/dist/ui/screen.d.ts.map +1 -0
  55. package/dist/ui/screen.js +79 -0
  56. package/dist/ui/screen.js.map +1 -0
  57. package/dist/ui/spinner.d.ts +22 -0
  58. package/dist/ui/spinner.d.ts.map +1 -0
  59. package/dist/ui/spinner.js +78 -0
  60. package/dist/ui/spinner.js.map +1 -0
  61. package/dist/ui/status.d.ts +10 -0
  62. package/dist/ui/status.d.ts.map +1 -0
  63. package/dist/ui/status.js +40 -0
  64. package/dist/ui/status.js.map +1 -0
  65. package/dist/ui/theme.d.ts +33 -0
  66. package/dist/ui/theme.d.ts.map +1 -0
  67. package/dist/ui/theme.js +89 -0
  68. package/dist/ui/theme.js.map +1 -0
  69. package/dist/utils/art.d.ts +2 -0
  70. package/dist/utils/art.d.ts.map +1 -0
  71. package/dist/utils/art.js +27 -0
  72. package/dist/utils/art.js.map +1 -0
  73. package/dist/utils/installer.d.ts +35 -0
  74. package/dist/utils/installer.d.ts.map +1 -0
  75. package/dist/utils/installer.js +125 -0
  76. package/dist/utils/installer.js.map +1 -0
  77. package/package.json +31 -0
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderDivider = renderDivider;
4
+ exports.renderSection = renderSection;
5
+ exports.renderSubSection = renderSubSection;
6
+ const theme_1 = require("./theme");
7
+ const DEFAULT_WIDTH = 72;
8
+ /**
9
+ * Render a horizontal divider line.
10
+ * ```
11
+ * ──────────────────────────────────────────────────────
12
+ * ```
13
+ */
14
+ function renderDivider(opts = {}) {
15
+ const char = opts.char || '─';
16
+ const width = opts.width ?? DEFAULT_WIDTH;
17
+ const color = opts.color || theme_1.BORDER;
18
+ return `${color}${char.repeat(width)}${theme_1.RESET}`;
19
+ }
20
+ /**
21
+ * Render a section header with title on the left.
22
+ * ```
23
+ * ━━━ AI 分析 ——————————————————————————————————————
24
+ * ```
25
+ */
26
+ function renderSection(title, opts = {}) {
27
+ const char = opts.char || '━';
28
+ const width = opts.width ?? DEFAULT_WIDTH;
29
+ const color = opts.color || theme_1.PRIMARY;
30
+ const titleColor = opts.titleColor || theme_1.PRIMARY;
31
+ const label = `${titleColor}${theme_1.BOLD}${title}${theme_1.RESET} ${color}`;
32
+ const labelWidth = (0, theme_1.visibleWidth)(title) + 1; // title + space
33
+ const remaining = Math.max(0, width - labelWidth);
34
+ const line = `${char.repeat(remaining)}`;
35
+ return `${label}${line}${theme_1.RESET}`;
36
+ }
37
+ /**
38
+ * Render a dimmed sub-section.
39
+ * ```
40
+ * ── 已安装 Skill ────────────────────────────────
41
+ * ```
42
+ */
43
+ function renderSubSection(title, opts = {}) {
44
+ const char = opts.char || '─';
45
+ const width = opts.width ?? DEFAULT_WIDTH;
46
+ const color = opts.color || theme_1.TEXT_MUTED;
47
+ const label = `${color}${title}${theme_1.RESET} ${color}`;
48
+ const labelWidth = (0, theme_1.visibleWidth)(title) + 1;
49
+ const remaining = Math.max(0, width - labelWidth);
50
+ const line = `${char.repeat(remaining)}`;
51
+ return `${label}${line}${theme_1.RESET}`;
52
+ }
53
+ //# sourceMappingURL=divider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"divider.js","sourceRoot":"","sources":["../../src/ui/divider.ts"],"names":[],"mappings":";;AAgBA,sCAKC;AAaD,sCAWC;AAQD,4CAUC;AA/DD,mCAAgF;AAEhF,MAAM,aAAa,GAAG,EAAE,CAAA;AAQxB;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,OAAuB,EAAE;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,CAAA;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,cAAM,CAAA;IAClC,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,aAAK,EAAE,CAAA;AAChD,CAAC;AAOD;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,KAAa,EAAE,OAAuB,EAAE;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,CAAA;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,eAAO,CAAA;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,eAAO,CAAA;IAE7C,MAAM,KAAK,GAAG,GAAG,UAAU,GAAG,YAAI,GAAG,KAAK,GAAG,aAAK,IAAI,KAAK,EAAE,CAAA;IAC7D,MAAM,UAAU,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,GAAG,CAAC,CAAA,CAAC,gBAAgB;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,CAAA;IACjD,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAA;IACxC,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,aAAK,EAAE,CAAA;AAClC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,KAAa,EAAE,OAAuB,EAAE;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,CAAA;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,kBAAU,CAAA;IAEtC,MAAM,KAAK,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,aAAK,IAAI,KAAK,EAAE,CAAA;IACjD,MAAM,UAAU,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,CAAA;IACjD,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAA;IACxC,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,aAAK,EAAE,CAAA;AAClC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Truncate text to maxWidth, adding "…" if truncated.
3
+ * Strips ANSI codes for width calculation.
4
+ */
5
+ export declare function truncate(text: string, maxWidth: number): string;
6
+ /** Left-pad text to target width */
7
+ export declare function pad(text: string, width: number, char?: string): string;
8
+ /** Right-pad text to target width */
9
+ export declare function padEnd(text: string, width: number, char?: string): string;
10
+ /**
11
+ * Word-wrap text to specified width.
12
+ * Respects ANSI codes (passes them through).
13
+ */
14
+ export declare function wrap(text: string, width: number, indent?: number): string[];
15
+ /** Format star count: 1234 → "1,234" */
16
+ export declare function formatStars(count: number): string;
17
+ /** Render a horizontal line of `char`, `width` columns */
18
+ export declare function hr(char?: string, width?: number): string;
19
+ /** Render a horizontal line with dim style */
20
+ export declare function hrDim(char?: string, width?: number): string;
21
+ /**
22
+ * Align text into two columns.
23
+ * Left is left-justified, right is right-justified within total width.
24
+ */
25
+ export declare function alignColumns(left: string, right: string, totalWidth?: number): string;
26
+ /** Repeat a string to fill width */
27
+ export declare function fill(text: string, width: number): string;
28
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED,oCAAoC;AACpC,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,MAAM,CAGnE;AAED,qCAAqC;AACrC,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,MAAM,CAGtE;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,MAAM,EAAE,CAqBtE;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,0DAA0D;AAC1D,wBAAgB,EAAE,CAAC,IAAI,SAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAEjD;AAED,8CAA8C;AAC9C,wBAAgB,KAAK,CAAC,IAAI,SAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG,MAAM,CAWjF;AAED,oCAAoC;AACpC,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.truncate = truncate;
4
+ exports.pad = pad;
5
+ exports.padEnd = padEnd;
6
+ exports.wrap = wrap;
7
+ exports.formatStars = formatStars;
8
+ exports.hr = hr;
9
+ exports.hrDim = hrDim;
10
+ exports.alignColumns = alignColumns;
11
+ exports.fill = fill;
12
+ const theme_1 = require("./theme");
13
+ /**
14
+ * Truncate text to maxWidth, adding "…" if truncated.
15
+ * Strips ANSI codes for width calculation.
16
+ */
17
+ function truncate(text, maxWidth) {
18
+ const clean = (0, theme_1.visibleWidth)(text);
19
+ if (clean <= maxWidth)
20
+ return text;
21
+ // Simple truncation approach — approximate by string length ratio
22
+ const ratio = maxWidth / Math.max(clean, 1);
23
+ const cut = Math.floor(text.length * ratio);
24
+ return text.slice(0, Math.max(cut - 1, 0)) + '…';
25
+ }
26
+ /** Left-pad text to target width */
27
+ function pad(text, width, char = ' ') {
28
+ const vw = (0, theme_1.visibleWidth)(text);
29
+ return vw >= width ? text : char.repeat(width - vw) + text;
30
+ }
31
+ /** Right-pad text to target width */
32
+ function padEnd(text, width, char = ' ') {
33
+ const vw = (0, theme_1.visibleWidth)(text);
34
+ return vw >= width ? text : text + char.repeat(width - vw);
35
+ }
36
+ /**
37
+ * Word-wrap text to specified width.
38
+ * Respects ANSI codes (passes them through).
39
+ */
40
+ function wrap(text, width, indent = 0) {
41
+ const indentStr = ' '.repeat(indent);
42
+ const words = text.split(/(\s+)/);
43
+ const lines = [];
44
+ let current = indentStr;
45
+ let currentWidth = indent;
46
+ for (const word of words) {
47
+ const wordWidth = (0, theme_1.visibleWidth)(word);
48
+ if (currentWidth + wordWidth > width && currentWidth > indent) {
49
+ lines.push(current);
50
+ current = indentStr;
51
+ currentWidth = indent;
52
+ }
53
+ current += word;
54
+ currentWidth += wordWidth;
55
+ }
56
+ if (currentWidth > indent) {
57
+ lines.push(current);
58
+ }
59
+ return lines.length > 0 ? lines : [indentStr];
60
+ }
61
+ /** Format star count: 1234 → "1,234" */
62
+ function formatStars(count) {
63
+ return count.toLocaleString('en-US');
64
+ }
65
+ /** Render a horizontal line of `char`, `width` columns */
66
+ function hr(char = '─', width = 72) {
67
+ return theme_1.BORDER + char.repeat(width) + theme_1.RESET;
68
+ }
69
+ /** Render a horizontal line with dim style */
70
+ function hrDim(char = '─', width = 72) {
71
+ return theme_1.DIM + char.repeat(width) + theme_1.RESET;
72
+ }
73
+ /**
74
+ * Align text into two columns.
75
+ * Left is left-justified, right is right-justified within total width.
76
+ */
77
+ function alignColumns(left, right, totalWidth = 72) {
78
+ const lw = (0, theme_1.visibleWidth)(left);
79
+ const rw = (0, theme_1.visibleWidth)(right);
80
+ const gap = Math.max(1, totalWidth - lw - rw);
81
+ const spacer = ' '.repeat(gap < 0 ? 1 : gap);
82
+ // If too wide, truncate left side
83
+ if (lw + gap + rw > totalWidth) {
84
+ const available = totalWidth - rw - 1;
85
+ return truncate(left, available) + spacer + right;
86
+ }
87
+ return left + spacer + right;
88
+ }
89
+ /** Repeat a string to fill width */
90
+ function fill(text, width) {
91
+ return text.repeat(Math.ceil(width / (0, theme_1.visibleWidth)(text))).slice(0, width);
92
+ }
93
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export * from './theme';
2
+ export * from './format';
3
+ export * from './status';
4
+ export * from './divider';
5
+ export * from './box';
6
+ export * from './badge';
7
+ export * from './card';
8
+ export * from './spinner';
9
+ export * from './screen';
10
+ export * from './progress';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./theme"), exports);
18
+ __exportStar(require("./format"), exports);
19
+ __exportStar(require("./status"), exports);
20
+ __exportStar(require("./divider"), exports);
21
+ __exportStar(require("./box"), exports);
22
+ __exportStar(require("./badge"), exports);
23
+ __exportStar(require("./card"), exports);
24
+ __exportStar(require("./spinner"), exports);
25
+ __exportStar(require("./screen"), exports);
26
+ __exportStar(require("./progress"), exports);
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB;AACvB,2CAAwB;AACxB,2CAAwB;AACxB,4CAAyB;AACzB,wCAAqB;AACrB,0CAAuB;AACvB,yCAAsB;AACtB,4CAAyB;AACzB,2CAAwB;AACxB,6CAA0B"}
@@ -0,0 +1,47 @@
1
+ /** Phase definition for PhaseTracker */
2
+ export interface Phase {
3
+ name: string;
4
+ status: 'pending' | 'active' | 'completed' | 'failed';
5
+ }
6
+ export interface SubTask {
7
+ name: string;
8
+ status: 'pending' | 'active' | 'completed' | 'failed';
9
+ detail?: string;
10
+ }
11
+ /**
12
+ * PhaseTracker — manages multi-phase display with sub-tasks.
13
+ *
14
+ * Renders a region like:
15
+ * ```
16
+ * 阶段 1/4: 创建项目目录 ✓ 完成
17
+ * 阶段 2/4: 下载 Skill ◌ 进行中
18
+ * └─ ✓ mcp-server-patterns (0.8s)
19
+ * └─ ◌ testing-standards 下载中...
20
+ * ```
21
+ */
22
+ export declare class PhaseTracker {
23
+ private phases;
24
+ private subTasks;
25
+ private section;
26
+ private width;
27
+ constructor(width?: number);
28
+ begin(): void;
29
+ setPhases(phases: Phase[]): void;
30
+ updatePhase(index: number, status: Phase['status']): void;
31
+ addSubTask(phaseIndex: number, task: SubTask): void;
32
+ updateSubTask(phaseIndex: number, taskIndex: number, status: SubTask['status'], detail?: string): void;
33
+ complete(): void;
34
+ private render;
35
+ private statusIcon;
36
+ private statusText;
37
+ get lineCount(): number;
38
+ }
39
+ /**
40
+ * Render a progress bar.
41
+ *
42
+ * ```
43
+ * [████████████████░░░░░░░░░░] 57%
44
+ * ```
45
+ */
46
+ export declare function renderProgressBar(percent: number, width?: number): string;
47
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/ui/progress.ts"],"names":[],"mappings":"AAKA,wCAAwC;AACxC,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAA;CACtD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAA;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,KAAK,CAAQ;gBAET,KAAK,SAAK;IAKtB,KAAK,IAAI,IAAI;IAKb,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IAKhC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI;IAOzD,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAOnD,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAWtG,QAAQ,IAAI,IAAI;IAIhB,OAAO,CAAC,MAAM;IAsBd,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,UAAU;IASlB,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAMrE"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PhaseTracker = void 0;
4
+ exports.renderProgressBar = renderProgressBar;
5
+ const theme_1 = require("./theme");
6
+ const screen_1 = require("./screen");
7
+ /**
8
+ * PhaseTracker — manages multi-phase display with sub-tasks.
9
+ *
10
+ * Renders a region like:
11
+ * ```
12
+ * 阶段 1/4: 创建项目目录 ✓ 完成
13
+ * 阶段 2/4: 下载 Skill ◌ 进行中
14
+ * └─ ✓ mcp-server-patterns (0.8s)
15
+ * └─ ◌ testing-standards 下载中...
16
+ * ```
17
+ */
18
+ class PhaseTracker {
19
+ phases = [];
20
+ subTasks = [];
21
+ section;
22
+ width;
23
+ constructor(width = 72) {
24
+ this.section = new screen_1.DynamicSection();
25
+ this.width = width;
26
+ }
27
+ begin() {
28
+ this.section.begin();
29
+ this.render();
30
+ }
31
+ setPhases(phases) {
32
+ this.phases = phases;
33
+ this.subTasks = phases.map(() => []);
34
+ }
35
+ updatePhase(index, status) {
36
+ if (index >= 0 && index < this.phases.length) {
37
+ this.phases[index].status = status;
38
+ this.render();
39
+ }
40
+ }
41
+ addSubTask(phaseIndex, task) {
42
+ if (phaseIndex >= 0 && phaseIndex < this.subTasks.length) {
43
+ this.subTasks[phaseIndex].push(task);
44
+ this.render();
45
+ }
46
+ }
47
+ updateSubTask(phaseIndex, taskIndex, status, detail) {
48
+ if (phaseIndex >= 0 && phaseIndex < this.subTasks.length) {
49
+ const tasks = this.subTasks[phaseIndex];
50
+ if (taskIndex >= 0 && taskIndex < tasks.length) {
51
+ tasks[taskIndex].status = status;
52
+ if (detail !== undefined)
53
+ tasks[taskIndex].detail = detail;
54
+ this.render();
55
+ }
56
+ }
57
+ }
58
+ complete() {
59
+ this.section.end();
60
+ }
61
+ render() {
62
+ const lines = [];
63
+ for (let p = 0; p < this.phases.length; p++) {
64
+ const phase = this.phases[p];
65
+ const icon = this.statusIcon(phase.status);
66
+ const statusText = this.statusText(phase.status);
67
+ const line = ` ${icon} ${phase.name} ${theme_1.DIM}${statusText}${theme_1.RESET}`;
68
+ lines.push(line);
69
+ // Sub-tasks
70
+ const tasks = this.subTasks[p] || [];
71
+ for (const task of tasks) {
72
+ const taskIcon = this.statusIcon(task.status);
73
+ const detail = task.detail ? ` ${theme_1.DIM}${task.detail}${theme_1.RESET}` : '';
74
+ lines.push(` └─ ${taskIcon} ${task.name}${detail}`);
75
+ }
76
+ }
77
+ this.section.update(lines);
78
+ }
79
+ statusIcon(status) {
80
+ switch (status) {
81
+ case 'completed': return `${theme_1.SUCCESS}✓${theme_1.RESET}`;
82
+ case 'active': return `${theme_1.PRIMARY}◌${theme_1.RESET}`;
83
+ case 'failed': return `${theme_1.ERROR}✗${theme_1.RESET}`;
84
+ default: return `${theme_1.TEXT_MUTED}⏳${theme_1.RESET}`;
85
+ }
86
+ }
87
+ statusText(status) {
88
+ switch (status) {
89
+ case 'completed': return '完成';
90
+ case 'active': return '进行中';
91
+ case 'failed': return '失败';
92
+ default: return '等待';
93
+ }
94
+ }
95
+ get lineCount() {
96
+ return this.section.lines;
97
+ }
98
+ }
99
+ exports.PhaseTracker = PhaseTracker;
100
+ /**
101
+ * Render a progress bar.
102
+ *
103
+ * ```
104
+ * [████████████████░░░░░░░░░░] 57%
105
+ * ```
106
+ */
107
+ function renderProgressBar(percent, width = 40) {
108
+ const p = Math.max(0, Math.min(100, percent));
109
+ const filled = Math.round((p / 100) * width);
110
+ const empty = width - filled;
111
+ const bar = `${theme_1.PRIMARY}${'█'.repeat(filled)}${theme_1.RESET}${theme_1.DIM}${'░'.repeat(empty)}${theme_1.RESET}`;
112
+ return ` ${bar} ${theme_1.BOLD}${p}%${theme_1.RESET}`;
113
+ }
114
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/ui/progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * DynamicSection — manages a region of the terminal that can be
3
+ * re-rendered dynamically with varying line counts.
4
+ *
5
+ * Uses cursor-up (\x1b[A) and clear-line (\x1b[K) sequences.
6
+ *
7
+ * Usage:
8
+ * const section = new DynamicSection()
9
+ * section.begin() // mark start position
10
+ * section.update(['a', 'b']) // render 2 lines
11
+ * section.update(['1', '2', '3']) // render 3 lines (adds 1)
12
+ * section.update(['x']) // render 1 line (clears 2)
13
+ * section.end() // move cursor past tracked area
14
+ */
15
+ export declare class DynamicSection {
16
+ private lineCount;
17
+ private started;
18
+ /**
19
+ * Begin tracking. Records current cursor position.
20
+ * Call this BEFORE writing anything.
21
+ */
22
+ begin(): void;
23
+ /**
24
+ * Replace the content of the tracked region with new lines.
25
+ * Handles size changes: adds lines if longer, clears if shorter.
26
+ */
27
+ update(lines: string[]): void;
28
+ /**
29
+ * End tracking. Positions cursor after the last tracked line.
30
+ */
31
+ end(): void;
32
+ /**
33
+ * Get the current number of tracked lines.
34
+ */
35
+ get lines(): number;
36
+ }
37
+ //# sourceMappingURL=screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/ui/screen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,OAAO,CAAQ;IAEvB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAKb;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IA+B7B;;OAEG;IACH,GAAG,IAAI,IAAI;IASX;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;CACF"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynamicSection = void 0;
4
+ /**
5
+ * DynamicSection — manages a region of the terminal that can be
6
+ * re-rendered dynamically with varying line counts.
7
+ *
8
+ * Uses cursor-up (\x1b[A) and clear-line (\x1b[K) sequences.
9
+ *
10
+ * Usage:
11
+ * const section = new DynamicSection()
12
+ * section.begin() // mark start position
13
+ * section.update(['a', 'b']) // render 2 lines
14
+ * section.update(['1', '2', '3']) // render 3 lines (adds 1)
15
+ * section.update(['x']) // render 1 line (clears 2)
16
+ * section.end() // move cursor past tracked area
17
+ */
18
+ class DynamicSection {
19
+ lineCount = 0;
20
+ started = false;
21
+ /**
22
+ * Begin tracking. Records current cursor position.
23
+ * Call this BEFORE writing anything.
24
+ */
25
+ begin() {
26
+ this.started = true;
27
+ this.lineCount = 0;
28
+ }
29
+ /**
30
+ * Replace the content of the tracked region with new lines.
31
+ * Handles size changes: adds lines if longer, clears if shorter.
32
+ */
33
+ update(lines) {
34
+ if (!this.started)
35
+ return;
36
+ const prevCount = this.lineCount;
37
+ if (prevCount > 0) {
38
+ // Move cursor up to the start of the tracked region
39
+ process.stdout.write(`\x1b[${prevCount}A`);
40
+ }
41
+ // Write new lines
42
+ for (let i = 0; i < lines.length; i++) {
43
+ if (i > 0) {
44
+ process.stdout.write('\n');
45
+ }
46
+ process.stdout.write(lines[i] + '\x1b[K');
47
+ }
48
+ // If previous output was longer, clear remaining lines
49
+ if (lines.length < prevCount) {
50
+ const extra = prevCount - lines.length;
51
+ for (let i = 0; i < extra; i++) {
52
+ process.stdout.write('\n\x1b[K');
53
+ }
54
+ // Move back up to the last content line
55
+ process.stdout.write(`\x1b[${extra}A`);
56
+ }
57
+ this.lineCount = lines.length;
58
+ }
59
+ /**
60
+ * End tracking. Positions cursor after the last tracked line.
61
+ */
62
+ end() {
63
+ if (!this.started)
64
+ return;
65
+ if (this.lineCount > 0) {
66
+ process.stdout.write('\n');
67
+ }
68
+ this.started = false;
69
+ this.lineCount = 0;
70
+ }
71
+ /**
72
+ * Get the current number of tracked lines.
73
+ */
74
+ get lines() {
75
+ return this.lineCount;
76
+ }
77
+ }
78
+ exports.DynamicSection = DynamicSection;
79
+ //# sourceMappingURL=screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/ui/screen.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;GAaG;AACH,MAAa,cAAc;IACjB,SAAS,GAAG,CAAC,CAAA;IACb,OAAO,GAAG,KAAK,CAAA;IAEvB;;;OAGG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;IACpB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAe;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAA;QAEhC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,oDAAoD;YACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,SAAS,GAAG,CAAC,CAAA;QAC5C,CAAC;QAED,kBAAkB;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC5B,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAA;QAC3C,CAAC;QAED,uDAAuD;QACvD,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,CAAA;YACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YAClC,CAAC;YACD,wCAAwC;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAA;QACxC,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAA;IAC/B,CAAC;IAED;;OAEG;IACH,GAAG;QACD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;IACpB,CAAC;IAED;;OAEG;IACH,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;CACF;AAlED,wCAkEC"}
@@ -0,0 +1,22 @@
1
+ export declare class Spinner {
2
+ private frames;
3
+ private interval;
4
+ private color;
5
+ private frameIndex;
6
+ private timer;
7
+ private message;
8
+ private running;
9
+ constructor(message: string, opts?: {
10
+ frames?: string[];
11
+ interval?: number;
12
+ color?: string;
13
+ });
14
+ start(message?: string): void;
15
+ setMessage(msg: string): void;
16
+ stop(finalMessage?: string): void;
17
+ succeed(message?: string): void;
18
+ fail(message?: string): void;
19
+ private render;
20
+ private clear;
21
+ }
22
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAKA,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAQ;gBAEX,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAO5F,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAY7B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAYjC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAU/B,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAU5B,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,KAAK;CAId"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Spinner = void 0;
4
+ const theme_1 = require("./theme");
5
+ const BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
6
+ const FRAME_INTERVAL = 80; // ms
7
+ class Spinner {
8
+ frames;
9
+ interval;
10
+ color;
11
+ frameIndex = 0;
12
+ timer = null;
13
+ message;
14
+ running = false;
15
+ constructor(message, opts) {
16
+ this.message = message;
17
+ this.frames = opts?.frames || BRAILLE_FRAMES;
18
+ this.interval = opts?.interval || FRAME_INTERVAL;
19
+ this.color = opts?.color || theme_1.PRIMARY;
20
+ }
21
+ start(message) {
22
+ if (message !== undefined)
23
+ this.message = message;
24
+ if (this.running)
25
+ return;
26
+ this.running = true;
27
+ this.frameIndex = 0;
28
+ this.render();
29
+ this.timer = setInterval(() => {
30
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length;
31
+ this.render();
32
+ }, this.interval);
33
+ }
34
+ setMessage(msg) {
35
+ this.message = msg;
36
+ if (this.running)
37
+ this.render();
38
+ }
39
+ stop(finalMessage) {
40
+ this.clear();
41
+ if (this.timer) {
42
+ clearInterval(this.timer);
43
+ this.timer = null;
44
+ }
45
+ this.running = false;
46
+ if (finalMessage) {
47
+ console.log(` ${finalMessage}`);
48
+ }
49
+ }
50
+ succeed(message) {
51
+ this.clear();
52
+ if (this.timer) {
53
+ clearInterval(this.timer);
54
+ this.timer = null;
55
+ }
56
+ this.running = false;
57
+ console.log(` ${theme_1.SUCCESS}✓${theme_1.RESET} ${message || this.message}`);
58
+ }
59
+ fail(message) {
60
+ this.clear();
61
+ if (this.timer) {
62
+ clearInterval(this.timer);
63
+ this.timer = null;
64
+ }
65
+ this.running = false;
66
+ console.log(` ${theme_1.ERROR}✗${theme_1.RESET} ${message || this.message}`);
67
+ }
68
+ render() {
69
+ const frame = this.frames[this.frameIndex];
70
+ process.stdout.write(`\r ${this.color}${frame}${theme_1.RESET} ${this.message}\x1b[K`);
71
+ }
72
+ clear() {
73
+ // Clear the spinner line
74
+ process.stdout.write('\r\x1b[K');
75
+ }
76
+ }
77
+ exports.Spinner = Spinner;
78
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"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"}