@easbot/terminal 0.3.11 → 0.3.12
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.
- package/README.en.md +165 -14
- package/README.md +162 -15
- package/dist/index.cjs +15 -9
- package/dist/index.d.cts +108 -11
- package/dist/index.d.ts +108 -11
- package/dist/index.mjs +15 -9
- package/package.json +3 -4
package/README.en.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# @easbot/terminal
|
|
4
4
|
|
|
5
|
-
> Terminal interaction toolkit — unified terminal output, formatting, prompts, and state recovery for EASBOT
|
|
5
|
+
> Terminal interaction toolkit — unified terminal output, formatting, prompts, and state recovery for the EASBOT ecosystem.
|
|
6
6
|
|
|
7
7
|
## Introduction
|
|
8
8
|
|
|
9
|
-
`@easbot/terminal` is a terminal interaction toolkit for the EASBOT ecosystem. It encapsulates the common capabilities required by CLI / TUI scenarios: themed color output, ANSI handling, OSC-8 hyperlinks, table rendering, styled prompts, safe stream writes, progress-line management,
|
|
9
|
+
`@easbot/terminal` is a terminal interaction toolkit for the EASBOT ecosystem. It encapsulates the common capabilities required by CLI / TUI scenarios: themed color output, ANSI handling, OSC-8 hyperlinks, table rendering, styled prompts, safe stream writes, progress-line management, terminal-state recovery, an interactive searchable multi-select prompt, a simple CLI input helper, and a lightweight markdown renderer. Every module auto-detects terminal capability (`NO_COLOR` / `FORCE_COLOR` / TTY) and degrades gracefully in non-TTY environments (pipes, redirected files, CI logs).
|
|
10
|
+
|
|
11
|
+
The package is **vendor-neutral**: it does not hard-code any external doc site or vendor-specific configuration. Helper functions such as `formatRootedLink` / `formatRootLink` accept an explicit root URL, leaving integration choices to the caller.
|
|
10
12
|
|
|
11
13
|
## Features
|
|
12
14
|
|
|
@@ -18,10 +20,16 @@
|
|
|
18
20
|
- **Table rendering** — `renderTable` with auto-fit columns, Unicode / ASCII / borderless styles, ANSI-safe wrapping
|
|
19
21
|
- **Command output formatting** — success / error / warning / info / heading / key-value / command / list / status / count helpers
|
|
20
22
|
- **Styled prompts** — styled wrappers around `@clack/prompts` (`selectStyled` / `note` / `stylePromptMessage` …)
|
|
23
|
+
- **Searchable multi-select** — `Search.multiselect` is an interactive, real-time-filtered, multi-select prompt with full keyboard control, optional locked section, and graceful stdin / signal cleanup
|
|
24
|
+
- **Loader** — `Loader.create()` returns a stateless spinner instance (no Component / TUI inheritance). Customizable frames, color, message; integrates with `MockTerminalIO` for tests
|
|
25
|
+
- **Input** — `Input.readText` / `Input.readConfirm` / `Input.readPassword` are readline-based helpers for CLI prompts; inject `input` / `output` streams for test isolation
|
|
26
|
+
- **Markdown** — `renderMarkdown` parses a minimal markdown subset (heading / list / code-block / bold / italic / link) without pulling in `marked`
|
|
21
27
|
- **Safe stream writer** — `createSafeStreamWriter` swallows `EPIPE` / `EIO`, so a closed pipe never throws
|
|
22
28
|
- **Progress line** — register / clear / unregister an active progress line (TTY-only)
|
|
23
29
|
- **Terminal-state recovery** — `restoreTerminalState` resets cursor, mouse tracking, and bracketed paste on exit
|
|
24
30
|
- **CLI JSON output** — `emitJsonOk` / `emitJsonError` implement the EASBOT CLI `--json` contract (`{ ok, data | error }`)
|
|
31
|
+
- **Color discipline** — every styled output goes through `isRich()` + `colorize()`, and snapshot / non-TTY runs never leak ANSI sequences
|
|
32
|
+
- **TTY injection for tests** — interactive components (e.g. `formatTerminalLink`, `Search.multiselect`, `Input.readText`) accept an optional `isTTY` parameter so unit tests can run without depending on `process.stdout.isTTY`
|
|
25
33
|
|
|
26
34
|
## Installation
|
|
27
35
|
|
|
@@ -73,10 +81,15 @@ console.log(formatStatus('running', 'Building...'));
|
|
|
73
81
|
```typescript
|
|
74
82
|
import { resolveUserPath, resolveConfigDir, displayPath, formatTerminalLink } from '@easbot/terminal';
|
|
75
83
|
|
|
76
|
-
const configDir = resolveConfigDir(); // ~/.
|
|
84
|
+
const configDir = resolveConfigDir(); // ~/.config/easbot (or $EASBOT_STATE_DIR if set)
|
|
77
85
|
console.log(displayPath(configDir));
|
|
78
86
|
|
|
87
|
+
// TTY: OSC-8 link; non-TTY: "Label (URL)" fallback
|
|
79
88
|
console.log(formatTerminalLink('EASBOT repo', 'https://github.com/houjallen/easbot'));
|
|
89
|
+
|
|
90
|
+
// Generic root-URL helper — call site controls the root (vendor-neutral)
|
|
91
|
+
import { formatRootedLink } from '@easbot/terminal';
|
|
92
|
+
console.log(formatRootedLink('https://docs.example.com', '/guide', 'Quick start'));
|
|
80
93
|
```
|
|
81
94
|
|
|
82
95
|
### Table rendering
|
|
@@ -95,7 +108,8 @@ console.log(
|
|
|
95
108
|
{ name: '@easbot/terminal', version: '0.3.11', status: '✓' },
|
|
96
109
|
{ name: '@easbot/note', version: '0.3.11', status: '✓' },
|
|
97
110
|
],
|
|
98
|
-
|
|
111
|
+
width: 80,
|
|
112
|
+
border: 'unicode',
|
|
99
113
|
}),
|
|
100
114
|
);
|
|
101
115
|
```
|
|
@@ -116,6 +130,77 @@ const choice = await selectStyled({
|
|
|
116
130
|
note(wrapNoteMessage('Config file saved to ~/.config/app/config.json'), 'Success');
|
|
117
131
|
```
|
|
118
132
|
|
|
133
|
+
### Loader (CLI spinner)
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { Loader, colorize, isRich, theme } from '@easbot/terminal';
|
|
137
|
+
|
|
138
|
+
const loader = Loader.create({
|
|
139
|
+
message: 'Loading…',
|
|
140
|
+
spinnerColor: (s) => colorize(isRich(), theme.accent, s),
|
|
141
|
+
messageColor: (s) => colorize(isRich(), theme.muted, s),
|
|
142
|
+
});
|
|
143
|
+
loader.start();
|
|
144
|
+
|
|
145
|
+
// Each tick: print the latest line (caller controls output)
|
|
146
|
+
process.stdout.write(`\r${loader.line()}\x1b[K`);
|
|
147
|
+
|
|
148
|
+
loader.stop();
|
|
149
|
+
process.stdout.write('\n');
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`Loader` is a **namespace** (stateless factory). It does not depend on any TUI component model — it returns a plain object with `start` / `stop` / `isRunning` / `line` / `setMessage` / `setIndicator`. Defaults: 10-frame Braille spinner, 80 ms interval.
|
|
153
|
+
|
|
154
|
+
### Input (readline-based prompts)
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { Input } from '@easbot/terminal';
|
|
158
|
+
|
|
159
|
+
const name = await Input.readText({ message: 'Name:' });
|
|
160
|
+
const ok = await Input.readConfirm({ message: 'Continue?' });
|
|
161
|
+
const pw = await Input.readPassword({ message: 'Password:' });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`Input` is a **namespace** with three stateless helpers. For tests, inject `input` / `output` streams (use `MockTerminalIO` from the `__tests__/helpers` path).
|
|
165
|
+
|
|
166
|
+
### Markdown (minimal subset)
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { renderMarkdown } from '@easbot/terminal';
|
|
170
|
+
|
|
171
|
+
console.log(renderMarkdown('# Title\n\nHello **world**.', { stripAnsi: true }).join('\n'));
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Supports `# / ## / ###` headings, `-` / `*` / `1.` lists, fenced code blocks, and inline `**bold**` / `*italic*` / `` `code` `` / `[text](url)`. Does not depend on `marked` — keeps the bundle small for CLI output.
|
|
175
|
+
|
|
176
|
+
### Searchable multi-select
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { Search, cancelSymbol } from '@easbot/terminal';
|
|
180
|
+
|
|
181
|
+
const result = await Search.multiselect({
|
|
182
|
+
message: 'Select agents to enable:',
|
|
183
|
+
items: [
|
|
184
|
+
{ value: 'a', label: 'Agent A', hint: 'General-purpose' },
|
|
185
|
+
{ value: 'b', label: 'Agent B', hint: 'Code-focused' },
|
|
186
|
+
],
|
|
187
|
+
required: true,
|
|
188
|
+
lockedSection: {
|
|
189
|
+
title: 'Always included',
|
|
190
|
+
items: [{ value: 'core', label: 'Core agent' }],
|
|
191
|
+
hiddenCount: 2,
|
|
192
|
+
},
|
|
193
|
+
// Test / embedded scenarios can override the TTY state explicitly:
|
|
194
|
+
// isTTY: true // force raw mode + colors
|
|
195
|
+
// isTTY: false // force no raw mode and no colors
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
if (result === cancelSymbol) return;
|
|
199
|
+
// result is T[] of selected values
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Keyboard shortcuts: `↑↓ ←→` move · `PageUp/Down` page · `Home/End` jump · `Space` toggle · `Backspace` delete search · `Enter` confirm · `Esc` / `Ctrl+C` cancel.
|
|
203
|
+
|
|
119
204
|
### Safe stream writes & state recovery
|
|
120
205
|
|
|
121
206
|
```typescript
|
|
@@ -148,10 +233,10 @@ emitJsonError('E_NOT_FOUND', 'Resource not found');
|
|
|
148
233
|
|
|
149
234
|
### Theme & styling
|
|
150
235
|
|
|
151
|
-
- `theme` — themed color helpers (`accent`, `info`, `success`, `warn`, `error`, `muted`, `heading`, `command`, `option`)
|
|
236
|
+
- `theme` — themed color helpers (`accent`, `accentBright`, `accentDim`, `info`, `success`, `warn`, `error`, `muted`, `heading`, `command`, `option`)
|
|
152
237
|
- `isRich()` — whether the terminal supports rich color output
|
|
153
238
|
- `colorize(rich, color, value)` — conditional coloring helper
|
|
154
|
-
- `LOBSTER_PALETTE` — raw Lobster palette values
|
|
239
|
+
- `LOBSTER_PALETTE` — raw Lobster palette values (8 colors, `as const`)
|
|
155
240
|
|
|
156
241
|
### ANSI utilities
|
|
157
242
|
|
|
@@ -161,19 +246,20 @@ emitJsonError('E_NOT_FOUND', 'Resource not found');
|
|
|
161
246
|
### Paths & display
|
|
162
247
|
|
|
163
248
|
- `resolveUserPath(input)` — resolve user paths (supports `~`)
|
|
164
|
-
- `resolveConfigDir(env?, homedir?)` — resolve the config dir (
|
|
249
|
+
- `resolveConfigDir(env?, homedir?)` — resolve the config dir (overridable via `EASBOT_STATE_DIR`; defaults to `~/.config/easbot`)
|
|
165
250
|
- `resolveHomeDir()` — resolve the effective home directory
|
|
166
251
|
- `shortenHomePath(input)` / `displayPath(input)` — shorten the home prefix in a single path
|
|
167
252
|
- `shortenHomeInString(input)` / `displayString(input)` — replace every occurrence of the home prefix in a string
|
|
168
253
|
- `resolveEffectiveHomeDir` / `resolveRequiredHomeDir` / `expandHomePrefix` — low-level home helpers
|
|
169
|
-
- `formatTerminalLink(label, url, opts?)` — format an OSC-8 hyperlink
|
|
170
|
-
- `
|
|
254
|
+
- `formatTerminalLink(label, url, opts?, isTTY?)` — format an OSC-8 hyperlink with explicit TTY injection
|
|
255
|
+
- `formatRootedLink(root, path, label?, opts?, isTTY?)` — generic root-URL link helper (vendor-neutral)
|
|
256
|
+
- `formatRootLink(root, label?, isTTY?)` — generic root-URL single link
|
|
171
257
|
|
|
172
258
|
### Command output formatting
|
|
173
259
|
|
|
174
|
-
- `formatSuccess` / `formatError` / `formatWarning` / `formatInfo`
|
|
175
|
-
- `formatHeading` / `formatKeyValue` / `formatCommandExample` / `formatListItem`
|
|
176
|
-
- `formatStatus` / `formatSeparator` / `formatEmptyMessage` / `formatCount`
|
|
260
|
+
- `formatSuccess` / `formatError` / `formatWarning` / `formatInfo` — icon-prefixed messages
|
|
261
|
+
- `formatHeading` / `formatKeyValue` / `formatCommandExample` / `formatListItem` — sections & lists
|
|
262
|
+
- `formatStatus` / `formatSeparator` / `formatEmptyMessage` / `formatCount` — progress & counters
|
|
177
263
|
|
|
178
264
|
### Tables
|
|
179
265
|
|
|
@@ -184,9 +270,54 @@ emitJsonError('E_NOT_FOUND', 'Resource not found');
|
|
|
184
270
|
|
|
185
271
|
- `stylePromptMessage` / `stylePromptTitle` / `stylePromptHint` — prompt text styling
|
|
186
272
|
- `selectStyled<T>(params)` — themed select prompt
|
|
187
|
-
- `note(message, title?)` — themed note box
|
|
273
|
+
- `note(message, title?, options?)` — themed note box (supports `columns` / `maxWidth` injection)
|
|
188
274
|
- `wrapNoteMessage(message, options?)` — auto-wrap a note's message
|
|
189
275
|
|
|
276
|
+
### Interactive multi-select
|
|
277
|
+
|
|
278
|
+
- `Search.multiselect<T>(options)` — searchable, real-time-filtered multi-select prompt
|
|
279
|
+
- `options.message` — prompt message
|
|
280
|
+
- `options.items` — selectable items
|
|
281
|
+
- `options.maxVisible?` — page size
|
|
282
|
+
- `options.initialSelected?` — pre-selected values (deduplicated)
|
|
283
|
+
- `options.required?` — reject empty submission
|
|
284
|
+
- `options.lockedSection?` — always-included partition
|
|
285
|
+
- `options.isTTY?` — explicit TTY state (test / embedded injection)
|
|
286
|
+
- `Search.cancelSymbol` — sentinel returned on cancel / stdin end
|
|
287
|
+
- `Search.approxStringWidth` / `Search.visualRowsForLine` / `Search.countVisualRowsForLines` — display-width helpers
|
|
288
|
+
- `cancelSymbol` — top-level re-export of `Search.cancelSymbol` (kept for backwards compatibility)
|
|
289
|
+
|
|
290
|
+
### Loader (CLI spinner)
|
|
291
|
+
|
|
292
|
+
`Loader` is a **namespace** with a single factory:
|
|
293
|
+
|
|
294
|
+
- `Loader.create(options?)` → `Loader.Instance`
|
|
295
|
+
- `options.message?` — main text (default `'Loading...'`)
|
|
296
|
+
- `options.spinnerColor?` — color function for the frame (default: `colorize(isRich(), theme.accent, ...)`)
|
|
297
|
+
- `options.messageColor?` — color function for the message (default: `colorize(isRich(), theme.muted, ...)`)
|
|
298
|
+
- `options.indicator?` — `{ frames?: string[]; intervalMs?: number }` (default: 10 Braille frames, 80 ms)
|
|
299
|
+
- `Loader.Instance`:
|
|
300
|
+
- `start()` — idempotent (restarts the interval)
|
|
301
|
+
- `stop()` — idempotent
|
|
302
|
+
- `isRunning()` — current animation state
|
|
303
|
+
- `line()` — current rendered line (`'<spinner> <message>'`)
|
|
304
|
+
- `setMessage(message)` — update text
|
|
305
|
+
- `setIndicator(indicator?)` — update frames / interval; auto-restarts
|
|
306
|
+
|
|
307
|
+
### Input (readline-based prompts)
|
|
308
|
+
|
|
309
|
+
`Input` is a **namespace** with three stateless helpers. Pass `input` / `output` to swap in a mock stream for tests.
|
|
310
|
+
|
|
311
|
+
- `Input.readText(options)` — read a single line. Options: `message`, `hint?`, `defaultValue?`, `hidden?`, `messageColor?`, `hintColor?`, `input?`, `output?`
|
|
312
|
+
- `Input.readConfirm(options)` — yes/no prompt; recursively re-prompts on invalid input. Options: `message`, `hint?`, `defaultValue?` (default `true`)
|
|
313
|
+
- `Input.readPassword(options)` — alias for `readText` with `hidden: true`
|
|
314
|
+
|
|
315
|
+
### Markdown (minimal subset)
|
|
316
|
+
|
|
317
|
+
- `renderMarkdown(md, opts?)` → `string[]` (one entry per logical line)
|
|
318
|
+
- Supports: `# / ## / ###` headings, `---` horizontal rules, `- / * / 1.` lists, fenced code blocks (` ``` `), inline `**bold**` / `*italic*` / `` `code` `` / `[text](url)`
|
|
319
|
+
- `opts.headingColor?` / `boldColor?` / `italicColor?` / `codeColor?` / `linkColor?` — color functions to override the default theme
|
|
320
|
+
|
|
190
321
|
### CLI JSON output
|
|
191
322
|
|
|
192
323
|
- `emitJsonOk(data, meta?)` — emit `{ ok: true, data, meta? }`
|
|
@@ -198,10 +329,12 @@ emitJsonError('E_NOT_FOUND', 'Resource not found');
|
|
|
198
329
|
- `createSafeStreamWriter(options?)` — create a writer that swallows `EPIPE` / `EIO`
|
|
199
330
|
- `registerActiveProgressLine(stream)` / `clearActiveProgressLine()` / `unregisterActiveProgressLine(stream?)` — progress line management
|
|
200
331
|
- `restoreTerminalState(reason?, options?)` — restore cursor / mouse / bracketed-paste state
|
|
332
|
+
- `RestoreTerminalStateOptions` — `{ resumeStdin? | resumeStdinIfPaused? }` (default `false`; Docker TTY behavior)
|
|
201
333
|
|
|
202
334
|
### Misc
|
|
203
335
|
|
|
204
336
|
- `styleHealthChannelLine(line, rich)` — themed health-check channel line
|
|
337
|
+
- `StatusKind` — `'pending' | 'running' | 'success' | 'error' | 'skipped'`
|
|
205
338
|
|
|
206
339
|
## Environment Variables
|
|
207
340
|
|
|
@@ -210,8 +343,12 @@ emitJsonError('E_NOT_FOUND', 'Resource not found');
|
|
|
210
343
|
| `NO_COLOR` | Disables colors when set (unless `FORCE_COLOR` is also set) — see [no-color.org](https://no-color.org/) |
|
|
211
344
|
| `FORCE_COLOR` | Forces colors when non-empty and not equal to `'0'` |
|
|
212
345
|
| `HOME` / `USERPROFILE` | Fallback sources for home directory resolution |
|
|
346
|
+
| `EASBOT_TEST_HOME` | **Test-only** highest-priority home override (highest priority; see `home-dir.ts`) |
|
|
213
347
|
| `EASBOT_HOME` | Explicit override for the home directory; changes the display prefix from `~` to `$EASBOT_HOME` |
|
|
214
|
-
| `
|
|
348
|
+
| `EASBOT_STATE_DIR` | Override the resolved config directory |
|
|
349
|
+
|
|
350
|
+
**Home resolution order (highest to lowest):**
|
|
351
|
+
`EASBOT_TEST_HOME` → `EASBOT_HOME` → `HOME` → `USERPROFILE` → `os.homedir()`.
|
|
215
352
|
|
|
216
353
|
## Development
|
|
217
354
|
|
|
@@ -233,6 +370,20 @@ pnpm lint
|
|
|
233
370
|
pnpm format:fix
|
|
234
371
|
```
|
|
235
372
|
|
|
373
|
+
## Publishing
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Linux / macOS
|
|
377
|
+
pnpm publish:npm # = bash scripts/publish.sh
|
|
378
|
+
|
|
379
|
+
# Windows PowerShell
|
|
380
|
+
pnpm publish:npm:win # = powershell -ExecutionPolicy Bypass -File scripts/publish.ps1
|
|
381
|
+
|
|
382
|
+
# Equivalent manual flow
|
|
383
|
+
pnpm build
|
|
384
|
+
pnpm publish --access public --git-checks false --registry https://registry.npmjs.org
|
|
385
|
+
```
|
|
386
|
+
|
|
236
387
|
## License
|
|
237
388
|
|
|
238
389
|
MIT
|
package/README.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# @easbot/terminal
|
|
4
4
|
|
|
5
|
-
> 终端交互工具库 — 为 EASBOT
|
|
5
|
+
> 终端交互工具库 — 为 EASBOT 生态提供统一的终端输出、格式化、提示与状态恢复能力。
|
|
6
6
|
|
|
7
7
|
## 简介
|
|
8
8
|
|
|
9
|
-
`@easbot/terminal` 是一个面向 EASBOT 生态的终端交互工具库,封装了命令行 / TUI 场景下常用的能力:终端主题色、ANSI
|
|
9
|
+
`@easbot/terminal` 是一个面向 EASBOT 生态的终端交互工具库,封装了命令行 / TUI 场景下常用的能力:终端主题色、ANSI 处理、超链接、表格渲染、提示样式、安全流写入、进度行管理、终端状态恢复、一个**可搜索的多选交互 prompt**、一个**CLI 输入 helper** 以及一个**轻量级 markdown 渲染器**。所有能力都基于终端能力自动检测(`NO_COLOR` / `FORCE_COLOR` / TTY)进行降级,可在管道、文件重定向等非 TTY 场景下安全使用。
|
|
10
|
+
|
|
11
|
+
本包**完全 vendor-neutral**:不绑定任何外部文档站或 vendor-specific 配置。`formatRootedLink` / `formatRootLink` 等 helper 显式接受 `root` 参数,由调用方决定集成方式。
|
|
10
12
|
|
|
11
13
|
## 特性
|
|
12
14
|
|
|
@@ -18,10 +20,16 @@
|
|
|
18
20
|
- **表格渲染**:`renderTable` 支持自适应列宽、Unicode / ASCII / 无边框三种样式、文本换行、ANSI 样式保持
|
|
19
21
|
- **命令输出格式化**:成功 / 错误 / 警告 / 信息 / 标题 / 键值对 / 命令示例 / 列表项 / 进度状态 / 计数等
|
|
20
22
|
- **提示样式化**:`@clack/prompts` 的样式化封装(`selectStyled` / `note` / `stylePromptMessage` 等)
|
|
23
|
+
- **可搜索多选 prompt**:`Search.multiselect` 是交互式、实时过滤的多选 prompt,支持完整键盘控制、可选锁定分区、对 stdin / 信号优雅清理
|
|
24
|
+
- **Loader 旋转动画**:`Loader.create()` 返回**stateless** spinner 实例(不继承 tui 组件模型),可定制帧 / 颜色 / 消息
|
|
25
|
+
- **Input CLI 输入**:`Input.readText` / `Input.readConfirm` / `Input.readPassword` 是 readline 薄包装的 CLI prompt;支持注入 `input` / `output` 用于测试隔离
|
|
26
|
+
- **Markdown 渲染**:`renderMarkdown` 解析极简 markdown 子集(标题 / 列表 / 代码块 / 加粗 / 斜体 / 链接),**不引 `marked`**,保持 CLI 包体小
|
|
21
27
|
- **安全流写入**:`createSafeStreamWriter` 自动处理 `EPIPE` / `EIO`,流关闭后静默忽略后续写入
|
|
22
28
|
- **进度行管理**:注册 / 清除 / 注销活动进度行,仅在 TTY 下生效
|
|
23
29
|
- **终端状态恢复**:`restoreTerminalState` 在退出 / 异常时重置光标、鼠标跟踪、括号粘贴模式
|
|
24
30
|
- **JSON 规范输出**:`emitJsonOk` / `emitJsonError` 实现 CLI `--json` 规范的 `{ ok, data | error }` 协议
|
|
31
|
+
- **色彩一致性**:所有样式化输出统一经过 `isRich()` + `colorize()`,快照 / 非 TTY 场景不会泄漏 ANSI 转义
|
|
32
|
+
- **TTY 注入**:交互组件(`formatTerminalLink`、`Search.multiselect`、`Input.readText` 等)接受可选 `isTTY` 参数,单元测试不再依赖 `process.stdout.isTTY`
|
|
25
33
|
|
|
26
34
|
## 安装
|
|
27
35
|
|
|
@@ -73,10 +81,15 @@ console.log(formatStatus('running', '正在执行构建...'));
|
|
|
73
81
|
```typescript
|
|
74
82
|
import { resolveUserPath, resolveConfigDir, displayPath, formatTerminalLink } from '@easbot/terminal';
|
|
75
83
|
|
|
76
|
-
const configDir = resolveConfigDir(); // ~/.
|
|
84
|
+
const configDir = resolveConfigDir(); // ~/.config/easbot(如设了 EASBOT_STATE_DIR 则用之)
|
|
77
85
|
console.log(displayPath(configDir));
|
|
78
86
|
|
|
79
|
-
|
|
87
|
+
// TTY: OSC-8 链接;非 TTY: "Label (URL)" 降级
|
|
88
|
+
console.log(formatTerminalLink('EASBOT 仓库', 'https://github.com/houjallen/easbot'));
|
|
89
|
+
|
|
90
|
+
// 通用根域名 helper(vendor-neutral —— 调用方决定 root)
|
|
91
|
+
import { formatRootedLink } from '@easbot/terminal';
|
|
92
|
+
console.log(formatRootedLink('https://docs.example.com', '/guide', '快速开始'));
|
|
80
93
|
```
|
|
81
94
|
|
|
82
95
|
### 表格渲染
|
|
@@ -95,7 +108,8 @@ console.log(
|
|
|
95
108
|
{ name: '@easbot/terminal', version: '0.3.11', status: '✓' },
|
|
96
109
|
{ name: '@easbot/note', version: '0.3.11', status: '✓' },
|
|
97
110
|
],
|
|
98
|
-
|
|
111
|
+
width: 80,
|
|
112
|
+
border: 'unicode',
|
|
99
113
|
}),
|
|
100
114
|
);
|
|
101
115
|
```
|
|
@@ -116,6 +130,77 @@ const choice = await selectStyled({
|
|
|
116
130
|
note(wrapNoteMessage('配置文件已成功保存到 ~/.config/app/config.json'), '成功');
|
|
117
131
|
```
|
|
118
132
|
|
|
133
|
+
### Loader 旋转动画
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { Loader, colorize, isRich, theme } from '@easbot/terminal';
|
|
137
|
+
|
|
138
|
+
const loader = Loader.create({
|
|
139
|
+
message: '正在加载…',
|
|
140
|
+
spinnerColor: (s) => colorize(isRich(), theme.accent, s),
|
|
141
|
+
messageColor: (s) => colorize(isRich(), theme.muted, s),
|
|
142
|
+
});
|
|
143
|
+
loader.start();
|
|
144
|
+
|
|
145
|
+
// 每帧调用 line() 取出最新一行的文本
|
|
146
|
+
process.stdout.write(`\r${loader.line()}\x1b[K`);
|
|
147
|
+
|
|
148
|
+
loader.stop();
|
|
149
|
+
process.stdout.write('\n');
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`Loader` 是一个 **namespace**(stateless 工厂),不依赖 tui 组件模型 —— 返回一个普通对象,方法:`start` / `stop` / `isRunning` / `line` / `setMessage` / `setIndicator`。默认:10 帧 Braille spinner,80 ms 间隔。
|
|
153
|
+
|
|
154
|
+
### Input CLI 输入
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { Input } from '@easbot/terminal';
|
|
158
|
+
|
|
159
|
+
const name = await Input.readText({ message: '请输入名称:' });
|
|
160
|
+
const ok = await Input.readConfirm({ message: '继续吗?' });
|
|
161
|
+
const pw = await Input.readPassword({ message: '密码:' });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`Input` 是一个 **namespace**,含 3 个 stateless helper。测试时通过 `input` / `output` 注入 mock stream(使用 `__tests__/helpers/mock-terminal.ts` 的 `MockTerminalIO`)。
|
|
165
|
+
|
|
166
|
+
### Markdown 渲染
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { renderMarkdown } from '@easbot/terminal';
|
|
170
|
+
|
|
171
|
+
console.log(renderMarkdown('# 标题\n\n这是一段 **加粗** 文本。').join('\n'));
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
支持 `# / ## / ###` 标题、`- / * / 1.` 列表、围栏代码块、行内 `**加粗**` / `*斜体*` / `` `code` `` / `[文本](链接)`。**不依赖 `marked`**,保持 CLI 包体小。
|
|
175
|
+
|
|
176
|
+
### 可搜索多选(`Search.multiselect`)
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { Search, cancelSymbol } from '@easbot/terminal';
|
|
180
|
+
|
|
181
|
+
const result = await Search.multiselect({
|
|
182
|
+
message: '请选择要启用的 Agent:',
|
|
183
|
+
items: [
|
|
184
|
+
{ value: 'a', label: 'Agent A', hint: '通用任务' },
|
|
185
|
+
{ value: 'b', label: 'Agent B', hint: '代码导向' },
|
|
186
|
+
],
|
|
187
|
+
required: true,
|
|
188
|
+
lockedSection: {
|
|
189
|
+
title: '始终包含',
|
|
190
|
+
items: [{ value: 'core', label: '核心 Agent' }],
|
|
191
|
+
hiddenCount: 2,
|
|
192
|
+
},
|
|
193
|
+
// 测试 / 嵌入式场景可显式注入 TTY 状态:
|
|
194
|
+
// isTTY: true // 强制启用 raw mode + 颜色
|
|
195
|
+
// isTTY: false // 强制禁用 raw mode 与颜色
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
if (result === cancelSymbol) return;
|
|
199
|
+
// result 为已选项的值数组(type T[])
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
键盘约定:`↑↓ ←→` 单步移动 · `PageUp/Down` 翻页 · `Home/End` 跳首末 · `Space` 切换 · `Backspace` 删除搜索字符 · `Enter` 提交 · `Esc` / `Ctrl+C` 取消。
|
|
203
|
+
|
|
119
204
|
### 安全流写入与状态恢复
|
|
120
205
|
|
|
121
206
|
```typescript
|
|
@@ -148,10 +233,10 @@ emitJsonError('E_NOT_FOUND', '资源不存在');
|
|
|
148
233
|
|
|
149
234
|
### 主题与样式
|
|
150
235
|
|
|
151
|
-
- `theme` —
|
|
236
|
+
- `theme` — 主题颜色对象(`accent` / `accentBright` / `accentDim` / `info` / `success` / `warn` / `error` / `muted` / `heading` / `command` / `option`)
|
|
152
237
|
- `isRich()` — 判断终端是否支持富文本颜色
|
|
153
238
|
- `colorize(rich, color, value)` — 条件着色工具
|
|
154
|
-
- `LOBSTER_PALETTE` — Lobster
|
|
239
|
+
- `LOBSTER_PALETTE` — Lobster 调色板原始色值(8 种颜色,`as const` 锁定)
|
|
155
240
|
|
|
156
241
|
### ANSI 工具
|
|
157
242
|
|
|
@@ -161,19 +246,20 @@ emitJsonError('E_NOT_FOUND', '资源不存在');
|
|
|
161
246
|
### 路径与显示
|
|
162
247
|
|
|
163
248
|
- `resolveUserPath(input)` — 解析用户路径(支持 `~` 波浪号)
|
|
164
|
-
- `resolveConfigDir(env?, homedir?)` —
|
|
249
|
+
- `resolveConfigDir(env?, homedir?)` — 解析配置目录(可被 `EASBOT_STATE_DIR` 覆盖;默认 `~/.config/easbot`)
|
|
165
250
|
- `resolveHomeDir()` — 解析用户主目录
|
|
166
251
|
- `shortenHomePath(input)` / `displayPath(input)` — 缩短路径中的主目录部分
|
|
167
252
|
- `shortenHomeInString(input)` / `displayString(input)` — 替换字符串中所有匹配的主目录路径
|
|
168
253
|
- `resolveEffectiveHomeDir` / `resolveRequiredHomeDir` / `expandHomePrefix` — 主目录解析工具
|
|
169
|
-
- `formatTerminalLink(label, url, opts?)` — 格式化 OSC-8
|
|
170
|
-
- `
|
|
254
|
+
- `formatTerminalLink(label, url, opts?, isTTY?)` — 格式化 OSC-8 终端超链接,支持 `isTTY` 注入
|
|
255
|
+
- `formatRootedLink(root, path, label?, opts?, isTTY?)` — 通用根 URL 链接 helper(vendor-neutral)
|
|
256
|
+
- `formatRootLink(root, label?, isTTY?)` — 通用根 URL 单链接
|
|
171
257
|
|
|
172
258
|
### 命令输出格式化
|
|
173
259
|
|
|
174
|
-
- `formatSuccess` / `formatError` / `formatWarning` / `formatInfo`
|
|
175
|
-
- `formatHeading` / `formatKeyValue` / `formatCommandExample` / `formatListItem`
|
|
176
|
-
- `formatStatus` / `formatSeparator` / `formatEmptyMessage` / `formatCount`
|
|
260
|
+
- `formatSuccess` / `formatError` / `formatWarning` / `formatInfo` — 带图标的前缀消息
|
|
261
|
+
- `formatHeading` / `formatKeyValue` / `formatCommandExample` / `formatListItem` — 章节与列表
|
|
262
|
+
- `formatStatus` / `formatSeparator` / `formatEmptyMessage` / `formatCount` — 进度与计数
|
|
177
263
|
|
|
178
264
|
### 表格
|
|
179
265
|
|
|
@@ -184,9 +270,54 @@ emitJsonError('E_NOT_FOUND', '资源不存在');
|
|
|
184
270
|
|
|
185
271
|
- `stylePromptMessage` / `stylePromptTitle` / `stylePromptHint` — 提示文本样式化
|
|
186
272
|
- `selectStyled<T>(params)` — 样式化的选择提示
|
|
187
|
-
- `note(message, title?)` —
|
|
273
|
+
- `note(message, title?, options?)` — 样式化的注释框(支持 `columns` / `maxWidth` 注入)
|
|
188
274
|
- `wrapNoteMessage(message, options?)` — 注释消息自动换行
|
|
189
275
|
|
|
276
|
+
### 交互式多选
|
|
277
|
+
|
|
278
|
+
- `Search.multiselect<T>(options)` — 可搜索、实时过滤的多选 prompt
|
|
279
|
+
- `options.message` — 提示信息
|
|
280
|
+
- `options.items` — 候选项列表
|
|
281
|
+
- `options.maxVisible?` — 每页显示条数
|
|
282
|
+
- `options.initialSelected?` — 预选值集合(去重)
|
|
283
|
+
- `options.required?` — 是否强制至少选一项
|
|
284
|
+
- `options.lockedSection?` — 始终包含的锁定分区
|
|
285
|
+
- `options.isTTY?` — 显式 TTY 状态(测试 / 嵌入式注入)
|
|
286
|
+
- `Search.cancelSymbol` — 用户取消或 stdin 关闭时返回的哨兵值
|
|
287
|
+
- `Search.approxStringWidth` / `Search.visualRowsForLine` / `Search.countVisualRowsForLines` — 渲染器用到的显示宽度辅助
|
|
288
|
+
- `cancelSymbol` — 顶层再导出,等价于 `Search.cancelSymbol`(保留旧调用点无需改动)
|
|
289
|
+
|
|
290
|
+
### Loader 旋转动画
|
|
291
|
+
|
|
292
|
+
`Loader` 是 **namespace**,提供单一工厂方法:
|
|
293
|
+
|
|
294
|
+
- `Loader.create(options?)` → `Loader.Instance`
|
|
295
|
+
- `options.message?` — 主文本(默认 `'Loading...'`)
|
|
296
|
+
- `options.spinnerColor?` — 帧字符颜色函数(默认 `colorize(isRich(), theme.accent, ...)`)
|
|
297
|
+
- `options.messageColor?` — 消息颜色函数(默认 `colorize(isRich(), theme.muted, ...)`)
|
|
298
|
+
- `options.indicator?` — `{ frames?: string[]; intervalMs?: number }`(默认 10 帧 Braille / 80 ms)
|
|
299
|
+
- `Loader.Instance`:
|
|
300
|
+
- `start()` — 幂等(重启 interval)
|
|
301
|
+
- `stop()` — 幂等
|
|
302
|
+
- `isRunning()` — 当前动画状态
|
|
303
|
+
- `line()` — 当前渲染行(`'帧 消息'`)
|
|
304
|
+
- `setMessage(message)` — 更新文本
|
|
305
|
+
- `setIndicator(indicator?)` — 更新帧 / 间隔;自动重启
|
|
306
|
+
|
|
307
|
+
### Input CLI 输入
|
|
308
|
+
|
|
309
|
+
`Input` 是 **namespace**,含 3 个 stateless helper。测试时通过 `input` / `output` 注入 mock stream。
|
|
310
|
+
|
|
311
|
+
- `Input.readText(options)` — 读单行。Options: `message` / `hint?` / `defaultValue?` / `hidden?` / `messageColor?` / `hintColor?` / `input?` / `output?`
|
|
312
|
+
- `Input.readConfirm(options)` — y/n 确认,无效输入会递归重试。Options: `message` / `hint?` / `defaultValue?`(默认 `true`)
|
|
313
|
+
- `Input.readPassword(options)` — `readText` 的 `hidden: true` 别名
|
|
314
|
+
|
|
315
|
+
### Markdown 渲染
|
|
316
|
+
|
|
317
|
+
- `renderMarkdown(md, opts?)` → `string[]`(每行一段)
|
|
318
|
+
- 支持:`# / ## / ###` 标题、`---` 分隔线、`- / * / 1.` 列表、围栏代码块(` ``` `)、行内 `**加粗**` / `*斜体*` / `` `code` `` / `[文本](链接)`
|
|
319
|
+
- `opts.headingColor?` / `boldColor?` / `italicColor?` / `codeColor?` / `linkColor?` — 覆盖默认主题的颜色函数
|
|
320
|
+
|
|
190
321
|
### JSON 规范输出
|
|
191
322
|
|
|
192
323
|
- `emitJsonOk(data, meta?)` — 输出 `{ ok: true, data, meta? }` JSON 响应
|
|
@@ -198,10 +329,12 @@ emitJsonError('E_NOT_FOUND', '资源不存在');
|
|
|
198
329
|
- `createSafeStreamWriter(options?)` — 创建安全流写入器,自动处理 `EPIPE` / `EIO`
|
|
199
330
|
- `registerActiveProgressLine(stream)` / `clearActiveProgressLine()` / `unregisterActiveProgressLine(stream?)` — 进度行管理
|
|
200
331
|
- `restoreTerminalState(reason?, options?)` — 恢复终端状态(光标 / 鼠标 / 括号粘贴模式)
|
|
332
|
+
- `RestoreTerminalStateOptions` — `{ resumeStdin? | resumeStdinIfPaused? }`(默认 `false`;Docker TTY 行为)
|
|
201
333
|
|
|
202
334
|
### 其它
|
|
203
335
|
|
|
204
336
|
- `styleHealthChannelLine(line, rich)` — 健康检查通道行样式化
|
|
337
|
+
- `StatusKind` — `'pending' | 'running' | 'success' | 'error' | 'skipped'`
|
|
205
338
|
|
|
206
339
|
## 环境变量
|
|
207
340
|
|
|
@@ -210,8 +343,12 @@ emitJsonError('E_NOT_FOUND', '资源不存在');
|
|
|
210
343
|
| `NO_COLOR` | 存在时禁用终端颜色(除非同时设置了 `FORCE_COLOR`),遵循 [no-color.org](https://no-color.org/) 规范 |
|
|
211
344
|
| `FORCE_COLOR` | 非空且不为 `'0'` 时强制启用颜色 |
|
|
212
345
|
| `HOME` / `USERPROFILE` | 主目录解析的备选来源(OS 默认值) |
|
|
346
|
+
| `EASBOT_TEST_HOME` | **测试专用** 最高优先级的主目录覆盖(详见 `home-dir.ts`) |
|
|
213
347
|
| `EASBOT_HOME` | 显式指定主目录;设置后路径显示前缀由 `~` 切换为 `$EASBOT_HOME` |
|
|
214
|
-
| `
|
|
348
|
+
| `EASBOT_STATE_DIR` | 配置目录覆盖项 |
|
|
349
|
+
|
|
350
|
+
**主目录解析顺序(高 → 低)**:
|
|
351
|
+
`EASBOT_TEST_HOME` → `EASBOT_HOME` → `HOME` → `USERPROFILE` → `os.homedir()`。
|
|
215
352
|
|
|
216
353
|
## 开发
|
|
217
354
|
|
|
@@ -233,6 +370,16 @@ pnpm lint
|
|
|
233
370
|
pnpm format:fix
|
|
234
371
|
```
|
|
235
372
|
|
|
373
|
+
## 发布
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Windows
|
|
377
|
+
powershell -ExecutionPolicy Bypass -File scripts/publish.ps1
|
|
378
|
+
|
|
379
|
+
# Unix/macOS
|
|
380
|
+
bash scripts/publish.sh
|
|
381
|
+
```
|
|
382
|
+
|
|
236
383
|
## 许可证
|
|
237
384
|
|
|
238
385
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
'use strict';var
|
|
2
|
-
`).flatMap(
|
|
3
|
-
`)}function
|
|
4
|
-
`);}catch(
|
|
5
|
-
`),reset:()=>{
|
|
6
|
-
`))){if(
|
|
7
|
-
`||
|
|
1
|
+
'use strict';var fe=require('chalk'),ae=require('os'),$e=require('path'),utils=require('@easbot/utils'),prompts=require('@clack/prompts'),ue=require('process'),de=require('readline'),util=require('util'),stream=require('stream');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var fe__default=/*#__PURE__*/_interopDefault(fe);var ae__default=/*#__PURE__*/_interopDefault(ae);var $e__default=/*#__PURE__*/_interopDefault($e);var ue__default=/*#__PURE__*/_interopDefault(ue);var de__namespace=/*#__PURE__*/_interopNamespace(de);var xt="\\x1b\\[[0-9;]*m",bt="\\x1b\\]8;;.*?\\x1b\\\\|\\x1b\\]8;;\\x1b\\\\",St=new RegExp(xt,"g"),$t=new RegExp(bt,"g");function ne(e){return e?e.replace($t,"").replace(St,""):""}function D(e){return e?Array.from(ne(e)).length:0}var B={accent:"#FF5A2D",accentBright:"#FF7A3D",accentDim:"#D14A22",info:"#FF8A5B",success:"#2FBF71",warn:"#FFB020",error:"#E23D2D",muted:"#8B7F77"};var Ct=typeof process.env.FORCE_COLOR=="string"&&process.env.FORCE_COLOR.trim().length>0&&process.env.FORCE_COLOR.trim()!=="0",he=process.env.NO_COLOR&&!Ct?new fe.Chalk({level:0}):fe__default.default,j=e=>he.hex(e),b={accent:j(B.accent),accentBright:j(B.accentBright),accentDim:j(B.accentDim),info:j(B.info),success:j(B.success),warn:j(B.warn),error:j(B.error),muted:j(B.muted),heading:he.bold.hex(B.accent),command:j(B.accentBright),option:j(B.warn)},k=()=>he.level>0,y=(e,t,r)=>e?t(r):r;function yt(e){return y(k(),b.success,"\u2713")+` ${e}`}function wt(e){return y(k(),b.error,"\u2717")+` ${e}`}function Et(e){return y(k(),b.warn,"\u26A0")+` ${e}`}function Rt(e){return y(k(),b.info,"\u2139")+` ${e}`}function It(e){return y(k(),b.heading,e)}function kt(e,t,r=15){let s=e.padEnd(r);return `${y(k(),b.muted,s)} ${t}`}function Ot(e,t){let r=k(),s=y(r,b.command,e);if(!t)return ` ${s}`;let c=y(r,b.muted,`# ${t}`);return ` ${s} ${c}`}function Wt(e,t,r){let s=k(),c=y(s,b.info,e),f=y(s,b.command,t),m=r?` ${y(s,b.muted,r)}`:"";return `${c} ${f}${m}`}var Lt={pending:{icon:"\u25CB",color:b.muted},running:{icon:"\u25CF",color:b.info},success:{icon:"\u2713",color:b.success},error:{icon:"\u2717",color:b.error},skipped:{icon:"\u25CB",color:b.muted}};function Mt(e,t){let{icon:r,color:s}=Lt[e];return y(k(),s,r)+` ${t}`}function Pt(e=80,t="\u2500"){return y(k(),b.muted,t.repeat(e))}function Ft(e){return y(k(),b.muted,e)}function Nt(e,t,r){let s=e===1?t:r||`${t}s`;return `${y(k(),b.accent,String(e))} ${s}`}function V(e){let t=e?.trim();return t?utils.Filesystem.toUnixPath(t):void 0}function Je(e){try{return V(e())}catch{return}}function At(e,t){let r=V(e.EASBOT_TEST_HOME);if(r)return r;let s=V(e.EASBOT_HOME);if(s){if(s==="~"||s.startsWith("~/")||s.startsWith("~\\")){let m=V(e.HOME)??V(e.USERPROFILE)??Je(t);return m?s.replace(/^~(?=$|[\\/])/,m):void 0}return s}let c=V(e.HOME);if(c)return c;let f=V(e.USERPROFILE);return f||Je(t)}function q(e=process.env,t=ae__default.default.homedir){let r=At(e,t);if(r)return r}function be(e=process.env,t=ae__default.default.homedir){return q(e,t)??utils.Filesystem.resolve(process.cwd())}function Se(e,t){if(!e.startsWith("~"))return V(e);let r=process.env.EASBOT_TEST_HOME?.trim();return r||(r=V(t?.home)??q(t?.env??process.env,t?.homedir??ae__default.default.homedir)),r?e.replace(/^~(?=$|[\\/])/,r):V(e)}function je(e){if(!e)return "";let t=e.trim();if(!t)return t;if(t.startsWith("~")){let r=Se(t,{home:be(process.env,ae__default.default.homedir),env:process.env,homedir:ae__default.default.homedir});return $e__default.default.resolve(r)}return $e__default.default.resolve(t)}function _t(e=process.env,t=ae__default.default.homedir){let r=e.EASBOT_STATE_DIR?.trim();if(r)return je(r);let c=q(e,t)??process.cwd();return $e__default.default.join(c,".config","easbot")}function Ve(){return q(process.env,ae__default.default.homedir)}function Ke(){let e=Ve();return e?process.env.EASBOT_TEST_HOME?.trim()?{home:e,prefix:"~"}:process.env.EASBOT_HOME?.trim()?{home:e,prefix:"$EASBOT_HOME"}:{home:e,prefix:"~"}:void 0}function ze(e){if(!e)return e;let t=Ke();if(!t)return e;let{home:r,prefix:s}=t;return e===r?s:e.startsWith(`${r}/`)||e.startsWith(`${r}\\`)?`${s}${e.slice(r.length)}`:e}function Ye(e){if(!e)return e;let t=Ke();return t?e.split(t.home).join(t.prefix):e}function Ht(e){return ze(e)}function ve(e){return Ye(e)}function Bt(e,t){return e?.force===true?true:e?.force===false?false:!!(t??process.stdout?.isTTY)}function re(e,t,r,s){let c=ne(e??""),f=ne(t??"");return Bt(r,s)?`\x1B]8;;${f}\x07${c}\x1B]8;;\x07`:r?.fallback??`${c} (${f})`}function Jt(e,t,r,s,c){let f=t.trim();if(!e)return re(r??f,f,s,c);let m=/^[a-z]+:\/\//i.test(f)?f:`${e}${f.startsWith("/")?f:`/${f}`}`;return re(r??m,m,s,c)}function Dt(e,t,r){return re(t??e,e,void 0,r)}function jt(e,t){let r={ok:true,data:e};t!==void 0&&(r.meta=t),console.log(JSON.stringify(r,null,2));}function Vt(e,t){console.log(JSON.stringify({ok:false,error:{code:e,message:t}},null,2));}var Te=e=>k()?b.accent(e):e,Ce=e=>e&&k()?b.heading(e):e,ye=e=>e&&k()?b.muted(e):e;var zt=/^(https?:\/\/|file:\/\/)/i,Yt=/^[a-zA-Z]:[\\/]/,Ut=/^[a-zA-Z0-9._-]+$/;function Ue(e,t){if(t<=0)return [e];let r=Array.from(e),s=[];for(let c=0;c<r.length;c+=t)s.push(r.slice(c,c+t).join(""));return s.length>0?s:[e]}function Ge(e){return e?zt.test(e)||e.startsWith("/")||e.startsWith("~/")||e.startsWith("./")||e.startsWith("../")||Yt.test(e)||e.startsWith("\\\\")||e.includes("/")||e.includes("\\")?true:e.includes("_")&&Ut.test(e):false}function Gt(e,t){if(e.trim().length===0)return [e];if(t<=0)return [e];let r=e.match(/^(\s*)([-*\u2022]\s+)?(.*)$/),s=r?.[1]??"",c=r?.[2]??"",f=r?.[3]??"",m=`${s}${c}`,a=`${s}${c?" ".repeat(c.length):""}`,v=Math.max(10,t-D(m)),$=Math.max(10,t-D(a)),E=f.split(/\s+/).filter(Boolean),O=[],h="",o=m,l=v;for(let T of E){if(!h){if(D(T)>l){if(Ge(T)){h=T;continue}let w=Ue(T,l),S=w.shift()??"";O.push(o+S),o=a,l=$;for(let p of w)O.push(o+p);continue}h=T;continue}let n=`${h} ${T}`;if(D(n)<=l){h=n;continue}if(O.push(o+h),o=a,l=$,D(T)>l){if(Ge(T)){h=T;continue}let w=Ue(T,l),S=w.shift()??"";O.push(o+S);for(let p of w)O.push(o+p);h="";continue}h=T;}return (h||E.length===0)&&O.push(o+h),O}function qe(e,t={}){let r=process.stdout?.columns??80,s=t.columns??r,c=t.maxWidth??Math.max(40,Math.min(88,s-10));return e.split(`
|
|
2
|
+
`).flatMap(f=>Gt(f,c)).join(`
|
|
3
|
+
`)}function qt(e,t,r={}){let s=r.columns??process.stdout?.columns,c=qe(e,{columns:s,maxWidth:r.maxWidth});prompts.note(c,Ce(t));}var Q=null;function Qt(e,t){try{e.write(t);}catch{}}function Xt(e){e.isTTY&&(Q=e);}function we(){Q?.isTTY&&Qt(Q,"\r\x1B[2K");}function Zt(e){Q&&(e&&Q!==e||(Q=null));}function tn(e){return prompts.select({...e,message:Te(e.message),options:e.options.map(t=>t.hint===void 0?t:{...t,hint:ye(t.hint)})})}var nn="\x1B[0m\x1B[?25h\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004l";function le(e,t,r){let s=r?` (${r})`:"",c=`[terminal] restore ${e} failed${s}: ${String(t)}`;try{ue__default.default.stderr.write(`${c}
|
|
4
|
+
`);}catch(f){console.error(`[terminal] restore reporting failed${s}: ${String(f)}`);}}function rn(e,t={}){let r=t.resumeStdinIfPaused??t.resumeStdin??false;try{we();}catch(c){le("progress line",c,e);}let s=ue__default.default.stdin;if(s?.isTTY&&typeof s.setRawMode=="function"){try{s.setRawMode(!1);}catch(c){le("raw mode",c,e);}if(r&&typeof s.isPaused=="function"&&s.isPaused())try{s.resume();}catch(c){le("stdin resume",c,e);}}if(ue__default.default.stdout?.isTTY)try{ue__default.default.stdout.write(nn);}catch(c){le("stdout reset",c,e);}}function sn(e){let t=e?.code;return t==="EPIPE"||t==="EIO"}function cn(e={}){let t=false,r=false,s=(a,v)=>{r||(r=true,e.onBrokenPipe?.(a,v));},c=(a,v)=>{if(!sn(a))throw a;return t=true,s(a,v),false},f=(a,v)=>{if(t)return false;try{e.beforeWrite?.();}catch($){return c($,ue__default.default.stderr)}try{return a.write(v),!t}catch($){return c($,a)}};return {write:f,writeLine:(a,v)=>f(a,`${v}
|
|
5
|
+
`),reset:()=>{t=false,r=false;},isClosed:()=>t}}function X(e,t){return !Number.isFinite(t)||t<=0?"":e.repeat(t)}function an(e,t,r){let s=D(e);if(s>=t)return e;let c=t-s;if(r==="right")return `${X(" ",c)}${e}`;if(r==="center"){let f=Math.floor(c/2),m=c-f;return `${X(" ",f)}${e}${X(" ",m)}`}return `${e}${X(" ",c)}`}function ln(e,t){if(!e||e.length===0)return [""];if(!Number.isFinite(t)||t<=0)return [e];let r="\x1B",s=[];for(let i=0;i<e.length;){if(e[i]===r){if(e[i+1]==="["){let g=i+2;for(;g<e.length;){let C=e[g];if(C==="m")break;if(C&&C>="0"&&C<="9"){g+=1;continue}if(C===";"){g+=1;continue}break}if(e[g]==="m"){s.push({kind:"ansi",value:e.slice(i,g+1)}),i=g+1;continue}}if(e[i+1]==="]"&&e.slice(i+2,i+5)==="8;;"){let g=e.indexOf(`${r}\\`,i+5);if(g>=0){s.push({kind:"ansi",value:e.slice(i,g+2)}),i=g+2;continue}}}let u=e.codePointAt(i);if(!u)break;let x=String.fromCodePoint(u);s.push({kind:"char",value:x}),i+=x.length;}let c=s.findIndex(i=>i.kind==="char");if(c<0)return [e];let f=-1;for(let i=s.length-1;i>=0;i-=1){let u=s[i];if(u&&u.kind==="char"){f=i;break}}let m=s.slice(0,c).filter(i=>i.kind==="ansi").map(i=>i.value).join(""),a=s.slice(f+1).filter(i=>i.kind==="ansi").map(i=>i.value).join(""),v=s.slice(c,f+1),$=[],E=i=>i===" "||i===" "||i==="/"||i==="-"||i==="_"||i===".",O=i=>i===" "||i===" ",h=false,o=[],l=0,T=null,n=i=>(i??o).map(u=>u.value).join(""),w=i=>i.reduce((u,x)=>u+(x.kind==="char"?1:0),0),S=i=>{let u=i.replace(/\s+$/,"");u.trim().length!==0&&$.push(u);},p=i=>{if(o.length===0)return;if(i==null||i<=0){S(n()),o.length=0,l=0,T=null;return}let u=o.slice(0,i),x=o.slice(i);for(S(n(u));x.length>0;){let g=x[0];if(g?.kind!=="char"||!O(g.value))break;x.shift();}o.length=0,o.push(...x),l=w(o),T=null;};for(let i of v){if(i.kind==="ansi"){o.push(i);continue}let u=i.value;if(!(h&&(h=false,u===`
|
|
6
|
+
`))){if(u===`
|
|
7
|
+
`||u==="\r"){p(o.length),u==="\r"&&(h=true);continue}l+1>t&&l>0&&p(T),o.push(i),l+=1,E(u)&&(T=o.length);}}return p(o.length),$.length===0?[""]:!m&&!a?$:$.map(i=>i&&`${m}${i}${a}`)}function un(e){if(e!=null&&!(!Number.isFinite(e)||e<=0))return Math.floor(e)}function fn(e){let t=e.rows.map(S=>{let p={};for(let[i,u]of Object.entries(S))p[i]=ve(u);return p}),r=e.border??"unicode";if(r==="none"){let S=e.columns;return `${[S.map(u=>u.header).join(" | "),...t.map(u=>S.map(x=>u[x.key]??"").join(" | "))].join(`
|
|
8
8
|
`)}
|
|
9
|
-
`}let
|
|
9
|
+
`}let s=Math.max(0,e.padding??1),c=e.columns,f=c.map(S=>{let p=D(S.header),i=Math.max(0,...t.map(u=>D(u[S.key]??"")));return {headerW:p,cellW:i}}),m=c.map((S,p)=>{let i=f[p];if(!i)throw new Error(`Internal error: metrics[${p}] is undefined`);let u=Math.max(i.headerW,i.cellW)+s*2,x=S.maxWidth?Math.min(u,S.maxWidth):u;return Math.max(S.minWidth??3,x)}),a=un(e.width),v=c.length+1,$=m.reduce((S,p)=>S+p,0)+v,E=c.map((S,p)=>{let i=f[p];if(!i)throw new Error(`Internal error: metrics[${p}] is undefined`);return Math.max(S.minWidth??3,i.headerW+s*2,3)}),O=c.map((S,p)=>{let i=f[p];if(!i)throw new Error(`Internal error: metrics[${p}] is undefined`);return Math.max(i.headerW+s*2,3)});if(a&&$>a){let S=$-a,p=c.map((x,g)=>{let C=m[g];if(C===void 0)throw new Error(`Internal error: widths[${g}] is undefined`);return {i:g,w:C}}).filter(({i:x})=>!!c[x]?.flex).toSorted((x,g)=>g.w-x.w).map(x=>x.i),i=c.map((x,g)=>{let C=m[g];if(C===void 0)throw new Error(`Internal error: widths[${g}] is undefined`);return {i:g,w:C}}).filter(({i:x})=>!c[x]?.flex).toSorted((x,g)=>g.w-x.w).map(x=>x.i),u=(x,g)=>{for(;S>0;){let C=false;for(let A of x){let F=m[A],_=g[A];if(!(F===void 0||_===void 0)&&!(F<=_)&&(m[A]=F-1,S-=1,C=true,S<=0))break}if(!C)break}};u(p,E),u(p,O),u(i,E),u(i,O);}if(a){let S=c.length+1,p=m.reduce((u,x)=>u+x,0)+S,i=a-p;if(i>0){let u=c.map((x,g)=>({c:x,i:g})).filter(({c:x})=>!!x.flex).map(({i:x})=>x);if(u.length>0){let x=c.map(g=>typeof g.maxWidth=="number"&&g.maxWidth>0?Math.floor(g.maxWidth):Number.POSITIVE_INFINITY);for(;i>0;){let g=false;for(let C of u){let A=m[C],F=x[C];if(!(A===void 0||F===void 0)&&!(A>=F)&&(m[C]=A+1,i-=1,g=true,i<=0))break}if(!g)break}}}}let h=r==="ascii"?{tl:"+",tr:"+",bl:"+",br:"+",h:"-",v:"|",t:"+",ml:"+",m:"+",mr:"+",b:"+"}:{tl:"\u250C",tr:"\u2510",bl:"\u2514",br:"\u2518",h:"\u2500",v:"\u2502",t:"\u252C",ml:"\u251C",m:"\u253C",mr:"\u2524",b:"\u2534"},o=(S,p,i)=>`${S}${m.map(u=>{if(u===void 0)throw new Error("Internal error: width is undefined");return X(h.h,u)}).join(p)}${i}`,l=S=>{let p=m[S];if(p===void 0)throw new Error(`Internal error: widths[${S}] is undefined`);return Math.max(1,p-s*2)},T=X(" ",s),n=(S,p=false)=>{let u=c.map(C=>p?C.header:S[C.key]??"").map((C,A)=>ln(C,l(A))),x=Math.max(...u.map(C=>C.length)),g=[];for(let C=0;C<x;C+=1){let A=u.map((F,_)=>{let W=F[C]??"",J=c[_];if(!J)throw new Error(`Internal error: columns[${_}] is undefined`);let M=an(W,l(_),J.align??"left");return `${T}${M}${T}`});g.push(`${h.v}${A.join(h.v)}${h.v}`);}return g},w=[];w.push(o(h.tl,h.t,h.tr)),w.push(...n({},true)),w.push(o(h.ml,h.m,h.mr));for(let S of t)w.push(...n(S,false));return w.push(o(h.bl,h.b,h.br)),`${w.join(`
|
|
10
10
|
`)}
|
|
11
|
-
`}function
|
|
11
|
+
`}var dn=[{prefix:"failed",color:b.error},{prefix:"ok",color:b.success},{prefix:"linked",color:b.success},{prefix:"configured",color:b.success},{prefix:"not linked",color:b.warn},{prefix:"not configured",color:b.muted},{prefix:"unknown",color:b.warn}];function mn(e,t){if(!t)return e;let r=e.indexOf(":");if(r===-1)return e;let s=e.slice(0,r+1),c=e.slice(r+1).trimStart(),f=c.toLowerCase();for(let{prefix:m,color:a}of dn)if(f.startsWith(m))return `${s} ${a(c.slice(0,m.length))}${c.slice(m.length)}`;return e}var hn=new stream.Writable({write(e,t,r){r();}}),oe;(h=>{h.cancelSymbol=Symbol("Search.cancel");function t(o){let l=0;for(let T of o){let n=T.codePointAt(0);if(n===void 0||n===0)continue;let w=n>=4352&&n<=4447||n>=8986&&n<=8987||n>=9001&&n<=9002||n>=9193&&n<=9196||n===9200||n===9203||n>=9725&&n<=9726||n>=9748&&n<=9749||n>=9800&&n<=9811||n===9855||n===9875||n===9889||n>=9898&&n<=9899||n>=9917&&n<=9918||n>=9924&&n<=9925||n===9934||n===9940||n===9962||n>=9970&&n<=9971||n===9973||n===9978||n===9981||n===9989||n>=9994&&n<=9995||n===10024||n===10060||n===10062||n>=10067&&n<=10069||n===10071||n>=10133&&n<=10135||n===10160||n===10175||n>=11035&&n<=11036||n===11088||n===11093||n>=11904&&n<=42191&&n!==12351||n>=43360&&n<=43388||n>=44032&&n<=55203||n>=63744&&n<=64255||n>=65040&&n<=65049||n>=65072&&n<=65135||n>=65280&&n<=65376||n>=65504&&n<=65510||n>=126976&&n<=129535;l+=w?2:1;}return l}h.approxStringWidth=t;function r(o,l){let T=util.stripVTControlCharacters(o),n=Math.max(1,l),w=t(T);return Math.max(1,Math.ceil(w/n))}h.visualRowsForLine=r;function s(o,l){let T=l!==void 0&&l>0?l:process.stdout.columns&&process.stdout.columns>0?process.stdout.columns:80,n=0;for(let w of o)n+=r(w,T);return n}h.countVisualRowsForLines=s;function c(o){let l=new Array(o.length);for(let T=0;T<o.length;T++){let n=o[T],w=n.value===null||n.value===void 0?"":String(n.value);l[T]={...n,searchKey:`${n.label}
|
|
12
|
+
${w}`.toLowerCase()};}return l}function f(o,l){return l===""||o.searchKey.includes(l)}function m(o,l){return l<=0||o<0?0:o>=l?l-1:o}function a(o){if(o?.length!==1)return false;let l=o.codePointAt(0);return !(l===void 0||l<32||l===127||l===27)}function v(){let o=process.stdout.rows;if(!o||o<=0)return 8;let l=Math.floor((o-8)/2);return Math.max(5,Math.min(15,l))}function $(o,l){try{o.write(l);}catch{}}function E(o){if(o&&o.isTTY&&typeof o.setRawMode=="function")try{o.setRawMode(!1);}catch{}}function O(o){let l=o.message,T=c(o.items),n=Math.max(1,o.maxVisible??v()),w=o.initialSelected??[],S=o.required??false,p=o.lockedSection,i=o.isTTY;i??!!process.stdout?.isTTY;return new Promise(x=>{let g=process.stdin,C=process.stdout,A=de__namespace.createInterface({input:g,output:hn,terminal:false});try{(i===!0||i===void 0&&g.isTTY)&&g.setRawMode?.(!0);}catch{}de__namespace.emitKeypressEvents(g,A);let F="",_="",W=0,J=new Set(w),M=0,U=false,z=p?p.items.map(R=>R.value):[],me=p?p.items.map(R=>R.label):[],ie=[],Oe=()=>{if(ie.length=0,_==="")for(let R=0;R<T.length;R++){let d=T[R];ie.push(d);}else for(let R=0;R<T.length;R++){let d=T[R];f(d,_)&&ie.push(d);}return ie},Xe=()=>{if(M>0){$(C,`\x1B[${M}A`);for(let R=0;R<M;R++)$(C,"\x1B[2K\x1B[1B");$(C,`\x1B[${M}A`);}},We=()=>{let R=me.slice();for(let d=0;d<T.length;d++){let L=T[d];J.has(L.value)&&R.push(L.label);}return R},H=(R="active")=>{Xe();let d=[],L=Oe(),K=i===false?false:i===true?true:k(),Ae=P=>y(K,b.error,P),ce=P=>y(K,b.success,P),I=P=>y(K,b.muted,P),pe=P=>y(K,b.heading,P),ot=P=>y(K,b.accentBright,P),it=P=>y(K,fe__default.default.bold,P),st=P=>y(K,fe__default.default.underline,P),ct=P=>y(K,fe__default.default.inverse,P),at=P=>y(K,fe__default.default.strikethrough,P),_e=R==="active"||R==="error"?"\u25C6":R==="cancel"?"\u25A0":"\u25C7",lt=R==="cancel"||R==="error"?Ae(_e):ce(_e);if(d.push(`${lt} ${it(l)}`),R==="active"||R==="error"){if(p&&p.items.length>0){d.push(I("\u2502"));let G=`${pe(p.title)} ${I("\u2500\u2500 always included")}`;d.push(`${I("\u2502")} ${I("\u2500\u2500")} ${G} ${I("\u2500".repeat(12))}`);for(let ee of p.items)d.push(`${I("\u2502")} ${ce("\u2022")} ${pe(ee.label)}`);p.hiddenCount&&p.hiddenCount>0&&d.push(`${I("\u2502")} ${I(`...and ${p.hiddenCount} more`)}`),d.push(I("\u2502")),d.push(`${I("\u2502")} ${I("\u2500\u2500")} ${pe("Additional agents")} ${I("\u2500".repeat(29))}`);}let P=`${I("\u2502")} ${I("Search:")} ${F}${ct(" ")}`;d.push(P),d.push(`${I("\u2502")} ${I("\u2191\u2193 move \xB7 space select \xB7 enter confirm")}`),d.push(I("\u2502"));let ut=Math.max(0,L.length-n),ft=W-Math.floor(n/2),ge=Math.max(0,Math.min(ft,ut)),He=Math.min(L.length,ge+n);if(L.length===0)d.push(`${I("\u2502")} ${I("No matches found")}`);else {for(let Y=ge;Y<He;Y++){let te=L[Y],dt=J.has(te.value),Be=Y===W,mt=dt?ce("\u25CF"):I("\u25CB"),pt=Be?st(te.label):te.label,gt=te.hint?I(` (${te.hint})`):"",ht=Be?ot("\u276F"):" ";d.push(`${I("\u2502")} ${ht} ${mt} ${pt}${gt}`);}let G=ge,ee=L.length-He;if(G>0||ee>0){let Y=[];G>0&&Y.push(`\u2191 ${G} more`),ee>0&&Y.push(`\u2193 ${ee} more`),d.push(`${I("\u2502")} ${I(Y.join(" "))}`);}}d.push(I("\u2502"));let Z=We();if(Z.length===0)d.push(`${I("\u2502")} ${I("Selected: (none)")}`);else {let G=Z.length<=3?Z.join(", "):`${Z.slice(0,3).join(", ")} +${Z.length-3} more`;d.push(`${I("\u2502")} ${ce("Selected:")} ${G}`);}R==="error"&&d.push(`${I("\u2502")} ${Ae("\u26A0 Please select at least one item before submitting")}`),d.push(`${I("\u2514")}`);}else if(R==="submit"){let P=We();d.push(`${I("\u2502")} ${I(P.join(", "))}`);}else d.push(`${I("\u2502")} ${at(I("Cancelled"))}`);$(C,`${d.join(`
|
|
13
|
+
`)}
|
|
14
|
+
`);try{M=s(d,C.columns);}catch{M=d.length;}},Le=false,Ze=()=>{if(!Le){Le=true;try{g.removeListener("keypress",Ne),g.removeListener("end",Fe);}catch{}try{process.removeListener("SIGINT",se),process.removeListener("SIGTERM",se);}catch{}E(g);try{A.close();}catch{}}},Me=R=>{U||(U=true,Ze(),x(R));},et=()=>{if(S&&J.size===0&&z.length===0){H("error");return}H("submit"),Me([...z,...Array.from(J)]);},Pe=()=>{H("cancel"),Me(h.cancelSymbol);},Fe=()=>{Pe();},se=()=>{E(g);},tt=R=>{let d=R[W];d&&(J.has(d.value)?J.delete(d.value):J.add(d.value));},nt=R=>{F+=R,_+=R.toLowerCase();},rt=()=>{F.length!==0&&(F=F.slice(0,-1),_=_.slice(0,-1));},Ne=(R,d)=>{if(!d)return;let L=Oe();if(W=m(W,L.length),d.name==="return"){et();return}if(d.name==="escape"||d.ctrl&&d.name==="c"){Pe();return}if(d.name==="up"||d.name==="left"){L.length>0&&(W=m(W-1,L.length),H());return}if(d.name==="down"||d.name==="right"){L.length>0&&(W=m(W+1,L.length),H());return}if(d.name==="pageup"){L.length>0&&(W=m(W-n,L.length),H());return}if(d.name==="pagedown"){L.length>0&&(W=m(W+n,L.length),H());return}if(d.name==="home"){L.length>0&&(W=0,H());return}if(d.name==="end"){L.length>0&&(W=L.length-1,H());return}if(d.name==="space"){tt(L),H();return}if(d.name==="backspace"){F.length>0&&(rt(),W=0,H());return}!d.ctrl&&!d.meta&&a(d.sequence)&&(nt(d.sequence),W=0,H());};g.on("keypress",Ne),g.once("end",Fe),process.on("SIGINT",se),process.on("SIGTERM",se),H();})}h.multiselect=O;})(oe||(oe={}));var Ee=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Re=80;exports.Loader=void 0;(t=>{function e(r={}){let s=[...Ee],c=Re,f=0,m=null,a=r.message??"Loading...",v=r.spinnerColor??(o=>y(k(),b.accent,o)),$=r.messageColor??(o=>y(k(),b.muted,o)),E=o=>{s=o.frames!==void 0?[...o.frames]:[...Ee],c=o.intervalMs!==void 0&&o.intervalMs>0?o.intervalMs:Re,f=0;};r.indicator&&E(r.indicator);function O(){h(),!(s.length<=1)&&(m=setInterval(()=>{f=(f+1)%s.length;},c));}function h(){m!==null&&(clearInterval(m),m=null);}return {start:O,stop:h,isRunning(){return m!==null},line(){let o=s[f]??"";return `${o.length>0?`${v(o)} `:""}${$(a)}`},setMessage(o){a=o;},setIndicator(o){o?E(o):(s=[...Ee],c=Re,f=0),O();}}}t.create=e;})(exports.Loader||(exports.Loader={}));var xn=e=>y(k(),b.accent,e),bn=e=>y(k(),b.muted,e);exports.Input=void 0;(m=>{function e(a){let v=a;typeof v.resume=="function"&&v.resume();}function t(a,v){try{a.write(v);}catch{}}function r(a,v,$){let E=a;for(let O=0;O<v.length;O+=1){let h=v[O],o=h.charCodeAt(0);if(o===3)return {buffer:E,done:true,line:""};if(o===4)return {buffer:E,done:true,line:E};if(o===10||o===13)return {buffer:"",done:true,line:E};if((o===8||o===127)){E=E.slice(0,-1);continue}E+=h;}return {buffer:E,done:false,line:""}}function s(a){return new Promise((v,$)=>{let{message:E,hint:O,defaultValue:h,hidden:o,input:l,output:T,messageColor:n,hintColor:w}=a,S=(n??xn)(E),p=O?` ${(w??bn)(`(${O})`)}`:"",i=h?` [${h}]`:"",u=o?`${S}${p}: `:`${S}${p}${i}: `,x=l??ue__default.default.stdin,g=T??ue__default.default.stdout;t(g,u);let C="",A=false,F=M=>{A||(A=true,M(),x.off("data",_),x.off("end",W));},_=M=>{let U=typeof M=="string"?M:M.toString("utf8"),z=r(C,U);if(C=z.buffer,!z.done)return;if(z.line===""&&C===""&&!U.includes(`
|
|
15
|
+
`)&&!U.includes("\r")){F(()=>$(new Error("Input canceled")));return}let me=z.line.length===0&&h!==void 0?h:z.line;F(()=>v(me));},W=()=>{if(A)return;let M=C.length===0&&h!==void 0?h:C;F(()=>v(M));},J=M=>{if((typeof M=="string"?M:M.toString("utf8")).includes("")){F(()=>$(new Error("Input canceled")));return}_(M);};x.on("data",J),x.once("end",W),e(x);})}m.readText=s;async function c(a){let v=a.defaultValue!==false,E=(await s({message:a.message,hint:a.hint??`y/n, default ${v?"y":"n"}`,defaultValue:v?"y":"n",messageColor:a.messageColor,hintColor:a.hintColor,input:a.input,output:a.output})).trim().toLowerCase();return E===""?v:E==="y"||E==="yes"?true:E==="n"||E==="no"?false:c(a)}m.readConfirm=c;function f(a){return s({...a,hidden:true})}m.readPassword=f;})(exports.Input||(exports.Input={}));var Sn=e=>y(k(),b.heading,e),$n=e=>y(k(),b.command,e),vn=e=>y(k(),b.muted,e),Tn=e=>y(k(),b.warn,e),Cn=e=>y(k(),b.accent,e);function yn(e,t,r,s,c,f){let m=e;return m=m.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(a,v,$)=>`${f(v)} (${$})`),m=m.replace(/`([^`]+)`/g,(a,v)=>c(v)),m=m.replace(/\*\*([^*]+)\*\*/g,(a,v)=>r(v)),m=m.replace(/(^|[^*])\*([^*]+)\*(?!\*)/g,(a,v,$)=>`${v}${s($)}`),m}function wn(e,t={}){if(!e)return [];let r=t.headingColor??Sn,s=t.boldColor??$n,c=t.italicColor??vn,f=t.codeColor??Tn,m=t.linkColor??Cn,a=n=>yn(n,r,s,c,f,m),v=e.replace(/\r\n/g,`
|
|
16
|
+
`).split(`
|
|
17
|
+
`),$=[],E=false,O=[],h="",o=0,l=true,T=()=>{if(O.length!==0){$.push(f(`\`\`\`${h}`));for(let n of O)$.push(f(n));$.push(f("```")),O=[],h="";}};for(let n of v){let w=n;if(w.trim().startsWith("```")){if(!E){T(),E=true,h=w.trim().slice(3).trim(),$.push(f(`\`\`\`${h}`)),l=false;continue}for(let u of O)$.push(f(u));O=[],$.push(f("```")),E=false,h="",l=false;continue}if(E){O.push(w);continue}let S=/^(#{1,3})\s+(.+)$/.exec(w);if(S){let u=S[1]??"#",x=S[2]??"";$.push(r(`${u} ${a(x)}`)),l=false;continue}if(/^(\s*[-*_])\s*\1\s*\1[-*_\s]*$/.test(w)||/^---\s*$/.test(w)||/^\*\*\*\s*$/.test(w)){$.push(f("\u2500".repeat(40))),l=true;continue}let p=/^\s*[-*]\s+(.+)$/.exec(w),i=/^\s*\d+\.\s+(.+)$/.exec(w);if(p){let u=p[1]??"";$.push(` \u2022 ${a(u)}`),o=0,l=false;continue}if(i){let u=i[1]??"";o+=1,$.push(` ${o}. ${a(u)}`),l=false;continue}if(w.trim()===""){l||$.push(""),l=true,o=0;continue}$.push(a(w)),l=false,o=0;}return E&&T(),$}var jr=oe,Vr=oe.cancelSymbol;exports.LOBSTER_PALETTE=B;exports.Search=jr;exports.cancelSymbol=Vr;exports.clearActiveProgressLine=we;exports.colorize=y;exports.createSafeStreamWriter=cn;exports.displayPath=Ht;exports.displayString=ve;exports.emitJsonError=Vt;exports.emitJsonOk=jt;exports.expandHomePrefix=Se;exports.formatCommandExample=Ot;exports.formatCount=Nt;exports.formatEmptyMessage=Ft;exports.formatError=wt;exports.formatHeading=It;exports.formatInfo=Rt;exports.formatKeyValue=kt;exports.formatListItem=Wt;exports.formatRootLink=Dt;exports.formatRootedLink=Jt;exports.formatSeparator=Pt;exports.formatStatus=Mt;exports.formatSuccess=yt;exports.formatTerminalLink=re;exports.formatWarning=Et;exports.isRich=k;exports.note=qt;exports.registerActiveProgressLine=Xt;exports.renderMarkdown=wn;exports.renderTable=fn;exports.resolveConfigDir=_t;exports.resolveEffectiveHomeDir=q;exports.resolveHomeDir=Ve;exports.resolveRequiredHomeDir=be;exports.resolveUserPath=je;exports.restoreTerminalState=rn;exports.selectStyled=tn;exports.shortenHomeInString=Ye;exports.shortenHomePath=ze;exports.stripAnsi=ne;exports.styleHealthChannelLine=mn;exports.stylePromptHint=ye;exports.stylePromptMessage=Te;exports.stylePromptTitle=Ce;exports.theme=b;exports.unregisterActiveProgressLine=Zt;exports.visibleWidth=D;exports.wrapNoteMessage=qe;
|
package/dist/index.d.cts
CHANGED
|
@@ -14,6 +14,8 @@ declare const LOBSTER_PALETTE: {
|
|
|
14
14
|
readonly error: "#E23D2D";
|
|
15
15
|
readonly muted: "#8B7F77";
|
|
16
16
|
};
|
|
17
|
+
type LobsterPalette = typeof LOBSTER_PALETTE;
|
|
18
|
+
type LobsterPaletteKey = keyof LobsterPalette;
|
|
17
19
|
|
|
18
20
|
declare const theme: {
|
|
19
21
|
readonly accent: chalk.ChalkInstance;
|
|
@@ -39,7 +41,8 @@ declare function formatHeading(title: string): string;
|
|
|
39
41
|
declare function formatKeyValue(key: string, value: string, keyWidth?: number): string;
|
|
40
42
|
declare function formatCommandExample(command: string, description?: string): string;
|
|
41
43
|
declare function formatListItem(icon: string, text: string, description?: string): string;
|
|
42
|
-
|
|
44
|
+
type StatusKind = 'pending' | 'running' | 'success' | 'error' | 'skipped';
|
|
45
|
+
declare function formatStatus(status: StatusKind, message: string): string;
|
|
43
46
|
declare function formatSeparator(width?: number, char?: string): string;
|
|
44
47
|
declare function formatEmptyMessage(message: string): string;
|
|
45
48
|
declare function formatCount(count: number, singular: string, plural?: string): string;
|
|
@@ -51,10 +54,11 @@ declare function shortenHomePath(input: string): string;
|
|
|
51
54
|
declare function shortenHomeInString(input: string): string;
|
|
52
55
|
declare function displayPath(input: string): string;
|
|
53
56
|
declare function displayString(input: string): string;
|
|
54
|
-
|
|
57
|
+
type FormatTerminalLinkOptions = {
|
|
55
58
|
fallback?: string;
|
|
56
59
|
force?: boolean;
|
|
57
|
-
}
|
|
60
|
+
};
|
|
61
|
+
declare function formatTerminalLink(label: string, url: string, opts?: FormatTerminalLinkOptions, isTTY?: boolean): string;
|
|
58
62
|
|
|
59
63
|
declare function resolveEffectiveHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string | undefined;
|
|
60
64
|
declare function resolveRequiredHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string;
|
|
@@ -64,21 +68,25 @@ declare function expandHomePrefix(input: string, opts?: {
|
|
|
64
68
|
homedir?: () => string;
|
|
65
69
|
}): string;
|
|
66
70
|
|
|
67
|
-
declare
|
|
68
|
-
declare function formatDocsLink(path: string, label?: string, opts?: {
|
|
71
|
+
declare function formatRootedLink(root: string, path: string, label?: string, opts?: {
|
|
69
72
|
fallback?: string;
|
|
70
73
|
force?: boolean;
|
|
71
|
-
}): string;
|
|
72
|
-
declare function
|
|
74
|
+
}, isTTY?: boolean): string;
|
|
75
|
+
declare function formatRootLink(root: string, label?: string, isTTY?: boolean): string;
|
|
73
76
|
|
|
74
77
|
declare function emitJsonOk(data: unknown, meta?: Record<string, unknown>): void;
|
|
75
78
|
declare function emitJsonError(code: string, message: string): void;
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
type WrapNoteMessageOptions = {
|
|
78
81
|
maxWidth?: number;
|
|
79
82
|
columns?: number;
|
|
80
|
-
}
|
|
81
|
-
declare function
|
|
83
|
+
};
|
|
84
|
+
declare function wrapNoteMessage(message: string, options?: WrapNoteMessageOptions): string;
|
|
85
|
+
type NoteOptions = {
|
|
86
|
+
columns?: number;
|
|
87
|
+
maxWidth?: number;
|
|
88
|
+
};
|
|
89
|
+
declare function note(message: string, title?: string, options?: NoteOptions): void;
|
|
82
90
|
|
|
83
91
|
declare function registerActiveProgressLine(stream: NodeJS.WriteStream): void;
|
|
84
92
|
declare function clearActiveProgressLine(): void;
|
|
@@ -128,4 +136,93 @@ declare function renderTable(opts: RenderTableOptions): string;
|
|
|
128
136
|
|
|
129
137
|
declare function styleHealthChannelLine(line: string, rich: boolean): string;
|
|
130
138
|
|
|
131
|
-
|
|
139
|
+
declare namespace Search$1 {
|
|
140
|
+
interface Item<T> {
|
|
141
|
+
value: T;
|
|
142
|
+
label: string;
|
|
143
|
+
hint?: string;
|
|
144
|
+
}
|
|
145
|
+
interface LockedSection<T> {
|
|
146
|
+
title: string;
|
|
147
|
+
items: Item<T>[];
|
|
148
|
+
hiddenCount?: number;
|
|
149
|
+
}
|
|
150
|
+
interface MultiselectOptions<T> {
|
|
151
|
+
message: string;
|
|
152
|
+
items: Item<T>[];
|
|
153
|
+
maxVisible?: number;
|
|
154
|
+
initialSelected?: T[];
|
|
155
|
+
required?: boolean;
|
|
156
|
+
lockedSection?: LockedSection<T>;
|
|
157
|
+
isTTY?: boolean;
|
|
158
|
+
}
|
|
159
|
+
const cancelSymbol: unique symbol;
|
|
160
|
+
function approxStringWidth(plain: string): number;
|
|
161
|
+
function visualRowsForLine(line: string, columns: number): number;
|
|
162
|
+
function countVisualRowsForLines(lines: string[], columns: number | undefined): number;
|
|
163
|
+
function multiselect<T>(options: MultiselectOptions<T>): Promise<T[] | typeof cancelSymbol>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
type ColorFn$2 = (text: string) => string;
|
|
167
|
+
declare namespace Loader {
|
|
168
|
+
interface IndicatorOptions {
|
|
169
|
+
frames?: string[];
|
|
170
|
+
intervalMs?: number;
|
|
171
|
+
}
|
|
172
|
+
interface Options {
|
|
173
|
+
message?: string;
|
|
174
|
+
spinnerColor?: ColorFn$2;
|
|
175
|
+
messageColor?: ColorFn$2;
|
|
176
|
+
indicator?: IndicatorOptions;
|
|
177
|
+
}
|
|
178
|
+
interface Instance {
|
|
179
|
+
start(): void;
|
|
180
|
+
stop(): void;
|
|
181
|
+
isRunning(): boolean;
|
|
182
|
+
line(): string;
|
|
183
|
+
setMessage(message: string): void;
|
|
184
|
+
setIndicator(indicator?: IndicatorOptions): void;
|
|
185
|
+
}
|
|
186
|
+
function create(options?: Options): Instance;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
type ColorFn$1 = (text: string) => string;
|
|
190
|
+
declare namespace Input {
|
|
191
|
+
interface ReadTextBaseOptions {
|
|
192
|
+
message: string;
|
|
193
|
+
hint?: string;
|
|
194
|
+
defaultValue?: string;
|
|
195
|
+
hidden?: boolean;
|
|
196
|
+
messageColor?: ColorFn$1;
|
|
197
|
+
hintColor?: ColorFn$1;
|
|
198
|
+
input?: NodeJS.ReadStream;
|
|
199
|
+
output?: NodeJS.WritableStream;
|
|
200
|
+
}
|
|
201
|
+
interface ReadConfirmOptions {
|
|
202
|
+
message: string;
|
|
203
|
+
hint?: string;
|
|
204
|
+
defaultValue?: boolean;
|
|
205
|
+
messageColor?: ColorFn$1;
|
|
206
|
+
hintColor?: ColorFn$1;
|
|
207
|
+
input?: NodeJS.ReadStream;
|
|
208
|
+
output?: NodeJS.WritableStream;
|
|
209
|
+
}
|
|
210
|
+
function readText(options: ReadTextBaseOptions): Promise<string>;
|
|
211
|
+
function readConfirm(options: ReadConfirmOptions): Promise<boolean>;
|
|
212
|
+
function readPassword(options: Omit<ReadTextBaseOptions, 'hidden'>): Promise<string>;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
type ColorFn = (text: string) => string;
|
|
216
|
+
interface RenderMarkdownOptions {
|
|
217
|
+
headingColor?: ColorFn;
|
|
218
|
+
boldColor?: ColorFn;
|
|
219
|
+
italicColor?: ColorFn;
|
|
220
|
+
codeColor?: ColorFn;
|
|
221
|
+
linkColor?: ColorFn;
|
|
222
|
+
}
|
|
223
|
+
declare function renderMarkdown(md: string, opts?: RenderMarkdownOptions): string[];
|
|
224
|
+
|
|
225
|
+
declare const Search: typeof Search$1;
|
|
226
|
+
declare const cancelSymbol: symbol;
|
|
227
|
+
|
|
228
|
+
export { type ColorFn$2 as ColorFn, type FormatTerminalLinkOptions, Input, type ColorFn$1 as InputColorFn, LOBSTER_PALETTE, Loader, type LobsterPalette, type LobsterPaletteKey, type ColorFn as MarkdownColorFn, type NoteOptions, type RenderMarkdownOptions, type RenderTableOptions, type RestoreTerminalStateOptions, type SafeStreamWriter, type SafeStreamWriterOptions, Search, type StatusKind, type TableColumn, type WrapNoteMessageOptions, cancelSymbol, clearActiveProgressLine, colorize, createSafeStreamWriter, displayPath, displayString, emitJsonError, emitJsonOk, expandHomePrefix, formatCommandExample, formatCount, formatEmptyMessage, formatError, formatHeading, formatInfo, formatKeyValue, formatListItem, formatRootLink, formatRootedLink, formatSeparator, formatStatus, formatSuccess, formatTerminalLink, formatWarning, isRich, note, registerActiveProgressLine, renderMarkdown, renderTable, resolveConfigDir, resolveEffectiveHomeDir, resolveHomeDir, resolveRequiredHomeDir, resolveUserPath, restoreTerminalState, selectStyled, shortenHomeInString, shortenHomePath, stripAnsi, styleHealthChannelLine, stylePromptHint, stylePromptMessage, stylePromptTitle, theme, unregisterActiveProgressLine, visibleWidth, wrapNoteMessage };
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ declare const LOBSTER_PALETTE: {
|
|
|
14
14
|
readonly error: "#E23D2D";
|
|
15
15
|
readonly muted: "#8B7F77";
|
|
16
16
|
};
|
|
17
|
+
type LobsterPalette = typeof LOBSTER_PALETTE;
|
|
18
|
+
type LobsterPaletteKey = keyof LobsterPalette;
|
|
17
19
|
|
|
18
20
|
declare const theme: {
|
|
19
21
|
readonly accent: chalk.ChalkInstance;
|
|
@@ -39,7 +41,8 @@ declare function formatHeading(title: string): string;
|
|
|
39
41
|
declare function formatKeyValue(key: string, value: string, keyWidth?: number): string;
|
|
40
42
|
declare function formatCommandExample(command: string, description?: string): string;
|
|
41
43
|
declare function formatListItem(icon: string, text: string, description?: string): string;
|
|
42
|
-
|
|
44
|
+
type StatusKind = 'pending' | 'running' | 'success' | 'error' | 'skipped';
|
|
45
|
+
declare function formatStatus(status: StatusKind, message: string): string;
|
|
43
46
|
declare function formatSeparator(width?: number, char?: string): string;
|
|
44
47
|
declare function formatEmptyMessage(message: string): string;
|
|
45
48
|
declare function formatCount(count: number, singular: string, plural?: string): string;
|
|
@@ -51,10 +54,11 @@ declare function shortenHomePath(input: string): string;
|
|
|
51
54
|
declare function shortenHomeInString(input: string): string;
|
|
52
55
|
declare function displayPath(input: string): string;
|
|
53
56
|
declare function displayString(input: string): string;
|
|
54
|
-
|
|
57
|
+
type FormatTerminalLinkOptions = {
|
|
55
58
|
fallback?: string;
|
|
56
59
|
force?: boolean;
|
|
57
|
-
}
|
|
60
|
+
};
|
|
61
|
+
declare function formatTerminalLink(label: string, url: string, opts?: FormatTerminalLinkOptions, isTTY?: boolean): string;
|
|
58
62
|
|
|
59
63
|
declare function resolveEffectiveHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string | undefined;
|
|
60
64
|
declare function resolveRequiredHomeDir(env?: NodeJS.ProcessEnv, homedir?: () => string): string;
|
|
@@ -64,21 +68,25 @@ declare function expandHomePrefix(input: string, opts?: {
|
|
|
64
68
|
homedir?: () => string;
|
|
65
69
|
}): string;
|
|
66
70
|
|
|
67
|
-
declare
|
|
68
|
-
declare function formatDocsLink(path: string, label?: string, opts?: {
|
|
71
|
+
declare function formatRootedLink(root: string, path: string, label?: string, opts?: {
|
|
69
72
|
fallback?: string;
|
|
70
73
|
force?: boolean;
|
|
71
|
-
}): string;
|
|
72
|
-
declare function
|
|
74
|
+
}, isTTY?: boolean): string;
|
|
75
|
+
declare function formatRootLink(root: string, label?: string, isTTY?: boolean): string;
|
|
73
76
|
|
|
74
77
|
declare function emitJsonOk(data: unknown, meta?: Record<string, unknown>): void;
|
|
75
78
|
declare function emitJsonError(code: string, message: string): void;
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
type WrapNoteMessageOptions = {
|
|
78
81
|
maxWidth?: number;
|
|
79
82
|
columns?: number;
|
|
80
|
-
}
|
|
81
|
-
declare function
|
|
83
|
+
};
|
|
84
|
+
declare function wrapNoteMessage(message: string, options?: WrapNoteMessageOptions): string;
|
|
85
|
+
type NoteOptions = {
|
|
86
|
+
columns?: number;
|
|
87
|
+
maxWidth?: number;
|
|
88
|
+
};
|
|
89
|
+
declare function note(message: string, title?: string, options?: NoteOptions): void;
|
|
82
90
|
|
|
83
91
|
declare function registerActiveProgressLine(stream: NodeJS.WriteStream): void;
|
|
84
92
|
declare function clearActiveProgressLine(): void;
|
|
@@ -128,4 +136,93 @@ declare function renderTable(opts: RenderTableOptions): string;
|
|
|
128
136
|
|
|
129
137
|
declare function styleHealthChannelLine(line: string, rich: boolean): string;
|
|
130
138
|
|
|
131
|
-
|
|
139
|
+
declare namespace Search$1 {
|
|
140
|
+
interface Item<T> {
|
|
141
|
+
value: T;
|
|
142
|
+
label: string;
|
|
143
|
+
hint?: string;
|
|
144
|
+
}
|
|
145
|
+
interface LockedSection<T> {
|
|
146
|
+
title: string;
|
|
147
|
+
items: Item<T>[];
|
|
148
|
+
hiddenCount?: number;
|
|
149
|
+
}
|
|
150
|
+
interface MultiselectOptions<T> {
|
|
151
|
+
message: string;
|
|
152
|
+
items: Item<T>[];
|
|
153
|
+
maxVisible?: number;
|
|
154
|
+
initialSelected?: T[];
|
|
155
|
+
required?: boolean;
|
|
156
|
+
lockedSection?: LockedSection<T>;
|
|
157
|
+
isTTY?: boolean;
|
|
158
|
+
}
|
|
159
|
+
const cancelSymbol: unique symbol;
|
|
160
|
+
function approxStringWidth(plain: string): number;
|
|
161
|
+
function visualRowsForLine(line: string, columns: number): number;
|
|
162
|
+
function countVisualRowsForLines(lines: string[], columns: number | undefined): number;
|
|
163
|
+
function multiselect<T>(options: MultiselectOptions<T>): Promise<T[] | typeof cancelSymbol>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
type ColorFn$2 = (text: string) => string;
|
|
167
|
+
declare namespace Loader {
|
|
168
|
+
interface IndicatorOptions {
|
|
169
|
+
frames?: string[];
|
|
170
|
+
intervalMs?: number;
|
|
171
|
+
}
|
|
172
|
+
interface Options {
|
|
173
|
+
message?: string;
|
|
174
|
+
spinnerColor?: ColorFn$2;
|
|
175
|
+
messageColor?: ColorFn$2;
|
|
176
|
+
indicator?: IndicatorOptions;
|
|
177
|
+
}
|
|
178
|
+
interface Instance {
|
|
179
|
+
start(): void;
|
|
180
|
+
stop(): void;
|
|
181
|
+
isRunning(): boolean;
|
|
182
|
+
line(): string;
|
|
183
|
+
setMessage(message: string): void;
|
|
184
|
+
setIndicator(indicator?: IndicatorOptions): void;
|
|
185
|
+
}
|
|
186
|
+
function create(options?: Options): Instance;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
type ColorFn$1 = (text: string) => string;
|
|
190
|
+
declare namespace Input {
|
|
191
|
+
interface ReadTextBaseOptions {
|
|
192
|
+
message: string;
|
|
193
|
+
hint?: string;
|
|
194
|
+
defaultValue?: string;
|
|
195
|
+
hidden?: boolean;
|
|
196
|
+
messageColor?: ColorFn$1;
|
|
197
|
+
hintColor?: ColorFn$1;
|
|
198
|
+
input?: NodeJS.ReadStream;
|
|
199
|
+
output?: NodeJS.WritableStream;
|
|
200
|
+
}
|
|
201
|
+
interface ReadConfirmOptions {
|
|
202
|
+
message: string;
|
|
203
|
+
hint?: string;
|
|
204
|
+
defaultValue?: boolean;
|
|
205
|
+
messageColor?: ColorFn$1;
|
|
206
|
+
hintColor?: ColorFn$1;
|
|
207
|
+
input?: NodeJS.ReadStream;
|
|
208
|
+
output?: NodeJS.WritableStream;
|
|
209
|
+
}
|
|
210
|
+
function readText(options: ReadTextBaseOptions): Promise<string>;
|
|
211
|
+
function readConfirm(options: ReadConfirmOptions): Promise<boolean>;
|
|
212
|
+
function readPassword(options: Omit<ReadTextBaseOptions, 'hidden'>): Promise<string>;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
type ColorFn = (text: string) => string;
|
|
216
|
+
interface RenderMarkdownOptions {
|
|
217
|
+
headingColor?: ColorFn;
|
|
218
|
+
boldColor?: ColorFn;
|
|
219
|
+
italicColor?: ColorFn;
|
|
220
|
+
codeColor?: ColorFn;
|
|
221
|
+
linkColor?: ColorFn;
|
|
222
|
+
}
|
|
223
|
+
declare function renderMarkdown(md: string, opts?: RenderMarkdownOptions): string[];
|
|
224
|
+
|
|
225
|
+
declare const Search: typeof Search$1;
|
|
226
|
+
declare const cancelSymbol: symbol;
|
|
227
|
+
|
|
228
|
+
export { type ColorFn$2 as ColorFn, type FormatTerminalLinkOptions, Input, type ColorFn$1 as InputColorFn, LOBSTER_PALETTE, Loader, type LobsterPalette, type LobsterPaletteKey, type ColorFn as MarkdownColorFn, type NoteOptions, type RenderMarkdownOptions, type RenderTableOptions, type RestoreTerminalStateOptions, type SafeStreamWriter, type SafeStreamWriterOptions, Search, type StatusKind, type TableColumn, type WrapNoteMessageOptions, cancelSymbol, clearActiveProgressLine, colorize, createSafeStreamWriter, displayPath, displayString, emitJsonError, emitJsonOk, expandHomePrefix, formatCommandExample, formatCount, formatEmptyMessage, formatError, formatHeading, formatInfo, formatKeyValue, formatListItem, formatRootLink, formatRootedLink, formatSeparator, formatStatus, formatSuccess, formatTerminalLink, formatWarning, isRich, note, registerActiveProgressLine, renderMarkdown, renderTable, resolveConfigDir, resolveEffectiveHomeDir, resolveHomeDir, resolveRequiredHomeDir, resolveUserPath, restoreTerminalState, selectStyled, shortenHomeInString, shortenHomePath, stripAnsi, styleHealthChannelLine, stylePromptHint, stylePromptMessage, stylePromptTitle, theme, unregisterActiveProgressLine, visibleWidth, wrapNoteMessage };
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
`).flatMap(
|
|
3
|
-
`)}function
|
|
4
|
-
`);}catch(
|
|
5
|
-
`),reset:()=>{
|
|
6
|
-
`))){if(
|
|
7
|
-
`||
|
|
1
|
+
import de,{Chalk}from'chalk';import le from'os';import ve from'path';import {Filesystem}from'@easbot/utils';import {note,select}from'@clack/prompts';import fe from'process';import*as me from'readline';import {stripVTControlCharacters}from'util';import {Writable}from'stream';var bt="\\x1b\\[[0-9;]*m",St="\\x1b\\]8;;.*?\\x1b\\\\|\\x1b\\]8;;\\x1b\\\\",$t=new RegExp(bt,"g"),vt=new RegExp(St,"g");function re(e){return e?e.replace(vt,"").replace($t,""):""}function j(e){return e?Array.from(re(e)).length:0}var J={accent:"#FF5A2D",accentBright:"#FF7A3D",accentDim:"#D14A22",info:"#FF8A5B",success:"#2FBF71",warn:"#FFB020",error:"#E23D2D",muted:"#8B7F77"};var yt=typeof process.env.FORCE_COLOR=="string"&&process.env.FORCE_COLOR.trim().length>0&&process.env.FORCE_COLOR.trim()!=="0",xe=process.env.NO_COLOR&&!yt?new Chalk({level:0}):de,V=e=>xe.hex(e),b={accent:V(J.accent),accentBright:V(J.accentBright),accentDim:V(J.accentDim),info:V(J.info),success:V(J.success),warn:V(J.warn),error:V(J.error),muted:V(J.muted),heading:xe.bold.hex(J.accent),command:V(J.accentBright),option:V(J.warn)},k=()=>xe.level>0,y=(e,t,r)=>e?t(r):r;function wt(e){return y(k(),b.success,"\u2713")+` ${e}`}function Et(e){return y(k(),b.error,"\u2717")+` ${e}`}function Rt(e){return y(k(),b.warn,"\u26A0")+` ${e}`}function It(e){return y(k(),b.info,"\u2139")+` ${e}`}function kt(e){return y(k(),b.heading,e)}function Ot(e,t,r=15){let s=e.padEnd(r);return `${y(k(),b.muted,s)} ${t}`}function Wt(e,t){let r=k(),s=y(r,b.command,e);if(!t)return ` ${s}`;let c=y(r,b.muted,`# ${t}`);return ` ${s} ${c}`}function Lt(e,t,r){let s=k(),c=y(s,b.info,e),f=y(s,b.command,t),m=r?` ${y(s,b.muted,r)}`:"";return `${c} ${f}${m}`}var Mt={pending:{icon:"\u25CB",color:b.muted},running:{icon:"\u25CF",color:b.info},success:{icon:"\u2713",color:b.success},error:{icon:"\u2717",color:b.error},skipped:{icon:"\u25CB",color:b.muted}};function Pt(e,t){let{icon:r,color:s}=Mt[e];return y(k(),s,r)+` ${t}`}function Ft(e=80,t="\u2500"){return y(k(),b.muted,t.repeat(e))}function Nt(e){return y(k(),b.muted,e)}function At(e,t,r){let s=e===1?t:r||`${t}s`;return `${y(k(),b.accent,String(e))} ${s}`}function K(e){let t=e?.trim();return t?Filesystem.toUnixPath(t):void 0}function De(e){try{return K(e())}catch{return}}function _t(e,t){let r=K(e.EASBOT_TEST_HOME);if(r)return r;let s=K(e.EASBOT_HOME);if(s){if(s==="~"||s.startsWith("~/")||s.startsWith("~\\")){let m=K(e.HOME)??K(e.USERPROFILE)??De(t);return m?s.replace(/^~(?=$|[\\/])/,m):void 0}return s}let c=K(e.HOME);if(c)return c;let f=K(e.USERPROFILE);return f||De(t)}function Q(e=process.env,t=le.homedir){let r=_t(e,t);if(r)return r}function Se(e=process.env,t=le.homedir){return Q(e,t)??Filesystem.resolve(process.cwd())}function $e(e,t){if(!e.startsWith("~"))return K(e);let r=process.env.EASBOT_TEST_HOME?.trim();return r||(r=K(t?.home)??Q(t?.env??process.env,t?.homedir??le.homedir)),r?e.replace(/^~(?=$|[\\/])/,r):K(e)}function Ve(e){if(!e)return "";let t=e.trim();if(!t)return t;if(t.startsWith("~")){let r=$e(t,{home:Se(process.env,le.homedir),env:process.env,homedir:le.homedir});return ve.resolve(r)}return ve.resolve(t)}function Ht(e=process.env,t=le.homedir){let r=e.EASBOT_STATE_DIR?.trim();if(r)return Ve(r);let c=Q(e,t)??process.cwd();return ve.join(c,".config","easbot")}function Ke(){return Q(process.env,le.homedir)}function ze(){let e=Ke();return e?process.env.EASBOT_TEST_HOME?.trim()?{home:e,prefix:"~"}:process.env.EASBOT_HOME?.trim()?{home:e,prefix:"$EASBOT_HOME"}:{home:e,prefix:"~"}:void 0}function Ye(e){if(!e)return e;let t=ze();if(!t)return e;let{home:r,prefix:s}=t;return e===r?s:e.startsWith(`${r}/`)||e.startsWith(`${r}\\`)?`${s}${e.slice(r.length)}`:e}function Ue(e){if(!e)return e;let t=ze();return t?e.split(t.home).join(t.prefix):e}function Bt(e){return Ye(e)}function Te(e){return Ue(e)}function Jt(e,t){return e?.force===true?true:e?.force===false?false:!!(t??process.stdout?.isTTY)}function oe(e,t,r,s){let c=re(e??""),f=re(t??"");return Jt(r,s)?`\x1B]8;;${f}\x07${c}\x1B]8;;\x07`:r?.fallback??`${c} (${f})`}function Dt(e,t,r,s,c){let f=t.trim();if(!e)return oe(r??f,f,s,c);let m=/^[a-z]+:\/\//i.test(f)?f:`${e}${f.startsWith("/")?f:`/${f}`}`;return oe(r??m,m,s,c)}function jt(e,t,r){return oe(t??e,e,void 0,r)}function Vt(e,t){let r={ok:true,data:e};t!==void 0&&(r.meta=t),console.log(JSON.stringify(r,null,2));}function Kt(e,t){console.log(JSON.stringify({ok:false,error:{code:e,message:t}},null,2));}var Ce=e=>k()?b.accent(e):e,ye=e=>e&&k()?b.heading(e):e,we=e=>e&&k()?b.muted(e):e;var Yt=/^(https?:\/\/|file:\/\/)/i,Ut=/^[a-zA-Z]:[\\/]/,Gt=/^[a-zA-Z0-9._-]+$/;function Ge(e,t){if(t<=0)return [e];let r=Array.from(e),s=[];for(let c=0;c<r.length;c+=t)s.push(r.slice(c,c+t).join(""));return s.length>0?s:[e]}function qe(e){return e?Yt.test(e)||e.startsWith("/")||e.startsWith("~/")||e.startsWith("./")||e.startsWith("../")||Ut.test(e)||e.startsWith("\\\\")||e.includes("/")||e.includes("\\")?true:e.includes("_")&&Gt.test(e):false}function qt(e,t){if(e.trim().length===0)return [e];if(t<=0)return [e];let r=e.match(/^(\s*)([-*\u2022]\s+)?(.*)$/),s=r?.[1]??"",c=r?.[2]??"",f=r?.[3]??"",m=`${s}${c}`,a=`${s}${c?" ".repeat(c.length):""}`,v=Math.max(10,t-j(m)),$=Math.max(10,t-j(a)),E=f.split(/\s+/).filter(Boolean),O=[],h="",o=m,l=v;for(let T of E){if(!h){if(j(T)>l){if(qe(T)){h=T;continue}let w=Ge(T,l),S=w.shift()??"";O.push(o+S),o=a,l=$;for(let p of w)O.push(o+p);continue}h=T;continue}let n=`${h} ${T}`;if(j(n)<=l){h=n;continue}if(O.push(o+h),o=a,l=$,j(T)>l){if(qe(T)){h=T;continue}let w=Ge(T,l),S=w.shift()??"";O.push(o+S);for(let p of w)O.push(o+p);h="";continue}h=T;}return (h||E.length===0)&&O.push(o+h),O}function Qe(e,t={}){let r=process.stdout?.columns??80,s=t.columns??r,c=t.maxWidth??Math.max(40,Math.min(88,s-10));return e.split(`
|
|
2
|
+
`).flatMap(f=>qt(f,c)).join(`
|
|
3
|
+
`)}function Qt(e,t,r={}){let s=r.columns??process.stdout?.columns,c=Qe(e,{columns:s,maxWidth:r.maxWidth});note(c,ye(t));}var X=null;function Xt(e,t){try{e.write(t);}catch{}}function Zt(e){e.isTTY&&(X=e);}function Ee(){X?.isTTY&&Xt(X,"\r\x1B[2K");}function en(e){X&&(e&&X!==e||(X=null));}function nn(e){return select({...e,message:Ce(e.message),options:e.options.map(t=>t.hint===void 0?t:{...t,hint:we(t.hint)})})}var rn="\x1B[0m\x1B[?25h\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004l";function ue(e,t,r){let s=r?` (${r})`:"",c=`[terminal] restore ${e} failed${s}: ${String(t)}`;try{fe.stderr.write(`${c}
|
|
4
|
+
`);}catch(f){console.error(`[terminal] restore reporting failed${s}: ${String(f)}`);}}function on(e,t={}){let r=t.resumeStdinIfPaused??t.resumeStdin??false;try{Ee();}catch(c){ue("progress line",c,e);}let s=fe.stdin;if(s?.isTTY&&typeof s.setRawMode=="function"){try{s.setRawMode(!1);}catch(c){ue("raw mode",c,e);}if(r&&typeof s.isPaused=="function"&&s.isPaused())try{s.resume();}catch(c){ue("stdin resume",c,e);}}if(fe.stdout?.isTTY)try{fe.stdout.write(rn);}catch(c){ue("stdout reset",c,e);}}function cn(e){let t=e?.code;return t==="EPIPE"||t==="EIO"}function an(e={}){let t=false,r=false,s=(a,v)=>{r||(r=true,e.onBrokenPipe?.(a,v));},c=(a,v)=>{if(!cn(a))throw a;return t=true,s(a,v),false},f=(a,v)=>{if(t)return false;try{e.beforeWrite?.();}catch($){return c($,fe.stderr)}try{return a.write(v),!t}catch($){return c($,a)}};return {write:f,writeLine:(a,v)=>f(a,`${v}
|
|
5
|
+
`),reset:()=>{t=false,r=false;},isClosed:()=>t}}function Z(e,t){return !Number.isFinite(t)||t<=0?"":e.repeat(t)}function ln(e,t,r){let s=j(e);if(s>=t)return e;let c=t-s;if(r==="right")return `${Z(" ",c)}${e}`;if(r==="center"){let f=Math.floor(c/2),m=c-f;return `${Z(" ",f)}${e}${Z(" ",m)}`}return `${e}${Z(" ",c)}`}function un(e,t){if(!e||e.length===0)return [""];if(!Number.isFinite(t)||t<=0)return [e];let r="\x1B",s=[];for(let i=0;i<e.length;){if(e[i]===r){if(e[i+1]==="["){let g=i+2;for(;g<e.length;){let C=e[g];if(C==="m")break;if(C&&C>="0"&&C<="9"){g+=1;continue}if(C===";"){g+=1;continue}break}if(e[g]==="m"){s.push({kind:"ansi",value:e.slice(i,g+1)}),i=g+1;continue}}if(e[i+1]==="]"&&e.slice(i+2,i+5)==="8;;"){let g=e.indexOf(`${r}\\`,i+5);if(g>=0){s.push({kind:"ansi",value:e.slice(i,g+2)}),i=g+2;continue}}}let u=e.codePointAt(i);if(!u)break;let x=String.fromCodePoint(u);s.push({kind:"char",value:x}),i+=x.length;}let c=s.findIndex(i=>i.kind==="char");if(c<0)return [e];let f=-1;for(let i=s.length-1;i>=0;i-=1){let u=s[i];if(u&&u.kind==="char"){f=i;break}}let m=s.slice(0,c).filter(i=>i.kind==="ansi").map(i=>i.value).join(""),a=s.slice(f+1).filter(i=>i.kind==="ansi").map(i=>i.value).join(""),v=s.slice(c,f+1),$=[],E=i=>i===" "||i===" "||i==="/"||i==="-"||i==="_"||i===".",O=i=>i===" "||i===" ",h=false,o=[],l=0,T=null,n=i=>(i??o).map(u=>u.value).join(""),w=i=>i.reduce((u,x)=>u+(x.kind==="char"?1:0),0),S=i=>{let u=i.replace(/\s+$/,"");u.trim().length!==0&&$.push(u);},p=i=>{if(o.length===0)return;if(i==null||i<=0){S(n()),o.length=0,l=0,T=null;return}let u=o.slice(0,i),x=o.slice(i);for(S(n(u));x.length>0;){let g=x[0];if(g?.kind!=="char"||!O(g.value))break;x.shift();}o.length=0,o.push(...x),l=w(o),T=null;};for(let i of v){if(i.kind==="ansi"){o.push(i);continue}let u=i.value;if(!(h&&(h=false,u===`
|
|
6
|
+
`))){if(u===`
|
|
7
|
+
`||u==="\r"){p(o.length),u==="\r"&&(h=true);continue}l+1>t&&l>0&&p(T),o.push(i),l+=1,E(u)&&(T=o.length);}}return p(o.length),$.length===0?[""]:!m&&!a?$:$.map(i=>i&&`${m}${i}${a}`)}function fn(e){if(e!=null&&!(!Number.isFinite(e)||e<=0))return Math.floor(e)}function dn(e){let t=e.rows.map(S=>{let p={};for(let[i,u]of Object.entries(S))p[i]=Te(u);return p}),r=e.border??"unicode";if(r==="none"){let S=e.columns;return `${[S.map(u=>u.header).join(" | "),...t.map(u=>S.map(x=>u[x.key]??"").join(" | "))].join(`
|
|
8
8
|
`)}
|
|
9
|
-
`}let
|
|
9
|
+
`}let s=Math.max(0,e.padding??1),c=e.columns,f=c.map(S=>{let p=j(S.header),i=Math.max(0,...t.map(u=>j(u[S.key]??"")));return {headerW:p,cellW:i}}),m=c.map((S,p)=>{let i=f[p];if(!i)throw new Error(`Internal error: metrics[${p}] is undefined`);let u=Math.max(i.headerW,i.cellW)+s*2,x=S.maxWidth?Math.min(u,S.maxWidth):u;return Math.max(S.minWidth??3,x)}),a=fn(e.width),v=c.length+1,$=m.reduce((S,p)=>S+p,0)+v,E=c.map((S,p)=>{let i=f[p];if(!i)throw new Error(`Internal error: metrics[${p}] is undefined`);return Math.max(S.minWidth??3,i.headerW+s*2,3)}),O=c.map((S,p)=>{let i=f[p];if(!i)throw new Error(`Internal error: metrics[${p}] is undefined`);return Math.max(i.headerW+s*2,3)});if(a&&$>a){let S=$-a,p=c.map((x,g)=>{let C=m[g];if(C===void 0)throw new Error(`Internal error: widths[${g}] is undefined`);return {i:g,w:C}}).filter(({i:x})=>!!c[x]?.flex).toSorted((x,g)=>g.w-x.w).map(x=>x.i),i=c.map((x,g)=>{let C=m[g];if(C===void 0)throw new Error(`Internal error: widths[${g}] is undefined`);return {i:g,w:C}}).filter(({i:x})=>!c[x]?.flex).toSorted((x,g)=>g.w-x.w).map(x=>x.i),u=(x,g)=>{for(;S>0;){let C=false;for(let _ of x){let F=m[_],H=g[_];if(!(F===void 0||H===void 0)&&!(F<=H)&&(m[_]=F-1,S-=1,C=true,S<=0))break}if(!C)break}};u(p,E),u(p,O),u(i,E),u(i,O);}if(a){let S=c.length+1,p=m.reduce((u,x)=>u+x,0)+S,i=a-p;if(i>0){let u=c.map((x,g)=>({c:x,i:g})).filter(({c:x})=>!!x.flex).map(({i:x})=>x);if(u.length>0){let x=c.map(g=>typeof g.maxWidth=="number"&&g.maxWidth>0?Math.floor(g.maxWidth):Number.POSITIVE_INFINITY);for(;i>0;){let g=false;for(let C of u){let _=m[C],F=x[C];if(!(_===void 0||F===void 0)&&!(_>=F)&&(m[C]=_+1,i-=1,g=true,i<=0))break}if(!g)break}}}}let h=r==="ascii"?{tl:"+",tr:"+",bl:"+",br:"+",h:"-",v:"|",t:"+",ml:"+",m:"+",mr:"+",b:"+"}:{tl:"\u250C",tr:"\u2510",bl:"\u2514",br:"\u2518",h:"\u2500",v:"\u2502",t:"\u252C",ml:"\u251C",m:"\u253C",mr:"\u2524",b:"\u2534"},o=(S,p,i)=>`${S}${m.map(u=>{if(u===void 0)throw new Error("Internal error: width is undefined");return Z(h.h,u)}).join(p)}${i}`,l=S=>{let p=m[S];if(p===void 0)throw new Error(`Internal error: widths[${S}] is undefined`);return Math.max(1,p-s*2)},T=Z(" ",s),n=(S,p=false)=>{let u=c.map(C=>p?C.header:S[C.key]??"").map((C,_)=>un(C,l(_))),x=Math.max(...u.map(C=>C.length)),g=[];for(let C=0;C<x;C+=1){let _=u.map((F,H)=>{let W=F[C]??"",D=c[H];if(!D)throw new Error(`Internal error: columns[${H}] is undefined`);let M=ln(W,l(H),D.align??"left");return `${T}${M}${T}`});g.push(`${h.v}${_.join(h.v)}${h.v}`);}return g},w=[];w.push(o(h.tl,h.t,h.tr)),w.push(...n({},true)),w.push(o(h.ml,h.m,h.mr));for(let S of t)w.push(...n(S,false));return w.push(o(h.bl,h.b,h.br)),`${w.join(`
|
|
10
10
|
`)}
|
|
11
|
-
`}function
|
|
11
|
+
`}var mn=[{prefix:"failed",color:b.error},{prefix:"ok",color:b.success},{prefix:"linked",color:b.success},{prefix:"configured",color:b.success},{prefix:"not linked",color:b.warn},{prefix:"not configured",color:b.muted},{prefix:"unknown",color:b.warn}];function pn(e,t){if(!t)return e;let r=e.indexOf(":");if(r===-1)return e;let s=e.slice(0,r+1),c=e.slice(r+1).trimStart(),f=c.toLowerCase();for(let{prefix:m,color:a}of mn)if(f.startsWith(m))return `${s} ${a(c.slice(0,m.length))}${c.slice(m.length)}`;return e}var xn=new Writable({write(e,t,r){r();}}),ie;(h=>{h.cancelSymbol=Symbol("Search.cancel");function t(o){let l=0;for(let T of o){let n=T.codePointAt(0);if(n===void 0||n===0)continue;let w=n>=4352&&n<=4447||n>=8986&&n<=8987||n>=9001&&n<=9002||n>=9193&&n<=9196||n===9200||n===9203||n>=9725&&n<=9726||n>=9748&&n<=9749||n>=9800&&n<=9811||n===9855||n===9875||n===9889||n>=9898&&n<=9899||n>=9917&&n<=9918||n>=9924&&n<=9925||n===9934||n===9940||n===9962||n>=9970&&n<=9971||n===9973||n===9978||n===9981||n===9989||n>=9994&&n<=9995||n===10024||n===10060||n===10062||n>=10067&&n<=10069||n===10071||n>=10133&&n<=10135||n===10160||n===10175||n>=11035&&n<=11036||n===11088||n===11093||n>=11904&&n<=42191&&n!==12351||n>=43360&&n<=43388||n>=44032&&n<=55203||n>=63744&&n<=64255||n>=65040&&n<=65049||n>=65072&&n<=65135||n>=65280&&n<=65376||n>=65504&&n<=65510||n>=126976&&n<=129535;l+=w?2:1;}return l}h.approxStringWidth=t;function r(o,l){let T=stripVTControlCharacters(o),n=Math.max(1,l),w=t(T);return Math.max(1,Math.ceil(w/n))}h.visualRowsForLine=r;function s(o,l){let T=l!==void 0&&l>0?l:process.stdout.columns&&process.stdout.columns>0?process.stdout.columns:80,n=0;for(let w of o)n+=r(w,T);return n}h.countVisualRowsForLines=s;function c(o){let l=new Array(o.length);for(let T=0;T<o.length;T++){let n=o[T],w=n.value===null||n.value===void 0?"":String(n.value);l[T]={...n,searchKey:`${n.label}
|
|
12
|
+
${w}`.toLowerCase()};}return l}function f(o,l){return l===""||o.searchKey.includes(l)}function m(o,l){return l<=0||o<0?0:o>=l?l-1:o}function a(o){if(o?.length!==1)return false;let l=o.codePointAt(0);return !(l===void 0||l<32||l===127||l===27)}function v(){let o=process.stdout.rows;if(!o||o<=0)return 8;let l=Math.floor((o-8)/2);return Math.max(5,Math.min(15,l))}function $(o,l){try{o.write(l);}catch{}}function E(o){if(o&&o.isTTY&&typeof o.setRawMode=="function")try{o.setRawMode(!1);}catch{}}function O(o){let l=o.message,T=c(o.items),n=Math.max(1,o.maxVisible??v()),w=o.initialSelected??[],S=o.required??false,p=o.lockedSection,i=o.isTTY;i??!!process.stdout?.isTTY;return new Promise(x=>{let g=process.stdin,C=process.stdout,_=me.createInterface({input:g,output:xn,terminal:false});try{(i===!0||i===void 0&&g.isTTY)&&g.setRawMode?.(!0);}catch{}me.emitKeypressEvents(g,_);let F="",H="",W=0,D=new Set(w),M=0,G=false,Y=p?p.items.map(R=>R.value):[],pe=p?p.items.map(R=>R.label):[],se=[],We=()=>{if(se.length=0,H==="")for(let R=0;R<T.length;R++){let d=T[R];se.push(d);}else for(let R=0;R<T.length;R++){let d=T[R];f(d,H)&&se.push(d);}return se},Ze=()=>{if(M>0){$(C,`\x1B[${M}A`);for(let R=0;R<M;R++)$(C,"\x1B[2K\x1B[1B");$(C,`\x1B[${M}A`);}},Le=()=>{let R=pe.slice();for(let d=0;d<T.length;d++){let L=T[d];D.has(L.value)&&R.push(L.label);}return R},B=(R="active")=>{Ze();let d=[],L=We(),z=i===false?false:i===true?true:k(),_e=P=>y(z,b.error,P),ae=P=>y(z,b.success,P),I=P=>y(z,b.muted,P),ge=P=>y(z,b.heading,P),it=P=>y(z,b.accentBright,P),st=P=>y(z,de.bold,P),ct=P=>y(z,de.underline,P),at=P=>y(z,de.inverse,P),lt=P=>y(z,de.strikethrough,P),He=R==="active"||R==="error"?"\u25C6":R==="cancel"?"\u25A0":"\u25C7",ut=R==="cancel"||R==="error"?_e(He):ae(He);if(d.push(`${ut} ${st(l)}`),R==="active"||R==="error"){if(p&&p.items.length>0){d.push(I("\u2502"));let q=`${ge(p.title)} ${I("\u2500\u2500 always included")}`;d.push(`${I("\u2502")} ${I("\u2500\u2500")} ${q} ${I("\u2500".repeat(12))}`);for(let te of p.items)d.push(`${I("\u2502")} ${ae("\u2022")} ${ge(te.label)}`);p.hiddenCount&&p.hiddenCount>0&&d.push(`${I("\u2502")} ${I(`...and ${p.hiddenCount} more`)}`),d.push(I("\u2502")),d.push(`${I("\u2502")} ${I("\u2500\u2500")} ${ge("Additional agents")} ${I("\u2500".repeat(29))}`);}let P=`${I("\u2502")} ${I("Search:")} ${F}${at(" ")}`;d.push(P),d.push(`${I("\u2502")} ${I("\u2191\u2193 move \xB7 space select \xB7 enter confirm")}`),d.push(I("\u2502"));let ft=Math.max(0,L.length-n),dt=W-Math.floor(n/2),he=Math.max(0,Math.min(dt,ft)),Be=Math.min(L.length,he+n);if(L.length===0)d.push(`${I("\u2502")} ${I("No matches found")}`);else {for(let U=he;U<Be;U++){let ne=L[U],mt=D.has(ne.value),Je=U===W,pt=mt?ae("\u25CF"):I("\u25CB"),gt=Je?ct(ne.label):ne.label,ht=ne.hint?I(` (${ne.hint})`):"",xt=Je?it("\u276F"):" ";d.push(`${I("\u2502")} ${xt} ${pt} ${gt}${ht}`);}let q=he,te=L.length-Be;if(q>0||te>0){let U=[];q>0&&U.push(`\u2191 ${q} more`),te>0&&U.push(`\u2193 ${te} more`),d.push(`${I("\u2502")} ${I(U.join(" "))}`);}}d.push(I("\u2502"));let ee=Le();if(ee.length===0)d.push(`${I("\u2502")} ${I("Selected: (none)")}`);else {let q=ee.length<=3?ee.join(", "):`${ee.slice(0,3).join(", ")} +${ee.length-3} more`;d.push(`${I("\u2502")} ${ae("Selected:")} ${q}`);}R==="error"&&d.push(`${I("\u2502")} ${_e("\u26A0 Please select at least one item before submitting")}`),d.push(`${I("\u2514")}`);}else if(R==="submit"){let P=Le();d.push(`${I("\u2502")} ${I(P.join(", "))}`);}else d.push(`${I("\u2502")} ${lt(I("Cancelled"))}`);$(C,`${d.join(`
|
|
13
|
+
`)}
|
|
14
|
+
`);try{M=s(d,C.columns);}catch{M=d.length;}},Me=false,et=()=>{if(!Me){Me=true;try{g.removeListener("keypress",Ae),g.removeListener("end",Ne);}catch{}try{process.removeListener("SIGINT",ce),process.removeListener("SIGTERM",ce);}catch{}E(g);try{_.close();}catch{}}},Pe=R=>{G||(G=true,et(),x(R));},tt=()=>{if(S&&D.size===0&&Y.length===0){B("error");return}B("submit"),Pe([...Y,...Array.from(D)]);},Fe=()=>{B("cancel"),Pe(h.cancelSymbol);},Ne=()=>{Fe();},ce=()=>{E(g);},nt=R=>{let d=R[W];d&&(D.has(d.value)?D.delete(d.value):D.add(d.value));},rt=R=>{F+=R,H+=R.toLowerCase();},ot=()=>{F.length!==0&&(F=F.slice(0,-1),H=H.slice(0,-1));},Ae=(R,d)=>{if(!d)return;let L=We();if(W=m(W,L.length),d.name==="return"){tt();return}if(d.name==="escape"||d.ctrl&&d.name==="c"){Fe();return}if(d.name==="up"||d.name==="left"){L.length>0&&(W=m(W-1,L.length),B());return}if(d.name==="down"||d.name==="right"){L.length>0&&(W=m(W+1,L.length),B());return}if(d.name==="pageup"){L.length>0&&(W=m(W-n,L.length),B());return}if(d.name==="pagedown"){L.length>0&&(W=m(W+n,L.length),B());return}if(d.name==="home"){L.length>0&&(W=0,B());return}if(d.name==="end"){L.length>0&&(W=L.length-1,B());return}if(d.name==="space"){nt(L),B();return}if(d.name==="backspace"){F.length>0&&(ot(),W=0,B());return}!d.ctrl&&!d.meta&&a(d.sequence)&&(rt(d.sequence),W=0,B());};g.on("keypress",Ae),g.once("end",Ne),process.on("SIGINT",ce),process.on("SIGTERM",ce),B();})}h.multiselect=O;})(ie||(ie={}));var Re=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Ie=80,ke;(t=>{function e(r={}){let s=[...Re],c=Ie,f=0,m=null,a=r.message??"Loading...",v=r.spinnerColor??(o=>y(k(),b.accent,o)),$=r.messageColor??(o=>y(k(),b.muted,o)),E=o=>{s=o.frames!==void 0?[...o.frames]:[...Re],c=o.intervalMs!==void 0&&o.intervalMs>0?o.intervalMs:Ie,f=0;};r.indicator&&E(r.indicator);function O(){h(),!(s.length<=1)&&(m=setInterval(()=>{f=(f+1)%s.length;},c));}function h(){m!==null&&(clearInterval(m),m=null);}return {start:O,stop:h,isRunning(){return m!==null},line(){let o=s[f]??"";return `${o.length>0?`${v(o)} `:""}${$(a)}`},setMessage(o){a=o;},setIndicator(o){o?E(o):(s=[...Re],c=Ie,f=0),O();}}}t.create=e;})(ke||(ke={}));var bn=e=>y(k(),b.accent,e),Sn=e=>y(k(),b.muted,e),Oe;(m=>{function e(a){let v=a;typeof v.resume=="function"&&v.resume();}function t(a,v){try{a.write(v);}catch{}}function r(a,v,$){let E=a;for(let O=0;O<v.length;O+=1){let h=v[O],o=h.charCodeAt(0);if(o===3)return {buffer:E,done:true,line:""};if(o===4)return {buffer:E,done:true,line:E};if(o===10||o===13)return {buffer:"",done:true,line:E};if((o===8||o===127)){E=E.slice(0,-1);continue}E+=h;}return {buffer:E,done:false,line:""}}function s(a){return new Promise((v,$)=>{let{message:E,hint:O,defaultValue:h,hidden:o,input:l,output:T,messageColor:n,hintColor:w}=a,S=(n??bn)(E),p=O?` ${(w??Sn)(`(${O})`)}`:"",i=h?` [${h}]`:"",u=o?`${S}${p}: `:`${S}${p}${i}: `,x=l??fe.stdin,g=T??fe.stdout;t(g,u);let C="",_=false,F=M=>{_||(_=true,M(),x.off("data",H),x.off("end",W));},H=M=>{let G=typeof M=="string"?M:M.toString("utf8"),Y=r(C,G);if(C=Y.buffer,!Y.done)return;if(Y.line===""&&C===""&&!G.includes(`
|
|
15
|
+
`)&&!G.includes("\r")){F(()=>$(new Error("Input canceled")));return}let pe=Y.line.length===0&&h!==void 0?h:Y.line;F(()=>v(pe));},W=()=>{if(_)return;let M=C.length===0&&h!==void 0?h:C;F(()=>v(M));},D=M=>{if((typeof M=="string"?M:M.toString("utf8")).includes("")){F(()=>$(new Error("Input canceled")));return}H(M);};x.on("data",D),x.once("end",W),e(x);})}m.readText=s;async function c(a){let v=a.defaultValue!==false,E=(await s({message:a.message,hint:a.hint??`y/n, default ${v?"y":"n"}`,defaultValue:v?"y":"n",messageColor:a.messageColor,hintColor:a.hintColor,input:a.input,output:a.output})).trim().toLowerCase();return E===""?v:E==="y"||E==="yes"?true:E==="n"||E==="no"?false:c(a)}m.readConfirm=c;function f(a){return s({...a,hidden:true})}m.readPassword=f;})(Oe||(Oe={}));var $n=e=>y(k(),b.heading,e),vn=e=>y(k(),b.command,e),Tn=e=>y(k(),b.muted,e),Cn=e=>y(k(),b.warn,e),yn=e=>y(k(),b.accent,e);function wn(e,t,r,s,c,f){let m=e;return m=m.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(a,v,$)=>`${f(v)} (${$})`),m=m.replace(/`([^`]+)`/g,(a,v)=>c(v)),m=m.replace(/\*\*([^*]+)\*\*/g,(a,v)=>r(v)),m=m.replace(/(^|[^*])\*([^*]+)\*(?!\*)/g,(a,v,$)=>`${v}${s($)}`),m}function En(e,t={}){if(!e)return [];let r=t.headingColor??$n,s=t.boldColor??vn,c=t.italicColor??Tn,f=t.codeColor??Cn,m=t.linkColor??yn,a=n=>wn(n,r,s,c,f,m),v=e.replace(/\r\n/g,`
|
|
16
|
+
`).split(`
|
|
17
|
+
`),$=[],E=false,O=[],h="",o=0,l=true,T=()=>{if(O.length!==0){$.push(f(`\`\`\`${h}`));for(let n of O)$.push(f(n));$.push(f("```")),O=[],h="";}};for(let n of v){let w=n;if(w.trim().startsWith("```")){if(!E){T(),E=true,h=w.trim().slice(3).trim(),$.push(f(`\`\`\`${h}`)),l=false;continue}for(let u of O)$.push(f(u));O=[],$.push(f("```")),E=false,h="",l=false;continue}if(E){O.push(w);continue}let S=/^(#{1,3})\s+(.+)$/.exec(w);if(S){let u=S[1]??"#",x=S[2]??"";$.push(r(`${u} ${a(x)}`)),l=false;continue}if(/^(\s*[-*_])\s*\1\s*\1[-*_\s]*$/.test(w)||/^---\s*$/.test(w)||/^\*\*\*\s*$/.test(w)){$.push(f("\u2500".repeat(40))),l=true;continue}let p=/^\s*[-*]\s+(.+)$/.exec(w),i=/^\s*\d+\.\s+(.+)$/.exec(w);if(p){let u=p[1]??"";$.push(` \u2022 ${a(u)}`),o=0,l=false;continue}if(i){let u=i[1]??"";o+=1,$.push(` ${o}. ${a(u)}`),l=false;continue}if(w.trim()===""){l||$.push(""),l=true,o=0;continue}$.push(a(w)),l=false,o=0;}return E&&T(),$}var Vr=ie,Kr=ie.cancelSymbol;export{Oe as Input,J as LOBSTER_PALETTE,ke as Loader,Vr as Search,Kr as cancelSymbol,Ee as clearActiveProgressLine,y as colorize,an as createSafeStreamWriter,Bt as displayPath,Te as displayString,Kt as emitJsonError,Vt as emitJsonOk,$e as expandHomePrefix,Wt as formatCommandExample,At as formatCount,Nt as formatEmptyMessage,Et as formatError,kt as formatHeading,It as formatInfo,Ot as formatKeyValue,Lt as formatListItem,jt as formatRootLink,Dt as formatRootedLink,Ft as formatSeparator,Pt as formatStatus,wt as formatSuccess,oe as formatTerminalLink,Rt as formatWarning,k as isRich,Qt as note,Zt as registerActiveProgressLine,En as renderMarkdown,dn as renderTable,Ht as resolveConfigDir,Q as resolveEffectiveHomeDir,Ke as resolveHomeDir,Se as resolveRequiredHomeDir,Ve as resolveUserPath,on as restoreTerminalState,nn as selectStyled,Ue as shortenHomeInString,Ye as shortenHomePath,re as stripAnsi,pn as styleHealthChannelLine,we as stylePromptHint,Ce as stylePromptMessage,ye as stylePromptTitle,b as theme,en as unregisterActiveProgressLine,j as visibleWidth,Qe as wrapNoteMessage};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easbot/terminal",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.12",
|
|
4
4
|
"description": "Terminal interaction toolkit for the EASBOT ecosystem — themed colors, ANSI utilities, OSC-8 hyperlinks, command formatting, table rendering, styled prompts, safe stream writes, and terminal-state recovery",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -47,9 +47,8 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@clack/prompts": "^1.7.0",
|
|
49
49
|
"chalk": "^6.0.0",
|
|
50
|
-
"
|
|
51
|
-
"@easbot/types": "0.3.
|
|
52
|
-
"@easbot/utils": "0.3.11"
|
|
50
|
+
"@easbot/utils": "0.3.12",
|
|
51
|
+
"@easbot/types": "0.3.12"
|
|
53
52
|
},
|
|
54
53
|
"devDependencies": {
|
|
55
54
|
"@types/node": "^25.6.2",
|