myshell-tools 2.0.0-alpha.0 → 2.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 (60) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +6 -3
  3. package/dist/cli.js +85 -30
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/doctor.d.ts +3 -2
  6. package/dist/commands/doctor.js +9 -5
  7. package/dist/commands/doctor.js.map +1 -1
  8. package/dist/commands/login.d.ts +20 -0
  9. package/dist/commands/login.js +60 -0
  10. package/dist/commands/login.js.map +1 -0
  11. package/dist/core/orchestrate.js +80 -28
  12. package/dist/core/orchestrate.js.map +1 -1
  13. package/dist/core/policy.d.ts +10 -0
  14. package/dist/core/policy.js +40 -0
  15. package/dist/core/policy.js.map +1 -1
  16. package/dist/core/review.d.ts +5 -0
  17. package/dist/core/review.js +2 -2
  18. package/dist/core/review.js.map +1 -1
  19. package/dist/infra/atomic.d.ts +0 -3
  20. package/dist/infra/atomic.js +1 -1
  21. package/dist/infra/atomic.js.map +1 -1
  22. package/dist/infra/config.d.ts +23 -0
  23. package/dist/infra/config.js +64 -0
  24. package/dist/infra/config.js.map +1 -0
  25. package/dist/infra/conversation-store.d.ts +42 -0
  26. package/dist/infra/conversation-store.js +14 -0
  27. package/dist/infra/conversation-store.js.map +1 -0
  28. package/dist/infra/conversations.d.ts +18 -0
  29. package/dist/infra/conversations.js +296 -0
  30. package/dist/infra/conversations.js.map +1 -0
  31. package/dist/infra/insights.d.ts +66 -0
  32. package/dist/infra/insights.js +105 -0
  33. package/dist/infra/insights.js.map +1 -0
  34. package/dist/infra/ledger.d.ts +4 -6
  35. package/dist/infra/ledger.js.map +1 -1
  36. package/dist/interface/menu.d.ts +112 -0
  37. package/dist/interface/menu.js +622 -0
  38. package/dist/interface/menu.js.map +1 -0
  39. package/dist/providers/claude.d.ts +4 -13
  40. package/dist/providers/claude.js +5 -4
  41. package/dist/providers/claude.js.map +1 -1
  42. package/dist/providers/codex.d.ts +6 -12
  43. package/dist/providers/codex.js +6 -4
  44. package/dist/providers/codex.js.map +1 -1
  45. package/dist/providers/detect.d.ts +63 -14
  46. package/dist/providers/detect.js +123 -27
  47. package/dist/providers/detect.js.map +1 -1
  48. package/dist/ui/tui.d.ts +127 -0
  49. package/dist/ui/tui.js +316 -0
  50. package/dist/ui/tui.js.map +1 -0
  51. package/package.json +4 -1
  52. package/dist/core/index.d.ts +0 -13
  53. package/dist/core/index.js +0 -12
  54. package/dist/core/index.js.map +0 -1
  55. package/dist/infra/index.d.ts +0 -9
  56. package/dist/infra/index.js +0 -7
  57. package/dist/infra/index.js.map +0 -1
  58. package/dist/providers/index.d.ts +0 -9
  59. package/dist/providers/index.js +0 -7
  60. package/dist/providers/index.js.map +0 -1
@@ -14,9 +14,10 @@
14
14
  * permission-bypass flag here.
15
15
  *
16
16
  * Authentication note:
17
- * Auth state is OPTIMISTIC at detect() time we cannot cheaply probe it.
18
- * The real auth state surfaces at run time: an unauthenticated run produces
19
- * a stderr that classifyError() maps to category 'auth'.
17
+ * Auth state is probed at detect() time by spawning `claude auth status` and
18
+ * parsing its JSON output (see detect.ts / parseClaudeAuth). An unauthenticated
19
+ * run will also surface at run time: the stderr is classified as category 'auth'
20
+ * by classifyError().
20
21
  *
21
22
  * Execa v9 streaming:
22
23
  * We use `subprocess[Symbol.asyncIterator]()` (i.e. `for await … of subprocess`)
@@ -25,16 +26,6 @@
25
26
  * yields one string per stdout line.
26
27
  */
27
28
  import type { Provider } from './port.js';
28
- /**
29
- * Map a concrete model id to a CLI-safe alias so a stale full id never 404s.
30
- *
31
- * Patterns:
32
- * - claude-opus-* → 'opus'
33
- * - claude-sonnet-* → 'sonnet'
34
- * - claude-haiku-* → 'haiku'
35
- * - anything else → returned unchanged
36
- */
37
- export declare function toClaudeModelArg(model: string): string;
38
29
  /**
39
30
  * Create a Claude provider adapter.
40
31
  *
@@ -14,9 +14,10 @@
14
14
  * permission-bypass flag here.
15
15
  *
16
16
  * Authentication note:
17
- * Auth state is OPTIMISTIC at detect() time we cannot cheaply probe it.
18
- * The real auth state surfaces at run time: an unauthenticated run produces
19
- * a stderr that classifyError() maps to category 'auth'.
17
+ * Auth state is probed at detect() time by spawning `claude auth status` and
18
+ * parsing its JSON output (see detect.ts / parseClaudeAuth). An unauthenticated
19
+ * run will also surface at run time: the stderr is classified as category 'auth'
20
+ * by classifyError().
20
21
  *
21
22
  * Execa v9 streaming:
22
23
  * We use `subprocess[Symbol.asyncIterator]()` (i.e. `for await … of subprocess`)
@@ -40,7 +41,7 @@ import { parseClaudeLine } from './claude-parse.js';
40
41
  * - claude-haiku-* → 'haiku'
41
42
  * - anything else → returned unchanged
42
43
  */
43
- export function toClaudeModelArg(model) {
44
+ function toClaudeModelArg(model) {
44
45
  if (model.startsWith('claude-opus'))
45
46
  return 'opus';
46
47
  if (model.startsWith('claude-sonnet'))
@@ -1 +1 @@
1
- {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/providers/claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/providers/claude.ts"],"names":[],"mappings":"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"}
@@ -11,9 +11,11 @@
11
11
  * full-access → '--sandbox danger-full-access'
12
12
  *
13
13
  * Authentication note:
14
- * Auth state is OPTIMISTIC at detect() time we cannot cheaply probe it.
15
- * The real auth state surfaces at run time: an unauthenticated run produces
16
- * a stderr/event that classifyError() maps to category 'auth'.
14
+ * Auth state is probed at detect() time by spawning `codex login status` and
15
+ * inspecting both stdout and stderr (see detect.ts / parseCodexAuth). In
16
+ * practice codex writes "Logged in using ChatGPT" to stderr. An unauthenticated
17
+ * run will also surface at run time: the stderr/event is classified as category
18
+ * 'auth' by classifyError().
17
19
  *
18
20
  * costUsd note:
19
21
  * Codex does NOT report a USD cost. The `done` event therefore omits
@@ -25,15 +27,7 @@
25
27
  * lines as strings. Confirmed from execa types: the subprocess IS an
26
28
  * AsyncIterable<string>.
27
29
  */
28
- import type { Provider, SandboxLevel } from './port.js';
29
- /**
30
- * Map the abstract {@link SandboxLevel} to the concrete `--sandbox` argument
31
- * that the Codex CLI accepts.
32
- *
33
- * NEVER default to 'danger-full-access' — always require the caller to opt in
34
- * explicitly by passing SandboxLevel 'full-access'.
35
- */
36
- export declare function toSandboxArg(level: SandboxLevel): string;
30
+ import type { Provider } from './port.js';
37
31
  /**
38
32
  * Create a Codex provider adapter.
39
33
  *
@@ -11,9 +11,11 @@
11
11
  * full-access → '--sandbox danger-full-access'
12
12
  *
13
13
  * Authentication note:
14
- * Auth state is OPTIMISTIC at detect() time we cannot cheaply probe it.
15
- * The real auth state surfaces at run time: an unauthenticated run produces
16
- * a stderr/event that classifyError() maps to category 'auth'.
14
+ * Auth state is probed at detect() time by spawning `codex login status` and
15
+ * inspecting both stdout and stderr (see detect.ts / parseCodexAuth). In
16
+ * practice codex writes "Logged in using ChatGPT" to stderr. An unauthenticated
17
+ * run will also surface at run time: the stderr/event is classified as category
18
+ * 'auth' by classifyError().
17
19
  *
18
20
  * costUsd note:
19
21
  * Codex does NOT report a USD cost. The `done` event therefore omits
@@ -39,7 +41,7 @@ import { createCodexParser } from './codex-parse.js';
39
41
  * NEVER default to 'danger-full-access' — always require the caller to opt in
40
42
  * explicitly by passing SandboxLevel 'full-access'.
41
43
  */
42
- export function toSandboxArg(level) {
44
+ function toSandboxArg(level) {
43
45
  switch (level) {
44
46
  case 'read-only':
45
47
  return 'read-only';
@@ -1 +1 @@
1
- {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/providers/codex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/providers/codex.ts"],"names":[],"mappings":"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"}
@@ -3,17 +3,19 @@
3
3
  *
4
4
  * Provider-detection logic.
5
5
  *
6
- * Claude detection is REAL: spawns `claude --version` to probe installation.
7
- * Codex detection is REAL: spawns `codex --version` to probe installation.
8
- * Authentication is OPTIMISTIC for both we cannot cheaply probe auth state
9
- * without spending API quota. The real auth state surfaces at run time and is
10
- * classified by errors.ts (category 'auth').
6
+ * Claude detection is REAL: spawns `claude --version` to probe installation,
7
+ * then `claude auth status` to probe real authentication state.
8
+ * Codex detection is REAL: spawns `codex --version` to probe installation,
9
+ * then `codex login status` to probe real authentication state.
10
+ *
11
+ * Plan labels are only set when clearly present in CLI output — never fabricated.
11
12
  */
12
13
  export interface ProviderStatus {
13
14
  readonly id: 'claude' | 'codex';
14
15
  readonly installed: boolean;
15
16
  readonly version: string | null;
16
17
  readonly authenticated: boolean;
18
+ readonly plan: string | null;
17
19
  readonly binaryPath: string | null;
18
20
  readonly availableModels: readonly string[];
19
21
  }
@@ -24,17 +26,64 @@ export interface EnvironmentStatus {
24
26
  readonly platform: NodeJS.Platform;
25
27
  }
26
28
  /**
27
- * Detect whether a provider CLI is installed and (optimistically) usable.
29
+ * Parse the output of `claude auth status` into an auth result.
30
+ *
31
+ * Real output shape (exit code 0, authenticated):
32
+ * ```json
33
+ * {
34
+ * "loggedIn": true,
35
+ * "authMethod": "claude.ai",
36
+ * "apiProvider": "firstParty",
37
+ * "email": "user@example.com",
38
+ * "orgId": "...",
39
+ * "orgName": "...",
40
+ * "subscriptionType": "pro"
41
+ * }
42
+ * ```
43
+ *
44
+ * Authenticated when: exitCode === 0 AND the JSON contains `"loggedIn": true`.
45
+ * Plan: the `subscriptionType` string when present and non-empty, else null.
46
+ * Conservative: on any parse error, authenticated stays false and plan is null.
47
+ */
48
+ export declare function parseClaudeAuth(stdout: string, _stderr: string, exitCode: number): {
49
+ authenticated: boolean;
50
+ plan: string | null;
51
+ };
52
+ /**
53
+ * Parse the output of `codex login status` into an auth result.
54
+ *
55
+ * Real output shape (exit code 0, authenticated):
56
+ * ```
57
+ * Logged in using ChatGPT ← written to stderr (not stdout)
58
+ * ```
59
+ *
60
+ * Authenticated when: exitCode === 0 AND either stdout OR stderr contains
61
+ * "logged in" (case-insensitive). The haystack is built from both streams
62
+ * because `codex login status` writes to stderr in practice.
63
+ *
64
+ * Plan: null — codex login status does not expose a subscription/plan label.
65
+ * Conservative: on any unexpected output, authenticated stays false and plan is null.
66
+ *
67
+ * @remarks Codex has no plan/subscription field in `codex login status` output.
68
+ * plan is always null; it is never fabricated.
69
+ */
70
+ export declare function parseCodexAuth(stdout: string, stderr: string, exitCode: number): {
71
+ authenticated: boolean;
72
+ plan: string | null;
73
+ };
74
+ /**
75
+ * Detect whether a provider CLI is installed and probe its real auth state.
28
76
  *
29
- * For 'claude': runs `claude --version` to confirm the binary is present and
30
- * executable. Authentication is reported as `true` optimistically we cannot
31
- * cheaply probe auth state without spending API quota. If the user is not
32
- * authenticated, the real auth failure surfaces at run time via classifyError()
33
- * (category 'auth').
77
+ * For 'claude': runs `claude --version` to confirm the binary is present, then
78
+ * `claude auth status` (JSON output) to determine real auth state and plan.
79
+ * On spawn failure of the status command, falls back gracefully: installed
80
+ * remains true, authenticated false, plan null.
34
81
  *
35
- * For 'codex': runs `codex --version` to confirm the binary is present and
36
- * executable. Authentication is reported as `true` optimistically for the same
37
- * reason real auth failures surface at run time via classifyError().
82
+ * For 'codex': runs `codex --version` to confirm the binary is present, then
83
+ * `codex login status` to determine real auth state. Plan is always null because
84
+ * `codex login status` does not expose subscription information.
85
+ * On spawn failure of the status command, falls back gracefully: installed
86
+ * remains true, authenticated false, plan null.
38
87
  */
39
88
  export declare function detectProvider(id: 'claude' | 'codex'): Promise<ProviderStatus>;
40
89
  /**
@@ -3,11 +3,12 @@
3
3
  *
4
4
  * Provider-detection logic.
5
5
  *
6
- * Claude detection is REAL: spawns `claude --version` to probe installation.
7
- * Codex detection is REAL: spawns `codex --version` to probe installation.
8
- * Authentication is OPTIMISTIC for both we cannot cheaply probe auth state
9
- * without spending API quota. The real auth state surfaces at run time and is
10
- * classified by errors.ts (category 'auth').
6
+ * Claude detection is REAL: spawns `claude --version` to probe installation,
7
+ * then `claude auth status` to probe real authentication state.
8
+ * Codex detection is REAL: spawns `codex --version` to probe installation,
9
+ * then `codex login status` to probe real authentication state.
10
+ *
11
+ * Plan labels are only set when clearly present in CLI output — never fabricated.
11
12
  */
12
13
  import { execa } from 'execa';
13
14
  // ---------------------------------------------------------------------------
@@ -19,25 +20,99 @@ function notDetected(id) {
19
20
  installed: false,
20
21
  version: null,
21
22
  authenticated: false,
23
+ plan: null,
22
24
  binaryPath: null,
23
25
  availableModels: [],
24
26
  };
25
27
  }
26
28
  // ---------------------------------------------------------------------------
29
+ // Pure auth parsers (no I/O — hermetic-testable)
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Parse the output of `claude auth status` into an auth result.
33
+ *
34
+ * Real output shape (exit code 0, authenticated):
35
+ * ```json
36
+ * {
37
+ * "loggedIn": true,
38
+ * "authMethod": "claude.ai",
39
+ * "apiProvider": "firstParty",
40
+ * "email": "user@example.com",
41
+ * "orgId": "...",
42
+ * "orgName": "...",
43
+ * "subscriptionType": "pro"
44
+ * }
45
+ * ```
46
+ *
47
+ * Authenticated when: exitCode === 0 AND the JSON contains `"loggedIn": true`.
48
+ * Plan: the `subscriptionType` string when present and non-empty, else null.
49
+ * Conservative: on any parse error, authenticated stays false and plan is null.
50
+ */
51
+ export function parseClaudeAuth(stdout, _stderr, exitCode) {
52
+ if (exitCode !== 0) {
53
+ return { authenticated: false, plan: null };
54
+ }
55
+ try {
56
+ const data = JSON.parse(stdout.trim());
57
+ if (typeof data !== 'object' || data === null) {
58
+ return { authenticated: false, plan: null };
59
+ }
60
+ const obj = data;
61
+ const loggedIn = obj['loggedIn'] === true;
62
+ if (!loggedIn) {
63
+ return { authenticated: false, plan: null };
64
+ }
65
+ const sub = obj['subscriptionType'];
66
+ const plan = typeof sub === 'string' && sub.length > 0 ? sub : null;
67
+ return { authenticated: true, plan };
68
+ }
69
+ catch {
70
+ return { authenticated: false, plan: null };
71
+ }
72
+ }
73
+ /**
74
+ * Parse the output of `codex login status` into an auth result.
75
+ *
76
+ * Real output shape (exit code 0, authenticated):
77
+ * ```
78
+ * Logged in using ChatGPT ← written to stderr (not stdout)
79
+ * ```
80
+ *
81
+ * Authenticated when: exitCode === 0 AND either stdout OR stderr contains
82
+ * "logged in" (case-insensitive). The haystack is built from both streams
83
+ * because `codex login status` writes to stderr in practice.
84
+ *
85
+ * Plan: null — codex login status does not expose a subscription/plan label.
86
+ * Conservative: on any unexpected output, authenticated stays false and plan is null.
87
+ *
88
+ * @remarks Codex has no plan/subscription field in `codex login status` output.
89
+ * plan is always null; it is never fabricated.
90
+ */
91
+ export function parseCodexAuth(stdout, stderr, exitCode) {
92
+ if (exitCode !== 0) {
93
+ return { authenticated: false, plan: null };
94
+ }
95
+ // Build haystack from both streams — codex login status uses stderr in practice.
96
+ const haystack = (stdout + '\n' + stderr).toLowerCase();
97
+ const authenticated = haystack.includes('logged in');
98
+ return { authenticated, plan: null };
99
+ }
100
+ // ---------------------------------------------------------------------------
27
101
  // Public API
28
102
  // ---------------------------------------------------------------------------
29
103
  /**
30
- * Detect whether a provider CLI is installed and (optimistically) usable.
104
+ * Detect whether a provider CLI is installed and probe its real auth state.
31
105
  *
32
- * For 'claude': runs `claude --version` to confirm the binary is present and
33
- * executable. Authentication is reported as `true` optimistically we cannot
34
- * cheaply probe auth state without spending API quota. If the user is not
35
- * authenticated, the real auth failure surfaces at run time via classifyError()
36
- * (category 'auth').
106
+ * For 'claude': runs `claude --version` to confirm the binary is present, then
107
+ * `claude auth status` (JSON output) to determine real auth state and plan.
108
+ * On spawn failure of the status command, falls back gracefully: installed
109
+ * remains true, authenticated false, plan null.
37
110
  *
38
- * For 'codex': runs `codex --version` to confirm the binary is present and
39
- * executable. Authentication is reported as `true` optimistically for the same
40
- * reason real auth failures surface at run time via classifyError().
111
+ * For 'codex': runs `codex --version` to confirm the binary is present, then
112
+ * `codex login status` to determine real auth state. Plan is always null because
113
+ * `codex login status` does not expose subscription information.
114
+ * On spawn failure of the status command, falls back gracefully: installed
115
+ * remains true, authenticated false, plan null.
41
116
  */
42
117
  export async function detectProvider(id) {
43
118
  if (id === 'claude') {
@@ -47,18 +122,29 @@ export async function detectProvider(id) {
47
122
  timeout: 10_000,
48
123
  });
49
124
  if (result.exitCode === 0) {
125
+ // Binary confirmed present — now probe real auth state.
126
+ let authenticated = false;
127
+ let plan = null;
128
+ try {
129
+ const authResult = await execa('claude', ['auth', 'status'], {
130
+ reject: false,
131
+ timeout: 10_000,
132
+ });
133
+ const parsed = parseClaudeAuth(typeof authResult.stdout === 'string' ? authResult.stdout : '', typeof authResult.stderr === 'string' ? authResult.stderr : '', authResult.exitCode ?? 1);
134
+ authenticated = parsed.authenticated;
135
+ plan = parsed.plan;
136
+ }
137
+ catch {
138
+ // Spawn failure — leave authenticated false, plan null
139
+ }
50
140
  return {
51
141
  id: 'claude',
52
142
  installed: true,
53
143
  version: result.stdout.trim(),
54
144
  binaryPath: 'claude',
55
145
  availableModels: ['opus', 'sonnet', 'haiku'],
56
- /**
57
- * Authentication is OPTIMISTIC: we assume the user is authenticated
58
- * if the binary is installed. The real auth state surfaces at run
59
- * time when classifyError() maps an auth-related stderr to 'auth'.
60
- */
61
- authenticated: true,
146
+ authenticated,
147
+ plan,
62
148
  };
63
149
  }
64
150
  }
@@ -67,25 +153,35 @@ export async function detectProvider(id) {
67
153
  }
68
154
  return notDetected('claude');
69
155
  }
70
- // codex: run `codex --version` to probe installation
156
+ // codex: run `codex --version` to probe installation, then `codex login status`
71
157
  try {
72
158
  const result = await execa('codex', ['--version'], {
73
159
  reject: false,
74
160
  timeout: 10_000,
75
161
  });
76
162
  if (result.exitCode === 0) {
163
+ // Binary confirmed present — now probe real auth state.
164
+ let authenticated = false;
165
+ const plan = null; // codex login status never exposes plan
166
+ try {
167
+ const authResult = await execa('codex', ['login', 'status'], {
168
+ reject: false,
169
+ timeout: 10_000,
170
+ });
171
+ const parsed = parseCodexAuth(typeof authResult.stdout === 'string' ? authResult.stdout : '', typeof authResult.stderr === 'string' ? authResult.stderr : '', authResult.exitCode ?? 1);
172
+ authenticated = parsed.authenticated;
173
+ }
174
+ catch {
175
+ // Spawn failure — leave authenticated false, plan null
176
+ }
77
177
  return {
78
178
  id: 'codex',
79
179
  installed: true,
80
180
  version: result.stdout.trim(),
81
181
  binaryPath: 'codex',
82
182
  availableModels: ['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini'],
83
- /**
84
- * Authentication is OPTIMISTIC: we assume the user is authenticated
85
- * if the binary is installed. The real auth state surfaces at run
86
- * time when classifyError() maps an auth-related stderr to 'auth'.
87
- */
88
- authenticated: true,
183
+ authenticated,
184
+ plan,
89
185
  };
90
186
  }
91
187
  }
@@ -1 +1 @@
1
- {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/providers/detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAsB9B,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,WAAW,CAAC,EAAsB;IACzC,OAAO;QACL,EAAE;QACF,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,IAAI;QACb,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,IAAI;QAChB,eAAe,EAAE,EAAE;KACpB,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAsB;IAEtB,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE;gBAClD,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,MAAM;aAChB,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO;oBACL,EAAE,EAAE,QAAQ;oBACZ,SAAS,EAAE,IAAI;oBACf,OAAO,EAAG,MAAM,CAAC,MAAiB,CAAC,IAAI,EAAE;oBACzC,UAAU,EAAE,QAAQ;oBACpB,eAAe,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC;oBAC5C;;;;uBAIG;oBACH,aAAa,EAAE,IAAI;iBACpB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;QAClE,CAAC;QAED,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,qDAAqD;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE;YACjD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,EAAE,EAAE,OAAO;gBACX,SAAS,EAAE,IAAI;gBACf,OAAO,EAAG,MAAM,CAAC,MAAiB,CAAC,IAAI,EAAE;gBACzC,UAAU,EAAE,OAAO;gBACnB,eAAe,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,CAAC;gBACvD;;;;mBAIG;gBACH,aAAa,EAAE,IAAI;aACpB,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;IAClE,CAAC;IAED,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,cAAc,CAAC,QAAQ,CAAC;QACxB,cAAc,CAAC,OAAO,CAAC;KACxB,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,KAAK;QACL,cAAc,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS;QACnD,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAsB;IACtD,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,QAAQ;YACX,OAAO,0CAA0C,CAAC;QACpD,KAAK,OAAO;YACV,OAAO,8BAA8B,CAAC;IAC1C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/providers/detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * src/ui/tui.ts — Terminal UI rendering kit for myshell-tools v2.
3
+ *
4
+ * Zero-dependency pure string builders. Every color-emitting function accepts
5
+ * an explicit `color: boolean` argument; when false, no ANSI escape codes are
6
+ * emitted — safe for CI, pipes, and tests.
7
+ *
8
+ * Ported from dual-brain/src/tui.ts. Self-test block omitted (no I/O, no
9
+ * file reads, no import.meta.url branching). Math.random is never used.
10
+ *
11
+ * Honesty Contract: no hardcoded percentages, no fabricated figures, no mock
12
+ * AI-response phrases.
13
+ */
14
+ /**
15
+ * Strip ANSI escape codes from a string.
16
+ */
17
+ export declare function stripAnsi(s: string): string;
18
+ /**
19
+ * Visible display width of a string.
20
+ * Strips ANSI codes first, then counts emoji/wide symbols as 2 columns.
21
+ *
22
+ * Variation selectors (U+FE00–U+FE0F, including U+FE0F / VS16) are counted
23
+ * as zero-width: a base symbol + VS16 (e.g. ⚠️ = U+26A0 + U+FE0F) renders
24
+ * as a single 2-column glyph in terminals — not 4 columns. Treating the
25
+ * variation selector as zero-width keeps box borders aligned.
26
+ */
27
+ export declare function visibleLength(s: string): number;
28
+ /**
29
+ * Right-pad `s` with spaces so its visible width equals `width`.
30
+ * Accounts for wide emoji and ANSI codes.
31
+ */
32
+ export declare function pad(s: string, width: number): string;
33
+ /**
34
+ * Renders a Unicode double-line box with a title bar and optional content lines.
35
+ *
36
+ * @param title - Title displayed in the top section.
37
+ * @param lines - Body lines displayed below the title divider.
38
+ * @param opts - Optional: `width` controls the inner content width (default 56).
39
+ */
40
+ export declare function box(title: string, lines?: string[], opts?: {
41
+ width?: number;
42
+ }): string;
43
+ /**
44
+ * Renders a percentage progress bar using block characters.
45
+ * Clamps `percent` to 0–100. The percentage value is assembled by
46
+ * concatenation to avoid a digit-immediately-before-% literal in source.
47
+ *
48
+ * @param percent - Value to display (clamped 0–100).
49
+ * @param width - Track width in characters (default 20).
50
+ * @param opts - Optional label appended after the percentage.
51
+ */
52
+ export declare function bar(percent: number, width?: number, opts?: {
53
+ label?: string;
54
+ }): string;
55
+ /**
56
+ * Returns a status badge emoji for the given status key.
57
+ * Unmapped keys return ❓.
58
+ */
59
+ export declare function badge(status: string): string;
60
+ /**
61
+ * Returns a section separator line. When a label is provided it is included
62
+ * after the dash run.
63
+ */
64
+ export declare function separator(label?: string): string;
65
+ /**
66
+ * Renders a menu grouped by section, with section separators.
67
+ * Items with the same `section` value are grouped together.
68
+ * Rows are formatted as ` [key] label`.
69
+ *
70
+ * @param options - Array of menu items; `section` is optional.
71
+ */
72
+ export declare function menu(options: ReadonlyArray<{
73
+ key: string;
74
+ label: string;
75
+ section?: string;
76
+ }>): string;
77
+ /**
78
+ * Renders a rounded-corner panel box with a title bar.
79
+ *
80
+ * @param title - Panel title.
81
+ * @param content - Content string or array of strings.
82
+ * @param color - When false, no ANSI codes are emitted.
83
+ * @param opts - Optional: `width` (default 70).
84
+ */
85
+ export declare function panel(title: string, content: string | string[], color: boolean, opts?: {
86
+ width?: number;
87
+ }): string;
88
+ /**
89
+ * Renders a mid-section horizontal divider using rounded-corner tee chars.
90
+ *
91
+ * @param width - Total display width (default: uses full width chars).
92
+ * @param color - When false, no ANSI codes are emitted.
93
+ */
94
+ export declare function divider(width: number, color: boolean): string;
95
+ /**
96
+ * Renders a small status chip: a colored dot + dim label.
97
+ *
98
+ * @param label - Text label.
99
+ * @param healthy - True → green dot, false → red dot.
100
+ * @param color - When false, no ANSI codes are emitted.
101
+ */
102
+ export declare function statusChip(label: string, healthy: boolean, color: boolean): string;
103
+ /**
104
+ * Renders a single line with `left` and `right` text separated by spaces to
105
+ * fill the given width.
106
+ *
107
+ * @param left - Left-aligned content (may include ANSI codes).
108
+ * @param right - Right-aligned content (may include ANSI codes).
109
+ * @param width - Total line width (default 70).
110
+ */
111
+ export declare function headerBar(left: string, right: string, width?: number): string;
112
+ /**
113
+ * Renders a styled prompt line.
114
+ *
115
+ * @param text - Prompt hint text (leading `>` is stripped if present).
116
+ * @param color - When false, no ANSI codes are emitted.
117
+ */
118
+ export declare function prompt(text: string, color: boolean): string;
119
+ /**
120
+ * Renders a one-line signal/log entry with a type icon.
121
+ *
122
+ * @param type - 'success' | 'warning' | 'info'
123
+ * @param text - Main message text.
124
+ * @param color - When false, no ANSI codes are emitted.
125
+ * @param meta - Optional dim metadata appended at the end.
126
+ */
127
+ export declare function signalLine(type: 'success' | 'warning' | 'info', text: string, color: boolean, meta?: string): string;