zelari-code 1.8.3 → 1.9.3
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 +13 -0
- package/dist/cli/app.js +11 -33
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/components/Sidebar.js +49 -31
- package/dist/cli/components/Sidebar.js.map +1 -1
- package/dist/cli/components/StartupBanner.js +28 -0
- package/dist/cli/components/StartupBanner.js.map +1 -0
- package/dist/cli/components/StatusBar.js +1 -7
- package/dist/cli/components/StatusBar.js.map +1 -1
- package/dist/cli/desktopConfig.js +281 -0
- package/dist/cli/desktopConfig.js.map +1 -0
- package/dist/cli/headless.js +62 -5
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/main.bundled.js +721 -193
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +132 -5
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/runHeadless.js +184 -44
- package/dist/cli/runHeadless.js.map +1 -1
- package/package.json +7 -4
package/dist/cli/main.bundled.js
CHANGED
|
@@ -30754,12 +30754,12 @@ var init_fixPath = __esm({
|
|
|
30754
30754
|
});
|
|
30755
30755
|
|
|
30756
30756
|
// src/cli/main.ts
|
|
30757
|
-
import
|
|
30757
|
+
import React15 from "react";
|
|
30758
30758
|
import { render } from "ink";
|
|
30759
30759
|
|
|
30760
30760
|
// src/cli/app.tsx
|
|
30761
|
-
import
|
|
30762
|
-
import { Box as
|
|
30761
|
+
import React10, { useState as useState8, useMemo, useCallback as useCallback5, useEffect as useEffect7 } from "react";
|
|
30762
|
+
import { Box as Box9, Static, useInput as useInput2, useStdin as useStdin2 } from "ink";
|
|
30763
30763
|
|
|
30764
30764
|
// src/cli/components/InputBar.tsx
|
|
30765
30765
|
import React from "react";
|
|
@@ -31273,8 +31273,7 @@ function StatusBar({
|
|
|
31273
31273
|
costUsd = 0,
|
|
31274
31274
|
cachedTokens = 0,
|
|
31275
31275
|
contextUsed = 0,
|
|
31276
|
-
contextLimit = 0
|
|
31277
|
-
brandVersion
|
|
31276
|
+
contextLimit = 0
|
|
31278
31277
|
}) {
|
|
31279
31278
|
const ctxLabel = contextLimit > 0 ? `${formatTokens(contextUsed)}/${formatTokens(contextLimit)}` : contextUsed > 0 ? formatTokens(contextUsed) : null;
|
|
31280
31279
|
return /* @__PURE__ */ React6.createElement(Box5, { paddingX: 1, width: "100%", justifyContent: "space-between", gap: 2 }, /* @__PURE__ */ React6.createElement(Box5, { flexShrink: 2 }, /* @__PURE__ */ React6.createElement(Text6, { wrap: "truncate" }, /* @__PURE__ */ React6.createElement(Text6, { color: sessionActive ? "green" : "gray" }, sessionActive ? "\u25CF" : "\u25CB"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: phase2 === "plan" ? "yellow" : "green" }, phase2 === "plan" ? "\u25C7 plan" : "\u25C6 build"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(
|
|
@@ -31284,7 +31283,7 @@ function StatusBar({
|
|
|
31284
31283
|
color: mode === "council" ? "magenta" : mode === "zelari" ? "green" : "cyan"
|
|
31285
31284
|
},
|
|
31286
31285
|
mode === "council" ? "council" : mode === "zelari" ? "zelari" : "agent"
|
|
31287
|
-
), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, provider), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, null, model), cwd ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, cwd)) : null)), /* @__PURE__ */ React6.createElement(Box5, { flexShrink: 1 }, /* @__PURE__ */ React6.createElement(Text6, { wrap: "truncate" }, busy && elapsedMs !== null ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Spinner, { color: "yellow" }), /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, " ", formatDuration(elapsedMs)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : lastMs !== null ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "last ", formatDuration(lastMs)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, queueCount > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, "queue ", queueCount), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, ctxLabel ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, ctxLabel), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, costUsd > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, formatCost(costUsd)), cachedTokens > 0 ? /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (", formatTokens(cachedTokens), " cached)") : null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null,
|
|
31286
|
+
), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, provider), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, null, model), cwd ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, cwd)) : null)), /* @__PURE__ */ React6.createElement(Box5, { flexShrink: 1 }, /* @__PURE__ */ React6.createElement(Text6, { wrap: "truncate" }, busy && elapsedMs !== null ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Spinner, { color: "yellow" }), /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, " ", formatDuration(elapsedMs)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : lastMs !== null ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "last ", formatDuration(lastMs)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, queueCount > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, "queue ", queueCount), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, ctxLabel ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, ctxLabel), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, costUsd > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, formatCost(costUsd)), cachedTokens > 0 ? /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (", formatTokens(cachedTokens), " cached)") : null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "session ", sessionId))));
|
|
31288
31287
|
}
|
|
31289
31288
|
|
|
31290
31289
|
// src/cli/components/SelectList.tsx
|
|
@@ -31332,14 +31331,47 @@ function SelectList({
|
|
|
31332
31331
|
// src/cli/components/Sidebar.tsx
|
|
31333
31332
|
import React8 from "react";
|
|
31334
31333
|
import { Box as Box7, Text as Text8 } from "ink";
|
|
31334
|
+
|
|
31335
|
+
// src/cli/components/brandArt.ts
|
|
31336
|
+
var BRAND_LOGO_ASCII = [
|
|
31337
|
+
" -#%=",
|
|
31338
|
+
" +%%%%#.",
|
|
31339
|
+
" :#%%%%%%%-",
|
|
31340
|
+
":%%@@@@@@@@=",
|
|
31341
|
+
"-%@@@@@@@@@@@+",
|
|
31342
|
+
":%@@@@@@%@@@@@@=",
|
|
31343
|
+
"-%%@@@@@.+%@@%@+",
|
|
31344
|
+
" -@@@@@@:%++%@=",
|
|
31345
|
+
"=*%@@@@@@:@@%=*@#+.",
|
|
31346
|
+
"%%%%%@@@@:+++-*%@@*",
|
|
31347
|
+
".%%%%%@@@@@+%+=:%@@@@:",
|
|
31348
|
+
"*@@@@@@@@@@@@@%@@@@@@*"
|
|
31349
|
+
].join("\n");
|
|
31350
|
+
var BRAND_LOGO_COMPACT = [
|
|
31351
|
+
" -#%=",
|
|
31352
|
+
" +%%%%#.",
|
|
31353
|
+
":%%@@@@=",
|
|
31354
|
+
"*@@@@@@*"
|
|
31355
|
+
].join("\n");
|
|
31356
|
+
|
|
31357
|
+
// src/cli/components/Sidebar.tsx
|
|
31358
|
+
var EMBLEM_BRAILLE = `\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2880\u28F4\u28FF\u28F7\u28C6\u2840
|
|
31359
|
+
\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2880\u28F6\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28E6\u2840
|
|
31360
|
+
\u2800\u2800\u2800\u2800\u2800\u2800\u28F0\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28E6
|
|
31361
|
+
\u2800\u2800\u2800\u2800\u28A0\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28F7\u2844
|
|
31362
|
+
\u2800\u2800\u2800\u2800\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2819\u283B\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2806
|
|
31363
|
+
\u2800\u2800\u2800\u2800\u28C8\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2800\u28F7\u28EC\u285B\u28BF\u28FF\u28DF\u28C1
|
|
31364
|
+
\u2800\u2880\u28F4\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2800\u287F\u28BF\u287F\u2883\u28C8\u28FB\u28FF\u28FF\u28F6
|
|
31365
|
+
\u2800\u28FC\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28E0\u28F4\u28C6\u283B\u280E\u28BF\u28FF\u28FF\u28FF\u28FF\u28E7
|
|
31366
|
+
\u28F0\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2847`;
|
|
31335
31367
|
var SIDEBAR_WIDTH = 28;
|
|
31336
31368
|
var SIDEBAR_MIN_COLUMNS = 96;
|
|
31337
31369
|
var SIDEBAR_HIDE_COLUMNS = 88;
|
|
31338
31370
|
var SIDEBAR_MIN_ROWS = 16;
|
|
31339
31371
|
var SIDEBAR_HIDE_ROWS = 14;
|
|
31340
|
-
var
|
|
31341
|
-
var
|
|
31342
|
-
var
|
|
31372
|
+
var BRAILLE_MIN_ROWS = 28;
|
|
31373
|
+
var MAX_FILES_SHORT = 6;
|
|
31374
|
+
var MAX_FILES_TALL = 10;
|
|
31343
31375
|
function shouldShowSidebar(columns, rows) {
|
|
31344
31376
|
return columns >= SIDEBAR_MIN_COLUMNS && rows >= SIDEBAR_MIN_ROWS;
|
|
31345
31377
|
}
|
|
@@ -31349,18 +31381,19 @@ function sidebarVisibility(columns, rows, currentlyVisible) {
|
|
|
31349
31381
|
}
|
|
31350
31382
|
return shouldShowSidebar(columns, rows);
|
|
31351
31383
|
}
|
|
31352
|
-
function maxSidebarFiles(rows) {
|
|
31353
|
-
const budget = Math.max(2, rows - 14 - SIDEBAR_CHROME_LINES);
|
|
31354
|
-
const cap = rows >= 28 ? MAX_FILES_TALL : MAX_FILES_SHORT;
|
|
31355
|
-
return Math.min(cap, budget);
|
|
31356
|
-
}
|
|
31357
31384
|
function truncatePath(p3, max) {
|
|
31358
31385
|
if (p3.length <= max) return p3;
|
|
31359
31386
|
return `\u2026${p3.slice(-(max - 1))}`;
|
|
31360
31387
|
}
|
|
31388
|
+
function preferAsciiLogo() {
|
|
31389
|
+
if (process.env.ZELARI_ASCII_LOGO === "1") return true;
|
|
31390
|
+
if (process.env.ZELARI_ASCII_LOGO === "0") return false;
|
|
31391
|
+
return process.platform === "win32";
|
|
31392
|
+
}
|
|
31361
31393
|
function Sidebar({ version: version2, changes, rows }) {
|
|
31362
|
-
|
|
31363
|
-
const
|
|
31394
|
+
const useBraille = !preferAsciiLogo() && rows >= BRAILLE_MIN_ROWS;
|
|
31395
|
+
const logoLines = useBraille ? EMBLEM_BRAILLE.split("\n") : BRAND_LOGO_COMPACT.split("\n");
|
|
31396
|
+
const maxFiles = rows >= BRAILLE_MIN_ROWS + 8 ? MAX_FILES_TALL : MAX_FILES_SHORT;
|
|
31364
31397
|
const visible = changes.files.slice(0, maxFiles);
|
|
31365
31398
|
const hidden = changes.files.length - visible.length;
|
|
31366
31399
|
const innerWidth = SIDEBAR_WIDTH - 4;
|
|
@@ -31372,65 +31405,42 @@ function Sidebar({ version: version2, changes, rows }) {
|
|
|
31372
31405
|
borderStyle: "single",
|
|
31373
31406
|
borderColor: "gray",
|
|
31374
31407
|
paddingX: 1,
|
|
31375
|
-
flexShrink: 0
|
|
31376
|
-
height: Math.min(rows - 8, SIDEBAR_CHROME_LINES + maxFiles + 2),
|
|
31377
|
-
overflow: "hidden"
|
|
31408
|
+
flexShrink: 0
|
|
31378
31409
|
},
|
|
31379
|
-
/* @__PURE__ */ React8.createElement(Box7, {
|
|
31410
|
+
/* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column", alignItems: "center" }, logoLines.map((line, i) => /* @__PURE__ */ React8.createElement(Text8, { key: i, color: "cyan" }, line))),
|
|
31411
|
+
/* @__PURE__ */ React8.createElement(Box7, { justifyContent: "center" }, /* @__PURE__ */ React8.createElement(Text8, { bold: true, color: "white" }, "ZELARI CODE")),
|
|
31412
|
+
/* @__PURE__ */ React8.createElement(Box7, { justifyContent: "center" }, /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "v", version2, changes.branch ? ` \xB7 ${truncatePath(changes.branch, 12)}` : "")),
|
|
31380
31413
|
/* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "\u2500".repeat(innerWidth)),
|
|
31381
31414
|
!changes.isRepo ? /* @__PURE__ */ React8.createElement(Text8, { dimColor: true, italic: true }, "not a git repo") : changes.files.length === 0 ? /* @__PURE__ */ React8.createElement(Text8, { dimColor: true, italic: true }, "no changes") : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, "changes (", changes.files.length, ")"), visible.map((f) => /* @__PURE__ */ React8.createElement(FileRow, { key: f.path, file: f, pathWidth: innerWidth - 10 })), hidden > 0 && /* @__PURE__ */ React8.createElement(Text8, { dimColor: true }, " +", hidden, " more\u2026"))
|
|
31382
31415
|
);
|
|
31383
31416
|
}
|
|
31384
|
-
function FileRow({
|
|
31417
|
+
function FileRow({
|
|
31418
|
+
file: file2,
|
|
31419
|
+
pathWidth
|
|
31420
|
+
}) {
|
|
31385
31421
|
const name = truncatePath(file2.path, Math.max(6, pathWidth));
|
|
31386
31422
|
return /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text8, { wrap: "truncate" }, /* @__PURE__ */ React8.createElement(Text8, { color: file2.untracked ? "yellow" : "white" }, name), file2.untracked ? /* @__PURE__ */ React8.createElement(Text8, { color: "yellow" }, " new") : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text8, { color: "green" }, " +", file2.added ?? "\xB7"), /* @__PURE__ */ React8.createElement(Text8, { color: "red" }, " -", file2.removed ?? "\xB7"))));
|
|
31387
31423
|
}
|
|
31388
31424
|
|
|
31389
|
-
// src/cli/components/
|
|
31390
|
-
|
|
31391
|
-
|
|
31392
|
-
|
|
31393
|
-
|
|
31394
|
-
|
|
31395
|
-
|
|
31396
|
-
|
|
31397
|
-
|
|
31398
|
-
|
|
31399
|
-
|
|
31400
|
-
|
|
31401
|
-
"
|
|
31402
|
-
|
|
31403
|
-
|
|
31404
|
-
|
|
31405
|
-
|
|
31406
|
-
|
|
31407
|
-
"
|
|
31408
|
-
"*@@@@@@*"
|
|
31409
|
-
].join("\n");
|
|
31410
|
-
function formatBannerWithLogoRight(opts) {
|
|
31411
|
-
const logoSrc = opts.compact ? BRAND_LOGO_COMPACT : BRAND_LOGO_ASCII;
|
|
31412
|
-
const logoLines = logoSrc.split("\n");
|
|
31413
|
-
const logoWidth = Math.max(...logoLines.map((l) => l.length));
|
|
31414
|
-
const cols = Math.max(logoWidth + 20, Math.min(opts.columns, 120));
|
|
31415
|
-
const left = [...opts.leftLines];
|
|
31416
|
-
const wordmark = `ZELARI CODE v${opts.version}`;
|
|
31417
|
-
const rightExtra = [wordmark];
|
|
31418
|
-
const rightBlock = [...logoLines, ...rightExtra];
|
|
31419
|
-
const rows = Math.max(left.length, rightBlock.length);
|
|
31420
|
-
const out = [];
|
|
31421
|
-
for (let i = 0; i < rows; i++) {
|
|
31422
|
-
const L = left[i] ?? "";
|
|
31423
|
-
const R = rightBlock[i] ?? "";
|
|
31424
|
-
if (!R) {
|
|
31425
|
-
out.push(L);
|
|
31426
|
-
continue;
|
|
31427
|
-
}
|
|
31428
|
-
const maxLeft = Math.max(0, cols - R.length - 2);
|
|
31429
|
-
const leftClipped = L.length > maxLeft ? L.slice(0, Math.max(0, maxLeft - 1)) + "\u2026" : L;
|
|
31430
|
-
const pad = Math.max(2, cols - leftClipped.length - R.length);
|
|
31431
|
-
out.push(leftClipped + " ".repeat(pad) + R);
|
|
31432
|
-
}
|
|
31433
|
-
return out.join("\n");
|
|
31425
|
+
// src/cli/components/StartupBanner.tsx
|
|
31426
|
+
import React9 from "react";
|
|
31427
|
+
import { Box as Box8, Text as Text9 } from "ink";
|
|
31428
|
+
function StartupBanner({
|
|
31429
|
+
version: version2,
|
|
31430
|
+
providerId,
|
|
31431
|
+
model,
|
|
31432
|
+
cwd,
|
|
31433
|
+
columns,
|
|
31434
|
+
rows
|
|
31435
|
+
}) {
|
|
31436
|
+
const compact = columns < 72 || rows < 20;
|
|
31437
|
+
const logo = (compact ? BRAND_LOGO_COMPACT : BRAND_LOGO_ASCII).split("\n");
|
|
31438
|
+
const leftLines = [
|
|
31439
|
+
`zelari-code v${version2} \u2014 ${providerId}/${model}`,
|
|
31440
|
+
`cwd: ${cwd}`,
|
|
31441
|
+
`/help \xB7 /plan \xB7 /build \xB7 /view-plan \xB7 shift+tab mode`
|
|
31442
|
+
];
|
|
31443
|
+
return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", flexGrow: 1, marginRight: 2 }, leftLines.map((line, i) => /* @__PURE__ */ React9.createElement(Text9, { key: i, color: i === 0 ? "cyan" : void 0, dimColor: i > 0 }, line))), /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", flexShrink: 0, alignItems: "flex-end" }, logo.map((line, i) => /* @__PURE__ */ React9.createElement(Text9, { key: i, color: "cyan" }, line)), /* @__PURE__ */ React9.createElement(Text9, { bold: true, color: "white" }, "ZELARI CODE"), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "v", version2)));
|
|
31434
31444
|
}
|
|
31435
31445
|
|
|
31436
31446
|
// src/cli/modelDiscovery.ts
|
|
@@ -36311,6 +36321,10 @@ function nextMode(current) {
|
|
|
36311
36321
|
const i = MODES.indexOf(current);
|
|
36312
36322
|
return MODES[(i + 1) % MODES.length] ?? "agent";
|
|
36313
36323
|
}
|
|
36324
|
+
function parseMode(input) {
|
|
36325
|
+
const v = input.trim().toLowerCase();
|
|
36326
|
+
return MODES.includes(v) ? v : null;
|
|
36327
|
+
}
|
|
36314
36328
|
function describeMode(mode) {
|
|
36315
36329
|
switch (mode) {
|
|
36316
36330
|
case "council":
|
|
@@ -38065,89 +38079,73 @@ function App() {
|
|
|
38065
38079
|
}
|
|
38066
38080
|
setPicker(null);
|
|
38067
38081
|
}, [picker]);
|
|
38068
|
-
const bannerColsRef = useRef6(null);
|
|
38069
|
-
if (bannerColsRef.current === null) {
|
|
38070
|
-
bannerColsRef.current = size.columns > 0 ? size.columns : 80;
|
|
38071
|
-
}
|
|
38072
38082
|
const banner = useMemo(() => {
|
|
38073
|
-
const cols = bannerColsRef.current ?? 80;
|
|
38074
|
-
const content = formatBannerWithLogoRight({
|
|
38075
|
-
leftLines: [
|
|
38076
|
-
`zelari-code \xB7 ${activeProviderSpec.id}/${activeModel}`,
|
|
38077
|
-
`cwd: ${cwd}`,
|
|
38078
|
-
`/help \xB7 /plan \xB7 /build \xB7 /view-plan \xB7 shift+tab mode`
|
|
38079
|
-
],
|
|
38080
|
-
version: VERSION,
|
|
38081
|
-
columns: cols,
|
|
38082
|
-
compact: cols < 72
|
|
38083
|
-
});
|
|
38084
38083
|
return {
|
|
38085
38084
|
id: "banner-once",
|
|
38086
38085
|
role: "system",
|
|
38087
38086
|
ts: 0,
|
|
38088
|
-
content
|
|
38087
|
+
content: ""
|
|
38089
38088
|
};
|
|
38090
|
-
}, [
|
|
38089
|
+
}, []);
|
|
38091
38090
|
const [sidebarOpen, setSidebarOpen] = useState8(false);
|
|
38092
38091
|
useEffect7(() => {
|
|
38093
38092
|
setSidebarOpen((prev2) => sidebarVisibility(size.columns, size.rows, prev2));
|
|
38094
38093
|
}, [size.columns, size.rows]);
|
|
38095
38094
|
const staticKey = `${session.sessionId || "pre-bootstrap"}-${clearEpoch}`;
|
|
38096
38095
|
const staticItems = session.sessionId ? [banner, ...session.messages] : [];
|
|
38097
|
-
|
|
38098
|
-
|
|
38099
|
-
Box8,
|
|
38096
|
+
return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Static, { key: staticKey, items: staticItems }, (item) => item.id === "banner-once" ? /* @__PURE__ */ React10.createElement(
|
|
38097
|
+
StartupBanner,
|
|
38100
38098
|
{
|
|
38101
|
-
|
|
38102
|
-
|
|
38103
|
-
|
|
38104
|
-
|
|
38105
|
-
|
|
38106
|
-
|
|
38107
|
-
|
|
38108
|
-
|
|
38109
|
-
|
|
38110
|
-
|
|
38111
|
-
|
|
38112
|
-
|
|
38113
|
-
|
|
38114
|
-
|
|
38115
|
-
|
|
38116
|
-
|
|
38117
|
-
|
|
38118
|
-
|
|
38119
|
-
|
|
38120
|
-
|
|
38121
|
-
|
|
38122
|
-
|
|
38123
|
-
|
|
38124
|
-
|
|
38125
|
-
|
|
38126
|
-
|
|
38127
|
-
|
|
38128
|
-
|
|
38129
|
-
|
|
38130
|
-
|
|
38131
|
-
|
|
38132
|
-
|
|
38133
|
-
|
|
38134
|
-
|
|
38135
|
-
|
|
38136
|
-
|
|
38137
|
-
|
|
38138
|
-
|
|
38139
|
-
|
|
38140
|
-
|
|
38141
|
-
|
|
38142
|
-
|
|
38143
|
-
|
|
38144
|
-
|
|
38145
|
-
));
|
|
38099
|
+
key: item.id,
|
|
38100
|
+
version: VERSION,
|
|
38101
|
+
providerId: activeProviderSpec.id,
|
|
38102
|
+
model: activeModel,
|
|
38103
|
+
cwd,
|
|
38104
|
+
columns: size.columns || 80,
|
|
38105
|
+
rows: size.rows || 24
|
|
38106
|
+
}
|
|
38107
|
+
) : renderMessage(item)), /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", flexGrow: 1, paddingX: 1 }, /* @__PURE__ */ React10.createElement(LiveRegion, { live: session.live, busy, elapsedMs: timer.elapsedMs }), picker ? /* @__PURE__ */ React10.createElement(
|
|
38108
|
+
SelectList,
|
|
38109
|
+
{
|
|
38110
|
+
title: picker.title,
|
|
38111
|
+
items: picker.items,
|
|
38112
|
+
onSelect: onPickerSelect,
|
|
38113
|
+
onCancel: onPickerCancel,
|
|
38114
|
+
maxVisible: Math.max(4, Math.min(10, size.rows - 10))
|
|
38115
|
+
}
|
|
38116
|
+
) : /* @__PURE__ */ React10.createElement(
|
|
38117
|
+
InputBar,
|
|
38118
|
+
{
|
|
38119
|
+
value: input,
|
|
38120
|
+
onChange: setInput,
|
|
38121
|
+
onSubmit: handleSubmit,
|
|
38122
|
+
disabled: busy
|
|
38123
|
+
}
|
|
38124
|
+
), /* @__PURE__ */ React10.createElement(
|
|
38125
|
+
StatusBar,
|
|
38126
|
+
{
|
|
38127
|
+
model: activeModel,
|
|
38128
|
+
provider: activeProviderSpec.id,
|
|
38129
|
+
sessionId: session.sessionId ? session.sessionId.slice(0, 8) : "...",
|
|
38130
|
+
sessionActive: session.sessionActive,
|
|
38131
|
+
queueCount: chatTurn.queueCount,
|
|
38132
|
+
busy,
|
|
38133
|
+
mode,
|
|
38134
|
+
phase: phase2,
|
|
38135
|
+
cwd,
|
|
38136
|
+
elapsedMs: timer.elapsedMs,
|
|
38137
|
+
lastMs: timer.lastMs,
|
|
38138
|
+
costUsd: sessionStats.totalCostUsd,
|
|
38139
|
+
cachedTokens: sessionStats.cachedTokens,
|
|
38140
|
+
contextUsed: sessionStats.contextTokens || 0,
|
|
38141
|
+
contextLimit: Number(process.env.ZELARI_CONTEXT_LIMIT) || 2e5
|
|
38142
|
+
}
|
|
38143
|
+
)), sidebarOpen && /* @__PURE__ */ React10.createElement(Sidebar, { version: VERSION, changes: gitChanges, rows: size.rows })));
|
|
38146
38144
|
}
|
|
38147
38145
|
|
|
38148
38146
|
// src/cli/components/SplashScreen.tsx
|
|
38149
|
-
import
|
|
38150
|
-
import { Box as
|
|
38147
|
+
import React11, { useEffect as useEffect8, useState as useState9 } from "react";
|
|
38148
|
+
import { Box as Box10, Text as Text11, useInput as useInput3, useStdin as useStdin3 } from "ink";
|
|
38151
38149
|
var SPLASH_DURATION_MS = 2e3;
|
|
38152
38150
|
var EMBLEM_LARGE = ` =%@*-
|
|
38153
38151
|
=%@@@@@#:
|
|
@@ -38283,8 +38281,8 @@ function Splash({ onDone, version: version2 }) {
|
|
|
38283
38281
|
{ isActive: isRawModeSupported === true }
|
|
38284
38282
|
);
|
|
38285
38283
|
if (!picked) return null;
|
|
38286
|
-
return /* @__PURE__ */
|
|
38287
|
-
|
|
38284
|
+
return /* @__PURE__ */ React11.createElement(
|
|
38285
|
+
Box10,
|
|
38288
38286
|
{
|
|
38289
38287
|
flexDirection: "column",
|
|
38290
38288
|
alignItems: "center",
|
|
@@ -38292,10 +38290,10 @@ function Splash({ onDone, version: version2 }) {
|
|
|
38292
38290
|
width: columns,
|
|
38293
38291
|
height: rows - 1
|
|
38294
38292
|
},
|
|
38295
|
-
/* @__PURE__ */
|
|
38296
|
-
/* @__PURE__ */
|
|
38297
|
-
!picked.compact && /* @__PURE__ */
|
|
38298
|
-
!picked.compact && /* @__PURE__ */
|
|
38293
|
+
/* @__PURE__ */ React11.createElement(Text11, { color: "cyan" }, picked.art),
|
|
38294
|
+
/* @__PURE__ */ React11.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { bold: true, color: "white" }, "Z E L A R I C O D E")),
|
|
38295
|
+
!picked.compact && /* @__PURE__ */ React11.createElement(Text11, { dimColor: true }, `${version2 ? `v${version2} \u2014 ` : ""}N-THEM Studio`),
|
|
38296
|
+
!picked.compact && /* @__PURE__ */ React11.createElement(Text11, { dimColor: true, italic: true }, "press any key to skip")
|
|
38299
38297
|
);
|
|
38300
38298
|
}
|
|
38301
38299
|
function SplashGate({
|
|
@@ -38311,14 +38309,14 @@ function SplashGate({
|
|
|
38311
38309
|
})
|
|
38312
38310
|
);
|
|
38313
38311
|
if (show) {
|
|
38314
|
-
return /* @__PURE__ */
|
|
38312
|
+
return /* @__PURE__ */ React11.createElement(Splash, { onDone: () => setShow(false), version: version2 });
|
|
38315
38313
|
}
|
|
38316
|
-
return /* @__PURE__ */
|
|
38314
|
+
return /* @__PURE__ */ React11.createElement(React11.Fragment, null, children);
|
|
38317
38315
|
}
|
|
38318
38316
|
|
|
38319
38317
|
// src/cli/components/PluginGate.tsx
|
|
38320
|
-
import
|
|
38321
|
-
import { Box as
|
|
38318
|
+
import React12, { useEffect as useEffect9, useState as useState10, useCallback as useCallback6 } from "react";
|
|
38319
|
+
import { Box as Box11, Text as Text12, useStdin as useStdin4 } from "ink";
|
|
38322
38320
|
init_registry2();
|
|
38323
38321
|
init_prefs();
|
|
38324
38322
|
var CHOICE_INSTALL = "__install__";
|
|
@@ -38407,20 +38405,20 @@ function PluginGate({ cwd, children }) {
|
|
|
38407
38405
|
[current, cwd, advance]
|
|
38408
38406
|
);
|
|
38409
38407
|
if (phase2 === "done") {
|
|
38410
|
-
return /* @__PURE__ */
|
|
38408
|
+
return /* @__PURE__ */ React12.createElement(React12.Fragment, null, children);
|
|
38411
38409
|
}
|
|
38412
38410
|
if (phase2 === "detecting") {
|
|
38413
|
-
return /* @__PURE__ */
|
|
38411
|
+
return /* @__PURE__ */ React12.createElement(Box11, { paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text12, { dimColor: true }, "Checking for optional tool plugins\u2026"));
|
|
38414
38412
|
}
|
|
38415
38413
|
if (!current) {
|
|
38416
|
-
return /* @__PURE__ */
|
|
38414
|
+
return /* @__PURE__ */ React12.createElement(React12.Fragment, null, children);
|
|
38417
38415
|
}
|
|
38418
38416
|
if (phase2 === "installing") {
|
|
38419
|
-
return /* @__PURE__ */
|
|
38417
|
+
return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text12, { color: "cyan" }, "\u23F3 Installing ", current.label, "\u2026"), /* @__PURE__ */ React12.createElement(Text12, { dimColor: true }, "npm install ", current.installScope === "global" ? "-g" : "-D", " ", current.npmPackage));
|
|
38420
38418
|
}
|
|
38421
38419
|
if (phase2 === "result") {
|
|
38422
38420
|
const ok = result?.ok === true;
|
|
38423
|
-
return /* @__PURE__ */
|
|
38421
|
+
return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React12.createElement(Text12, { color: ok ? "green" : "red" }, ok ? "\u2713" : "\u2717", " ", ok ? "Installed" : "Install failed", ": ", current.label), !ok && result?.error ? /* @__PURE__ */ React12.createElement(Text12, { dimColor: true }, result.error) : null, ok && current.postInstallHint ? /* @__PURE__ */ React12.createElement(Text12, { color: "yellow" }, " \u2192 ", current.postInstallHint) : null, /* @__PURE__ */ React12.createElement(Text12, { dimColor: true }, "Press any key to continue\u2026"), /* @__PURE__ */ React12.createElement(ContinueKey, { onContinue: advance }));
|
|
38424
38422
|
}
|
|
38425
38423
|
const items = [
|
|
38426
38424
|
{
|
|
@@ -38431,7 +38429,7 @@ function PluginGate({ cwd, children }) {
|
|
|
38431
38429
|
{ value: CHOICE_LATER, label: "Maybe later" },
|
|
38432
38430
|
{ value: CHOICE_NEVER, label: "Don't ask again" }
|
|
38433
38431
|
];
|
|
38434
|
-
return /* @__PURE__ */
|
|
38432
|
+
return /* @__PURE__ */ React12.createElement(
|
|
38435
38433
|
SelectList,
|
|
38436
38434
|
{
|
|
38437
38435
|
title: `Optional plugin missing: ${current.label}`,
|
|
@@ -38493,15 +38491,15 @@ function parseWizardFlags(argv) {
|
|
|
38493
38491
|
}
|
|
38494
38492
|
|
|
38495
38493
|
// src/cli/wizard/runWizard.tsx
|
|
38496
|
-
import
|
|
38497
|
-
import { Box as
|
|
38494
|
+
import React14, { useEffect as useEffect10, useState as useState11 } from "react";
|
|
38495
|
+
import { Box as Box13, Text as Text14 } from "ink";
|
|
38498
38496
|
import { useInput as useInput4 } from "ink";
|
|
38499
38497
|
init_keyStore();
|
|
38500
38498
|
init_providerConfig();
|
|
38501
38499
|
|
|
38502
38500
|
// src/cli/wizard/index.tsx
|
|
38503
|
-
import
|
|
38504
|
-
import { Box as
|
|
38501
|
+
import React13 from "react";
|
|
38502
|
+
import { Box as Box12, Text as Text13 } from "ink";
|
|
38505
38503
|
|
|
38506
38504
|
// src/cli/wizard/useWizardState.ts
|
|
38507
38505
|
init_providerConfig();
|
|
@@ -38617,16 +38615,16 @@ var API_KEY_OPTIONS = ["env", "keystore", "skip"];
|
|
|
38617
38615
|
|
|
38618
38616
|
// src/cli/wizard/index.tsx
|
|
38619
38617
|
function Frame({ children }) {
|
|
38620
|
-
return /* @__PURE__ */
|
|
38618
|
+
return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 }, children);
|
|
38621
38619
|
}
|
|
38622
38620
|
function Step(props) {
|
|
38623
|
-
return /* @__PURE__ */
|
|
38621
|
+
return /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text13, { color: props.active ? "cyan" : "gray", inverse: props.active }, " ", props.index, "/", props.total, " ", props.name, " "));
|
|
38624
38622
|
}
|
|
38625
38623
|
function renderProviderList(providers, cursor) {
|
|
38626
|
-
return /* @__PURE__ */
|
|
38624
|
+
return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, providers.map((p3, i) => {
|
|
38627
38625
|
const arrow = i === cursor ? "\u279C " : " ";
|
|
38628
38626
|
const color = i === cursor ? "cyan" : void 0;
|
|
38629
|
-
return /* @__PURE__ */
|
|
38627
|
+
return /* @__PURE__ */ React13.createElement(Text13, { key: p3.id, color }, arrow, p3.displayName, " ", /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "(", p3.id, ", uses env ", p3.envVar, ")"));
|
|
38630
38628
|
}));
|
|
38631
38629
|
}
|
|
38632
38630
|
function renderApiKeyOptions(cursor) {
|
|
@@ -38635,18 +38633,18 @@ function renderApiKeyOptions(cursor) {
|
|
|
38635
38633
|
keystore: "Save to local keyStore (encrypted)",
|
|
38636
38634
|
skip: "Skip for now (chat will fail until key is set)"
|
|
38637
38635
|
};
|
|
38638
|
-
return /* @__PURE__ */
|
|
38636
|
+
return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, API_KEY_OPTIONS.map((choice, i) => {
|
|
38639
38637
|
const arrow = i === cursor ? "\u279C " : " ";
|
|
38640
38638
|
const color = i === cursor ? "cyan" : void 0;
|
|
38641
|
-
return /* @__PURE__ */
|
|
38639
|
+
return /* @__PURE__ */ React13.createElement(Text13, { key: choice, color }, arrow, labels[choice]);
|
|
38642
38640
|
}));
|
|
38643
38641
|
}
|
|
38644
38642
|
function Wizard({ state: state2, providers }) {
|
|
38645
38643
|
const s = state2.state;
|
|
38646
38644
|
if (s.committed) {
|
|
38647
|
-
return /* @__PURE__ */
|
|
38645
|
+
return /* @__PURE__ */ React13.createElement(Frame, null, /* @__PURE__ */ React13.createElement(Text13, { color: "green" }, "\u2713 Setup complete!"), /* @__PURE__ */ React13.createElement(Text13, null, "Provider: ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.providerId), " | ", "Model: ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.model), " | ", "API key: ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.apiKeyChoice ?? "n/a")), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "Launching zelari-code\u2026 (press any key)")));
|
|
38648
38646
|
}
|
|
38649
|
-
return /* @__PURE__ */
|
|
38647
|
+
return /* @__PURE__ */ React13.createElement(Frame, null, /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", bold: true }, "zelari-code v", VERSION, " \u2014 first-time setup"), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1, marginBottom: 1, flexDirection: "row" }, /* @__PURE__ */ React13.createElement(Step, { index: 1, total: 5, name: "welcome", active: s.step === "welcome" }), /* @__PURE__ */ React13.createElement(Step, { index: 2, total: 5, name: "provider", active: s.step === "provider" }), /* @__PURE__ */ React13.createElement(Step, { index: 3, total: 5, name: "model", active: s.step === "model" }), /* @__PURE__ */ React13.createElement(Step, { index: 4, total: 5, name: "apikey", active: s.step === "apikey" }), /* @__PURE__ */ React13.createElement(Step, { index: 5, total: 5, name: "confirm", active: s.step === "confirm" })), s.step === "welcome" && /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text13, null, "Welcome! Let's get you coding in under two minutes."), /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "We'll pick a provider, default model, and how to handle your API key."), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, null, "Press "), /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", inverse: true }, " Enter "), /* @__PURE__ */ React13.createElement(Text13, null, " to continue, or "), /* @__PURE__ */ React13.createElement(Text13, { color: "red", inverse: true }, " Q "), /* @__PURE__ */ React13.createElement(Text13, null, " to quit (re-run with "), /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "--no-wizard"), /* @__PURE__ */ React13.createElement(Text13, null, " to skip later)."))), s.step === "provider" && /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text13, null, "Choose your LLM provider:"), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, renderProviderList(providers, s.providerCursor)), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "\u2191/\u2193 to move, Enter to confirm"))), s.step === "model" && /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text13, null, "Model for ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.providerId), ":"), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1, borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React13.createElement(Text13, null, s.model ?? "(empty)")), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, null, "Press ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", inverse: true }, " Enter "), "to accept, or type a new name. ", /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "(default kept on empty input)")))), s.step === "apikey" && /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text13, null, "How should we handle the API key?"), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, renderApiKeyOptions(s.apiKeyCursor)), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, "\u2191/\u2193 to move, Enter to confirm"))), s.step === "confirm" && /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Text13, null, "Confirm your setup:"), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Text13, null, "Provider: ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.providerId)), /* @__PURE__ */ React13.createElement(Text13, null, "Model: ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.model)), /* @__PURE__ */ React13.createElement(Text13, null, "API key: ", /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, s.apiKeyChoice ?? "(unset)"))), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, null, "Press ", /* @__PURE__ */ React13.createElement(Text13, { color: "green", inverse: true }, " Enter "), "to save and launch, or ", /* @__PURE__ */ React13.createElement(Text13, { color: "yellow", inverse: true }, " B "), "to go back."))));
|
|
38650
38648
|
}
|
|
38651
38649
|
|
|
38652
38650
|
// src/cli/wizard/runWizard.tsx
|
|
@@ -38722,9 +38720,9 @@ function RunWizard(_props) {
|
|
|
38722
38720
|
}
|
|
38723
38721
|
});
|
|
38724
38722
|
if (wiz.state.committed) {
|
|
38725
|
-
return /* @__PURE__ */
|
|
38723
|
+
return /* @__PURE__ */ React14.createElement(PostCommitBridge, null);
|
|
38726
38724
|
}
|
|
38727
|
-
return /* @__PURE__ */
|
|
38725
|
+
return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React14.createElement(Wizard, { state: wiz, providers: PROVIDERS }));
|
|
38728
38726
|
}
|
|
38729
38727
|
function PostCommitBridge() {
|
|
38730
38728
|
const [showApp, setShowApp] = useState11(false);
|
|
@@ -38733,22 +38731,26 @@ function PostCommitBridge() {
|
|
|
38733
38731
|
return () => clearTimeout(t);
|
|
38734
38732
|
}, []);
|
|
38735
38733
|
if (showApp) {
|
|
38736
|
-
return /* @__PURE__ */
|
|
38734
|
+
return /* @__PURE__ */ React14.createElement(App, null);
|
|
38737
38735
|
}
|
|
38738
|
-
return /* @__PURE__ */
|
|
38736
|
+
return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React14.createElement(Box13, { borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text14, { color: "green", bold: true }, "\u2713 Setup complete! Launching zelari-code\u2026"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, "Press Ctrl+C any time to exit.")));
|
|
38739
38737
|
}
|
|
38740
38738
|
|
|
38741
38739
|
// src/cli/headless.ts
|
|
38742
38740
|
init_keyStore();
|
|
38743
38741
|
init_providerConfig();
|
|
38744
38742
|
init_openai_compatible();
|
|
38743
|
+
init_phase();
|
|
38745
38744
|
function parseHeadlessFlags(argv) {
|
|
38746
38745
|
if (!argv.includes("--headless")) {
|
|
38747
38746
|
return { options: null };
|
|
38748
38747
|
}
|
|
38749
38748
|
let task;
|
|
38750
38749
|
let output = "json";
|
|
38751
|
-
let
|
|
38750
|
+
let mode = "agent";
|
|
38751
|
+
let phase2 = "build";
|
|
38752
|
+
let modeExplicit = false;
|
|
38753
|
+
let councilFlag = false;
|
|
38752
38754
|
let provider;
|
|
38753
38755
|
let model;
|
|
38754
38756
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -38769,7 +38771,30 @@ function parseHeadlessFlags(argv) {
|
|
|
38769
38771
|
task = argv[i + 1];
|
|
38770
38772
|
i++;
|
|
38771
38773
|
} else if (arg === "--council") {
|
|
38772
|
-
|
|
38774
|
+
councilFlag = true;
|
|
38775
|
+
} else if (arg === "--mode") {
|
|
38776
|
+
const next = argv[i + 1];
|
|
38777
|
+
const parsed = next ? parseMode(next) : null;
|
|
38778
|
+
if (!parsed) {
|
|
38779
|
+
return {
|
|
38780
|
+
options: null,
|
|
38781
|
+
error: `--mode requires 'agent', 'council', or 'zelari', got '${next ?? "(missing)"}'`
|
|
38782
|
+
};
|
|
38783
|
+
}
|
|
38784
|
+
mode = parsed;
|
|
38785
|
+
modeExplicit = true;
|
|
38786
|
+
i++;
|
|
38787
|
+
} else if (arg === "--phase") {
|
|
38788
|
+
const next = argv[i + 1];
|
|
38789
|
+
const parsed = next ? parsePhase(next) : null;
|
|
38790
|
+
if (!parsed) {
|
|
38791
|
+
return {
|
|
38792
|
+
options: null,
|
|
38793
|
+
error: `--phase requires 'plan' or 'build', got '${next ?? "(missing)"}'`
|
|
38794
|
+
};
|
|
38795
|
+
}
|
|
38796
|
+
phase2 = parsed;
|
|
38797
|
+
i++;
|
|
38773
38798
|
} else if (arg === "--provider") {
|
|
38774
38799
|
provider = argv[i + 1];
|
|
38775
38800
|
i++;
|
|
@@ -38778,11 +38803,27 @@ function parseHeadlessFlags(argv) {
|
|
|
38778
38803
|
i++;
|
|
38779
38804
|
}
|
|
38780
38805
|
}
|
|
38806
|
+
if (councilFlag && !modeExplicit) {
|
|
38807
|
+
mode = "council";
|
|
38808
|
+
} else if (councilFlag && modeExplicit && mode !== "council") {
|
|
38809
|
+
return {
|
|
38810
|
+
options: null,
|
|
38811
|
+
error: `--council conflicts with --mode ${mode}`
|
|
38812
|
+
};
|
|
38813
|
+
}
|
|
38781
38814
|
if (!task || task.trim().length === 0) {
|
|
38782
38815
|
return { options: null, error: "--headless requires --task <prompt>" };
|
|
38783
38816
|
}
|
|
38784
38817
|
return {
|
|
38785
|
-
options: {
|
|
38818
|
+
options: {
|
|
38819
|
+
task,
|
|
38820
|
+
output,
|
|
38821
|
+
mode,
|
|
38822
|
+
phase: phase2,
|
|
38823
|
+
useCouncil: mode === "council",
|
|
38824
|
+
provider,
|
|
38825
|
+
model
|
|
38826
|
+
}
|
|
38786
38827
|
};
|
|
38787
38828
|
}
|
|
38788
38829
|
async function resolveHeadlessKey(providerId) {
|
|
@@ -38817,7 +38858,10 @@ init_harness();
|
|
|
38817
38858
|
init_toolRegistry();
|
|
38818
38859
|
init_skills2();
|
|
38819
38860
|
init_envNumber();
|
|
38861
|
+
init_phaseState();
|
|
38862
|
+
init_phase();
|
|
38820
38863
|
async function runHeadless(opts) {
|
|
38864
|
+
setPhase(opts.phase ?? "build");
|
|
38821
38865
|
const { provider, model } = resolveHeadlessProvider(opts);
|
|
38822
38866
|
const key = await resolveHeadlessKey(provider);
|
|
38823
38867
|
if ("error" in key) {
|
|
@@ -38831,14 +38875,34 @@ async function runHeadless(opts) {
|
|
|
38831
38875
|
baseUrl: key.baseUrl,
|
|
38832
38876
|
model
|
|
38833
38877
|
});
|
|
38834
|
-
|
|
38878
|
+
const mode = opts.mode ?? (opts.useCouncil ? "council" : "agent");
|
|
38879
|
+
if (opts.output === "json") {
|
|
38880
|
+
emitEvent({
|
|
38881
|
+
type: "log",
|
|
38882
|
+
message: `[headless] mode=${mode} phase=${opts.phase ?? "build"} provider=${provider} model=${model}`
|
|
38883
|
+
});
|
|
38884
|
+
} else {
|
|
38885
|
+
process.stderr.write(
|
|
38886
|
+
`[zelari-code --headless] mode=${mode} phase=${describePhase(opts.phase ?? "build")}
|
|
38887
|
+
`
|
|
38888
|
+
);
|
|
38889
|
+
}
|
|
38890
|
+
if (mode === "zelari") {
|
|
38891
|
+
return runHeadlessZelari(opts, provider, model, providerStream);
|
|
38892
|
+
}
|
|
38893
|
+
if (mode === "council" || opts.useCouncil) {
|
|
38835
38894
|
return runHeadlessCouncil(opts, provider, model, providerStream);
|
|
38836
38895
|
}
|
|
38837
38896
|
return runHeadlessSingle(opts, provider, model, providerStream);
|
|
38838
38897
|
}
|
|
38898
|
+
function planModeFromOpts(opts) {
|
|
38899
|
+
return (opts.phase ?? "build") === "plan";
|
|
38900
|
+
}
|
|
38839
38901
|
async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
38840
38902
|
const sessionId = crypto.randomUUID();
|
|
38841
|
-
const { registry: toolRegistry } = createBuiltinToolRegistry(
|
|
38903
|
+
const { registry: toolRegistry } = createBuiltinToolRegistry({
|
|
38904
|
+
planMode: planModeFromOpts(opts)
|
|
38905
|
+
});
|
|
38842
38906
|
const tools = toolRegistry.toOpenAITools().map((t) => ({
|
|
38843
38907
|
name: t.function.name,
|
|
38844
38908
|
description: t.function.description,
|
|
@@ -38861,10 +38925,6 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
38861
38925
|
color: "#00d9a3",
|
|
38862
38926
|
avatar: "\u25C6",
|
|
38863
38927
|
tools: toolNames,
|
|
38864
|
-
// v1.7.0 fix (agy audit): include platform/shell context in the role
|
|
38865
|
-
// prompt so the agent knows its cwd and shell — previously this was
|
|
38866
|
-
// empty (systemPrompt: '') and the agent lacked the platform block
|
|
38867
|
-
// the TUI single-agent path gets.
|
|
38868
38928
|
systemPrompt: [
|
|
38869
38929
|
"# Platform",
|
|
38870
38930
|
`platform: ${process.platform}`,
|
|
@@ -38873,7 +38933,10 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
38873
38933
|
"# Working Directory",
|
|
38874
38934
|
`You are running in: ${process.cwd()}`,
|
|
38875
38935
|
"All relative file paths are resolved against this directory.",
|
|
38876
|
-
"The shell is NON-INTERACTIVE (stdin closed): pass non-interactive flags (--yes, --force, --template)."
|
|
38936
|
+
"The shell is NON-INTERACTIVE (stdin closed): pass non-interactive flags (--yes, --force, --template).",
|
|
38937
|
+
"",
|
|
38938
|
+
`# Work phase: ${opts.phase ?? "build"}`,
|
|
38939
|
+
(opts.phase ?? "build") === "plan" ? "PLAN phase: explore and design only. Do not write project source files (write_file/edit_file/bash blocked). Plan artifacts under .zelari are allowed." : "BUILD phase: full tools; implement changes."
|
|
38877
38940
|
].join("\n")
|
|
38878
38941
|
};
|
|
38879
38942
|
systemPrompt = buildSystemPrompt(headlessRole, {
|
|
@@ -38952,18 +39015,11 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
38952
39015
|
if (finalReason === "error") return 3;
|
|
38953
39016
|
return exitCode;
|
|
38954
39017
|
}
|
|
38955
|
-
async function
|
|
38956
|
-
const {
|
|
38957
|
-
const sessionId = crypto.randomUUID();
|
|
38958
|
-
const { registry: toolRegistry } = createBuiltinToolRegistry();
|
|
38959
|
-
const workspaceCtx = {
|
|
38960
|
-
projectRoot: process.cwd(),
|
|
38961
|
-
getActiveBranch: () => null
|
|
38962
|
-
};
|
|
39018
|
+
async function buildCouncilToolRegistry(planMode) {
|
|
39019
|
+
const { registry: toolRegistry } = createBuiltinToolRegistry({ planMode });
|
|
38963
39020
|
const { createWorkspaceContext: createWorkspaceContext2, createWorkspaceStubs: createWorkspaceStubs2 } = await Promise.resolve().then(() => (init_stubs(), stubs_exports));
|
|
38964
39021
|
const { createWorkspaceToolRegistry: createWorkspaceToolRegistry2 } = await Promise.resolve().then(() => (init_toolRegistry2(), toolRegistry_exports2));
|
|
38965
39022
|
const { setWorkspaceStubs: setWorkspaceStubs2 } = await Promise.resolve().then(() => (init_skills2(), skills_exports));
|
|
38966
|
-
const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
|
|
38967
39023
|
const realCtx = createWorkspaceContext2();
|
|
38968
39024
|
const realReg = createWorkspaceToolRegistry2(realCtx);
|
|
38969
39025
|
for (const name of realReg.list()) {
|
|
@@ -38971,6 +39027,13 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
38971
39027
|
if (td) toolRegistry.register(td);
|
|
38972
39028
|
}
|
|
38973
39029
|
setWorkspaceStubs2(createWorkspaceStubs2(realCtx));
|
|
39030
|
+
return { toolRegistry, workspaceCtx: realCtx };
|
|
39031
|
+
}
|
|
39032
|
+
async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
39033
|
+
const { dispatchCouncil: dispatchCouncil2 } = await Promise.resolve().then(() => (init_councilDispatcher(), councilDispatcher_exports));
|
|
39034
|
+
const sessionId = crypto.randomUUID();
|
|
39035
|
+
const { toolRegistry } = await buildCouncilToolRegistry(planModeFromOpts(opts));
|
|
39036
|
+
const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
|
|
38974
39037
|
const feedbackStore = new FeedbackStore2();
|
|
38975
39038
|
let exitCode = 0;
|
|
38976
39039
|
try {
|
|
@@ -38981,7 +39044,8 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
38981
39044
|
providerStream,
|
|
38982
39045
|
sessionId,
|
|
38983
39046
|
tools: toolRegistry,
|
|
38984
|
-
feedbackStore
|
|
39047
|
+
feedbackStore,
|
|
39048
|
+
runMode: planModeFromOpts(opts) ? "design-phase" : "implementation"
|
|
38985
39049
|
})) {
|
|
38986
39050
|
if (opts.output === "json") {
|
|
38987
39051
|
emitEvent(event);
|
|
@@ -39002,6 +39066,378 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
39002
39066
|
}
|
|
39003
39067
|
return exitCode;
|
|
39004
39068
|
}
|
|
39069
|
+
async function runHeadlessZelari(opts, provider, model, providerStream) {
|
|
39070
|
+
const projectRoot = process.cwd();
|
|
39071
|
+
const { buildMissionBrief: buildMissionBrief2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
39072
|
+
const { hasWorkspacePlan: hasWorkspacePlan2 } = await Promise.resolve().then(() => (init_planDetect(), planDetect_exports));
|
|
39073
|
+
const { getMemoryBackend: getMemoryBackend2 } = await Promise.resolve().then(() => (init_fileBackend(), fileBackend_exports));
|
|
39074
|
+
const { runZelariMission: runZelariMission2 } = await Promise.resolve().then(() => (init_zelariMission(), zelariMission_exports));
|
|
39075
|
+
const { dispatchCouncil: dispatchCouncil2 } = await Promise.resolve().then(() => (init_councilDispatcher(), councilDispatcher_exports));
|
|
39076
|
+
const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
|
|
39077
|
+
const { runPostCouncilHook: runPostCouncilHook2 } = await Promise.resolve().then(() => (init_postCouncilHook(), postCouncilHook_exports));
|
|
39078
|
+
const brief = buildMissionBrief2({
|
|
39079
|
+
userMessage: opts.task,
|
|
39080
|
+
hasPlan: hasWorkspacePlan2(projectRoot)
|
|
39081
|
+
});
|
|
39082
|
+
const memory = await getMemoryBackend2(projectRoot);
|
|
39083
|
+
const { toolRegistry, workspaceCtx } = await buildCouncilToolRegistry(planModeFromOpts(opts));
|
|
39084
|
+
const feedbackStore = new FeedbackStore2();
|
|
39085
|
+
const chairmanBudget = envNumber(process.env.ZELARI_MODE_MAX_TOOLS_LUCIFER, {
|
|
39086
|
+
default: 30,
|
|
39087
|
+
min: 1
|
|
39088
|
+
});
|
|
39089
|
+
const emit = (message) => {
|
|
39090
|
+
if (opts.output === "json") {
|
|
39091
|
+
emitEvent({ type: "log", message });
|
|
39092
|
+
} else {
|
|
39093
|
+
process.stderr.write(message + "\n");
|
|
39094
|
+
}
|
|
39095
|
+
};
|
|
39096
|
+
emit(`[zelari] mission brief
|
|
39097
|
+
${JSON.stringify({ deliverable: brief.deliverableThisMission, mvp: brief.sliceMvp?.title }, null, 0)}`);
|
|
39098
|
+
let exitCode = 0;
|
|
39099
|
+
try {
|
|
39100
|
+
const state2 = await runZelariMission2(opts.task, brief, {
|
|
39101
|
+
projectRoot,
|
|
39102
|
+
memory,
|
|
39103
|
+
emit,
|
|
39104
|
+
runSlice: async ({ userMessage: slicePrompt, runMode, ragContext }) => {
|
|
39105
|
+
const sessionId = crypto.randomUUID();
|
|
39106
|
+
const fullPrompt = ragContext ? `${slicePrompt}
|
|
39107
|
+
|
|
39108
|
+
## Memory context
|
|
39109
|
+
${ragContext}` : slicePrompt;
|
|
39110
|
+
let synthesisText = "";
|
|
39111
|
+
let writeCount = 0;
|
|
39112
|
+
let chairmanErrored = false;
|
|
39113
|
+
let membersCompleted = 0;
|
|
39114
|
+
for await (const event of dispatchCouncil2(fullPrompt, {
|
|
39115
|
+
apiKey: "REDACTED",
|
|
39116
|
+
model,
|
|
39117
|
+
provider: "openai-compatible",
|
|
39118
|
+
providerStream,
|
|
39119
|
+
sessionId,
|
|
39120
|
+
tools: toolRegistry,
|
|
39121
|
+
feedbackStore,
|
|
39122
|
+
runMode: planModeFromOpts(opts) ? "design-phase" : runMode,
|
|
39123
|
+
maxToolCallsChairman: chairmanBudget
|
|
39124
|
+
})) {
|
|
39125
|
+
if (opts.output === "json") {
|
|
39126
|
+
emitEvent(event);
|
|
39127
|
+
} else if (event.type === "message_delta") {
|
|
39128
|
+
process.stdout.write(event.delta);
|
|
39129
|
+
}
|
|
39130
|
+
if (event.type === "message_delta" && typeof event.delta === "string") {
|
|
39131
|
+
synthesisText += event.delta;
|
|
39132
|
+
}
|
|
39133
|
+
if (event.type === "tool_execution_end") {
|
|
39134
|
+
const name = event.toolName ?? event.name ?? "";
|
|
39135
|
+
if (name === "write_file" || name === "edit_file" || name === "apply_diff") {
|
|
39136
|
+
writeCount += 1;
|
|
39137
|
+
}
|
|
39138
|
+
}
|
|
39139
|
+
if (event.type === "agent_end") {
|
|
39140
|
+
membersCompleted += 1;
|
|
39141
|
+
if (event.reason === "error") chairmanErrored = true;
|
|
39142
|
+
}
|
|
39143
|
+
if (event.type === "error" && event.severity === "fatal") {
|
|
39144
|
+
chairmanErrored = true;
|
|
39145
|
+
exitCode = 2;
|
|
39146
|
+
}
|
|
39147
|
+
}
|
|
39148
|
+
let completionOk = false;
|
|
39149
|
+
let degraded = false;
|
|
39150
|
+
try {
|
|
39151
|
+
const { detectDegradedRun: detectDegradedRun2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
39152
|
+
const d = detectDegradedRun2({
|
|
39153
|
+
chairmanErrored,
|
|
39154
|
+
councilAborted: false,
|
|
39155
|
+
luciferWriteCount: writeCount,
|
|
39156
|
+
synthesisText,
|
|
39157
|
+
runMode
|
|
39158
|
+
});
|
|
39159
|
+
degraded = d.degraded;
|
|
39160
|
+
const hook = await runPostCouncilHook2(workspaceCtx, {
|
|
39161
|
+
runMode,
|
|
39162
|
+
userMessage: opts.task,
|
|
39163
|
+
synthesisText: synthesisText || void 0,
|
|
39164
|
+
degradedRun: d.degraded,
|
|
39165
|
+
degradedReasons: d.reasons
|
|
39166
|
+
});
|
|
39167
|
+
completionOk = hook.completion?.completion?.ok ?? false;
|
|
39168
|
+
if (completionOk) {
|
|
39169
|
+
emit(`[zelari] slice completion ok`);
|
|
39170
|
+
}
|
|
39171
|
+
} catch {
|
|
39172
|
+
}
|
|
39173
|
+
return {
|
|
39174
|
+
completionOk,
|
|
39175
|
+
ran: membersCompleted > 0 || synthesisText.length > 0,
|
|
39176
|
+
synthesisText: synthesisText || void 0,
|
|
39177
|
+
writeCount,
|
|
39178
|
+
degraded
|
|
39179
|
+
};
|
|
39180
|
+
}
|
|
39181
|
+
});
|
|
39182
|
+
if (state2.status === "error") exitCode = exitCode || 3;
|
|
39183
|
+
else if (state2.status === "success") exitCode = 0;
|
|
39184
|
+
else if (state2.status === "stalled" || state2.status === "stopped") exitCode = exitCode || 0;
|
|
39185
|
+
} catch (err) {
|
|
39186
|
+
process.stderr.write(
|
|
39187
|
+
`[zelari-code --headless] zelari error: ${err instanceof Error ? err.message : String(err)}
|
|
39188
|
+
`
|
|
39189
|
+
);
|
|
39190
|
+
return 2;
|
|
39191
|
+
} finally {
|
|
39192
|
+
await memory.close().catch(() => void 0);
|
|
39193
|
+
}
|
|
39194
|
+
return exitCode;
|
|
39195
|
+
}
|
|
39196
|
+
|
|
39197
|
+
// src/cli/desktopConfig.ts
|
|
39198
|
+
init_keyStore();
|
|
39199
|
+
init_providerConfig();
|
|
39200
|
+
init_updater();
|
|
39201
|
+
function wantsPrintConfig(argv) {
|
|
39202
|
+
return argv.includes("--print-config");
|
|
39203
|
+
}
|
|
39204
|
+
function wantsSetKey(argv) {
|
|
39205
|
+
return argv.includes("--set-key");
|
|
39206
|
+
}
|
|
39207
|
+
function wantsDiscoverModels(argv) {
|
|
39208
|
+
return argv.includes("--discover-models");
|
|
39209
|
+
}
|
|
39210
|
+
function parseSetConfigFlags(argv) {
|
|
39211
|
+
if (!argv.includes("--set-config")) {
|
|
39212
|
+
return { request: null };
|
|
39213
|
+
}
|
|
39214
|
+
let provider;
|
|
39215
|
+
let model;
|
|
39216
|
+
let endpoint;
|
|
39217
|
+
let endpointClear = false;
|
|
39218
|
+
for (let i = 0; i < argv.length; i++) {
|
|
39219
|
+
const arg = argv[i];
|
|
39220
|
+
if (arg === "--provider") {
|
|
39221
|
+
provider = argv[i + 1];
|
|
39222
|
+
i++;
|
|
39223
|
+
} else if (arg === "--model") {
|
|
39224
|
+
model = argv[i + 1];
|
|
39225
|
+
i++;
|
|
39226
|
+
} else if (arg === "--endpoint") {
|
|
39227
|
+
endpoint = argv[i + 1];
|
|
39228
|
+
i++;
|
|
39229
|
+
} else if (arg === "--endpoint-clear") {
|
|
39230
|
+
endpointClear = true;
|
|
39231
|
+
}
|
|
39232
|
+
}
|
|
39233
|
+
if (!provider && !model && !endpoint && !endpointClear) {
|
|
39234
|
+
return {
|
|
39235
|
+
request: null,
|
|
39236
|
+
error: "--set-config requires --provider, --model, --endpoint, and/or --endpoint-clear"
|
|
39237
|
+
};
|
|
39238
|
+
}
|
|
39239
|
+
if (provider !== void 0 && provider.trim().length === 0) {
|
|
39240
|
+
return { request: null, error: "--provider cannot be empty" };
|
|
39241
|
+
}
|
|
39242
|
+
if (model !== void 0 && model.trim().length === 0) {
|
|
39243
|
+
return { request: null, error: "--model cannot be empty" };
|
|
39244
|
+
}
|
|
39245
|
+
if (endpoint !== void 0 && endpoint.trim().length === 0) {
|
|
39246
|
+
return { request: null, error: "--endpoint cannot be empty" };
|
|
39247
|
+
}
|
|
39248
|
+
if (endpoint && endpointClear) {
|
|
39249
|
+
return { request: null, error: "--endpoint and --endpoint-clear conflict" };
|
|
39250
|
+
}
|
|
39251
|
+
return {
|
|
39252
|
+
request: {
|
|
39253
|
+
provider: provider?.trim(),
|
|
39254
|
+
model: model?.trim(),
|
|
39255
|
+
endpoint: endpoint?.trim(),
|
|
39256
|
+
endpointClear: endpointClear || void 0
|
|
39257
|
+
}
|
|
39258
|
+
};
|
|
39259
|
+
}
|
|
39260
|
+
function parseSetKeyFlags(argv) {
|
|
39261
|
+
if (!argv.includes("--set-key")) {
|
|
39262
|
+
return { request: null };
|
|
39263
|
+
}
|
|
39264
|
+
let provider;
|
|
39265
|
+
let key;
|
|
39266
|
+
for (let i = 0; i < argv.length; i++) {
|
|
39267
|
+
const arg = argv[i];
|
|
39268
|
+
if (arg === "--provider") {
|
|
39269
|
+
provider = argv[i + 1];
|
|
39270
|
+
i++;
|
|
39271
|
+
} else if (arg === "--key") {
|
|
39272
|
+
key = argv[i + 1];
|
|
39273
|
+
i++;
|
|
39274
|
+
}
|
|
39275
|
+
}
|
|
39276
|
+
if (!provider || provider.trim().length === 0) {
|
|
39277
|
+
return { request: null, error: "--set-key requires --provider <id>" };
|
|
39278
|
+
}
|
|
39279
|
+
if (!key || key.trim().length === 0) {
|
|
39280
|
+
return { request: null, error: "--set-key requires --key <secret>" };
|
|
39281
|
+
}
|
|
39282
|
+
return {
|
|
39283
|
+
request: {
|
|
39284
|
+
provider: provider.trim(),
|
|
39285
|
+
key: key.trim()
|
|
39286
|
+
}
|
|
39287
|
+
};
|
|
39288
|
+
}
|
|
39289
|
+
function parseDiscoverModelsFlags(argv) {
|
|
39290
|
+
if (!argv.includes("--discover-models")) {
|
|
39291
|
+
return { provider: null, present: false };
|
|
39292
|
+
}
|
|
39293
|
+
let provider;
|
|
39294
|
+
for (let i = 0; i < argv.length; i++) {
|
|
39295
|
+
if (argv[i] === "--provider") {
|
|
39296
|
+
provider = argv[i + 1];
|
|
39297
|
+
i++;
|
|
39298
|
+
}
|
|
39299
|
+
}
|
|
39300
|
+
return {
|
|
39301
|
+
present: true,
|
|
39302
|
+
provider: provider?.trim() || null
|
|
39303
|
+
};
|
|
39304
|
+
}
|
|
39305
|
+
function buildDesktopConfigSnapshot() {
|
|
39306
|
+
const config2 = getProviderConfig();
|
|
39307
|
+
const providers = PROVIDERS.map((p3) => {
|
|
39308
|
+
const cached2 = getCachedModels(p3.id);
|
|
39309
|
+
const models = cached2?.models.map((m) => m.id) ?? [];
|
|
39310
|
+
const defaultModel = config2.modelByProvider[p3.id] ?? "";
|
|
39311
|
+
if (defaultModel && !models.includes(defaultModel)) {
|
|
39312
|
+
models.unshift(defaultModel);
|
|
39313
|
+
}
|
|
39314
|
+
const custom2 = getCustomEndpoint(p3.id);
|
|
39315
|
+
const builtin = p3.baseUrl ?? null;
|
|
39316
|
+
return {
|
|
39317
|
+
id: p3.id,
|
|
39318
|
+
displayName: p3.displayName,
|
|
39319
|
+
hasKey: !!resolveApiKey(p3.id),
|
|
39320
|
+
envVar: p3.envVar,
|
|
39321
|
+
models,
|
|
39322
|
+
defaultModel,
|
|
39323
|
+
endpoint: custom2 ?? null,
|
|
39324
|
+
baseUrl: custom2 ?? builtin
|
|
39325
|
+
};
|
|
39326
|
+
});
|
|
39327
|
+
return {
|
|
39328
|
+
activeProviderId: config2.activeProviderId,
|
|
39329
|
+
modelByProvider: { ...config2.modelByProvider },
|
|
39330
|
+
providers,
|
|
39331
|
+
cliVersion: getCurrentVersion(),
|
|
39332
|
+
configPaths: {
|
|
39333
|
+
provider: getProviderConfigPath(),
|
|
39334
|
+
keys: getKeyStorePath()
|
|
39335
|
+
}
|
|
39336
|
+
};
|
|
39337
|
+
}
|
|
39338
|
+
function printDesktopConfig() {
|
|
39339
|
+
const snap = buildDesktopConfigSnapshot();
|
|
39340
|
+
process.stdout.write(JSON.stringify(snap, null, 2) + "\n");
|
|
39341
|
+
}
|
|
39342
|
+
function applySetConfig(req) {
|
|
39343
|
+
try {
|
|
39344
|
+
const config2 = getProviderConfig();
|
|
39345
|
+
let targetProvider = req.provider ?? config2.activeProviderId;
|
|
39346
|
+
if (req.provider) {
|
|
39347
|
+
const exists = PROVIDERS.some((p3) => p3.id === req.provider);
|
|
39348
|
+
if (!exists) {
|
|
39349
|
+
return {
|
|
39350
|
+
ok: false,
|
|
39351
|
+
error: `unknown provider '${req.provider}'. Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`
|
|
39352
|
+
};
|
|
39353
|
+
}
|
|
39354
|
+
setActiveProviderId(req.provider);
|
|
39355
|
+
targetProvider = req.provider;
|
|
39356
|
+
}
|
|
39357
|
+
if (req.endpointClear) {
|
|
39358
|
+
clearCustomEndpoint(targetProvider);
|
|
39359
|
+
}
|
|
39360
|
+
if (req.endpoint) {
|
|
39361
|
+
setCustomEndpoint(targetProvider, req.endpoint);
|
|
39362
|
+
}
|
|
39363
|
+
if (req.model) {
|
|
39364
|
+
setModelForProvider(targetProvider, req.model);
|
|
39365
|
+
}
|
|
39366
|
+
const after = getProviderConfig();
|
|
39367
|
+
const ep = getCustomEndpoint(after.activeProviderId);
|
|
39368
|
+
return {
|
|
39369
|
+
ok: true,
|
|
39370
|
+
message: `activeProvider=${after.activeProviderId} model=${after.modelByProvider[after.activeProviderId]}` + (ep ? ` endpoint=${ep}` : "")
|
|
39371
|
+
};
|
|
39372
|
+
} catch (err) {
|
|
39373
|
+
return {
|
|
39374
|
+
ok: false,
|
|
39375
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39376
|
+
};
|
|
39377
|
+
}
|
|
39378
|
+
}
|
|
39379
|
+
function applySetKey(req) {
|
|
39380
|
+
try {
|
|
39381
|
+
const exists = PROVIDERS.some((p3) => p3.id === req.provider);
|
|
39382
|
+
if (!exists) {
|
|
39383
|
+
return {
|
|
39384
|
+
ok: false,
|
|
39385
|
+
error: `unknown provider '${req.provider}'. Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`
|
|
39386
|
+
};
|
|
39387
|
+
}
|
|
39388
|
+
setApiKey(req.provider, req.key);
|
|
39389
|
+
setActiveProviderId(req.provider);
|
|
39390
|
+
return {
|
|
39391
|
+
ok: true,
|
|
39392
|
+
provider: req.provider,
|
|
39393
|
+
masked: maskKey(req.key)
|
|
39394
|
+
};
|
|
39395
|
+
} catch (err) {
|
|
39396
|
+
return {
|
|
39397
|
+
ok: false,
|
|
39398
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39399
|
+
};
|
|
39400
|
+
}
|
|
39401
|
+
}
|
|
39402
|
+
var DISCOVERABLE = [
|
|
39403
|
+
"grok",
|
|
39404
|
+
"glm",
|
|
39405
|
+
"minimax",
|
|
39406
|
+
"deepseek",
|
|
39407
|
+
"openai-compatible"
|
|
39408
|
+
];
|
|
39409
|
+
async function runDiscoverModels(providerArg) {
|
|
39410
|
+
const config2 = getProviderConfig();
|
|
39411
|
+
const providerId = (providerArg ?? config2.activeProviderId).trim();
|
|
39412
|
+
if (!DISCOVERABLE.includes(providerId)) {
|
|
39413
|
+
if (providerId === "custom") {
|
|
39414
|
+
} else {
|
|
39415
|
+
return {
|
|
39416
|
+
ok: false,
|
|
39417
|
+
error: `provider '${providerId}' is not discoverable. Use: ${DISCOVERABLE.join(", ")}`
|
|
39418
|
+
};
|
|
39419
|
+
}
|
|
39420
|
+
}
|
|
39421
|
+
const discoveryId = providerId === "custom" ? "openai-compatible" : providerId;
|
|
39422
|
+
try {
|
|
39423
|
+
const entry = await discoverModelsForProvider(discoveryId);
|
|
39424
|
+
return {
|
|
39425
|
+
ok: true,
|
|
39426
|
+
payload: {
|
|
39427
|
+
ok: true,
|
|
39428
|
+
provider: providerId,
|
|
39429
|
+
models: entry.models.map((m) => m.id),
|
|
39430
|
+
fetchedAt: entry.fetchedAt,
|
|
39431
|
+
baseUrl: entry.baseUrl
|
|
39432
|
+
}
|
|
39433
|
+
};
|
|
39434
|
+
} catch (err) {
|
|
39435
|
+
return {
|
|
39436
|
+
ok: false,
|
|
39437
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39438
|
+
};
|
|
39439
|
+
}
|
|
39440
|
+
}
|
|
39005
39441
|
|
|
39006
39442
|
// src/cli/skillsMd.ts
|
|
39007
39443
|
init_skills2();
|
|
@@ -39211,10 +39647,85 @@ function pickRootComponent() {
|
|
|
39211
39647
|
}
|
|
39212
39648
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
39213
39649
|
console.log(
|
|
39214
|
-
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --council
|
|
39650
|
+
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode agent|council|zelari Dispatch mode (default: agent)\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --print-config Print provider/model config as JSON (no secrets)\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
39215
39651
|
);
|
|
39216
39652
|
process.exit(0);
|
|
39217
39653
|
}
|
|
39654
|
+
if (wantsPrintConfig(argv)) {
|
|
39655
|
+
try {
|
|
39656
|
+
printDesktopConfig();
|
|
39657
|
+
process.exit(0);
|
|
39658
|
+
} catch (err) {
|
|
39659
|
+
console.error(
|
|
39660
|
+
`[zelari-code --print-config] ${err instanceof Error ? err.message : String(err)}`
|
|
39661
|
+
);
|
|
39662
|
+
process.exit(1);
|
|
39663
|
+
}
|
|
39664
|
+
}
|
|
39665
|
+
const setConfigParse = parseSetConfigFlags(argv);
|
|
39666
|
+
if (setConfigParse.error) {
|
|
39667
|
+
console.error(`[zelari-code --set-config] ${setConfigParse.error}`);
|
|
39668
|
+
process.exit(1);
|
|
39669
|
+
}
|
|
39670
|
+
if (setConfigParse.request) {
|
|
39671
|
+
const result = applySetConfig(setConfigParse.request);
|
|
39672
|
+
if (!result.ok) {
|
|
39673
|
+
console.error(`[zelari-code --set-config] ${result.error}`);
|
|
39674
|
+
process.exit(1);
|
|
39675
|
+
}
|
|
39676
|
+
console.log(JSON.stringify({ ok: true, message: result.message }));
|
|
39677
|
+
process.exit(0);
|
|
39678
|
+
}
|
|
39679
|
+
if (wantsSetKey(argv)) {
|
|
39680
|
+
const keyParse = parseSetKeyFlags(argv);
|
|
39681
|
+
if (keyParse.error || !keyParse.request) {
|
|
39682
|
+
console.error(
|
|
39683
|
+
`[zelari-code --set-key] ${keyParse.error ?? "invalid arguments"}`
|
|
39684
|
+
);
|
|
39685
|
+
process.exit(1);
|
|
39686
|
+
}
|
|
39687
|
+
const result = applySetKey(keyParse.request);
|
|
39688
|
+
if (!result.ok) {
|
|
39689
|
+
console.error(`[zelari-code --set-key] ${result.error}`);
|
|
39690
|
+
process.exit(1);
|
|
39691
|
+
}
|
|
39692
|
+
console.log(
|
|
39693
|
+
JSON.stringify({
|
|
39694
|
+
ok: true,
|
|
39695
|
+
provider: result.provider,
|
|
39696
|
+
masked: result.masked
|
|
39697
|
+
})
|
|
39698
|
+
);
|
|
39699
|
+
process.exit(0);
|
|
39700
|
+
}
|
|
39701
|
+
if (wantsDiscoverModels(argv)) {
|
|
39702
|
+
const disc = parseDiscoverModelsFlags(argv);
|
|
39703
|
+
void runDiscoverModels(disc.provider).then(async (result) => {
|
|
39704
|
+
if (!result.ok) {
|
|
39705
|
+
console.error(JSON.stringify({ ok: false, error: result.error }));
|
|
39706
|
+
await new Promise((r) => setImmediate(r));
|
|
39707
|
+
process.exit(1);
|
|
39708
|
+
return;
|
|
39709
|
+
}
|
|
39710
|
+
console.log(JSON.stringify(result.payload));
|
|
39711
|
+
try {
|
|
39712
|
+
await getMetricsLogger().flush();
|
|
39713
|
+
} catch {
|
|
39714
|
+
}
|
|
39715
|
+
await new Promise((r) => setImmediate(r));
|
|
39716
|
+
process.exit(0);
|
|
39717
|
+
}).catch(async (err) => {
|
|
39718
|
+
console.error(
|
|
39719
|
+
JSON.stringify({
|
|
39720
|
+
ok: false,
|
|
39721
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39722
|
+
})
|
|
39723
|
+
);
|
|
39724
|
+
await new Promise((r) => setImmediate(r));
|
|
39725
|
+
process.exit(1);
|
|
39726
|
+
});
|
|
39727
|
+
return { kind: "done" };
|
|
39728
|
+
}
|
|
39218
39729
|
const headlessParse = parseHeadlessFlags(argv);
|
|
39219
39730
|
if (headlessParse.options !== null) {
|
|
39220
39731
|
return { kind: "headless", headlessOpts: headlessParse.options };
|
|
@@ -39232,16 +39743,16 @@ function pickRootComponent() {
|
|
|
39232
39743
|
});
|
|
39233
39744
|
if (decision.shouldRun) {
|
|
39234
39745
|
console.error(`[zelari-code] starting wizard: ${decision.reason}`);
|
|
39235
|
-
return { kind: "wizard", element:
|
|
39746
|
+
return { kind: "wizard", element: React15.createElement(RunWizard) };
|
|
39236
39747
|
}
|
|
39237
39748
|
return {
|
|
39238
39749
|
kind: "app",
|
|
39239
|
-
element:
|
|
39750
|
+
element: React15.createElement(
|
|
39240
39751
|
SplashGate,
|
|
39241
39752
|
{ version: VERSION },
|
|
39242
|
-
|
|
39753
|
+
React15.createElement(PluginGate, {
|
|
39243
39754
|
cwd: process.cwd(),
|
|
39244
|
-
children:
|
|
39755
|
+
children: React15.createElement(App)
|
|
39245
39756
|
})
|
|
39246
39757
|
)
|
|
39247
39758
|
};
|
|
@@ -39267,10 +39778,27 @@ function main() {
|
|
|
39267
39778
|
runPreflight();
|
|
39268
39779
|
loadUserSkills();
|
|
39269
39780
|
if (picked.kind === "headless") {
|
|
39270
|
-
void runHeadless(picked.headlessOpts).then((code) => {
|
|
39271
|
-
|
|
39272
|
-
|
|
39781
|
+
void runHeadless(picked.headlessOpts).then(async (code) => {
|
|
39782
|
+
try {
|
|
39783
|
+
await getMetricsLogger().flush();
|
|
39784
|
+
} catch {
|
|
39785
|
+
}
|
|
39786
|
+
try {
|
|
39787
|
+
const { closeMcpClients: closeMcpClients2 } = await Promise.resolve().then(() => (init_mcpManager(), mcpManager_exports));
|
|
39788
|
+
closeMcpClients2();
|
|
39789
|
+
} catch {
|
|
39790
|
+
}
|
|
39791
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
39273
39792
|
process.exit(code);
|
|
39793
|
+
}).catch(async (err) => {
|
|
39794
|
+
console.error(
|
|
39795
|
+
`[zelari-code --headless] fatal: ${err instanceof Error ? err.message : String(err)}`
|
|
39796
|
+
);
|
|
39797
|
+
try {
|
|
39798
|
+
await getMetricsLogger().flush();
|
|
39799
|
+
} catch {
|
|
39800
|
+
}
|
|
39801
|
+
process.exit(2);
|
|
39274
39802
|
});
|
|
39275
39803
|
return;
|
|
39276
39804
|
}
|