@mrciphersmith/keryx 0.2.117 → 0.2.118
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/dist/cli.js +512 -245
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50252,7 +50252,7 @@ import path47 from "path";
|
|
|
50252
50252
|
// package.json
|
|
50253
50253
|
var package_default = {
|
|
50254
50254
|
name: "@mrciphersmith/keryx",
|
|
50255
|
-
version: "0.2.
|
|
50255
|
+
version: "0.2.118",
|
|
50256
50256
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
50257
50257
|
private: false,
|
|
50258
50258
|
publishConfig: {
|
|
@@ -74138,6 +74138,15 @@ function parseGrokToml(file, text) {
|
|
|
74138
74138
|
}
|
|
74139
74139
|
continue;
|
|
74140
74140
|
}
|
|
74141
|
+
const arrayHeader = /^\[\[([^[\]]+)\]\]$/.exec(line);
|
|
74142
|
+
if (arrayHeader !== null) {
|
|
74143
|
+
const first = arrayHeader[1].split(".")[0]?.trim().replace(/^(["'])(.*)\1$/, "$2");
|
|
74144
|
+
current = undefined;
|
|
74145
|
+
if (first === "mcp_servers") {
|
|
74146
|
+
problems.push({ file, message: `line ${lineNo}: "${line}" is not a table header this reader understands` });
|
|
74147
|
+
}
|
|
74148
|
+
continue;
|
|
74149
|
+
}
|
|
74141
74150
|
if (line.startsWith("[")) {
|
|
74142
74151
|
problems.push({ file, message: `line ${lineNo}: "${line}" is not a table header this reader understands` });
|
|
74143
74152
|
current = undefined;
|
|
@@ -89194,6 +89203,7 @@ function resolveInitialTab(tabs, initialTab) {
|
|
|
89194
89203
|
}
|
|
89195
89204
|
return first.id;
|
|
89196
89205
|
}
|
|
89206
|
+
var MODAL_BODY_SCROLLBAR_COLS = 1;
|
|
89197
89207
|
function innerWidthOf(state) {
|
|
89198
89208
|
const panelWidth = state.panel.width;
|
|
89199
89209
|
if (typeof panelWidth === "number" && panelWidth > MODAL_PANEL_CHROME_X) {
|
|
@@ -89246,7 +89256,7 @@ function mountTab(state, input, tabId) {
|
|
|
89246
89256
|
const size = resolveModalPanelSize(availWidth, state.chrome.renderer.height, input.contentRows);
|
|
89247
89257
|
const panelWidth = Math.min(availWidth, size.width);
|
|
89248
89258
|
const cleanup = input.renderTab(tabId, state.body, {
|
|
89249
|
-
width: resolveModalInnerWidth(panelWidth),
|
|
89259
|
+
width: resolveModalInnerWidth(panelWidth) - MODAL_BODY_SCROLLBAR_COLS,
|
|
89250
89260
|
height: modalBodyRows(size.height)
|
|
89251
89261
|
});
|
|
89252
89262
|
state.tabCleanup = typeof cleanup === "function" ? cleanup : undefined;
|
|
@@ -89423,6 +89433,9 @@ function ensureHost(otui, chrome) {
|
|
|
89423
89433
|
if (key.name === "right" && claimArrow("right")) {
|
|
89424
89434
|
return;
|
|
89425
89435
|
}
|
|
89436
|
+
if (state.tabs.length < 2 && (key.name === "left" || key.name === "right")) {
|
|
89437
|
+
return;
|
|
89438
|
+
}
|
|
89426
89439
|
if (key.name === "left" || onStrip && key.name === "tab" && key.shift === true) {
|
|
89427
89440
|
const prev = idx > 0 ? state.tabs[idx - 1] : undefined;
|
|
89428
89441
|
if (prev !== undefined) {
|
|
@@ -89464,11 +89477,11 @@ function ensureHost(otui, chrome) {
|
|
|
89464
89477
|
}
|
|
89465
89478
|
function makeHandle(state, generation) {
|
|
89466
89479
|
return {
|
|
89467
|
-
close() {
|
|
89480
|
+
close(opts) {
|
|
89468
89481
|
if (state.generation !== generation) {
|
|
89469
89482
|
return;
|
|
89470
89483
|
}
|
|
89471
|
-
closeHost(state, { restoreFocus: true, runOnClose: true });
|
|
89484
|
+
closeHost(state, { restoreFocus: opts?.restoreFocus ?? true, runOnClose: true });
|
|
89472
89485
|
},
|
|
89473
89486
|
setTab(id) {
|
|
89474
89487
|
if (state.generation !== generation || !state.open || state.input === undefined) {
|
|
@@ -89517,6 +89530,12 @@ function openModal(otui, chrome, input) {
|
|
|
89517
89530
|
if (focused === null || !containsNode(state.scroll, focused)) {
|
|
89518
89531
|
state.tabStrip.focus();
|
|
89519
89532
|
}
|
|
89533
|
+
const r = chrome.renderer;
|
|
89534
|
+
setTimeout(() => {
|
|
89535
|
+
if (state.generation === generation && state.open) {
|
|
89536
|
+
r.requestRender();
|
|
89537
|
+
}
|
|
89538
|
+
}, 0);
|
|
89520
89539
|
return makeHandle(state, generation);
|
|
89521
89540
|
}
|
|
89522
89541
|
|
|
@@ -90511,7 +90530,7 @@ function classifyBusyDispatch(params) {
|
|
|
90511
90530
|
// src/tui/boot-animation.ts
|
|
90512
90531
|
var DEFAULT_BOOT_DURATION_MS = 350;
|
|
90513
90532
|
var WORDMARK = ["========================", " K E R Y X ", "========================"];
|
|
90514
|
-
var
|
|
90533
|
+
var SPLASH_HINT = "type a message to start \xB7 / for commands";
|
|
90515
90534
|
async function playBootAnimation(otui, r, opts) {
|
|
90516
90535
|
if (process.env.KERYX_SKIP_BOOT === "1" || opts.skip === true) {
|
|
90517
90536
|
return;
|
|
@@ -90536,29 +90555,14 @@ async function playBootAnimation(otui, r, opts) {
|
|
|
90536
90555
|
for (const [index, line] of WORDMARK.entries()) {
|
|
90537
90556
|
logoBox.add(new otui.TextRenderable(r, { id: `boot-logo-${index}`, content: otui.t`${otui.bold(line)}` }));
|
|
90538
90557
|
}
|
|
90539
|
-
const statusText = new otui.TextRenderable(r, {
|
|
90540
|
-
id: "boot-status",
|
|
90541
|
-
content: otui.t`${otui.dim(STEPS[0] ?? "")}`,
|
|
90542
|
-
marginTop: 1
|
|
90543
|
-
});
|
|
90544
|
-
box.add(statusText);
|
|
90545
90558
|
box.add(new otui.TextRenderable(r, { id: "boot-hint", content: otui.t`${otui.dim("any key to skip")}`, marginTop: 1 }));
|
|
90546
90559
|
await new Promise((resolve) => {
|
|
90547
90560
|
let settled = false;
|
|
90548
|
-
let stepIndex = 0;
|
|
90549
|
-
const stepTimer = setInterval(() => {
|
|
90550
|
-
stepIndex = Math.min(stepIndex + 1, STEPS.length - 1);
|
|
90551
|
-
const step = STEPS[stepIndex];
|
|
90552
|
-
if (step !== undefined) {
|
|
90553
|
-
statusText.content = otui.t`${otui.dim(step)}`;
|
|
90554
|
-
}
|
|
90555
|
-
}, Math.max(1, Math.floor(durationMs / STEPS.length)));
|
|
90556
90561
|
const finish = () => {
|
|
90557
90562
|
if (settled) {
|
|
90558
90563
|
return;
|
|
90559
90564
|
}
|
|
90560
90565
|
settled = true;
|
|
90561
|
-
clearInterval(stepTimer);
|
|
90562
90566
|
clearTimeout(doneTimer);
|
|
90563
90567
|
unsubscribe();
|
|
90564
90568
|
r.root.remove(box);
|
|
@@ -90568,6 +90572,31 @@ async function playBootAnimation(otui, r, opts) {
|
|
|
90568
90572
|
const unsubscribe = opts.onKeypress(() => finish());
|
|
90569
90573
|
});
|
|
90570
90574
|
}
|
|
90575
|
+
var SHELL_CHROME_ROWS = 8;
|
|
90576
|
+
function mountEmptyTranscriptSplash(otui, r, transcript) {
|
|
90577
|
+
const rows = WORDMARK.length + 2;
|
|
90578
|
+
const paneRows = Math.max(0, r.height - SHELL_CHROME_ROWS);
|
|
90579
|
+
const box = new otui.BoxRenderable(r, {
|
|
90580
|
+
id: "transcript-splash",
|
|
90581
|
+
width: "100%",
|
|
90582
|
+
flexDirection: "column",
|
|
90583
|
+
alignItems: "center",
|
|
90584
|
+
flexShrink: 0,
|
|
90585
|
+
marginTop: Math.max(1, Math.floor((paneRows - rows) / 2))
|
|
90586
|
+
});
|
|
90587
|
+
for (const [index, line] of WORDMARK.entries()) {
|
|
90588
|
+
box.add(new otui.TextRenderable(r, { id: `splash-logo-${index}`, content: otui.t`${otui.bold(line)}` }));
|
|
90589
|
+
}
|
|
90590
|
+
box.add(new otui.TextRenderable(r, { id: "splash-hint", content: otui.t`${otui.dim(SPLASH_HINT)}`, marginTop: 1 }));
|
|
90591
|
+
transcript.add(box);
|
|
90592
|
+
let removed = false;
|
|
90593
|
+
return () => {
|
|
90594
|
+
if (removed)
|
|
90595
|
+
return;
|
|
90596
|
+
removed = true;
|
|
90597
|
+
transcript.remove(box);
|
|
90598
|
+
};
|
|
90599
|
+
}
|
|
90571
90600
|
|
|
90572
90601
|
// src/tui/workspace-inspector.ts
|
|
90573
90602
|
var WORKSPACE_COMMAND = "/workspace";
|
|
@@ -91306,13 +91335,11 @@ async function declineProposalViaShell(run, workspaceId, proposalId) {
|
|
|
91306
91335
|
|
|
91307
91336
|
// src/tui/mcp-inspector.ts
|
|
91308
91337
|
var MCP_INSPECTOR_FOOTER = [
|
|
91309
|
-
{ key: "\u2191/\u2193", label: "select" },
|
|
91310
|
-
{ key: "click", label: "row: select/act" },
|
|
91311
|
-
{ key: "c/d", label: "connect/disconnect" },
|
|
91312
|
-
{ key: "y", label: "confirm" },
|
|
91338
|
+
{ key: "\u2191/\u2193", label: "scroll/select" },
|
|
91313
91339
|
{ key: "\u2190/\u2192", label: "tabs" },
|
|
91314
91340
|
{ key: "esc", label: "close" }
|
|
91315
91341
|
];
|
|
91342
|
+
var MCP_TAB_KEYS = "keys: c/d connect/disconnect \xB7 y confirm \xB7 click a row to arm, again to confirm";
|
|
91316
91343
|
var MCP_TOOLS_COMMAND = "/integrations";
|
|
91317
91344
|
function isMcpToolsCommand(line) {
|
|
91318
91345
|
return (line.trim().split(/\s+/)[0] ?? "") === MCP_TOOLS_COMMAND;
|
|
@@ -91330,10 +91357,87 @@ var RUNTIME_LABELS = {
|
|
|
91330
91357
|
function runtimeLabel(id) {
|
|
91331
91358
|
return RUNTIME_LABELS[id] ?? id;
|
|
91332
91359
|
}
|
|
91333
|
-
|
|
91334
|
-
|
|
91335
|
-
|
|
91336
|
-
|
|
91360
|
+
var MIN_HANGING_BUDGET = 24;
|
|
91361
|
+
var FALLBACK_INDENT = 4;
|
|
91362
|
+
function splitLongWord(word, budget) {
|
|
91363
|
+
const pieces = [];
|
|
91364
|
+
let rest = word;
|
|
91365
|
+
while (rest.length > budget) {
|
|
91366
|
+
const slash = rest.lastIndexOf("/", budget);
|
|
91367
|
+
const cut = slash > 0 ? slash : budget;
|
|
91368
|
+
pieces.push(rest.slice(0, cut));
|
|
91369
|
+
rest = rest.slice(cut);
|
|
91370
|
+
}
|
|
91371
|
+
pieces.push(rest);
|
|
91372
|
+
return pieces;
|
|
91373
|
+
}
|
|
91374
|
+
function wrapHangingRow(head, text, width, indent = head.length) {
|
|
91375
|
+
if (width === undefined) {
|
|
91376
|
+
return [`${head}${text}`.trimEnd()];
|
|
91377
|
+
}
|
|
91378
|
+
const hang = width - indent >= MIN_HANGING_BUDGET ? indent : Math.min(indent, FALLBACK_INDENT);
|
|
91379
|
+
const pad = " ".repeat(hang);
|
|
91380
|
+
const budget = Math.max(1, width - hang);
|
|
91381
|
+
const out = [];
|
|
91382
|
+
let current = head;
|
|
91383
|
+
let fresh = true;
|
|
91384
|
+
const units = [];
|
|
91385
|
+
for (const match of text.matchAll(/(\S+)( *)/g)) {
|
|
91386
|
+
const word = match[1];
|
|
91387
|
+
const last = units.at(-1);
|
|
91388
|
+
if (last !== undefined && last.gap === " " && last.word.includes("/") && word.includes("/") && !/^[/~-]/.test(word)) {
|
|
91389
|
+
last.word += ` ${word}`;
|
|
91390
|
+
last.gap = match[2];
|
|
91391
|
+
continue;
|
|
91392
|
+
}
|
|
91393
|
+
units.push({ word, gap: match[2] });
|
|
91394
|
+
}
|
|
91395
|
+
let gap = "";
|
|
91396
|
+
for (const unit of units) {
|
|
91397
|
+
for (const [i, piece] of splitLongWord(unit.word, budget).entries()) {
|
|
91398
|
+
const sep = fresh || i > 0 ? "" : gap;
|
|
91399
|
+
if (current.length + sep.length + piece.length <= width || fresh && current === pad) {
|
|
91400
|
+
current += sep + piece;
|
|
91401
|
+
} else {
|
|
91402
|
+
out.push(current.trimEnd());
|
|
91403
|
+
current = pad + piece;
|
|
91404
|
+
}
|
|
91405
|
+
fresh = false;
|
|
91406
|
+
}
|
|
91407
|
+
gap = unit.gap;
|
|
91408
|
+
}
|
|
91409
|
+
out.push(current.trimEnd());
|
|
91410
|
+
return out;
|
|
91411
|
+
}
|
|
91412
|
+
var TOOL_NAME_COLUMN = 28;
|
|
91413
|
+
var TOOL_APPROVAL_COLUMN = 8;
|
|
91414
|
+
function approvalLabel(risk) {
|
|
91415
|
+
const value = risk ?? "read";
|
|
91416
|
+
return value === "read" ? "none" : value;
|
|
91417
|
+
}
|
|
91418
|
+
var TOOLS_COLUMN_HEADER = `${"tool".padEnd(TOOL_NAME_COLUMN)} ${"approval".padEnd(TOOL_APPROVAL_COLUMN)} description`;
|
|
91419
|
+
function formatToolRowLines(tool, width) {
|
|
91420
|
+
const head = `${tool.name.padEnd(TOOL_NAME_COLUMN)} ${approvalLabel(tool.risk).padEnd(TOOL_APPROVAL_COLUMN)} `;
|
|
91421
|
+
return wrapHangingRow(head, tool.description ?? "", width, TOOL_NAME_COLUMN + TOOL_APPROVAL_COLUMN + 2);
|
|
91422
|
+
}
|
|
91423
|
+
function fitRowsByLines(lineCounts, start, rows) {
|
|
91424
|
+
if (lineCounts.length === 0) {
|
|
91425
|
+
return { start: 0, end: 0 };
|
|
91426
|
+
}
|
|
91427
|
+
let maxStart = lineCounts.length - 1;
|
|
91428
|
+
let tail = lineCounts[maxStart] ?? 1;
|
|
91429
|
+
while (maxStart > 0 && tail + (lineCounts[maxStart - 1] ?? 1) <= rows) {
|
|
91430
|
+
maxStart -= 1;
|
|
91431
|
+
tail += lineCounts[maxStart] ?? 1;
|
|
91432
|
+
}
|
|
91433
|
+
const from = Math.min(maxStart, Math.max(0, start));
|
|
91434
|
+
let end = from + 1;
|
|
91435
|
+
let used = lineCounts[from] ?? 1;
|
|
91436
|
+
while (end < lineCounts.length && used + (lineCounts[end] ?? 1) <= rows) {
|
|
91437
|
+
used += lineCounts[end] ?? 1;
|
|
91438
|
+
end += 1;
|
|
91439
|
+
}
|
|
91440
|
+
return { start: from, end };
|
|
91337
91441
|
}
|
|
91338
91442
|
function isActionable(id) {
|
|
91339
91443
|
return id !== "generic";
|
|
@@ -91348,7 +91452,7 @@ function formatOtherServers(otherServers) {
|
|
|
91348
91452
|
const list = rest > 0 ? `${shown.join(", ")}, +${rest} more` : shown.join(", ");
|
|
91349
91453
|
return ` \xB7 also has: ${list}`;
|
|
91350
91454
|
}
|
|
91351
|
-
function formatMcpRowLine(runtime, isSelected, status) {
|
|
91455
|
+
function formatMcpRowLine(runtime, isSelected, status, width) {
|
|
91352
91456
|
const mark = isSelected ? ">" : " ";
|
|
91353
91457
|
const label = runtimeLabel(runtime.id).padEnd(20);
|
|
91354
91458
|
const statusText = runtime.connected ? "\u25CF keryx connected" : "\u25CB keryx not connected";
|
|
@@ -91364,7 +91468,8 @@ function formatMcpRowLine(runtime, isSelected, status) {
|
|
|
91364
91468
|
} else {
|
|
91365
91469
|
action = runtime.connected ? " [d] disconnect" : " [c] connect";
|
|
91366
91470
|
}
|
|
91367
|
-
return `${mark} ${label}
|
|
91471
|
+
return wrapHangingRow(`${mark} ${label} `, `${statusText}${action}${formatOtherServers(runtime.otherServers)}`, width).join(`
|
|
91472
|
+
`);
|
|
91368
91473
|
}
|
|
91369
91474
|
function asRowTarget(body) {
|
|
91370
91475
|
const parent = body;
|
|
@@ -91388,6 +91493,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91388
91493
|
let rowCtor;
|
|
91389
91494
|
let activeRenderer;
|
|
91390
91495
|
let unsubscribeKey;
|
|
91496
|
+
let bodyWidth;
|
|
91391
91497
|
const rendererHint = options.renderer ?? chrome?.renderer;
|
|
91392
91498
|
const bodyRows = options.visibleRows ?? (typeof rendererHint?.width === "number" && typeof rendererHint.height === "number" ? modalBodyRows(resolveModalPanelSize(rendererHint.width, rendererHint.height).height) : 13);
|
|
91393
91499
|
const paintToolsRows = () => {
|
|
@@ -91400,11 +91506,23 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91400
91506
|
toolsBody.add(new rowCtor(activeRenderer, { id: "mcp-tools-empty", content: "No tools available." }));
|
|
91401
91507
|
return;
|
|
91402
91508
|
}
|
|
91403
|
-
|
|
91404
|
-
|
|
91405
|
-
|
|
91509
|
+
toolsBody.add(new rowCtor(activeRenderer, { id: "mcp-tools-columns", content: TOOLS_COLUMN_HEADER }));
|
|
91510
|
+
const rows = options.tools.map((tool) => formatToolRowLines(tool, bodyWidth));
|
|
91511
|
+
const window = toolsWindow(rows);
|
|
91512
|
+
toolsScroll = window.start;
|
|
91513
|
+
for (let index = window.start;index < window.end; index++) {
|
|
91514
|
+
toolsBody.add(new rowCtor(activeRenderer, {
|
|
91515
|
+
id: `mcp-tool-row-${index}`,
|
|
91516
|
+
content: (rows[index] ?? []).join(`
|
|
91517
|
+
`)
|
|
91518
|
+
}));
|
|
91406
91519
|
}
|
|
91407
91520
|
};
|
|
91521
|
+
const toolsRowBudget = () => {
|
|
91522
|
+
const captionLines = wrapHangingRow("", TOOLS_TAB_HEADER, bodyWidth, 0).length;
|
|
91523
|
+
return Math.max(1, bodyRows - captionLines - 1);
|
|
91524
|
+
};
|
|
91525
|
+
const toolsWindow = (rows) => fitRowsByLines(rows.map((lines) => lines.length), toolsScroll, toolsRowBudget());
|
|
91408
91526
|
const paintMcpRows = () => {
|
|
91409
91527
|
if (mcpBody === undefined || rowCtor === undefined) {
|
|
91410
91528
|
return;
|
|
@@ -91416,18 +91534,19 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91416
91534
|
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-empty", content: "No MCP client runtimes registered." }));
|
|
91417
91535
|
return;
|
|
91418
91536
|
}
|
|
91537
|
+
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-keys", content: MCP_TAB_KEYS }));
|
|
91419
91538
|
const start = clampScroll3(mcpScroll, runtimes.length, bodyRows);
|
|
91420
91539
|
for (const [i, runtime] of runtimes.slice(start, start + bodyRows).entries()) {
|
|
91421
91540
|
const index = start + i;
|
|
91422
91541
|
mcpBody.add(new rowCtor(activeRenderer, {
|
|
91423
91542
|
id: `mcp-row-${runtime.id}`,
|
|
91424
|
-
content: formatMcpRowLine(runtime, index === mcpSelected, status),
|
|
91543
|
+
content: formatMcpRowLine(runtime, index === mcpSelected, status, bodyWidth),
|
|
91425
91544
|
onMouseDown: () => handleRowClick(runtime.id, index)
|
|
91426
91545
|
}));
|
|
91427
91546
|
}
|
|
91428
91547
|
};
|
|
91429
91548
|
const paint = () => {
|
|
91430
|
-
toolsScroll =
|
|
91549
|
+
toolsScroll = Math.max(0, toolsScroll);
|
|
91431
91550
|
mcpScroll = scrollToReveal3(mcpSelected, mcpScroll, bodyRows);
|
|
91432
91551
|
mcpScroll = clampScroll3(mcpScroll, runtimes.length, bodyRows);
|
|
91433
91552
|
paintToolsRows();
|
|
@@ -91510,9 +91629,10 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91510
91629
|
}
|
|
91511
91630
|
rowCtor = ctor;
|
|
91512
91631
|
activeRenderer = renderer;
|
|
91632
|
+
bodyWidth = ctx?.width;
|
|
91513
91633
|
if (tabId === "tools") {
|
|
91514
91634
|
toolsBody = target;
|
|
91515
|
-
toolsScroll =
|
|
91635
|
+
toolsScroll = Math.max(0, toolsScroll);
|
|
91516
91636
|
paintToolsRows();
|
|
91517
91637
|
return;
|
|
91518
91638
|
}
|
|
@@ -91560,7 +91680,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91560
91680
|
if (onMcp) {
|
|
91561
91681
|
moveMcpSelection(mcpSelected - 1);
|
|
91562
91682
|
} else {
|
|
91563
|
-
toolsScroll =
|
|
91683
|
+
toolsScroll = Math.max(0, toolsScroll - 1);
|
|
91564
91684
|
paint();
|
|
91565
91685
|
}
|
|
91566
91686
|
return;
|
|
@@ -91569,7 +91689,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91569
91689
|
if (onMcp) {
|
|
91570
91690
|
moveMcpSelection(mcpSelected + 1);
|
|
91571
91691
|
} else {
|
|
91572
|
-
toolsScroll
|
|
91692
|
+
toolsScroll += 1;
|
|
91573
91693
|
paint();
|
|
91574
91694
|
}
|
|
91575
91695
|
return;
|
|
@@ -91579,7 +91699,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91579
91699
|
if (onMcp) {
|
|
91580
91700
|
mcpScroll = clampScroll3(mcpScroll + step, runtimes.length, bodyRows);
|
|
91581
91701
|
} else {
|
|
91582
|
-
toolsScroll =
|
|
91702
|
+
toolsScroll = Math.max(0, toolsScroll + step);
|
|
91583
91703
|
}
|
|
91584
91704
|
paint();
|
|
91585
91705
|
}
|
|
@@ -91592,6 +91712,7 @@ function openMcpTools(otui, chrome, options) {
|
|
|
91592
91712
|
}
|
|
91593
91713
|
|
|
91594
91714
|
// src/tui/mcp-consumer.ts
|
|
91715
|
+
import { homedir as homedir9 } from "os";
|
|
91595
91716
|
var MCP_CONSUMER_COMMAND = "/mcp";
|
|
91596
91717
|
function isMcpConsumerCommand(line) {
|
|
91597
91718
|
return (line.trim().split(/\s+/)[0] ?? "") === MCP_CONSUMER_COMMAND;
|
|
@@ -91620,12 +91741,21 @@ function credentialNames(server) {
|
|
|
91620
91741
|
}
|
|
91621
91742
|
return [...names].sort();
|
|
91622
91743
|
}
|
|
91623
|
-
|
|
91744
|
+
var MAX_TARGET_CHARS = 240;
|
|
91745
|
+
function collapseHome2(text, home) {
|
|
91746
|
+
const trimmed = home.replace(/\/+$/, "");
|
|
91747
|
+
if (trimmed === "")
|
|
91748
|
+
return text;
|
|
91749
|
+
const escaped = trimmed.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
91750
|
+
return text.replace(new RegExp(`(^|[\\s="'])${escaped}(?=/|$|[\\s"'])`, "g"), "$1~");
|
|
91751
|
+
}
|
|
91752
|
+
function targetOf(server, home) {
|
|
91624
91753
|
const raw = server.raw;
|
|
91625
|
-
const target = typeof raw.url === "string" && raw.url.length > 0 ? displayUrl(raw.url) : [raw.command, ...raw.args ?? []].filter(Boolean).join(" ");
|
|
91626
|
-
return sanitiseIdentifier(target);
|
|
91754
|
+
const target = typeof raw.url === "string" && raw.url.length > 0 ? displayUrl(raw.url) : collapseHome2([raw.command, ...raw.args ?? []].filter(Boolean).join(" "), home);
|
|
91755
|
+
return sanitiseIdentifier(target, MAX_TARGET_CHARS);
|
|
91627
91756
|
}
|
|
91628
91757
|
function buildConsumerModel(input) {
|
|
91758
|
+
const home = input.home ?? homedir9();
|
|
91629
91759
|
const stateByName = new Map(input.states.map((s) => [s.name, s]));
|
|
91630
91760
|
const rows = input.configured.map((server) => {
|
|
91631
91761
|
const state = stateByName.get(server.name);
|
|
@@ -91637,7 +91767,7 @@ function buildConsumerModel(input) {
|
|
|
91637
91767
|
transport: transportOf(server),
|
|
91638
91768
|
status,
|
|
91639
91769
|
toolCount: state?.toolCount ?? 0,
|
|
91640
|
-
target: targetOf(server),
|
|
91770
|
+
target: targetOf(server, home),
|
|
91641
91771
|
credentials: credentialNames(server),
|
|
91642
91772
|
detail,
|
|
91643
91773
|
action: status === "needs-approval" ? `keryx mcp trust ${server.name}` : status === "needs_auth" ? "set the variable named above, then restart the session" : undefined
|
|
@@ -91645,10 +91775,10 @@ function buildConsumerModel(input) {
|
|
|
91645
91775
|
});
|
|
91646
91776
|
return {
|
|
91647
91777
|
rows,
|
|
91648
|
-
problems: input.problems.map((p) => `${p.file}: ${sanitiseForDisplay(p.message)}`),
|
|
91778
|
+
problems: input.problems.map((p) => `${collapseHome2(p.file, home)}: ${sanitiseForDisplay(p.message)}`),
|
|
91649
91779
|
emptyHint: rows.length > 0 ? undefined : `No MCP servers configured.
|
|
91650
|
-
user: ${input.userFile}
|
|
91651
|
-
project: ${input.projectFile}`
|
|
91780
|
+
user: ${collapseHome2(input.userFile, home)}
|
|
91781
|
+
project: ${collapseHome2(input.projectFile, home)}`
|
|
91652
91782
|
};
|
|
91653
91783
|
}
|
|
91654
91784
|
var MCP_CONSUMER_FOOTER = [
|
|
@@ -91677,7 +91807,7 @@ function consumerActionFor(status) {
|
|
|
91677
91807
|
function statusGlyph(status) {
|
|
91678
91808
|
return STATUS_GLYPH[status] ?? status;
|
|
91679
91809
|
}
|
|
91680
|
-
function formatConsumerModalRow(row, isSelected, status) {
|
|
91810
|
+
function formatConsumerModalRow(row, isSelected, status, width) {
|
|
91681
91811
|
const mark = isSelected ? ">" : " ";
|
|
91682
91812
|
const name = row.name.padEnd(18);
|
|
91683
91813
|
const source = row.source.padEnd(10);
|
|
@@ -91702,7 +91832,8 @@ function formatConsumerModalRow(row, isSelected, status) {
|
|
|
91702
91832
|
action = "";
|
|
91703
91833
|
}
|
|
91704
91834
|
const creds = row.credentials.length > 0 ? ` [reads ${row.credentials.join(", ")}]` : "";
|
|
91705
|
-
return `${mark} ${name} ${source} ${transport} ${glyph}
|
|
91835
|
+
return wrapHangingRow(`${mark} ${name} ${source} ${transport} ${glyph}`, `${tools}${action} ${row.target}${creds}`, width).join(`
|
|
91836
|
+
`);
|
|
91706
91837
|
}
|
|
91707
91838
|
function formatConsumerModalLines(model, selected, status) {
|
|
91708
91839
|
if (model === undefined) {
|
|
@@ -91743,6 +91874,7 @@ function presentMcpConsumer(openModalFn, otui, chrome, options) {
|
|
|
91743
91874
|
let rowCtor;
|
|
91744
91875
|
let activeRenderer;
|
|
91745
91876
|
let unsubscribeKey;
|
|
91877
|
+
let bodyWidth;
|
|
91746
91878
|
const rendererHint = options.renderer ?? chrome?.renderer;
|
|
91747
91879
|
const bodyRows = options.visibleRows ?? (typeof rendererHint?.width === "number" && typeof rendererHint.height === "number" ? modalBodyRows(resolveModalPanelSize(rendererHint.width, rendererHint.height).height) : 13);
|
|
91748
91880
|
const rowsOf = () => options.snapshot()?.rows ?? [];
|
|
@@ -91775,7 +91907,7 @@ function presentMcpConsumer(openModalFn, otui, chrome, options) {
|
|
|
91775
91907
|
const index = start + i;
|
|
91776
91908
|
body.add(new rowCtor(activeRenderer, {
|
|
91777
91909
|
id: `mcp-consumer-row-${row.name}`,
|
|
91778
|
-
content: formatConsumerModalRow(row, index === selected, status),
|
|
91910
|
+
content: formatConsumerModalRow(row, index === selected, status, bodyWidth),
|
|
91779
91911
|
onMouseDown: () => handleRowClick(row.name, index)
|
|
91780
91912
|
}));
|
|
91781
91913
|
}
|
|
@@ -91846,6 +91978,7 @@ function presentMcpConsumer(openModalFn, otui, chrome, options) {
|
|
|
91846
91978
|
rowCtor = ctor;
|
|
91847
91979
|
activeRenderer = renderer;
|
|
91848
91980
|
body = target;
|
|
91981
|
+
bodyWidth = ctx?.width;
|
|
91849
91982
|
paint();
|
|
91850
91983
|
},
|
|
91851
91984
|
onClose: () => {
|
|
@@ -97654,30 +97787,31 @@ var CUSTOM_ADD_ENTRY = {
|
|
|
97654
97787
|
label: "\uFF0B Add custom provider (OpenAI-compatible)",
|
|
97655
97788
|
note: "name \xB7 URL \xB7 key \xB7 models \u2192 saved to llm-providers.json"
|
|
97656
97789
|
};
|
|
97657
|
-
function promptCustomFieldStep(otui,
|
|
97790
|
+
function promptCustomFieldStep(otui, target, opts) {
|
|
97791
|
+
const r = stepRenderer(target);
|
|
97658
97792
|
return new Promise((resolve) => {
|
|
97659
|
-
const
|
|
97660
|
-
|
|
97661
|
-
|
|
97793
|
+
const surface = openStepSurface(otui, target, {
|
|
97794
|
+
id: "custom-field-picker",
|
|
97795
|
+
title: opts.title,
|
|
97796
|
+
tab: "Custom provider",
|
|
97797
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
97798
|
+
footer: inputStepFooter("back"),
|
|
97799
|
+
contentRows: opts.note !== undefined ? 4 : 2,
|
|
97800
|
+
onEscape: () => {
|
|
97801
|
+
input.blur();
|
|
97802
|
+
resolve({ kind: "back" });
|
|
97803
|
+
}
|
|
97804
|
+
});
|
|
97662
97805
|
if (opts.note !== undefined) {
|
|
97663
|
-
|
|
97806
|
+
surface.body.add(new otui.TextRenderable(r, { id: "cf-note", content: otui.t`${otui.dim(opts.note)}`, marginTop: 1 }));
|
|
97664
97807
|
}
|
|
97665
97808
|
const input = new otui.InputRenderable(r, { id: "cf-input", value: opts.value ?? "", marginTop: 1 });
|
|
97666
|
-
|
|
97809
|
+
surface.body.add(input);
|
|
97667
97810
|
input.focus();
|
|
97668
97811
|
const cleanup = () => {
|
|
97669
|
-
unsub();
|
|
97670
97812
|
input.blur();
|
|
97671
|
-
|
|
97813
|
+
surface.close();
|
|
97672
97814
|
};
|
|
97673
|
-
const unsub = onKeypress4(r, (key) => {
|
|
97674
|
-
if (key.name === "escape") {
|
|
97675
|
-
cleanup();
|
|
97676
|
-
resolve({ kind: "back" });
|
|
97677
|
-
key.preventDefault();
|
|
97678
|
-
key.stopPropagation();
|
|
97679
|
-
}
|
|
97680
|
-
});
|
|
97681
97815
|
input.on(otui.InputRenderableEvents.ENTER, () => {
|
|
97682
97816
|
const entered = input.value.trim();
|
|
97683
97817
|
cleanup();
|
|
@@ -97697,9 +97831,9 @@ function parseOptionalPositiveWizardNumber(raw) {
|
|
|
97697
97831
|
const parsed = parseOptionalWizardNumber(raw);
|
|
97698
97832
|
return parsed !== undefined && parsed > 0 ? parsed : undefined;
|
|
97699
97833
|
}
|
|
97700
|
-
async function promptCustomProviderWizard(otui,
|
|
97834
|
+
async function promptCustomProviderWizard(otui, target) {
|
|
97701
97835
|
while (true) {
|
|
97702
|
-
const nameStep = await promptCustomFieldStep(otui,
|
|
97836
|
+
const nameStep = await promptCustomFieldStep(otui, target, {
|
|
97703
97837
|
title: "Provider name",
|
|
97704
97838
|
note: "unique id used in /provider (letters, digits, - _)"
|
|
97705
97839
|
});
|
|
@@ -97711,7 +97845,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97711
97845
|
continue;
|
|
97712
97846
|
}
|
|
97713
97847
|
while (true) {
|
|
97714
|
-
const urlStep = await promptCustomFieldStep(otui,
|
|
97848
|
+
const urlStep = await promptCustomFieldStep(otui, target, {
|
|
97715
97849
|
title: "Base URL",
|
|
97716
97850
|
note: "before the chat path \u2014 /v1/chat/completions is appended, e.g. http://10.110.43.19:8080",
|
|
97717
97851
|
value: "http://localhost:8000"
|
|
@@ -97733,7 +97867,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97733
97867
|
continue;
|
|
97734
97868
|
}
|
|
97735
97869
|
const baseUrl = baseUrlRaw.replace(/\/+$/, "");
|
|
97736
|
-
const keyStep = await promptCustomFieldStep(otui,
|
|
97870
|
+
const keyStep = await promptCustomFieldStep(otui, target, {
|
|
97737
97871
|
title: "API key (optional)",
|
|
97738
97872
|
note: "empty = no key \xB7 saved owner-only (0600) in your keryx config dir"
|
|
97739
97873
|
});
|
|
@@ -97741,7 +97875,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97741
97875
|
continue;
|
|
97742
97876
|
}
|
|
97743
97877
|
const apiKey = keyStep.value.length > 0 ? keyStep.value : undefined;
|
|
97744
|
-
const modelsStep = await promptCustomFieldStep(otui,
|
|
97878
|
+
const modelsStep = await promptCustomFieldStep(otui, target, {
|
|
97745
97879
|
title: "Models (optional)",
|
|
97746
97880
|
note: "comma-separated ids \xB7 empty = fetch the live /v1/models list"
|
|
97747
97881
|
});
|
|
@@ -97749,7 +97883,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97749
97883
|
continue;
|
|
97750
97884
|
}
|
|
97751
97885
|
const models = modelsStep.value.split(",").map((m) => m.trim()).filter((m) => m.length > 0);
|
|
97752
|
-
const temperatureStep = await promptCustomFieldStep(otui,
|
|
97886
|
+
const temperatureStep = await promptCustomFieldStep(otui, target, {
|
|
97753
97887
|
title: "Temperature (optional)",
|
|
97754
97888
|
note: "empty = provider default \xB7 e.g. 0.2"
|
|
97755
97889
|
});
|
|
@@ -97757,7 +97891,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97757
97891
|
continue;
|
|
97758
97892
|
}
|
|
97759
97893
|
const temperature = parseOptionalWizardNumber(temperatureStep.value);
|
|
97760
|
-
const maxOutputTokensStep = await promptCustomFieldStep(otui,
|
|
97894
|
+
const maxOutputTokensStep = await promptCustomFieldStep(otui, target, {
|
|
97761
97895
|
title: "Max output tokens (optional)",
|
|
97762
97896
|
note: "empty = default 1024 \xB7 e.g. 4096"
|
|
97763
97897
|
});
|
|
@@ -97765,7 +97899,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97765
97899
|
continue;
|
|
97766
97900
|
}
|
|
97767
97901
|
const maxOutputTokens = parseOptionalPositiveWizardNumber(maxOutputTokensStep.value);
|
|
97768
|
-
const timeoutMsStep = await promptCustomFieldStep(otui,
|
|
97902
|
+
const timeoutMsStep = await promptCustomFieldStep(otui, target, {
|
|
97769
97903
|
title: "Request timeout ms (optional)",
|
|
97770
97904
|
note: "empty = no engine-internal timeout \xB7 e.g. 180000"
|
|
97771
97905
|
});
|
|
@@ -98120,6 +98254,78 @@ function onKeypress4(r, handler) {
|
|
|
98120
98254
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
98121
98255
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
98122
98256
|
}
|
|
98257
|
+
function isModalChrome(target) {
|
|
98258
|
+
return target !== null && typeof target === "object" && "renderer" in target && "focusComposer" in target;
|
|
98259
|
+
}
|
|
98260
|
+
function stepRenderer(target) {
|
|
98261
|
+
return isModalChrome(target) ? target.renderer : target;
|
|
98262
|
+
}
|
|
98263
|
+
function openStepSurface(otui, target, opts) {
|
|
98264
|
+
const r = stepRenderer(target);
|
|
98265
|
+
if (!isModalChrome(target)) {
|
|
98266
|
+
const box = overlayBox(otui, r, opts.id);
|
|
98267
|
+
r.root.add(box);
|
|
98268
|
+
box.add(new otui.TextRenderable(r, { id: `${opts.id}-title`, content: otui.t`${otui.bold(opts.title)} ${otui.dim(opts.hint)}` }));
|
|
98269
|
+
let closed = false;
|
|
98270
|
+
const close = () => {
|
|
98271
|
+
if (closed)
|
|
98272
|
+
return;
|
|
98273
|
+
closed = true;
|
|
98274
|
+
unsub();
|
|
98275
|
+
r.root.remove(box);
|
|
98276
|
+
};
|
|
98277
|
+
const unsub = onKeypress4(r, (key) => {
|
|
98278
|
+
if (key.name === "escape") {
|
|
98279
|
+
close();
|
|
98280
|
+
opts.onEscape();
|
|
98281
|
+
key.preventDefault();
|
|
98282
|
+
key.stopPropagation();
|
|
98283
|
+
}
|
|
98284
|
+
});
|
|
98285
|
+
return { body: box, modal: false, close };
|
|
98286
|
+
}
|
|
98287
|
+
let body;
|
|
98288
|
+
let closedByStep = false;
|
|
98289
|
+
const handle = openModal(otui, target, {
|
|
98290
|
+
title: opts.title,
|
|
98291
|
+
tabs: [{ id: opts.id, label: opts.tab }],
|
|
98292
|
+
footer: opts.footer,
|
|
98293
|
+
contentRows: opts.contentRows,
|
|
98294
|
+
renderTab: (_tabId, tabBody) => {
|
|
98295
|
+
body = tabBody;
|
|
98296
|
+
},
|
|
98297
|
+
onClose: () => {
|
|
98298
|
+
if (!closedByStep)
|
|
98299
|
+
opts.onEscape();
|
|
98300
|
+
}
|
|
98301
|
+
});
|
|
98302
|
+
if (handle === undefined || body === undefined) {
|
|
98303
|
+
return openStepSurface(otui, r, opts);
|
|
98304
|
+
}
|
|
98305
|
+
return {
|
|
98306
|
+
body,
|
|
98307
|
+
modal: true,
|
|
98308
|
+
close: () => {
|
|
98309
|
+
if (closedByStep)
|
|
98310
|
+
return;
|
|
98311
|
+
closedByStep = true;
|
|
98312
|
+
handle.close({ restoreFocus: false });
|
|
98313
|
+
}
|
|
98314
|
+
};
|
|
98315
|
+
}
|
|
98316
|
+
function selectStepFooter(escLabel) {
|
|
98317
|
+
return [
|
|
98318
|
+
{ key: "\u2191/\u2193", label: "select" },
|
|
98319
|
+
{ key: "Enter", label: "confirm" },
|
|
98320
|
+
{ key: "esc", label: escLabel }
|
|
98321
|
+
];
|
|
98322
|
+
}
|
|
98323
|
+
function inputStepFooter(escLabel) {
|
|
98324
|
+
return [
|
|
98325
|
+
{ key: "Enter", label: "confirm" },
|
|
98326
|
+
{ key: "esc", label: escLabel }
|
|
98327
|
+
];
|
|
98328
|
+
}
|
|
98123
98329
|
function parseSearchProviderArgs(line) {
|
|
98124
98330
|
const parts = line.trim().length === 0 ? [] : line.trim().split(/\s+/);
|
|
98125
98331
|
const [providerId, ...tail] = parts;
|
|
@@ -98166,27 +98372,28 @@ async function selectSearchProviderAndReport(controller, onSystem, providerId) {
|
|
|
98166
98372
|
onSystem?.(`Search provider '${providerId}' selected.
|
|
98167
98373
|
`);
|
|
98168
98374
|
}
|
|
98169
|
-
function promptSearchFieldStep(otui,
|
|
98375
|
+
function promptSearchFieldStep(otui, target, field, value) {
|
|
98376
|
+
const r = stepRenderer(target);
|
|
98170
98377
|
return new Promise((resolve) => {
|
|
98171
|
-
const
|
|
98172
|
-
|
|
98173
|
-
|
|
98378
|
+
const surface = openStepSurface(otui, target, {
|
|
98379
|
+
id: "search-field-picker",
|
|
98380
|
+
title: field.label,
|
|
98381
|
+
tab: field.required ? "Required" : "Optional",
|
|
98382
|
+
hint: `${field.required ? "required" : "optional"} \xB7 Enter \xB7 Esc to go back`,
|
|
98383
|
+
footer: inputStepFooter("back"),
|
|
98384
|
+
contentRows: 2,
|
|
98385
|
+
onEscape: () => {
|
|
98386
|
+
input.blur();
|
|
98387
|
+
resolve({ kind: "back" });
|
|
98388
|
+
}
|
|
98389
|
+
});
|
|
98174
98390
|
const input = new otui.InputRenderable(r, { id: "sf-input", value, marginTop: 1 });
|
|
98175
|
-
|
|
98391
|
+
surface.body.add(input);
|
|
98176
98392
|
input.focus();
|
|
98177
98393
|
const cleanup = () => {
|
|
98178
|
-
unsub();
|
|
98179
98394
|
input.blur();
|
|
98180
|
-
|
|
98395
|
+
surface.close();
|
|
98181
98396
|
};
|
|
98182
|
-
const unsub = onKeypress4(r, (key) => {
|
|
98183
|
-
if (key.name === "escape") {
|
|
98184
|
-
cleanup();
|
|
98185
|
-
resolve({ kind: "back" });
|
|
98186
|
-
key.preventDefault();
|
|
98187
|
-
key.stopPropagation();
|
|
98188
|
-
}
|
|
98189
|
-
});
|
|
98190
98397
|
input.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98191
98398
|
const entered = input.value.trim();
|
|
98192
98399
|
cleanup();
|
|
@@ -98194,32 +98401,33 @@ function promptSearchFieldStep(otui, r, field, value) {
|
|
|
98194
98401
|
});
|
|
98195
98402
|
});
|
|
98196
98403
|
}
|
|
98197
|
-
function promptSearchCredentialStep(otui,
|
|
98404
|
+
function promptSearchCredentialStep(otui, target, opts) {
|
|
98405
|
+
const r = stepRenderer(target);
|
|
98198
98406
|
return new Promise((resolve) => {
|
|
98199
|
-
const
|
|
98200
|
-
|
|
98201
|
-
|
|
98202
|
-
|
|
98407
|
+
const surface = openStepSurface(otui, target, {
|
|
98408
|
+
id: "search-credential-picker",
|
|
98409
|
+
title: `Paste your ${opts.label}`,
|
|
98410
|
+
tab: "Credential",
|
|
98411
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
98412
|
+
footer: inputStepFooter("back"),
|
|
98413
|
+
contentRows: 4,
|
|
98414
|
+
onEscape: () => {
|
|
98415
|
+
keyInput.blur();
|
|
98416
|
+
resolve({ kind: "back" });
|
|
98417
|
+
}
|
|
98418
|
+
});
|
|
98419
|
+
surface.body.add(new otui.TextRenderable(r, {
|
|
98203
98420
|
id: "sc-note",
|
|
98204
98421
|
content: otui.t`${otui.dim("Saved to your keryx config dir (owner-only, 0600)")}`,
|
|
98205
98422
|
marginTop: 1
|
|
98206
98423
|
}));
|
|
98207
98424
|
const keyInput = new otui.InputRenderable(r, { id: "sc-input", placeholder: "...", marginTop: 1 });
|
|
98208
|
-
|
|
98425
|
+
surface.body.add(keyInput);
|
|
98209
98426
|
keyInput.focus();
|
|
98210
98427
|
const cleanup = () => {
|
|
98211
|
-
unsub();
|
|
98212
98428
|
keyInput.blur();
|
|
98213
|
-
|
|
98429
|
+
surface.close();
|
|
98214
98430
|
};
|
|
98215
|
-
const unsub = onKeypress4(r, (key) => {
|
|
98216
|
-
if (key.name === "escape") {
|
|
98217
|
-
cleanup();
|
|
98218
|
-
resolve({ kind: "back" });
|
|
98219
|
-
key.preventDefault();
|
|
98220
|
-
key.stopPropagation();
|
|
98221
|
-
}
|
|
98222
|
-
});
|
|
98223
98431
|
keyInput.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98224
98432
|
const value = keyInput.value.trim();
|
|
98225
98433
|
cleanup();
|
|
@@ -98227,14 +98435,24 @@ function promptSearchCredentialStep(otui, r, opts) {
|
|
|
98227
98435
|
});
|
|
98228
98436
|
});
|
|
98229
98437
|
}
|
|
98230
|
-
function promptSetActiveProviderStep(otui,
|
|
98438
|
+
function promptSetActiveProviderStep(otui, target) {
|
|
98439
|
+
const r = stepRenderer(target);
|
|
98231
98440
|
return new Promise((resolve) => {
|
|
98232
|
-
const
|
|
98233
|
-
|
|
98234
|
-
|
|
98441
|
+
const surface = openStepSurface(otui, target, {
|
|
98442
|
+
id: "search-active-picker",
|
|
98443
|
+
title: "Set as active provider after a successful test?",
|
|
98444
|
+
tab: "Active",
|
|
98445
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to go back)",
|
|
98446
|
+
footer: selectStepFooter("back"),
|
|
98447
|
+
contentRows: selectBoxHeight(2, true),
|
|
98448
|
+
onEscape: () => {
|
|
98449
|
+
select.blur();
|
|
98450
|
+
resolve(undefined);
|
|
98451
|
+
}
|
|
98452
|
+
});
|
|
98235
98453
|
const select = new otui.SelectRenderable(r, {
|
|
98236
98454
|
id: "sa-select",
|
|
98237
|
-
width: 60,
|
|
98455
|
+
width: surface.modal ? "100%" : 60,
|
|
98238
98456
|
height: selectBoxHeight(2, true),
|
|
98239
98457
|
options: [
|
|
98240
98458
|
{ name: "Yes", description: "select it once the test passes" },
|
|
@@ -98242,21 +98460,12 @@ function promptSetActiveProviderStep(otui, r) {
|
|
|
98242
98460
|
],
|
|
98243
98461
|
selectedTextColor: "#ffd166"
|
|
98244
98462
|
});
|
|
98245
|
-
|
|
98463
|
+
surface.body.add(select);
|
|
98246
98464
|
select.focus();
|
|
98247
98465
|
const cleanup = () => {
|
|
98248
|
-
unsub();
|
|
98249
98466
|
select.blur();
|
|
98250
|
-
|
|
98467
|
+
surface.close();
|
|
98251
98468
|
};
|
|
98252
|
-
const unsub = onKeypress4(r, (key) => {
|
|
98253
|
-
if (key.name === "escape") {
|
|
98254
|
-
cleanup();
|
|
98255
|
-
resolve(undefined);
|
|
98256
|
-
key.preventDefault();
|
|
98257
|
-
key.stopPropagation();
|
|
98258
|
-
}
|
|
98259
|
-
});
|
|
98260
98469
|
select.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98261
98470
|
const chosen = select.getSelectedOption();
|
|
98262
98471
|
cleanup();
|
|
@@ -98264,35 +98473,36 @@ function promptSetActiveProviderStep(otui, r) {
|
|
|
98264
98473
|
});
|
|
98265
98474
|
});
|
|
98266
98475
|
}
|
|
98267
|
-
function pickSearchProviderStep(otui,
|
|
98476
|
+
function pickSearchProviderStep(otui, target, providers) {
|
|
98477
|
+
const r = stepRenderer(target);
|
|
98268
98478
|
return new Promise((resolve) => {
|
|
98269
|
-
const
|
|
98270
|
-
|
|
98271
|
-
|
|
98479
|
+
const surface = openStepSurface(otui, target, {
|
|
98480
|
+
id: "search-provider-picker",
|
|
98481
|
+
title: "Select a search provider",
|
|
98482
|
+
tab: "Search providers",
|
|
98483
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to cancel)",
|
|
98484
|
+
footer: selectStepFooter("cancel"),
|
|
98485
|
+
contentRows: selectBoxHeight(providers.length, true),
|
|
98486
|
+
onEscape: () => {
|
|
98487
|
+
select.blur();
|
|
98488
|
+
resolve(undefined);
|
|
98489
|
+
}
|
|
98490
|
+
});
|
|
98272
98491
|
const labelOf = (p) => `${p.id} (${p.displayName})`;
|
|
98273
98492
|
const select = new otui.SelectRenderable(r, {
|
|
98274
98493
|
id: "spp-select",
|
|
98275
|
-
width: 60,
|
|
98494
|
+
width: surface.modal ? "100%" : 60,
|
|
98276
98495
|
height: selectBoxHeight(providers.length, true),
|
|
98277
98496
|
showScrollIndicator: true,
|
|
98278
98497
|
options: providers.map((p) => ({ name: labelOf(p), description: p.kind })),
|
|
98279
98498
|
selectedTextColor: "#ffd166"
|
|
98280
98499
|
});
|
|
98281
|
-
|
|
98500
|
+
surface.body.add(select);
|
|
98282
98501
|
select.focus();
|
|
98283
98502
|
const cleanup = () => {
|
|
98284
|
-
unsub();
|
|
98285
98503
|
select.blur();
|
|
98286
|
-
|
|
98504
|
+
surface.close();
|
|
98287
98505
|
};
|
|
98288
|
-
const unsub = onKeypress4(r, (key) => {
|
|
98289
|
-
if (key.name === "escape") {
|
|
98290
|
-
cleanup();
|
|
98291
|
-
resolve(undefined);
|
|
98292
|
-
key.preventDefault();
|
|
98293
|
-
key.stopPropagation();
|
|
98294
|
-
}
|
|
98295
|
-
});
|
|
98296
98506
|
select.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98297
98507
|
const chosen = select.getSelectedOption();
|
|
98298
98508
|
cleanup();
|
|
@@ -98352,19 +98562,46 @@ async function runSearchProviderFieldsStep(otui, r, provider, seed) {
|
|
|
98352
98562
|
}
|
|
98353
98563
|
return { kind: "done", fields, credential, setActive };
|
|
98354
98564
|
}
|
|
98355
|
-
function runSearchProviderTestStep(otui,
|
|
98565
|
+
function runSearchProviderTestStep(otui, target, controller, provider, fields, credential, setActive) {
|
|
98566
|
+
const r = stepRenderer(target);
|
|
98356
98567
|
return new Promise((resolve) => {
|
|
98357
|
-
|
|
98358
|
-
|
|
98568
|
+
let settled;
|
|
98569
|
+
let left = false;
|
|
98570
|
+
const modal = isModalChrome(target);
|
|
98571
|
+
let surface;
|
|
98572
|
+
if (modal) {
|
|
98573
|
+
surface = openStepSurface(otui, target, {
|
|
98574
|
+
id: "search-test-picker",
|
|
98575
|
+
title: `Test '${provider.id}'`,
|
|
98576
|
+
tab: "Test",
|
|
98577
|
+
hint: "",
|
|
98578
|
+
footer: [
|
|
98579
|
+
{ key: "Enter", label: "close after success" },
|
|
98580
|
+
{ key: "esc", label: "back" }
|
|
98581
|
+
],
|
|
98582
|
+
contentRows: 2,
|
|
98583
|
+
onEscape: () => {
|
|
98584
|
+
left = true;
|
|
98585
|
+
unsub();
|
|
98586
|
+
resolve(settled === "success" ? "done" : "retry");
|
|
98587
|
+
}
|
|
98588
|
+
});
|
|
98589
|
+
}
|
|
98590
|
+
const box = surface?.body ?? overlayBox(otui, r, "search-test-picker");
|
|
98591
|
+
if (surface === undefined)
|
|
98592
|
+
r.root.add(box);
|
|
98359
98593
|
const status = new otui.TextRenderable(r, { id: "st-title", content: otui.t`${otui.bold(`Testing '${provider.id}'`)} ${otui.dim("...")}` });
|
|
98360
98594
|
box.add(status);
|
|
98361
|
-
let settled;
|
|
98362
98595
|
const cleanup = () => {
|
|
98596
|
+
left = true;
|
|
98363
98597
|
unsub();
|
|
98364
|
-
|
|
98598
|
+
if (surface !== undefined)
|
|
98599
|
+
surface.close();
|
|
98600
|
+
else
|
|
98601
|
+
r.root.remove(box);
|
|
98365
98602
|
};
|
|
98366
98603
|
const unsub = onKeypress4(r, (key) => {
|
|
98367
|
-
if (settled === "failure" && key.name === "escape") {
|
|
98604
|
+
if (!modal && settled === "failure" && key.name === "escape") {
|
|
98368
98605
|
cleanup();
|
|
98369
98606
|
resolve("retry");
|
|
98370
98607
|
key.preventDefault();
|
|
@@ -98379,6 +98616,9 @@ function runSearchProviderTestStep(otui, r, controller, provider, fields, creden
|
|
|
98379
98616
|
(async () => {
|
|
98380
98617
|
controller.configure(provider.id, { ...provider.defaults, ...fields }, credential);
|
|
98381
98618
|
const tested = await controller.test(provider.id);
|
|
98619
|
+
if (left) {
|
|
98620
|
+
return;
|
|
98621
|
+
}
|
|
98382
98622
|
if (!tested.ok) {
|
|
98383
98623
|
settled = "failure";
|
|
98384
98624
|
const reason = tested.reason === "missing-credential" ? "missing credential" : "connection validation failed";
|
|
@@ -98391,6 +98631,9 @@ function runSearchProviderTestStep(otui, r, controller, provider, fields, creden
|
|
|
98391
98631
|
return;
|
|
98392
98632
|
}
|
|
98393
98633
|
const selected = await controller.select(provider.id);
|
|
98634
|
+
if (left) {
|
|
98635
|
+
return;
|
|
98636
|
+
}
|
|
98394
98637
|
status.content = selected.ok ? otui.t`${otui.green("\u2713")} ${otui.bold(`'${provider.id}' configured, tested, and set as active`)} ${otui.dim("(Enter to close)")}` : otui.t`${otui.green("\u2713")} ${otui.bold(`'${provider.id}' configured and tested`)} ${otui.dim(`but could not be set active (${selected.reason ?? "unknown"})`)} ${otui.dim("(Enter to close)")}`;
|
|
98395
98638
|
})();
|
|
98396
98639
|
});
|
|
@@ -98417,11 +98660,22 @@ async function searchProviderWizardInTui(otui, r, controller) {
|
|
|
98417
98660
|
}
|
|
98418
98661
|
}
|
|
98419
98662
|
}
|
|
98420
|
-
function promptBaseUrlStep(otui,
|
|
98663
|
+
function promptBaseUrlStep(otui, target, label, baseUrl, notice) {
|
|
98664
|
+
const r = stepRenderer(target);
|
|
98421
98665
|
return new Promise((resolve) => {
|
|
98422
|
-
const
|
|
98423
|
-
|
|
98424
|
-
|
|
98666
|
+
const surface = openStepSurface(otui, target, {
|
|
98667
|
+
id: "base-url-picker",
|
|
98668
|
+
title: `${label} endpoint URL`,
|
|
98669
|
+
tab: "Endpoint",
|
|
98670
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
98671
|
+
footer: inputStepFooter("back"),
|
|
98672
|
+
contentRows: notice !== undefined ? 6 : 4,
|
|
98673
|
+
onEscape: () => {
|
|
98674
|
+
input.blur();
|
|
98675
|
+
resolve(undefined);
|
|
98676
|
+
}
|
|
98677
|
+
});
|
|
98678
|
+
const box = surface.body;
|
|
98425
98679
|
if (notice !== undefined) {
|
|
98426
98680
|
box.add(new otui.TextRenderable(r, { id: "bp-notice", content: otui.t`${otui.red("\u2717")} ${notice}`, marginTop: 1 }));
|
|
98427
98681
|
}
|
|
@@ -98430,17 +98684,9 @@ function promptBaseUrlStep(otui, r, label, baseUrl, notice) {
|
|
|
98430
98684
|
box.add(input);
|
|
98431
98685
|
input.focus();
|
|
98432
98686
|
const cleanup = () => {
|
|
98433
|
-
|
|
98434
|
-
|
|
98687
|
+
input.blur();
|
|
98688
|
+
surface.close();
|
|
98435
98689
|
};
|
|
98436
|
-
const unsub = onKeypress4(r, (key) => {
|
|
98437
|
-
if (key.name === "escape") {
|
|
98438
|
-
cleanup();
|
|
98439
|
-
resolve(undefined);
|
|
98440
|
-
key.preventDefault();
|
|
98441
|
-
key.stopPropagation();
|
|
98442
|
-
}
|
|
98443
|
-
});
|
|
98444
98690
|
input.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98445
98691
|
const value = input.value.trim();
|
|
98446
98692
|
cleanup();
|
|
@@ -98448,11 +98694,25 @@ function promptBaseUrlStep(otui, r, label, baseUrl, notice) {
|
|
|
98448
98694
|
});
|
|
98449
98695
|
});
|
|
98450
98696
|
}
|
|
98451
|
-
function promptApiKeyStep(otui,
|
|
98697
|
+
function promptApiKeyStep(otui, target, opts) {
|
|
98698
|
+
const r = stepRenderer(target);
|
|
98452
98699
|
return new Promise((resolve) => {
|
|
98453
|
-
const
|
|
98454
|
-
|
|
98455
|
-
|
|
98700
|
+
const surface = openStepSurface(otui, target, {
|
|
98701
|
+
id: "key-picker",
|
|
98702
|
+
title: `Paste your ${opts.label} API key`,
|
|
98703
|
+
tab: "API key",
|
|
98704
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
98705
|
+
footer: [
|
|
98706
|
+
{ key: "Enter", label: "save (empty = skip)" },
|
|
98707
|
+
{ key: "esc", label: "back" }
|
|
98708
|
+
],
|
|
98709
|
+
contentRows: opts.notice !== undefined ? 6 : 4,
|
|
98710
|
+
onEscape: () => {
|
|
98711
|
+
keyInput.blur();
|
|
98712
|
+
resolve({ kind: "back" });
|
|
98713
|
+
}
|
|
98714
|
+
});
|
|
98715
|
+
const box = surface.body;
|
|
98456
98716
|
if (opts.notice !== undefined) {
|
|
98457
98717
|
box.add(new otui.TextRenderable(r, { id: "kp-notice", content: otui.t`${otui.red("\u2717")} ${opts.notice}`, marginTop: 1 }));
|
|
98458
98718
|
}
|
|
@@ -98464,18 +98724,9 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
98464
98724
|
const keyInput = new otui.InputRenderable(r, { id: "kp-input", placeholder: opts.placeholder ?? "sk-...", marginTop: 1 });
|
|
98465
98725
|
box.add(keyInput);
|
|
98466
98726
|
keyInput.focus();
|
|
98467
|
-
const onKey = (key) => {
|
|
98468
|
-
if (key.name === "escape") {
|
|
98469
|
-
cleanup();
|
|
98470
|
-
resolve({ kind: "back" });
|
|
98471
|
-
key.preventDefault();
|
|
98472
|
-
key.stopPropagation();
|
|
98473
|
-
}
|
|
98474
|
-
};
|
|
98475
|
-
const unsub = onKeypress4(r, onKey);
|
|
98476
98727
|
const cleanup = () => {
|
|
98477
|
-
|
|
98478
|
-
|
|
98728
|
+
keyInput.blur();
|
|
98729
|
+
surface.close();
|
|
98479
98730
|
};
|
|
98480
98731
|
keyInput.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98481
98732
|
const value = keyInput.value.trim();
|
|
@@ -98484,38 +98735,39 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
98484
98735
|
});
|
|
98485
98736
|
});
|
|
98486
98737
|
}
|
|
98487
|
-
function pickAuthMethodStep(otui,
|
|
98738
|
+
function pickAuthMethodStep(otui, target, providerLabel, methods) {
|
|
98739
|
+
const r = stepRenderer(target);
|
|
98488
98740
|
return new Promise((resolve) => {
|
|
98489
|
-
const
|
|
98490
|
-
|
|
98491
|
-
|
|
98741
|
+
const surface = openStepSurface(otui, target, {
|
|
98742
|
+
id: "auth-method-picker",
|
|
98743
|
+
title: `How to connect ${providerLabel}`,
|
|
98744
|
+
tab: "Sign-in",
|
|
98745
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to go back)",
|
|
98746
|
+
footer: selectStepFooter("back"),
|
|
98747
|
+
contentRows: selectBoxHeight(methods.length, true),
|
|
98748
|
+
onEscape: () => {
|
|
98749
|
+
select.blur();
|
|
98750
|
+
resolve(undefined);
|
|
98751
|
+
}
|
|
98752
|
+
});
|
|
98492
98753
|
const descriptions = {
|
|
98493
98754
|
"device-code": deviceCodeMethodLabel(providerLabel === "GitHub Copilot" ? "github-copilot" : providerLabel === "OpenAI" ? "openai" : "grok"),
|
|
98494
98755
|
"api-key": "Manually enter API Key"
|
|
98495
98756
|
};
|
|
98496
98757
|
const select = new otui.SelectRenderable(r, {
|
|
98497
98758
|
id: "amp-select",
|
|
98498
|
-
width: 60,
|
|
98759
|
+
width: surface.modal ? "100%" : 60,
|
|
98499
98760
|
height: selectBoxHeight(methods.length, true),
|
|
98500
98761
|
showScrollIndicator: true,
|
|
98501
98762
|
options: methods.map((m) => ({ name: m, description: descriptions[m] })),
|
|
98502
98763
|
selectedTextColor: "#ffd166"
|
|
98503
98764
|
});
|
|
98504
|
-
|
|
98765
|
+
surface.body.add(select);
|
|
98505
98766
|
select.focus();
|
|
98506
98767
|
const cleanup = () => {
|
|
98507
|
-
unsub();
|
|
98508
98768
|
select.blur();
|
|
98509
|
-
|
|
98769
|
+
surface.close();
|
|
98510
98770
|
};
|
|
98511
|
-
const unsub = onKeypress4(r, (key) => {
|
|
98512
|
-
if (key.name === "escape") {
|
|
98513
|
-
cleanup();
|
|
98514
|
-
resolve(undefined);
|
|
98515
|
-
key.preventDefault();
|
|
98516
|
-
key.stopPropagation();
|
|
98517
|
-
}
|
|
98518
|
-
});
|
|
98519
98771
|
select.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98520
98772
|
const chosen = select.getSelectedOption();
|
|
98521
98773
|
cleanup();
|
|
@@ -98523,30 +98775,27 @@ function pickAuthMethodStep(otui, r, providerLabel, methods) {
|
|
|
98523
98775
|
});
|
|
98524
98776
|
});
|
|
98525
98777
|
}
|
|
98526
|
-
function runDeviceLoginInTui(otui,
|
|
98778
|
+
function runDeviceLoginInTui(otui, target, provider, dir) {
|
|
98779
|
+
const r = stepRenderer(target);
|
|
98527
98780
|
return new Promise((resolve) => {
|
|
98528
|
-
const box = overlayBox(otui, r, "device-login");
|
|
98529
|
-
r.root.add(box);
|
|
98530
|
-
box.add(new otui.TextRenderable(r, {
|
|
98531
|
-
id: "dl-title",
|
|
98532
|
-
content: otui.t`${otui.bold(deviceCodeMethodLabel(provider))} ${otui.dim("(Esc to cancel)")}`
|
|
98533
|
-
}));
|
|
98534
|
-
const status = new otui.TextRenderable(r, { id: "dl-status", content: otui.t`${otui.dim("Requesting a device code\u2026")}`, marginTop: 1 });
|
|
98535
|
-
box.add(status);
|
|
98536
98781
|
const controller = new AbortController;
|
|
98537
|
-
const
|
|
98538
|
-
|
|
98539
|
-
|
|
98540
|
-
|
|
98541
|
-
|
|
98542
|
-
|
|
98782
|
+
const surface = openStepSurface(otui, target, {
|
|
98783
|
+
id: "device-login",
|
|
98784
|
+
title: deviceCodeMethodLabel(provider),
|
|
98785
|
+
tab: "Device login",
|
|
98786
|
+
hint: "(Esc to cancel)",
|
|
98787
|
+
footer: [{ key: "esc", label: "cancel" }],
|
|
98788
|
+
contentRows: 4,
|
|
98789
|
+
onEscape: () => {
|
|
98543
98790
|
controller.abort();
|
|
98544
|
-
cleanup();
|
|
98545
98791
|
resolve(false);
|
|
98546
|
-
key.preventDefault();
|
|
98547
|
-
key.stopPropagation();
|
|
98548
98792
|
}
|
|
98549
98793
|
});
|
|
98794
|
+
const status = new otui.TextRenderable(r, { id: "dl-status", content: otui.t`${otui.dim("Requesting a device code\u2026")}`, marginTop: 1 });
|
|
98795
|
+
surface.body.add(status);
|
|
98796
|
+
const cleanup = () => {
|
|
98797
|
+
surface.close();
|
|
98798
|
+
};
|
|
98550
98799
|
loginDeviceCode({
|
|
98551
98800
|
provider,
|
|
98552
98801
|
fetch: (input, init) => globalThis.fetch(input, init),
|
|
@@ -98588,15 +98837,26 @@ function modelPickerNotice(label, result) {
|
|
|
98588
98837
|
}
|
|
98589
98838
|
return modelsFailureLine(label, result.failure);
|
|
98590
98839
|
}
|
|
98591
|
-
function pickProviderStep(otui,
|
|
98840
|
+
function pickProviderStep(otui, target, detected) {
|
|
98841
|
+
const r = stepRenderer(target);
|
|
98592
98842
|
return new Promise((resolve) => {
|
|
98593
|
-
const
|
|
98594
|
-
|
|
98595
|
-
|
|
98843
|
+
const surface = openStepSurface(otui, target, {
|
|
98844
|
+
id: "picker",
|
|
98845
|
+
title: "Select a provider",
|
|
98846
|
+
tab: "Providers",
|
|
98847
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to cancel)",
|
|
98848
|
+
footer: selectStepFooter("cancel"),
|
|
98849
|
+
contentRows: selectBoxHeight(detected.length, true),
|
|
98850
|
+
onEscape: () => {
|
|
98851
|
+
provSelect.blur();
|
|
98852
|
+
resolve(undefined);
|
|
98853
|
+
}
|
|
98854
|
+
});
|
|
98855
|
+
const box = surface.body;
|
|
98596
98856
|
const labelOf = (d) => d.label ?? d.name;
|
|
98597
98857
|
const provSelect = new otui.SelectRenderable(r, {
|
|
98598
98858
|
id: "picker-provider",
|
|
98599
|
-
width: 60,
|
|
98859
|
+
width: surface.modal ? "100%" : 60,
|
|
98600
98860
|
height: selectBoxHeight(detected.length, true),
|
|
98601
98861
|
showScrollIndicator: true,
|
|
98602
98862
|
options: detected.map((d) => ({ name: labelOf(d), description: d.note ?? `${d.models.length} model(s)` })),
|
|
@@ -98604,18 +98864,9 @@ function pickProviderStep(otui, r, detected) {
|
|
|
98604
98864
|
});
|
|
98605
98865
|
box.add(provSelect);
|
|
98606
98866
|
provSelect.focus();
|
|
98607
|
-
const onKey = (key) => {
|
|
98608
|
-
if (key.name === "escape") {
|
|
98609
|
-
cleanup();
|
|
98610
|
-
resolve(undefined);
|
|
98611
|
-
key.preventDefault();
|
|
98612
|
-
key.stopPropagation();
|
|
98613
|
-
}
|
|
98614
|
-
};
|
|
98615
|
-
const unsub = onKeypress4(r, onKey);
|
|
98616
98867
|
const cleanup = () => {
|
|
98617
|
-
|
|
98618
|
-
|
|
98868
|
+
provSelect.blur();
|
|
98869
|
+
surface.close();
|
|
98619
98870
|
};
|
|
98620
98871
|
provSelect.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98621
98872
|
const chosen = provSelect.getSelectedOption();
|
|
@@ -98624,12 +98875,7 @@ function pickProviderStep(otui, r, detected) {
|
|
|
98624
98875
|
});
|
|
98625
98876
|
});
|
|
98626
98877
|
}
|
|
98627
|
-
function isModalChrome(target) {
|
|
98628
|
-
return target !== null && typeof target === "object" && "renderer" in target && "focusComposer" in target;
|
|
98629
|
-
}
|
|
98630
98878
|
function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
98631
|
-
const chrome = isModalChrome(rOrChrome) ? rOrChrome : undefined;
|
|
98632
|
-
const r = chrome !== undefined ? chrome.renderer : rOrChrome;
|
|
98633
98879
|
return new Promise((resolve) => {
|
|
98634
98880
|
if (detected.length === 0) {
|
|
98635
98881
|
resolve(undefined);
|
|
@@ -98647,13 +98893,13 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98647
98893
|
}
|
|
98648
98894
|
const allCandidates = options.onlyConnected ? candidates : [...candidates, CUSTOM_ADD_ENTRY];
|
|
98649
98895
|
while (true) {
|
|
98650
|
-
const prov = await pickProviderStep(otui,
|
|
98896
|
+
const prov = await pickProviderStep(otui, rOrChrome, allCandidates);
|
|
98651
98897
|
if (prov === undefined) {
|
|
98652
98898
|
resolve(undefined);
|
|
98653
98899
|
return;
|
|
98654
98900
|
}
|
|
98655
98901
|
if (prov.name === CUSTOM_PROVIDER_ADD_ID) {
|
|
98656
|
-
const created = await promptCustomProviderWizard(otui,
|
|
98902
|
+
const created = await promptCustomProviderWizard(otui, rOrChrome);
|
|
98657
98903
|
if (created !== undefined) {
|
|
98658
98904
|
saveCustomCompatProvider({
|
|
98659
98905
|
name: created.name,
|
|
@@ -98677,7 +98923,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98677
98923
|
continue;
|
|
98678
98924
|
}
|
|
98679
98925
|
const lockDiscoveredHost = prov.name === "github-copilot";
|
|
98680
|
-
let selectedBaseUrl = options.onlyConnected || prov.baseUrl === undefined || lockDiscoveredHost ? prov.baseUrl : await promptBaseUrlStep(otui,
|
|
98926
|
+
let selectedBaseUrl = options.onlyConnected || prov.baseUrl === undefined || lockDiscoveredHost ? prov.baseUrl : await promptBaseUrlStep(otui, rOrChrome, prov.label ?? prov.name, prov.baseUrl);
|
|
98681
98927
|
if (!options.onlyConnected && !lockDiscoveredHost && prov.baseUrl !== undefined && selectedBaseUrl === undefined) {
|
|
98682
98928
|
continue;
|
|
98683
98929
|
}
|
|
@@ -98705,13 +98951,13 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98705
98951
|
offered.push("api-key");
|
|
98706
98952
|
let method = offered.length === 1 ? offered[0] : undefined;
|
|
98707
98953
|
if (offered.length > 1) {
|
|
98708
|
-
method = await pickAuthMethodStep(otui,
|
|
98954
|
+
method = await pickAuthMethodStep(otui, rOrChrome, label, offered);
|
|
98709
98955
|
if (method === undefined) {
|
|
98710
98956
|
return "back";
|
|
98711
98957
|
}
|
|
98712
98958
|
}
|
|
98713
98959
|
if (method === "device-code") {
|
|
98714
|
-
if (!await runDeviceLoginInTui(otui,
|
|
98960
|
+
if (!await runDeviceLoginInTui(otui, rOrChrome, prov.name, options.configDir)) {
|
|
98715
98961
|
return "back";
|
|
98716
98962
|
}
|
|
98717
98963
|
const saved = loadShellConfig(options.configDir).baseUrls?.[prov.name];
|
|
@@ -98721,7 +98967,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98721
98967
|
}
|
|
98722
98968
|
return "ok";
|
|
98723
98969
|
}
|
|
98724
|
-
const kr = await promptApiKeyStep(otui,
|
|
98970
|
+
const kr = await promptApiKeyStep(otui, rOrChrome, {
|
|
98725
98971
|
label,
|
|
98726
98972
|
envKey,
|
|
98727
98973
|
...notice === undefined ? {} : { notice }
|
|
@@ -98751,7 +98997,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98751
98997
|
models = await modelsForPicker(selectedProvider, modelDeps);
|
|
98752
98998
|
}
|
|
98753
98999
|
if (!options.onlyConnected && selectedProvider.baseUrl !== undefined && endpointMayBeAtFault(models.failure)) {
|
|
98754
|
-
const corrected = await promptBaseUrlStep(otui,
|
|
99000
|
+
const corrected = await promptBaseUrlStep(otui, rOrChrome, label, selectedProvider.baseUrl, modelsFailureLine(label, models.failure));
|
|
98755
99001
|
if (corrected === undefined) {
|
|
98756
99002
|
continue;
|
|
98757
99003
|
}
|
|
@@ -98762,7 +99008,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98762
99008
|
models = await modelsForPicker(selectedProvider, modelDeps);
|
|
98763
99009
|
}
|
|
98764
99010
|
}
|
|
98765
|
-
const model = await pickModelInTui(otui,
|
|
99011
|
+
const model = await pickModelInTui(otui, rOrChrome, models.models, modelPickerNotice(label, models), {
|
|
98766
99012
|
escLabel: "back"
|
|
98767
99013
|
});
|
|
98768
99014
|
if (model === undefined) {
|
|
@@ -98998,6 +99244,9 @@ function pickSessionInTui(otui, rOrChrome, sessions) {
|
|
|
98998
99244
|
});
|
|
98999
99245
|
});
|
|
99000
99246
|
}
|
|
99247
|
+
function describeModeRow(mode, readOnly) {
|
|
99248
|
+
return readOnly ? { mode, readOnly: "\xB7 read-only" } : { mode };
|
|
99249
|
+
}
|
|
99001
99250
|
var MODE_PICKER_DESCRIPTIONS = {
|
|
99002
99251
|
ask: "Every mutating action asks first (today's default)",
|
|
99003
99252
|
trust: "Auto-approves safe actions; still asks for destructive/credential ones",
|
|
@@ -99109,6 +99358,8 @@ async function launchTuiAgentShell(opts) {
|
|
|
99109
99358
|
sidebar.add(new otui.TextRenderable(r, { id: "sb-model-k", content: otui.t`${otui.dim("Model")}`, marginTop: 1 }));
|
|
99110
99359
|
const sbModelV = new otui.TextRenderable(r, { id: "sb-model-v", content: otui.t`${otui.dim(`${sel.provider}/${sel.model}`)}` });
|
|
99111
99360
|
sidebar.add(sbModelV);
|
|
99361
|
+
const sbModeV = new otui.TextRenderable(r, { id: "sb-mode-v", content: "" });
|
|
99362
|
+
sidebar.add(sbModeV);
|
|
99112
99363
|
sidebar.add(new otui.TextRenderable(r, { id: "sb-usage-k", content: otui.t`${otui.dim("Usage")}`, marginTop: 1 }));
|
|
99113
99364
|
const sbUsageV = new otui.TextRenderable(r, { id: "sb-usage-v", content: otui.t`${otui.dim("\u21910 \u21930")}` });
|
|
99114
99365
|
sidebar.add(sbUsageV);
|
|
@@ -99725,6 +99976,11 @@ async function launchTuiAgentShell(opts) {
|
|
|
99725
99976
|
io.permissionMode = () => permissionMode;
|
|
99726
99977
|
let readOnly = false;
|
|
99727
99978
|
io.readOnly = () => readOnly;
|
|
99979
|
+
const paintModeRow = () => {
|
|
99980
|
+
const row = describeModeRow(permissionMode, readOnly);
|
|
99981
|
+
sbModeV.content = row.readOnly === undefined ? otui.t`${otui.dim(`mode ${row.mode}`)}` : otui.t`${otui.dim(`mode ${row.mode}`)} ${otui.yellow(row.readOnly)}`;
|
|
99982
|
+
};
|
|
99983
|
+
paintModeRow();
|
|
99728
99984
|
io.onAutoApproved = (tool, input, meta) => {
|
|
99729
99985
|
const preview = tool === "shell_exec" ? parseShellExecCommand(input) : tool;
|
|
99730
99986
|
const label = meta.destructive ? `\u25C7 auto-approved (${permissionMode}) [destructive]` : `\u25C7 auto-approved (${permissionMode})`;
|
|
@@ -99752,7 +100008,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
99752
100008
|
};
|
|
99753
100009
|
deps = { ...deps, onContextCompaction };
|
|
99754
100010
|
liveDeps = deps;
|
|
100011
|
+
let removeSplash;
|
|
99755
100012
|
const applyOpened = (opened, previewHistory) => {
|
|
100013
|
+
if (opened.history.length > 0) {
|
|
100014
|
+
removeSplash?.();
|
|
100015
|
+
removeSplash = undefined;
|
|
100016
|
+
}
|
|
99756
100017
|
liveSession = opened.handle;
|
|
99757
100018
|
history = previewHistory === true ? opened.history.slice(-SESSION_PREVIEW_MESSAGE_COUNT) : opened.history;
|
|
99758
100019
|
archive = opened.archive.length > 0 ? [...opened.archive] : [...opened.history];
|
|
@@ -99868,6 +100129,9 @@ async function launchTuiAgentShell(opts) {
|
|
|
99868
100129
|
}));
|
|
99869
100130
|
}
|
|
99870
100131
|
slateSession = { dir: liveSession.dir, cwd: sessionCwd, opened: false };
|
|
100132
|
+
if (history.length === 0) {
|
|
100133
|
+
removeSplash = mountEmptyTranscriptSplash(otui, r, transcript);
|
|
100134
|
+
}
|
|
99871
100135
|
refreshWorkspaceSidebar();
|
|
99872
100136
|
refreshReviewSidebar();
|
|
99873
100137
|
const paintSessionHeader = () => {
|
|
@@ -100164,6 +100428,7 @@ Staying in the current session.
|
|
|
100164
100428
|
}
|
|
100165
100429
|
}
|
|
100166
100430
|
permissionMode = next;
|
|
100431
|
+
paintModeRow();
|
|
100167
100432
|
chrome.showToast(`Permission mode: ${next}`);
|
|
100168
100433
|
if (saveFlag) {
|
|
100169
100434
|
const saved = setProjectPermissionMode(sessionCwd, next);
|
|
@@ -100221,11 +100486,13 @@ Staying in the current session.
|
|
|
100221
100486
|
}
|
|
100222
100487
|
if (wanted === "on") {
|
|
100223
100488
|
readOnly = true;
|
|
100489
|
+
paintModeRow();
|
|
100224
100490
|
chrome.showToast("Read-only mode: on");
|
|
100225
100491
|
return;
|
|
100226
100492
|
}
|
|
100227
100493
|
if (wanted === "off") {
|
|
100228
100494
|
readOnly = false;
|
|
100495
|
+
paintModeRow();
|
|
100229
100496
|
chrome.showToast(`Read-only mode: off (permission mode stays: ${permissionMode})`);
|
|
100230
100497
|
return;
|
|
100231
100498
|
}
|
|
@@ -100605,6 +100872,8 @@ Staying in the current session.
|
|
|
100605
100872
|
suggestionGate.cancel("new turn started");
|
|
100606
100873
|
if (origin === "operator") {
|
|
100607
100874
|
consecutiveAutoWakes = 0;
|
|
100875
|
+
removeSplash?.();
|
|
100876
|
+
removeSplash = undefined;
|
|
100608
100877
|
}
|
|
100609
100878
|
const displayLine = summarizeSubmittedLine(line);
|
|
100610
100879
|
if (chrome.isBusy()) {
|
|
@@ -100910,7 +101179,7 @@ Staying in the current session.
|
|
|
100910
101179
|
const args = parseSearchProviderArgs(line.slice(16));
|
|
100911
101180
|
const all = searchProviderController.configurable();
|
|
100912
101181
|
if (args.providerId === undefined) {
|
|
100913
|
-
await chrome.withOverlay(() => searchProviderWizardInTui(otui,
|
|
101182
|
+
await chrome.withOverlay(() => searchProviderWizardInTui(otui, chrome, searchProviderController));
|
|
100914
101183
|
input.focus();
|
|
100915
101184
|
return;
|
|
100916
101185
|
}
|
|
@@ -100946,7 +101215,7 @@ Staying in the current session.
|
|
|
100946
101215
|
`);
|
|
100947
101216
|
return;
|
|
100948
101217
|
}
|
|
100949
|
-
const picked = await chrome.withOverlay(() => pickSearchProviderStep(otui,
|
|
101218
|
+
const picked = await chrome.withOverlay(() => pickSearchProviderStep(otui, chrome, selectable));
|
|
100950
101219
|
input.focus();
|
|
100951
101220
|
if (picked === undefined) {
|
|
100952
101221
|
return;
|
|
@@ -101136,12 +101405,10 @@ Usage: /reasoning <${REASONING_EFFORT_LEVELS.join("|")}>
|
|
|
101136
101405
|
const ns = await chrome.withOverlay(() => command.name === "/connect" ? selectProviderModelInTui(otui, chrome, detected, { onlyConnected: true, env: process.env }) : selectProviderModelInTui(otui, chrome, detected));
|
|
101137
101406
|
if (ns !== undefined) {
|
|
101138
101407
|
await switchTo(ns);
|
|
101139
|
-
} else {
|
|
101140
|
-
|
|
101141
|
-
chrome.showToast("No connected providers found. Run /provider to configure one first.");
|
|
101142
|
-
}
|
|
101143
|
-
input.focus();
|
|
101408
|
+
} else if (command.name === "/connect") {
|
|
101409
|
+
chrome.showToast("No connected providers found. Run /provider to configure one first.");
|
|
101144
101410
|
}
|
|
101411
|
+
input.focus();
|
|
101145
101412
|
})();
|
|
101146
101413
|
return;
|
|
101147
101414
|
}
|
|
@@ -106956,7 +107223,7 @@ import { readFileSync as readFileSync9 } from "fs";
|
|
|
106956
107223
|
|
|
106957
107224
|
// src/agents/bootstrap.ts
|
|
106958
107225
|
import { mkdir as mkdir64, readFile as readFile101, writeFile as writeFile55 } from "fs/promises";
|
|
106959
|
-
import { homedir as
|
|
107226
|
+
import { homedir as homedir10 } from "os";
|
|
106960
107227
|
import path200 from "path";
|
|
106961
107228
|
init_fs();
|
|
106962
107229
|
var AGENT_BOOTSTRAP_START = "<!-- keryx:global-bootstrap -->";
|
|
@@ -107025,7 +107292,7 @@ function resolveAgentBootstrapRuntimes(ids) {
|
|
|
107025
107292
|
}
|
|
107026
107293
|
return { runtimes, unknown };
|
|
107027
107294
|
}
|
|
107028
|
-
async function agentBootstrapStatus(runtime, homeRoot =
|
|
107295
|
+
async function agentBootstrapStatus(runtime, homeRoot = homedir10()) {
|
|
107029
107296
|
const filePath = runtime.filePath(homeRoot);
|
|
107030
107297
|
const exists = await pathExists(filePath);
|
|
107031
107298
|
const content = exists ? await readFile101(filePath, "utf8") : "";
|
|
@@ -107035,7 +107302,7 @@ async function agentBootstrapStatus(runtime, homeRoot = homedir9()) {
|
|
|
107035
107302
|
return { runtime: runtime.id, label: runtime.label, filePath, exists, installed, current };
|
|
107036
107303
|
}
|
|
107037
107304
|
async function installAgentBootstrap(runtime, options = {}) {
|
|
107038
|
-
const homeRoot = options.homeRoot ??
|
|
107305
|
+
const homeRoot = options.homeRoot ?? homedir10();
|
|
107039
107306
|
const filePath = runtime.filePath(homeRoot);
|
|
107040
107307
|
const exists = await pathExists(filePath);
|
|
107041
107308
|
const current = exists ? await readFile101(filePath, "utf8") : "";
|
|
@@ -107050,7 +107317,7 @@ async function installAgentBootstrap(runtime, options = {}) {
|
|
|
107050
107317
|
return { ...status, wrote, dryRun };
|
|
107051
107318
|
}
|
|
107052
107319
|
async function uninstallAgentBootstrap(runtime, options = {}) {
|
|
107053
|
-
const homeRoot = options.homeRoot ??
|
|
107320
|
+
const homeRoot = options.homeRoot ?? homedir10();
|
|
107054
107321
|
const filePath = runtime.filePath(homeRoot);
|
|
107055
107322
|
const exists = await pathExists(filePath);
|
|
107056
107323
|
const current = exists ? await readFile101(filePath, "utf8") : "";
|