myshell-tools 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +44 -69
  2. package/LICENSE +21 -21
  3. package/README.md +178 -318
  4. package/dist/cli.d.ts +8 -0
  5. package/dist/cli.js +130 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/cost.d.ts +36 -0
  8. package/dist/commands/cost.js +103 -0
  9. package/dist/commands/cost.js.map +1 -0
  10. package/dist/commands/doctor.d.ts +36 -0
  11. package/dist/commands/doctor.js +115 -0
  12. package/dist/commands/doctor.js.map +1 -0
  13. package/dist/commands/login.d.ts +20 -0
  14. package/dist/commands/login.js +60 -0
  15. package/dist/commands/login.js.map +1 -0
  16. package/dist/core/assess.d.ts +25 -0
  17. package/dist/core/assess.js +142 -0
  18. package/dist/core/assess.js.map +1 -0
  19. package/dist/core/classify.d.ts +19 -0
  20. package/dist/core/classify.js +80 -0
  21. package/dist/core/classify.js.map +1 -0
  22. package/dist/core/escalate.d.ts +32 -0
  23. package/dist/core/escalate.js +57 -0
  24. package/dist/core/escalate.js.map +1 -0
  25. package/dist/core/index.d.ts +13 -0
  26. package/dist/core/index.js +12 -0
  27. package/dist/core/index.js.map +1 -0
  28. package/dist/core/orchestrate.d.ts +42 -0
  29. package/dist/core/orchestrate.js +439 -0
  30. package/dist/core/orchestrate.js.map +1 -0
  31. package/dist/core/policy.d.ts +9 -0
  32. package/dist/core/policy.js +27 -0
  33. package/dist/core/policy.js.map +1 -0
  34. package/dist/core/prompt.d.ts +26 -0
  35. package/dist/core/prompt.js +125 -0
  36. package/dist/core/prompt.js.map +1 -0
  37. package/dist/core/review.d.ts +46 -0
  38. package/dist/core/review.js +148 -0
  39. package/dist/core/review.js.map +1 -0
  40. package/dist/core/route.d.ts +28 -0
  41. package/dist/core/route.js +52 -0
  42. package/dist/core/route.js.map +1 -0
  43. package/dist/core/types.d.ts +141 -0
  44. package/dist/core/types.js +14 -0
  45. package/dist/core/types.js.map +1 -0
  46. package/dist/infra/atomic.d.ts +53 -0
  47. package/dist/infra/atomic.js +171 -0
  48. package/dist/infra/atomic.js.map +1 -0
  49. package/dist/infra/clock.d.ts +9 -0
  50. package/dist/infra/clock.js +15 -0
  51. package/dist/infra/clock.js.map +1 -0
  52. package/dist/infra/index.d.ts +9 -0
  53. package/dist/infra/index.js +7 -0
  54. package/dist/infra/index.js.map +1 -0
  55. package/dist/infra/ledger.d.ts +49 -0
  56. package/dist/infra/ledger.js +90 -0
  57. package/dist/infra/ledger.js.map +1 -0
  58. package/dist/infra/paths.d.ts +28 -0
  59. package/dist/infra/paths.js +38 -0
  60. package/dist/infra/paths.js.map +1 -0
  61. package/dist/infra/pricing.d.ts +47 -0
  62. package/dist/infra/pricing.js +151 -0
  63. package/dist/infra/pricing.js.map +1 -0
  64. package/dist/infra/session.d.ts +28 -0
  65. package/dist/infra/session.js +61 -0
  66. package/dist/infra/session.js.map +1 -0
  67. package/dist/interface/render.d.ts +27 -0
  68. package/dist/interface/render.js +134 -0
  69. package/dist/interface/render.js.map +1 -0
  70. package/dist/interface/repl.d.ts +23 -0
  71. package/dist/interface/repl.js +90 -0
  72. package/dist/interface/repl.js.map +1 -0
  73. package/dist/interface/run.d.ts +20 -0
  74. package/dist/interface/run.js +31 -0
  75. package/dist/interface/run.js.map +1 -0
  76. package/dist/providers/claude-parse.d.ts +24 -0
  77. package/dist/providers/claude-parse.js +113 -0
  78. package/dist/providers/claude-parse.js.map +1 -0
  79. package/dist/providers/claude.d.ts +45 -0
  80. package/dist/providers/claude.js +122 -0
  81. package/dist/providers/claude.js.map +1 -0
  82. package/dist/providers/codex-parse.d.ts +32 -0
  83. package/dist/providers/codex-parse.js +145 -0
  84. package/dist/providers/codex-parse.js.map +1 -0
  85. package/dist/providers/codex.d.ts +44 -0
  86. package/dist/providers/codex.js +124 -0
  87. package/dist/providers/codex.js.map +1 -0
  88. package/dist/providers/detect.d.ts +49 -0
  89. package/dist/providers/detect.js +125 -0
  90. package/dist/providers/detect.js.map +1 -0
  91. package/dist/providers/errors.d.ts +49 -0
  92. package/dist/providers/errors.js +189 -0
  93. package/dist/providers/errors.js.map +1 -0
  94. package/dist/providers/index.d.ts +9 -0
  95. package/dist/providers/index.js +7 -0
  96. package/dist/providers/index.js.map +1 -0
  97. package/dist/providers/port.d.ts +74 -0
  98. package/dist/providers/port.js +16 -0
  99. package/dist/providers/port.js.map +1 -0
  100. package/dist/providers/registry.d.ts +21 -0
  101. package/dist/providers/registry.js +34 -0
  102. package/dist/providers/registry.js.map +1 -0
  103. package/dist/ui/banner.d.ts +19 -0
  104. package/dist/ui/banner.js +32 -0
  105. package/dist/ui/banner.js.map +1 -0
  106. package/dist/ui/spinner.d.ts +27 -0
  107. package/dist/ui/spinner.js +67 -0
  108. package/dist/ui/spinner.js.map +1 -0
  109. package/dist/ui/theme.d.ts +32 -0
  110. package/dist/ui/theme.js +56 -0
  111. package/dist/ui/theme.js.map +1 -0
  112. package/package.json +55 -49
  113. package/data/orchestrator.json +0 -113
  114. package/src/auth/recovery.mjs +0 -328
  115. package/src/auth/refresh.mjs +0 -373
  116. package/src/chef.mjs +0 -348
  117. package/src/cli/doctor.mjs +0 -568
  118. package/src/cli/reset.mjs +0 -447
  119. package/src/cli/status.mjs +0 -379
  120. package/src/cli.mjs +0 -429
  121. package/src/commands/doctor.mjs +0 -375
  122. package/src/commands/help.mjs +0 -324
  123. package/src/commands/status.mjs +0 -331
  124. package/src/monitor/health.mjs +0 -486
  125. package/src/monitor/performance.mjs +0 -442
  126. package/src/monitor/report.mjs +0 -535
  127. package/src/orchestrator/classify.mjs +0 -391
  128. package/src/orchestrator/confidence.mjs +0 -151
  129. package/src/orchestrator/handoffs.mjs +0 -231
  130. package/src/orchestrator/review.mjs +0 -222
  131. package/src/providers/balance.mjs +0 -201
  132. package/src/providers/claude.mjs +0 -236
  133. package/src/providers/codex.mjs +0 -255
  134. package/src/providers/detect.mjs +0 -185
  135. package/src/providers/errors.mjs +0 -373
  136. package/src/providers/select.mjs +0 -162
  137. package/src/repl-enhanced.mjs +0 -417
  138. package/src/repl.mjs +0 -321
  139. package/src/state/archive.mjs +0 -366
  140. package/src/state/atomic.mjs +0 -116
  141. package/src/state/cleanup.mjs +0 -440
  142. package/src/state/recovery.mjs +0 -461
  143. package/src/state/session.mjs +0 -147
  144. package/src/ui/errors.mjs +0 -456
  145. package/src/ui/formatter.mjs +0 -327
  146. package/src/ui/icons.mjs +0 -318
  147. package/src/ui/progress.mjs +0 -468
  148. package/templates/prompts/confidence-format.txt +0 -14
  149. package/templates/prompts/ic-with-feedback.txt +0 -41
  150. package/templates/prompts/ic.txt +0 -13
  151. package/templates/prompts/manager-review.txt +0 -40
  152. package/templates/prompts/manager.txt +0 -14
  153. package/templates/prompts/worker.txt +0 -12
@@ -0,0 +1,189 @@
1
+ /**
2
+ * errors.ts — Error types, classification, backoff calculation, and message
3
+ * formatting for provider CLI operations.
4
+ *
5
+ * Pure module: no child_process, no fs, no console.log. All functions return
6
+ * data; callers decide how to display or act on it.
7
+ */
8
+ /**
9
+ * Calculate how long to wait before the next retry attempt.
10
+ *
11
+ * Returns a value in milliseconds. With jitter the actual value will be within
12
+ * `[(1 - jitter) * delay, (1 + jitter) * delay]` where `delay` is the pure
13
+ * exponential value capped at `maxMs`.
14
+ *
15
+ * @param attempt - Zero-based attempt index (0 = first retry).
16
+ */
17
+ export function calculateBackoff(attempt, opts) {
18
+ const baseMs = opts?.baseMs ?? 1000;
19
+ const multiplier = opts?.multiplier ?? 2;
20
+ const maxMs = opts?.maxMs ?? 30_000;
21
+ const jitter = opts?.jitter ?? 0.15;
22
+ const exponential = Math.min(baseMs * multiplier ** attempt, maxMs);
23
+ const spread = exponential * jitter;
24
+ // Random value in [-spread, +spread]
25
+ const noise = (Math.random() * 2 - 1) * spread;
26
+ return Math.round(Math.max(0, exponential + noise));
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Internal pattern helpers
30
+ // ---------------------------------------------------------------------------
31
+ function includesAny(text, patterns) {
32
+ return patterns.some((p) => text.includes(p));
33
+ }
34
+ function isAuthStderr(lower) {
35
+ // token-related matches require a companion word to avoid false positives
36
+ const tokenExpired = lower.includes('token') && (lower.includes('expired') || lower.includes('invalid'));
37
+ return (tokenExpired ||
38
+ includesAny(lower, [
39
+ 'authentication',
40
+ 'unauthorized',
41
+ '401',
42
+ 'invalid credentials',
43
+ 'login required',
44
+ ]));
45
+ }
46
+ function isRateLimitStderr(lower) {
47
+ const quotaExceeded = lower.includes('quota') && lower.includes('exceeded');
48
+ return (quotaExceeded || includesAny(lower, ['rate limit', '429', 'too many requests']));
49
+ }
50
+ function isTimeoutStderr(lower) {
51
+ // Exclude HTTP gateway codes (502/503/504) — those are network errors even
52
+ // though '504 Gateway Timeout' contains the word 'timeout'.
53
+ if (includesAny(lower, ['502', '503', '504']))
54
+ return false;
55
+ return includesAny(lower, ['timeout', 'timed out', 'deadline exceeded']);
56
+ }
57
+ function isNetworkStderr(lower) {
58
+ return includesAny(lower, [
59
+ 'network',
60
+ 'enotfound',
61
+ 'econnreset',
62
+ 'econnrefused',
63
+ 'enetunreach',
64
+ '502',
65
+ '503',
66
+ '504',
67
+ 'internal server error',
68
+ ]);
69
+ }
70
+ function isModelStderr(lower) {
71
+ return includesAny(lower, [
72
+ 'model not found',
73
+ 'model does not exist',
74
+ 'unsupported model',
75
+ 'invalid model',
76
+ 'context length',
77
+ 'context window',
78
+ ]);
79
+ }
80
+ function isPermissionStderr(lower, exitCode) {
81
+ return (exitCode === 126 ||
82
+ includesAny(lower, [
83
+ 'permission denied',
84
+ 'access denied',
85
+ 'forbidden',
86
+ '403',
87
+ ]));
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Per-category error descriptors
91
+ // ---------------------------------------------------------------------------
92
+ const CATEGORY_DESCRIPTORS = {
93
+ auth: {
94
+ recoverable: false,
95
+ message: 'Authentication failed.',
96
+ suggestion: 'Re-authenticate with the CLI (e.g. `claude auth login` or `codex login`) and try again.',
97
+ },
98
+ 'rate-limit': {
99
+ recoverable: true,
100
+ message: 'Rate limit or quota exceeded.',
101
+ suggestion: 'Wait before retrying. Consider using a different model tier or reducing request frequency.',
102
+ },
103
+ timeout: {
104
+ recoverable: true,
105
+ message: 'The request timed out.',
106
+ suggestion: 'Simplify the request or increase the timeout threshold and retry.',
107
+ },
108
+ network: {
109
+ recoverable: true,
110
+ message: 'A network or server connectivity error occurred.',
111
+ suggestion: 'Check your internet connection. The server may be temporarily unavailable.',
112
+ },
113
+ model: {
114
+ recoverable: false,
115
+ message: 'The requested model is unavailable or the context limit was exceeded.',
116
+ suggestion: 'Verify the model name is correct, or shorten the input to fit within the context window.',
117
+ },
118
+ permission: {
119
+ recoverable: false,
120
+ message: 'Permission or access denied.',
121
+ suggestion: 'Verify your account has access to the requested resource or operation.',
122
+ },
123
+ unknown: {
124
+ recoverable: false,
125
+ message: 'An unexpected error occurred.',
126
+ suggestion: 'Review the stderr output for details. If the problem persists, report it with the full error text.',
127
+ },
128
+ };
129
+ // ---------------------------------------------------------------------------
130
+ // Public classification function
131
+ // ---------------------------------------------------------------------------
132
+ /**
133
+ * Classify a CLI failure into a structured {@link CliError}.
134
+ *
135
+ * @param stderr - The stderr output from the CLI process (may be empty).
136
+ * @param exitCode - The numeric exit code of the process.
137
+ */
138
+ export function classifyError(stderr, exitCode) {
139
+ const lower = stderr.toLowerCase();
140
+ let category;
141
+ if (isAuthStderr(lower)) {
142
+ category = 'auth';
143
+ }
144
+ else if (isRateLimitStderr(lower)) {
145
+ category = 'rate-limit';
146
+ }
147
+ else if (isTimeoutStderr(lower)) {
148
+ category = 'timeout';
149
+ }
150
+ else if (isNetworkStderr(lower)) {
151
+ category = 'network';
152
+ }
153
+ else if (isModelStderr(lower)) {
154
+ category = 'model';
155
+ }
156
+ else if (isPermissionStderr(lower, exitCode)) {
157
+ category = 'permission';
158
+ }
159
+ else {
160
+ category = 'unknown';
161
+ }
162
+ const descriptor = CATEGORY_DESCRIPTORS[category];
163
+ return {
164
+ category,
165
+ recoverable: descriptor.recoverable,
166
+ message: descriptor.message,
167
+ suggestion: descriptor.suggestion,
168
+ };
169
+ }
170
+ // ---------------------------------------------------------------------------
171
+ // Friendly message formatting
172
+ // ---------------------------------------------------------------------------
173
+ /**
174
+ * Format a {@link CliError} into a human-readable string suitable for display.
175
+ * Does not include ANSI codes so it works in any context.
176
+ *
177
+ * @param error - A classified CLI error.
178
+ * @param provider - Optional provider name for contextual detail (e.g. `'claude'`).
179
+ */
180
+ export function formatErrorMessage(error, provider) {
181
+ const label = provider ? provider.toUpperCase() : 'CLI';
182
+ const lines = [`${label} Error [${error.category}]: ${error.message}`];
183
+ lines.push(`Suggestion: ${error.suggestion}`);
184
+ if (error.recoverable) {
185
+ lines.push('This error may be transient. Retrying with backoff is appropriate.');
186
+ }
187
+ return lines.join('\n');
188
+ }
189
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/providers/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqCH;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,IAAqB;IACrE,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC;IACpC,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,MAAM,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC;IAEpC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,UAAU,IAAI,OAAO,EAAE,KAAK,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,qCAAqC;IACrC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAE/C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,SAAS,WAAW,CAAC,IAAY,EAAE,QAAkB;IACnD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,0EAA0E;IAC1E,MAAM,YAAY,GAChB,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IACtF,OAAO,CACL,YAAY;QACZ,WAAW,CAAC,KAAK,EAAE;YACjB,gBAAgB;YAChB,cAAc;YACd,KAAK;YACL,qBAAqB;YACrB,gBAAgB;SACjB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC5E,OAAO,CACL,aAAa,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAChF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,2EAA2E;IAC3E,4DAA4D;IAC5D,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5D,OAAO,WAAW,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,WAAW,CAAC,KAAK,EAAE;QACxB,SAAS;QACT,WAAW;QACX,YAAY;QACZ,cAAc;QACd,aAAa;QACb,KAAK;QACL,KAAK;QACL,KAAK;QACL,uBAAuB;KACxB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,WAAW,CAAC,KAAK,EAAE;QACxB,iBAAiB;QACjB,sBAAsB;QACtB,mBAAmB;QACnB,eAAe;QACf,gBAAgB;QAChB,gBAAgB;KACjB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa,EAAE,QAAgB;IACzD,OAAO,CACL,QAAQ,KAAK,GAAG;QAChB,WAAW,CAAC,KAAK,EAAE;YACjB,mBAAmB;YACnB,eAAe;YACf,WAAW;YACX,KAAK;SACN,CAAC,CACH,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E,MAAM,oBAAoB,GAGtB;IACF,IAAI,EAAE;QACJ,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,wBAAwB;QACjC,UAAU,EACR,yFAAyF;KAC5F;IACD,YAAY,EAAE;QACZ,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,+BAA+B;QACxC,UAAU,EACR,4FAA4F;KAC/F;IACD,OAAO,EAAE;QACP,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,wBAAwB;QACjC,UAAU,EAAE,mEAAmE;KAChF;IACD,OAAO,EAAE;QACP,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,kDAAkD;QAC3D,UAAU,EAAE,4EAA4E;KACzF;IACD,KAAK,EAAE;QACL,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,uEAAuE;QAChF,UAAU,EACR,0FAA0F;KAC7F;IACD,UAAU,EAAE;QACV,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,8BAA8B;QACvC,UAAU,EACR,wEAAwE;KAC3E;IACD,OAAO,EAAE;QACP,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,+BAA+B;QACxC,UAAU,EACR,oGAAoG;KACvG;CACF,CAAC;AAEF,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,QAAgB;IAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAEnC,IAAI,QAAuB,CAAC;IAE5B,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,QAAQ,GAAG,MAAM,CAAC;IACpB,CAAC;SAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,QAAQ,GAAG,YAAY,CAAC;IAC1B,CAAC;SAAM,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,QAAQ,GAAG,SAAS,CAAC;IACvB,CAAC;SAAM,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,QAAQ,GAAG,SAAS,CAAC;IACvB,CAAC;SAAM,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;SAAM,IAAI,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC/C,QAAQ,GAAG,YAAY,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,SAAS,CAAC;IACvB,CAAC;IAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAElD,OAAO;QACL,QAAQ;QACR,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,UAAU,EAAE,UAAU,CAAC,UAAU;KAClC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,8BAA8B;AAC9B,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAe,EAAE,QAAiB;IACnE,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACxD,MAAM,KAAK,GAAa,CAAC,GAAG,KAAK,WAAW,KAAK,CAAC,QAAQ,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAEjF,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;IAE9C,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { classifyError, calculateBackoff, formatErrorMessage } from './errors.js';
2
+ export type { CliError, ErrorCategory, BackoffOptions } from './errors.js';
3
+ export { detectProvider, detectEnvironment, getInstallCommand } from './detect.js';
4
+ export type { ProviderStatus, EnvironmentStatus } from './detect.js';
5
+ export type { Provider, ProviderEvent, ProviderRequest, Usage, SandboxLevel, ProviderId, } from './port.js';
6
+ export { createClaudeProvider, toClaudeModelArg } from './claude.js';
7
+ export { parseClaudeLine } from './claude-parse.js';
8
+ export { createCodexProvider, toSandboxArg } from './codex.js';
9
+ export { createCodexParser } from './codex-parse.js';
@@ -0,0 +1,7 @@
1
+ export { classifyError, calculateBackoff, formatErrorMessage } from './errors.js';
2
+ export { detectProvider, detectEnvironment, getInstallCommand } from './detect.js';
3
+ export { createClaudeProvider, toClaudeModelArg } from './claude.js';
4
+ export { parseClaudeLine } from './claude-parse.js';
5
+ export { createCodexProvider, toSandboxArg } from './codex.js';
6
+ export { createCodexParser } from './codex-parse.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUnF,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * src/providers/port.ts — the Provider port (the keystone interface).
3
+ *
4
+ * The orchestration core talks to this interface and nothing vendor-specific.
5
+ * Claude and Codex each ship an adapter that implements `Provider`.
6
+ *
7
+ * Design contract:
8
+ * - `run()` returns an AsyncIterable so the UI can stream real tokens/tools as
9
+ * they arrive and the core can compute real cost from the `usage` event.
10
+ * - The prompt in `ProviderRequest` is delivered to the child process via STDIN
11
+ * (never as a shell argument) — see spawn.ts.
12
+ * - `model` is always a concrete model id (resolved from an alias before this
13
+ * layer), never a tier name or alias.
14
+ */
15
+ import type { CliError } from './errors.js';
16
+ import type { ProviderStatus } from './detect.js';
17
+ export type { CliError } from './errors.js';
18
+ /** Privilege ladder mapped onto each CLI's sandbox flags. Default is workspace-write. */
19
+ export type SandboxLevel = 'read-only' | 'workspace-write' | 'full-access';
20
+ export type ProviderId = 'claude' | 'codex';
21
+ export interface Usage {
22
+ readonly inputTokens: number;
23
+ readonly outputTokens: number;
24
+ readonly cachedInputTokens?: number;
25
+ }
26
+ export interface ProviderRequest {
27
+ /** Concrete model id, e.g. 'claude-sonnet-4-6' (never an alias at this layer). */
28
+ readonly model: string;
29
+ /** The full prompt; delivered via STDIN, not argv. */
30
+ readonly prompt: string;
31
+ /** Working directory the model operates in. */
32
+ readonly cwd: string;
33
+ /** Privilege level for model-initiated actions. */
34
+ readonly sandbox: SandboxLevel;
35
+ /** Hard wall-clock timeout for the run. */
36
+ readonly timeoutMs: number;
37
+ }
38
+ /**
39
+ * Streaming events emitted by a provider run. Discriminated on `type`.
40
+ * The terminal event is exactly one of `done` or `error`.
41
+ */
42
+ export type ProviderEvent = {
43
+ readonly type: 'text';
44
+ readonly delta: string;
45
+ } | {
46
+ readonly type: 'reasoning';
47
+ readonly delta: string;
48
+ } | {
49
+ readonly type: 'tool';
50
+ readonly name: string;
51
+ readonly phase: 'start' | 'end';
52
+ readonly detail?: string;
53
+ } | {
54
+ readonly type: 'usage';
55
+ readonly usage: Usage;
56
+ } | {
57
+ readonly type: 'done';
58
+ readonly text: string;
59
+ readonly usage?: Usage;
60
+ /** Cost in USD as reported by the provider CLI, when available (preferred
61
+ * over estimating from the pricing table — it accounts for caching etc.). */
62
+ readonly costUsd?: number;
63
+ readonly raw: unknown;
64
+ } | {
65
+ readonly type: 'error';
66
+ readonly error: CliError;
67
+ };
68
+ export interface Provider {
69
+ readonly id: ProviderId;
70
+ /** Probe install/auth/version/models. Cheap and cached by the adapter. */
71
+ detect(): Promise<ProviderStatus>;
72
+ /** Execute one request, streaming events until a terminal `done`/`error`. */
73
+ run(req: ProviderRequest, signal: AbortSignal): AsyncIterable<ProviderEvent>;
74
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * src/providers/port.ts — the Provider port (the keystone interface).
3
+ *
4
+ * The orchestration core talks to this interface and nothing vendor-specific.
5
+ * Claude and Codex each ship an adapter that implements `Provider`.
6
+ *
7
+ * Design contract:
8
+ * - `run()` returns an AsyncIterable so the UI can stream real tokens/tools as
9
+ * they arrive and the core can compute real cost from the `usage` event.
10
+ * - The prompt in `ProviderRequest` is delivered to the child process via STDIN
11
+ * (never as a shell argument) — see spawn.ts.
12
+ * - `model` is always a concrete model id (resolved from an alias before this
13
+ * layer), never a tier name or alias.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/providers/port.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * src/providers/registry.ts — provider registry for the CLI.
3
+ *
4
+ * Builds the Partial<Record<ProviderId, Provider>> map consumed by
5
+ * OrchestrateDeps. Each provider registers when `installed` is true — we gate
6
+ * on `installed`, NOT `authenticated`, because auth is only truly known at
7
+ * call time and errors render honestly via classifyError().
8
+ *
9
+ * With both Claude and Codex installed, `deps.providers` will have entries for
10
+ * both — which automatically activates cross-vendor review in the orchestrator.
11
+ */
12
+ import type { Provider, ProviderId } from './port.js';
13
+ /**
14
+ * Discover which providers are available in the current environment and build
15
+ * the provider map for OrchestrateDeps.
16
+ *
17
+ * @param _cwd - Working directory (used by real adapters to locate project-
18
+ * level config; may be forwarded to adapters in a future phase).
19
+ * @returns A (possibly empty) map of available providers.
20
+ */
21
+ export declare function buildProviders(_cwd: string): Promise<Partial<Record<ProviderId, Provider>>>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * src/providers/registry.ts — provider registry for the CLI.
3
+ *
4
+ * Builds the Partial<Record<ProviderId, Provider>> map consumed by
5
+ * OrchestrateDeps. Each provider registers when `installed` is true — we gate
6
+ * on `installed`, NOT `authenticated`, because auth is only truly known at
7
+ * call time and errors render honestly via classifyError().
8
+ *
9
+ * With both Claude and Codex installed, `deps.providers` will have entries for
10
+ * both — which automatically activates cross-vendor review in the orchestrator.
11
+ */
12
+ import { detectEnvironment } from './detect.js';
13
+ import { createClaudeProvider } from './claude.js';
14
+ import { createCodexProvider } from './codex.js';
15
+ /**
16
+ * Discover which providers are available in the current environment and build
17
+ * the provider map for OrchestrateDeps.
18
+ *
19
+ * @param _cwd - Working directory (used by real adapters to locate project-
20
+ * level config; may be forwarded to adapters in a future phase).
21
+ * @returns A (possibly empty) map of available providers.
22
+ */
23
+ export async function buildProviders(_cwd) {
24
+ const env = await detectEnvironment();
25
+ const providers = {};
26
+ if (env.claude.installed) {
27
+ providers.claude = createClaudeProvider();
28
+ }
29
+ if (env.codex.installed) {
30
+ providers.codex = createCodexProvider();
31
+ }
32
+ return providers;
33
+ }
34
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY;IAEZ,MAAM,GAAG,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACtC,MAAM,SAAS,GAA0C,EAAE,CAAC;IAE5D,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACzB,SAAS,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACxB,SAAS,CAAC,KAAK,GAAG,mBAAmB,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * src/ui/banner.ts — Compact product banner for myshell-tools-sh.
3
+ *
4
+ * Renders a tasteful multi-line banner showing the product name, real version,
5
+ * and a one-line tagline. The version is always supplied by the caller (no
6
+ * hardcoded value). No fake stats, no fabricated figures.
7
+ *
8
+ * Honesty Contract: this file contains no hardcoded percentages, no fabricated
9
+ * figures, and no mock phrases.
10
+ */
11
+ /**
12
+ * Build a compact product banner string.
13
+ *
14
+ * @param version - The real semver string for this release (e.g. '1.2.3').
15
+ * @param color - When false, no ANSI escape codes are emitted.
16
+ * @returns A multi-line banner string (does not end with a newline beyond the
17
+ * last line so the caller controls spacing).
18
+ */
19
+ export declare function banner(version: string, color: boolean): string;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * src/ui/banner.ts — Compact product banner for myshell-tools-sh.
3
+ *
4
+ * Renders a tasteful multi-line banner showing the product name, real version,
5
+ * and a one-line tagline. The version is always supplied by the caller (no
6
+ * hardcoded value). No fake stats, no fabricated figures.
7
+ *
8
+ * Honesty Contract: this file contains no hardcoded percentages, no fabricated
9
+ * figures, and no mock phrases.
10
+ */
11
+ import { bold, cyan, dim } from './theme.js';
12
+ // ---------------------------------------------------------------------------
13
+ // Banner
14
+ // ---------------------------------------------------------------------------
15
+ /**
16
+ * Build a compact product banner string.
17
+ *
18
+ * @param version - The real semver string for this release (e.g. '1.2.3').
19
+ * @param color - When false, no ANSI escape codes are emitted.
20
+ * @returns A multi-line banner string (does not end with a newline beyond the
21
+ * last line so the caller controls spacing).
22
+ */
23
+ export function banner(version, color) {
24
+ const name = bold(cyan('myshell-tools', color), color);
25
+ const ver = dim(`v${version}`, color);
26
+ const tag = dim('AI task orchestrator — honest, tier-aware, streaming', color);
27
+ return [
28
+ `${name} ${ver}`,
29
+ tag,
30
+ ].join('\n');
31
+ }
32
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/ui/banner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAE7C,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,OAAe,EAAE,KAAc;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IACvD,MAAM,GAAG,GAAI,GAAG,CAAC,IAAI,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IACvC,MAAM,GAAG,GAAI,GAAG,CAAC,sDAAsD,EAAE,KAAK,CAAC,CAAC;IAEhF,OAAO;QACL,GAAG,IAAI,IAAI,GAAG,EAAE;QAChB,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * src/ui/spinner.ts — Honest, indeterminate working indicator.
3
+ *
4
+ * Animates a braille-spinner frame while waiting for the first real output.
5
+ * No percentages, no fake progress — purely a "working" indicator.
6
+ * Frame cycling is deterministic (index-based); Math.random is never used.
7
+ *
8
+ * Honesty Contract: this file contains no hardcoded percentages, no fabricated
9
+ * figures, and no mock phrases.
10
+ */
11
+ import type { OutputSink } from '../interface/render.js';
12
+ /** A minimal working-indicator that can be started and stopped. */
13
+ export interface Spinner {
14
+ /** Display the spinner with the given text. */
15
+ start(text: string): void;
16
+ /** Stop the spinner and clear the line (TTY) or do nothing (non-TTY). */
17
+ stop(): void;
18
+ }
19
+ /**
20
+ * Create a spinner bound to the given OutputSink.
21
+ *
22
+ * - When `out.isTty` is true: animates braille frames + text on the current
23
+ * line using `\r`, driven by `setInterval`.
24
+ * - When `out.isTty` is false: prints the text once (static) and does nothing
25
+ * on stop — safe for CI / pipe output.
26
+ */
27
+ export declare function createSpinner(out: OutputSink): Spinner;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * src/ui/spinner.ts — Honest, indeterminate working indicator.
3
+ *
4
+ * Animates a braille-spinner frame while waiting for the first real output.
5
+ * No percentages, no fake progress — purely a "working" indicator.
6
+ * Frame cycling is deterministic (index-based); Math.random is never used.
7
+ *
8
+ * Honesty Contract: this file contains no hardcoded percentages, no fabricated
9
+ * figures, and no mock phrases.
10
+ */
11
+ // ---------------------------------------------------------------------------
12
+ // Frame set (braille dots — deterministic cycle, no Math.random)
13
+ // ---------------------------------------------------------------------------
14
+ const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
15
+ const FRAME_INTERVAL_MS = 80;
16
+ /**
17
+ * Create a spinner bound to the given OutputSink.
18
+ *
19
+ * - When `out.isTty` is true: animates braille frames + text on the current
20
+ * line using `\r`, driven by `setInterval`.
21
+ * - When `out.isTty` is false: prints the text once (static) and does nothing
22
+ * on stop — safe for CI / pipe output.
23
+ */
24
+ export function createSpinner(out) {
25
+ let frameIndex = 0;
26
+ let timer = null;
27
+ let active = false;
28
+ /** Exposed for deterministic testing: advance one frame and write it. */
29
+ function tick(text) {
30
+ frameIndex = (frameIndex + 1) % FRAMES.length;
31
+ const frame = FRAMES[frameIndex] ?? FRAMES[0] ?? '⠋';
32
+ out.write(`\r${frame} ${text}`);
33
+ }
34
+ return {
35
+ start(text) {
36
+ if (active)
37
+ return;
38
+ active = true;
39
+ if (out.isTty) {
40
+ // Write the first frame immediately so there is no blank gap.
41
+ const frame = FRAMES[frameIndex] ?? FRAMES[0] ?? '⠋';
42
+ out.write(`\r${frame} ${text}`);
43
+ timer = setInterval(() => {
44
+ tick(text);
45
+ }, FRAME_INTERVAL_MS);
46
+ }
47
+ else {
48
+ // Non-TTY: print once, no animation.
49
+ out.write(`${text}\n`);
50
+ }
51
+ },
52
+ stop() {
53
+ if (!active)
54
+ return;
55
+ active = false;
56
+ if (timer !== null) {
57
+ clearInterval(timer);
58
+ timer = null;
59
+ }
60
+ if (out.isTty) {
61
+ // Clear the spinner line so the real output follows cleanly.
62
+ out.write('\r\x1b[K');
63
+ }
64
+ },
65
+ };
66
+ }
67
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,8EAA8E;AAC9E,iEAAiE;AACjE,8EAA8E;AAE9E,MAAM,MAAM,GAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACrF,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAc7B;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,GAAe;IAC3C,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,KAAK,GAA0C,IAAI,CAAC;IACxD,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,yEAAyE;IACzE,SAAS,IAAI,CAAC,IAAY;QACxB,UAAU,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QACrD,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAY;YAChB,IAAI,MAAM;gBAAE,OAAO;YACnB,MAAM,GAAG,IAAI,CAAC;YAEd,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACd,8DAA8D;gBAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;gBACrD,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;gBAEhC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;oBACvB,IAAI,CAAC,IAAI,CAAC,CAAC;gBACb,CAAC,EAAE,iBAAiB,CAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,qCAAqC;gBACrC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAED,IAAI;YACF,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,GAAG,KAAK,CAAC;YAEf,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YAED,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACd,6DAA6D;gBAC7D,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * src/ui/theme.ts — Centralised ANSI colour / format helpers.
3
+ *
4
+ * Every helper accepts a `color` boolean flag. When false the text is returned
5
+ * unchanged, which honours NO_COLOR and non-TTY contexts. No other module in
6
+ * the project should hardcode ANSI escape codes.
7
+ *
8
+ * Honesty contract: this file contains no hardcoded percentages, no fabricated
9
+ * figures, and no mock phrases.
10
+ */
11
+ /** Dim / faint text. */
12
+ export declare function dim(text: string, color: boolean): string;
13
+ /** Bold text. */
14
+ export declare function bold(text: string, color: boolean): string;
15
+ /** Green text (success / ok). */
16
+ export declare function green(text: string, color: boolean): string;
17
+ /** Red text (failure / error). */
18
+ export declare function red(text: string, color: boolean): string;
19
+ /** Yellow text (warning / caution). */
20
+ export declare function yellow(text: string, color: boolean): string;
21
+ /** Cyan text (informational accent). */
22
+ export declare function cyan(text: string, color: boolean): string;
23
+ /**
24
+ * Render a labelled key in a key/value pair.
25
+ * e.g. `label('Status', true)` → bold cyan "Status"
26
+ */
27
+ export declare function label(text: string, color: boolean): string;
28
+ /**
29
+ * Return a horizontal rule of the given width (default 40).
30
+ * The divider is dim when colour is enabled.
31
+ */
32
+ export declare function divider(color: boolean, width?: number): string;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * src/ui/theme.ts — Centralised ANSI colour / format helpers.
3
+ *
4
+ * Every helper accepts a `color` boolean flag. When false the text is returned
5
+ * unchanged, which honours NO_COLOR and non-TTY contexts. No other module in
6
+ * the project should hardcode ANSI escape codes.
7
+ *
8
+ * Honesty contract: this file contains no hardcoded percentages, no fabricated
9
+ * figures, and no mock phrases.
10
+ */
11
+ // ---------------------------------------------------------------------------
12
+ // Primitive colour helpers
13
+ // ---------------------------------------------------------------------------
14
+ /** Dim / faint text. */
15
+ export function dim(text, color) {
16
+ return color ? `\x1b[2m${text}\x1b[0m` : text;
17
+ }
18
+ /** Bold text. */
19
+ export function bold(text, color) {
20
+ return color ? `\x1b[1m${text}\x1b[0m` : text;
21
+ }
22
+ /** Green text (success / ok). */
23
+ export function green(text, color) {
24
+ return color ? `\x1b[32m${text}\x1b[0m` : text;
25
+ }
26
+ /** Red text (failure / error). */
27
+ export function red(text, color) {
28
+ return color ? `\x1b[31m${text}\x1b[0m` : text;
29
+ }
30
+ /** Yellow text (warning / caution). */
31
+ export function yellow(text, color) {
32
+ return color ? `\x1b[33m${text}\x1b[0m` : text;
33
+ }
34
+ /** Cyan text (informational accent). */
35
+ export function cyan(text, color) {
36
+ return color ? `\x1b[36m${text}\x1b[0m` : text;
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Composite helpers
40
+ // ---------------------------------------------------------------------------
41
+ /**
42
+ * Render a labelled key in a key/value pair.
43
+ * e.g. `label('Status', true)` → bold cyan "Status"
44
+ */
45
+ export function label(text, color) {
46
+ return bold(cyan(text, color), color);
47
+ }
48
+ /**
49
+ * Return a horizontal rule of the given width (default 40).
50
+ * The divider is dim when colour is enabled.
51
+ */
52
+ export function divider(color, width = 40) {
53
+ const line = '─'.repeat(width);
54
+ return dim(line, color);
55
+ }
56
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,wBAAwB;AACxB,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,KAAc;IAC9C,OAAO,KAAK,CAAC,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,iBAAiB;AACjB,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,KAAc;IAC/C,OAAO,KAAK,CAAC,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,KAAc;IAChD,OAAO,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,KAAc;IAC9C,OAAO,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,KAAc;IACjD,OAAO,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,KAAc;IAC/C,OAAO,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,KAAc;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,KAAc,EAAE,KAAK,GAAG,EAAE;IAChD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC"}