@skein-code/cli 0.3.27 → 0.3.29
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.md +17 -2
- package/dist/cli.js +56 -24
- package/dist/cli.js.map +1 -1
- package/docs/NEXT_STEPS.md +25 -16
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ To build, verify, and install a local package artifact from this checkout:
|
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
98
|
npm run verify:package -- --output-dir artifacts/package
|
|
99
|
-
npm install -g ./artifacts/package/skein-code-cli-0.3.
|
|
99
|
+
npm install -g ./artifacts/package/skein-code-cli-0.3.29.tgz
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
To install the published package from npm:
|
|
@@ -252,7 +252,13 @@ as `accent`, `text`, `muted`, `success`, and `error`. Set
|
|
|
252
252
|
`SKEIN_GLYPHS=ascii` when a terminal or multiplexer renders Unicode symbols
|
|
253
253
|
inconsistently. `NO_COLOR=1` or `ui.color: false` removes palette colors while
|
|
254
254
|
keeping status symbols and semantic labels intact. `/density compact` and
|
|
255
|
-
`/density comfortable` control vertical rhythm.
|
|
255
|
+
`/density comfortable` control vertical rhythm. `TERM=dumb` automatically uses
|
|
256
|
+
ASCII, monochrome, reduced-motion, non-incremental output. Set
|
|
257
|
+
`SKEIN_SCREEN_READER=1` (or Ink's `INK_SCREEN_READER=true`) for linear
|
|
258
|
+
screen-reader output with semantic timeline, permission-choice, and input roles;
|
|
259
|
+
this profile applies the same low-motion fallbacks while preserving keyboard
|
|
260
|
+
commands. `SKEIN_REDUCE_MOTION=1` disables activity animation independently.
|
|
261
|
+
Skein enables Kitty keyboard
|
|
256
262
|
enhancements without probing when Kitty, WezTerm, Ghostty, or foot declares
|
|
257
263
|
support; set `SKEIN_KITTY_KEYBOARD=on|off` to override detection.
|
|
258
264
|
|
|
@@ -639,7 +645,16 @@ npm test
|
|
|
639
645
|
npm run build
|
|
640
646
|
npm run check
|
|
641
647
|
npm run test:pty
|
|
648
|
+
npm run benchmark:terminal-ui
|
|
642
649
|
npm run release:verify
|
|
643
650
|
```
|
|
644
651
|
|
|
652
|
+
The PTY suite exercises 20/24/40/80/120 columns, a 40×10 viewport,
|
|
653
|
+
`TERM=dumb`, ASCII/`NO_COLOR`, and screen-reader interaction. It replays raw
|
|
654
|
+
output in a headless terminal and checks the final visible frame for overflow,
|
|
655
|
+
stale panels, control-sequence leaks, and missing ready/permission/error state.
|
|
656
|
+
`benchmark:terminal-ui` is a local single-process regression gate with p95
|
|
657
|
+
budgets of 25 ms for input processing and 150 ms for streaming renders; it is
|
|
658
|
+
not a universal hardware performance claim.
|
|
659
|
+
|
|
645
660
|
Skein is licensed under MIT.
|
package/dist/cli.js
CHANGED
|
@@ -220,7 +220,7 @@ function isSqliteBusy(error) {
|
|
|
220
220
|
// package.json
|
|
221
221
|
var package_default = {
|
|
222
222
|
name: "@skein-code/cli",
|
|
223
|
-
version: "0.3.
|
|
223
|
+
version: "0.3.29",
|
|
224
224
|
description: "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
|
|
225
225
|
type: "module",
|
|
226
226
|
license: "MIT",
|
|
@@ -236,6 +236,11 @@ var package_default = {
|
|
|
236
236
|
},
|
|
237
237
|
skein: {
|
|
238
238
|
releaseNotes: [
|
|
239
|
+
"TERM=dumb and screen-reader sessions now use deterministic ASCII, monochrome, reduced-motion, non-incremental rendering without losing keyboard input",
|
|
240
|
+
"SKEIN_SCREEN_READER=1 enables Ink accessibility output with semantic timeline, permission, and composer roles plus clean phase boundaries",
|
|
241
|
+
"PTY release gates now replay eight terminal scenarios through a headless emulator and reject final-frame overflow, stale panels, announcement joins, and missing status",
|
|
242
|
+
"A local terminal UI benchmark enforces 25 ms input and 150 ms streaming-render p95 budgets while retaining the final streamed chunk",
|
|
243
|
+
"MCP trust and revoke confirmation rendering now has a deterministic cross-platform release regression gate",
|
|
239
244
|
"MCP now follows a no-network search and inspect review before explicit workspace-bound manifest trust and lazy activation",
|
|
240
245
|
"Declarative capability manifests expose redacted source, version, tools, permissions, network, command, path, sensitive-field, process, and completion-evidence effects",
|
|
241
246
|
"Persistent disable and revoke unload active remote schemas while manifest fingerprint changes fail closed to untrusted",
|
|
@@ -318,6 +323,7 @@ var package_default = {
|
|
|
318
323
|
"benchmark:context": "tsx scripts/benchmark-local-index.ts",
|
|
319
324
|
"benchmark:duplication": "tsx scripts/benchmark-duplication.ts",
|
|
320
325
|
"benchmark:token-economy": "tsx scripts/benchmark-token-economy.ts",
|
|
326
|
+
"benchmark:terminal-ui": "tsx scripts/benchmark-terminal-ui.ts",
|
|
321
327
|
"verify:package": "node scripts/verify-package.mjs",
|
|
322
328
|
"release:verify": "npm run check && npm run verify:package --",
|
|
323
329
|
typecheck: "tsc --noEmit",
|
|
@@ -345,6 +351,7 @@ var package_default = {
|
|
|
345
351
|
"@types/diff": "^8.0.0",
|
|
346
352
|
"@types/node": "^22.19.7",
|
|
347
353
|
"@types/react": "^19.2.7",
|
|
354
|
+
"@xterm/headless": "^6.0.0",
|
|
348
355
|
tsup: "^8.5.1",
|
|
349
356
|
tsx: "^4.21.0",
|
|
350
357
|
vitest: "^4.0.18"
|
|
@@ -14769,6 +14776,20 @@ import { constants as constants5 } from "node:fs";
|
|
|
14769
14776
|
import chalk from "chalk";
|
|
14770
14777
|
|
|
14771
14778
|
// src/ui/terminal-capabilities.ts
|
|
14779
|
+
function resolveTerminalAccessibility(environment = process.env) {
|
|
14780
|
+
const screenReader = truthy(environment.SKEIN_SCREEN_READER) || environment.INK_SCREEN_READER?.trim().toLowerCase() === "true";
|
|
14781
|
+
const dumb = environment.TERM?.trim().toLowerCase() === "dumb";
|
|
14782
|
+
const reducedMotion = screenReader || dumb || truthy(environment.SKEIN_REDUCE_MOTION);
|
|
14783
|
+
const ascii = screenReader || dumb || environment.SKEIN_GLYPHS === "ascii" || environment.MOSAIC_GLYPHS === "ascii";
|
|
14784
|
+
const color = !screenReader && !dumb && environment.NO_COLOR === void 0;
|
|
14785
|
+
return {
|
|
14786
|
+
screenReader,
|
|
14787
|
+
reducedMotion,
|
|
14788
|
+
ascii,
|
|
14789
|
+
color,
|
|
14790
|
+
incrementalRendering: !screenReader && !dumb
|
|
14791
|
+
};
|
|
14792
|
+
}
|
|
14772
14793
|
function resolveKittyKeyboardConfig(environment = process.env) {
|
|
14773
14794
|
const override = environment.SKEIN_KITTY_KEYBOARD?.trim().toLowerCase();
|
|
14774
14795
|
if (override && ["1", "true", "yes", "on", "enabled"].includes(override)) {
|
|
@@ -14790,6 +14811,9 @@ function enabledKittyKeyboard() {
|
|
|
14790
14811
|
function disabledKittyKeyboard() {
|
|
14791
14812
|
return { mode: "disabled", flags: ["disambiguateEscapeCodes"] };
|
|
14792
14813
|
}
|
|
14814
|
+
function truthy(value) {
|
|
14815
|
+
return value !== void 0 && ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
|
|
14816
|
+
}
|
|
14793
14817
|
|
|
14794
14818
|
// src/cli/glyphs.ts
|
|
14795
14819
|
var unicodeGlyphs = {
|
|
@@ -16218,7 +16242,7 @@ function Timeline({ items, width = 80, glyphMode = "auto", showToolOutput = fals
|
|
|
16218
16242
|
if (!items.length) {
|
|
16219
16243
|
return /* @__PURE__ */ jsx(Box, { paddingLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: theme.muted, children: "Start with a request, @file, or /help." }) });
|
|
16220
16244
|
}
|
|
16221
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: items.map((item, index) => {
|
|
16245
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", "aria-role": "list", children: items.map((item, index) => {
|
|
16222
16246
|
if (item.kind === "user") {
|
|
16223
16247
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: compact3 || item.clipped ? 0 : 1, children: [
|
|
16224
16248
|
/* @__PURE__ */ jsx(Box, { width: 2, children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.accent, children: glyphs.prompt }) }),
|
|
@@ -16689,7 +16713,7 @@ function PermissionCard({ call, category, reason, width = 80, glyphMode = "auto"
|
|
|
16689
16713
|
{ text: "[Esc]", color: theme.muted }
|
|
16690
16714
|
];
|
|
16691
16715
|
const marker = glyphs.borderStyle === "classic" ? "!" : "\u258E";
|
|
16692
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
16716
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, "aria-role": "radiogroup", children: [
|
|
16693
16717
|
/* @__PURE__ */ jsx(PermissionLine, { marker, children: /* @__PURE__ */ jsx(Text, { bold: true, color: theme.warning, children: title }) }),
|
|
16694
16718
|
/* @__PURE__ */ jsx(PermissionLine, { marker, children: /* @__PURE__ */ jsx(Text, { color: theme.muted, children: tool }) }),
|
|
16695
16719
|
/* @__PURE__ */ jsx(PermissionLine, { marker, children: /* @__PURE__ */ jsx(Text, { color: theme.text, children: summaryLine }) }),
|
|
@@ -16752,7 +16776,7 @@ function PromptBar({ busy, value, placeholder, width = 80, mode = "chat", queueC
|
|
|
16752
16776
|
] }),
|
|
16753
16777
|
/* @__PURE__ */ jsx(Text, { color: theme.text, children: truncateDisplay(safeQueuePreview, queuePreviewWidth) })
|
|
16754
16778
|
] }) : null,
|
|
16755
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
16779
|
+
/* @__PURE__ */ jsxs(Box, { "aria-role": "textbox", children: [
|
|
16756
16780
|
/* @__PURE__ */ jsx(Text, { bold: true, color: shell ? theme.warning : theme.accent, children: shell ? "! " : `${glyphs.prompt} ` }),
|
|
16757
16781
|
children
|
|
16758
16782
|
] }),
|
|
@@ -18416,13 +18440,14 @@ function SkeinApp({ runner, config, extensions, initialPrompt, askMode = false,
|
|
|
18416
18440
|
const terminalHeight = Math.max(1, rows || 24);
|
|
18417
18441
|
const horizontalPadding = terminalWidth >= 24 ? 1 : 0;
|
|
18418
18442
|
const contentWidth = Math.max(1, terminalWidth - horizontalPadding * 2);
|
|
18419
|
-
const
|
|
18443
|
+
const terminalAccessibility = resolveTerminalAccessibility();
|
|
18444
|
+
const glyphMode = terminalAccessibility.ascii ? "ascii" : "auto";
|
|
18420
18445
|
const glyphs = resolveGlyphs(glyphMode);
|
|
18421
18446
|
const separator = ` ${glyphs.separator} `;
|
|
18422
18447
|
const ellipsis = terminalEllipsis();
|
|
18423
18448
|
const initialSession = runner.getSession();
|
|
18424
18449
|
const setupProblem = config.model.provider !== "compatible" && !config.model.apiKey ? `No ${config.model.provider} API key found. Set it and restart: export ${providerApiKeyEnv(config.model.provider)}=<your-key>${separator}then run ${PRODUCT_COMMAND} again. Use ${PRODUCT_COMMAND} doctor to verify, or --model to switch provider.` : config.model.provider === "compatible" && !config.model.baseUrl ? `No model endpoint configured. Set one and restart: export SKEIN_BASE_URL=<endpoint>${separator}or pass --base-url <endpoint>. Run ${PRODUCT_COMMAND} doctor to verify.` : void 0;
|
|
18425
|
-
const colorEnabled = config.ui.color &&
|
|
18450
|
+
const colorEnabled = config.ui.color && terminalAccessibility.color;
|
|
18426
18451
|
const [theme, setTheme] = useState2(() => resolveThemeWithColor(config.ui.theme, colorEnabled));
|
|
18427
18452
|
const [themeCatalogRevision, setThemeCatalogRevision] = useState2(0);
|
|
18428
18453
|
const [compact3, setCompact] = useState2(config.ui.compact);
|
|
@@ -18558,13 +18583,13 @@ function SkeinApp({ runner, config, extensions, initialPrompt, askMode = false,
|
|
|
18558
18583
|
setHistorySearch((current) => current ? setHistorySearchQuery(current, input2) : current);
|
|
18559
18584
|
}, [input2]);
|
|
18560
18585
|
useEffect2(() => {
|
|
18561
|
-
if (!busy || reducedMotion
|
|
18586
|
+
if (!busy || terminalAccessibility.reducedMotion) {
|
|
18562
18587
|
setFrameIndex(0);
|
|
18563
18588
|
return void 0;
|
|
18564
18589
|
}
|
|
18565
18590
|
const timer = setInterval(() => setFrameIndex((value) => (value + 1) % spinnerFrames().length), 120);
|
|
18566
18591
|
return () => clearInterval(timer);
|
|
18567
|
-
}, [busy]);
|
|
18592
|
+
}, [busy, terminalAccessibility.reducedMotion]);
|
|
18568
18593
|
const requestPermission = useCallback((call, category, reason) => {
|
|
18569
18594
|
return new Promise((resolve28) => setPermission({
|
|
18570
18595
|
call,
|
|
@@ -20003,14 +20028,17 @@ function permissionPosture(config) {
|
|
|
20003
20028
|
}
|
|
20004
20029
|
async function runInteractiveTui(options) {
|
|
20005
20030
|
await reloadUserThemes();
|
|
20031
|
+
const terminalAccessibility = resolveTerminalAccessibility();
|
|
20006
20032
|
const instance = render2(/* @__PURE__ */ jsx3(SkeinApp, { ...options }), {
|
|
20007
20033
|
exitOnCtrlC: false,
|
|
20008
20034
|
patchConsole: true,
|
|
20009
|
-
incrementalRendering:
|
|
20035
|
+
incrementalRendering: terminalAccessibility.incrementalRendering,
|
|
20036
|
+
isScreenReaderEnabled: terminalAccessibility.screenReader,
|
|
20010
20037
|
maxFps: 30,
|
|
20011
20038
|
kittyKeyboard: resolveKittyKeyboardConfig()
|
|
20012
20039
|
});
|
|
20013
20040
|
await instance.waitUntilExit();
|
|
20041
|
+
if (terminalAccessibility.screenReader) process.stdout.write("\n");
|
|
20014
20042
|
}
|
|
20015
20043
|
function initialTimeline(session, banner, setupProblem) {
|
|
20016
20044
|
const items = session.messages.filter((message2) => (message2.role === "user" || message2.role === "assistant") && visibleMessage(message2)).slice(-20).map((message2) => ({ id: message2.id, kind: message2.role, text: message2.content }));
|
|
@@ -20200,12 +20228,9 @@ function toolDetail2(call) {
|
|
|
20200
20228
|
return keys.slice(0, 3).join(", ");
|
|
20201
20229
|
}
|
|
20202
20230
|
function spinnerFrames() {
|
|
20203
|
-
const ascii =
|
|
20231
|
+
const ascii = resolveTerminalAccessibility().ascii;
|
|
20204
20232
|
return ascii ? [".", "o", "O", "o"] : ["\u25CC", "\u25CD", "\u25CE", "\u25C9", "\u25CE", "\u25CD"];
|
|
20205
20233
|
}
|
|
20206
|
-
function reducedMotion() {
|
|
20207
|
-
return process.env.SKEIN_REDUCE_MOTION === "1" || process.env.SKEIN_REDUCE_MOTION === "true" || process.env.INK_SCREEN_READER === "true" || process.env.TERM === "dumb";
|
|
20208
|
-
}
|
|
20209
20234
|
|
|
20210
20235
|
// src/ui/workspace-preparation.tsx
|
|
20211
20236
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
@@ -20228,10 +20253,11 @@ function WorkspacePreparationView({
|
|
|
20228
20253
|
}) {
|
|
20229
20254
|
const theme = useTheme();
|
|
20230
20255
|
const safeWidth2 = Math.max(1, Math.floor(width));
|
|
20231
|
-
const innerWidth = Math.max(1, safeWidth2 - (safeWidth2 >= 24 ? 4 : 0));
|
|
20232
20256
|
const compact3 = safeWidth2 < 48;
|
|
20233
20257
|
const constrained = height < 14;
|
|
20234
|
-
const
|
|
20258
|
+
const horizontalPadding = safeWidth2 >= 24 && !constrained ? 2 : 0;
|
|
20259
|
+
const innerWidth = Math.max(1, safeWidth2 - horizontalPadding * 2);
|
|
20260
|
+
const ascii = resolveTerminalAccessibility().ascii;
|
|
20235
20261
|
const spinner = (ascii ? [".", "o", "O", "o"] : ["\u25DC", "\u25E0", "\u25DD", "\u25DE", "\u25E1", "\u25DF"])[frame % (ascii ? 4 : 6)];
|
|
20236
20262
|
const separator = ascii ? "|" : "\xB7";
|
|
20237
20263
|
const brand = ascii ? "*" : PRODUCT_MARK;
|
|
@@ -20241,7 +20267,7 @@ function WorkspacePreparationView({
|
|
|
20241
20267
|
const modelLine = `model ${sanitizeTerminalText(model)}`;
|
|
20242
20268
|
const workspaceLine = `workspace ${compactDisplayPath(sanitizeTerminalText(workspace), Math.max(1, innerWidth - 10))}`;
|
|
20243
20269
|
const steps = preparationSteps(phase, progress, readiness, error, { ascii, spinner });
|
|
20244
|
-
return /* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", paddingX:
|
|
20270
|
+
return /* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", paddingX: horizontalPadding, children: [
|
|
20245
20271
|
/* @__PURE__ */ jsxs4(Box3, { children: [
|
|
20246
20272
|
/* @__PURE__ */ jsxs4(Text4, { bold: true, color: theme.accent, children: [
|
|
20247
20273
|
brand,
|
|
@@ -20259,11 +20285,11 @@ function WorkspacePreparationView({
|
|
|
20259
20285
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: truncateDisplay(modelLine, innerWidth) }),
|
|
20260
20286
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: truncateDisplay(workspaceLine, innerWidth) })
|
|
20261
20287
|
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: truncateDisplay(workspaceLine, innerWidth) }),
|
|
20262
|
-
/* @__PURE__ */ jsx4(Box3, { marginTop: 1, flexDirection: constrained ? "row" : "column", children: steps.map((step2) => constrained ? /* @__PURE__ */ jsxs4(Text4, { color: step2.state === "active" ? theme.accent : step2.state === "complete" ? theme.success : step2.state === "error" ? theme.error : theme.dim, children: [
|
|
20288
|
+
/* @__PURE__ */ jsx4(Box3, { marginTop: 1, flexDirection: constrained ? "row" : "column", children: steps.map((step2, index) => constrained ? /* @__PURE__ */ jsxs4(Text4, { color: step2.state === "active" ? theme.accent : step2.state === "complete" ? theme.success : step2.state === "error" ? theme.error : theme.dim, children: [
|
|
20289
|
+
index ? " " : "",
|
|
20263
20290
|
step2.glyph,
|
|
20264
20291
|
" ",
|
|
20265
|
-
step2.id === "persist" ? "save" : step2.id
|
|
20266
|
-
step2.id === "verify" ? "" : " "
|
|
20292
|
+
step2.id === "persist" ? "save" : step2.id
|
|
20267
20293
|
] }, step2.id) : /* @__PURE__ */ jsxs4(Box3, { height: 1, overflowY: "hidden", children: [
|
|
20268
20294
|
/* @__PURE__ */ jsxs4(Text4, { bold: true, color: step2.state === "active" ? theme.accent : step2.state === "complete" ? theme.success : step2.state === "error" ? theme.error : theme.border, children: [
|
|
20269
20295
|
step2.glyph,
|
|
@@ -20275,7 +20301,7 @@ function WorkspacePreparationView({
|
|
|
20275
20301
|
truncateDisplay(step2.detail, Math.max(1, innerWidth - displayWidth(step2.glyph) - (compact3 ? 12 : 14)))
|
|
20276
20302
|
] })
|
|
20277
20303
|
] }, step2.id)) }),
|
|
20278
|
-
/* @__PURE__ */ jsxs4(Box3, { marginTop: 1, children: [
|
|
20304
|
+
/* @__PURE__ */ jsxs4(Box3, { marginTop: constrained ? 0 : 1, children: [
|
|
20279
20305
|
/* @__PURE__ */ jsxs4(Text4, { bold: true, color: error ? theme.error : readiness ? theme.success : theme.accent, children: [
|
|
20280
20306
|
readiness ? ascii ? "[ok]" : "\u2713" : error ? ascii ? "[x]" : "\xD7" : spinner,
|
|
20281
20307
|
" "
|
|
@@ -20384,7 +20410,8 @@ function WorkspacePreparationApp({
|
|
|
20384
20410
|
}
|
|
20385
20411
|
async function runWorkspacePreparation(engine, config, options = {}) {
|
|
20386
20412
|
let result;
|
|
20387
|
-
const
|
|
20413
|
+
const terminalAccessibility = resolveTerminalAccessibility();
|
|
20414
|
+
const colorEnabled = config.ui.color && terminalAccessibility.color;
|
|
20388
20415
|
const theme = resolveThemeWithColor(config.ui.theme, colorEnabled);
|
|
20389
20416
|
const instance = render3(
|
|
20390
20417
|
/* @__PURE__ */ jsx4(ThemeProvider, { theme, children: /* @__PURE__ */ jsx4(
|
|
@@ -20406,11 +20433,13 @@ async function runWorkspacePreparation(engine, config, options = {}) {
|
|
|
20406
20433
|
...options.stderr ? { stderr: options.stderr } : {},
|
|
20407
20434
|
exitOnCtrlC: false,
|
|
20408
20435
|
patchConsole: false,
|
|
20409
|
-
incrementalRendering:
|
|
20436
|
+
incrementalRendering: terminalAccessibility.incrementalRendering,
|
|
20437
|
+
isScreenReaderEnabled: terminalAccessibility.screenReader,
|
|
20410
20438
|
kittyKeyboard: resolveKittyKeyboardConfig()
|
|
20411
20439
|
}
|
|
20412
20440
|
);
|
|
20413
20441
|
await instance.waitUntilExit();
|
|
20442
|
+
if (terminalAccessibility.screenReader) (options.stdout ?? process.stdout).write("\n");
|
|
20414
20443
|
return result ?? { status: "cancelled" };
|
|
20415
20444
|
}
|
|
20416
20445
|
function preparationLabel(phase, progress, readiness, compact3 = false) {
|
|
@@ -20757,7 +20786,7 @@ function isLoopbackHostname(hostname) {
|
|
|
20757
20786
|
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/u.test(normalized);
|
|
20758
20787
|
}
|
|
20759
20788
|
function OnboardingApp({ initialConfig, saveConfig, onFinish }) {
|
|
20760
|
-
const colorEnabled = initialConfig.ui.color &&
|
|
20789
|
+
const colorEnabled = initialConfig.ui.color && resolveTerminalAccessibility().color;
|
|
20761
20790
|
const theme = useMemo2(() => resolveThemeWithColor(initialConfig.ui.theme, colorEnabled), [colorEnabled, initialConfig.ui.theme]);
|
|
20762
20791
|
return /* @__PURE__ */ jsx5(ThemeProvider, { theme, children: /* @__PURE__ */ jsx5(OnboardingFlow, { initialConfig, saveConfig, onFinish }) });
|
|
20763
20792
|
}
|
|
@@ -20980,6 +21009,7 @@ function providerLabel(provider) {
|
|
|
20980
21009
|
}
|
|
20981
21010
|
async function runFirstRunOnboarding(initialConfig, options = {}) {
|
|
20982
21011
|
let result;
|
|
21012
|
+
const terminalAccessibility = resolveTerminalAccessibility();
|
|
20983
21013
|
const instance = render4(
|
|
20984
21014
|
/* @__PURE__ */ jsx5(
|
|
20985
21015
|
OnboardingApp,
|
|
@@ -20997,11 +21027,13 @@ async function runFirstRunOnboarding(initialConfig, options = {}) {
|
|
|
20997
21027
|
...options.stderr ? { stderr: options.stderr } : {},
|
|
20998
21028
|
exitOnCtrlC: false,
|
|
20999
21029
|
patchConsole: false,
|
|
21000
|
-
incrementalRendering:
|
|
21030
|
+
incrementalRendering: terminalAccessibility.incrementalRendering,
|
|
21031
|
+
isScreenReaderEnabled: terminalAccessibility.screenReader,
|
|
21001
21032
|
kittyKeyboard: resolveKittyKeyboardConfig()
|
|
21002
21033
|
}
|
|
21003
21034
|
);
|
|
21004
21035
|
await instance.waitUntilExit();
|
|
21036
|
+
if (terminalAccessibility.screenReader) (options.stdout ?? process.stdout).write("\n");
|
|
21005
21037
|
return result ?? { status: "cancelled" };
|
|
21006
21038
|
}
|
|
21007
21039
|
|