@mrciphersmith/keryx 0.2.117 → 0.2.119
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 +517 -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.119",
|
|
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,90 @@ 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
|
+
if (end < lineCounts.length && used < rows) {
|
|
91441
|
+
return { start: from, end: end + 1, lastLines: rows - used };
|
|
91442
|
+
}
|
|
91443
|
+
return { start: from, end };
|
|
91337
91444
|
}
|
|
91338
91445
|
function isActionable(id) {
|
|
91339
91446
|
return id !== "generic";
|
|
@@ -91348,7 +91455,7 @@ function formatOtherServers(otherServers) {
|
|
|
91348
91455
|
const list = rest > 0 ? `${shown.join(", ")}, +${rest} more` : shown.join(", ");
|
|
91349
91456
|
return ` \xB7 also has: ${list}`;
|
|
91350
91457
|
}
|
|
91351
|
-
function formatMcpRowLine(runtime, isSelected, status) {
|
|
91458
|
+
function formatMcpRowLine(runtime, isSelected, status, width) {
|
|
91352
91459
|
const mark = isSelected ? ">" : " ";
|
|
91353
91460
|
const label = runtimeLabel(runtime.id).padEnd(20);
|
|
91354
91461
|
const statusText = runtime.connected ? "\u25CF keryx connected" : "\u25CB keryx not connected";
|
|
@@ -91364,7 +91471,8 @@ function formatMcpRowLine(runtime, isSelected, status) {
|
|
|
91364
91471
|
} else {
|
|
91365
91472
|
action = runtime.connected ? " [d] disconnect" : " [c] connect";
|
|
91366
91473
|
}
|
|
91367
|
-
return `${mark} ${label}
|
|
91474
|
+
return wrapHangingRow(`${mark} ${label} `, `${statusText}${action}${formatOtherServers(runtime.otherServers)}`, width).join(`
|
|
91475
|
+
`);
|
|
91368
91476
|
}
|
|
91369
91477
|
function asRowTarget(body) {
|
|
91370
91478
|
const parent = body;
|
|
@@ -91388,6 +91496,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91388
91496
|
let rowCtor;
|
|
91389
91497
|
let activeRenderer;
|
|
91390
91498
|
let unsubscribeKey;
|
|
91499
|
+
let bodyWidth;
|
|
91391
91500
|
const rendererHint = options.renderer ?? chrome?.renderer;
|
|
91392
91501
|
const bodyRows = options.visibleRows ?? (typeof rendererHint?.width === "number" && typeof rendererHint.height === "number" ? modalBodyRows(resolveModalPanelSize(rendererHint.width, rendererHint.height).height) : 13);
|
|
91393
91502
|
const paintToolsRows = () => {
|
|
@@ -91400,11 +91509,25 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91400
91509
|
toolsBody.add(new rowCtor(activeRenderer, { id: "mcp-tools-empty", content: "No tools available." }));
|
|
91401
91510
|
return;
|
|
91402
91511
|
}
|
|
91403
|
-
|
|
91404
|
-
|
|
91405
|
-
|
|
91512
|
+
toolsBody.add(new rowCtor(activeRenderer, { id: "mcp-tools-columns", content: TOOLS_COLUMN_HEADER }));
|
|
91513
|
+
const rows = options.tools.map((tool) => formatToolRowLines(tool, bodyWidth));
|
|
91514
|
+
const window = toolsWindow(rows);
|
|
91515
|
+
toolsScroll = window.start;
|
|
91516
|
+
for (let index = window.start;index < window.end; index++) {
|
|
91517
|
+
const lines = rows[index] ?? [];
|
|
91518
|
+
const cut = index === window.end - 1 && window.lastLines !== undefined;
|
|
91519
|
+
toolsBody.add(new rowCtor(activeRenderer, {
|
|
91520
|
+
id: `mcp-tool-row-${index}`,
|
|
91521
|
+
content: (cut ? lines.slice(0, window.lastLines) : lines).join(`
|
|
91522
|
+
`)
|
|
91523
|
+
}));
|
|
91406
91524
|
}
|
|
91407
91525
|
};
|
|
91526
|
+
const toolsRowBudget = () => {
|
|
91527
|
+
const captionLines = wrapHangingRow("", TOOLS_TAB_HEADER, bodyWidth, 0).length;
|
|
91528
|
+
return Math.max(1, bodyRows - captionLines - 1);
|
|
91529
|
+
};
|
|
91530
|
+
const toolsWindow = (rows) => fitRowsByLines(rows.map((lines) => lines.length), toolsScroll, toolsRowBudget());
|
|
91408
91531
|
const paintMcpRows = () => {
|
|
91409
91532
|
if (mcpBody === undefined || rowCtor === undefined) {
|
|
91410
91533
|
return;
|
|
@@ -91416,18 +91539,19 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91416
91539
|
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-empty", content: "No MCP client runtimes registered." }));
|
|
91417
91540
|
return;
|
|
91418
91541
|
}
|
|
91542
|
+
mcpBody.add(new rowCtor(activeRenderer, { id: "mcp-mcp-keys", content: MCP_TAB_KEYS }));
|
|
91419
91543
|
const start = clampScroll3(mcpScroll, runtimes.length, bodyRows);
|
|
91420
91544
|
for (const [i, runtime] of runtimes.slice(start, start + bodyRows).entries()) {
|
|
91421
91545
|
const index = start + i;
|
|
91422
91546
|
mcpBody.add(new rowCtor(activeRenderer, {
|
|
91423
91547
|
id: `mcp-row-${runtime.id}`,
|
|
91424
|
-
content: formatMcpRowLine(runtime, index === mcpSelected, status),
|
|
91548
|
+
content: formatMcpRowLine(runtime, index === mcpSelected, status, bodyWidth),
|
|
91425
91549
|
onMouseDown: () => handleRowClick(runtime.id, index)
|
|
91426
91550
|
}));
|
|
91427
91551
|
}
|
|
91428
91552
|
};
|
|
91429
91553
|
const paint = () => {
|
|
91430
|
-
toolsScroll =
|
|
91554
|
+
toolsScroll = Math.max(0, toolsScroll);
|
|
91431
91555
|
mcpScroll = scrollToReveal3(mcpSelected, mcpScroll, bodyRows);
|
|
91432
91556
|
mcpScroll = clampScroll3(mcpScroll, runtimes.length, bodyRows);
|
|
91433
91557
|
paintToolsRows();
|
|
@@ -91510,9 +91634,10 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91510
91634
|
}
|
|
91511
91635
|
rowCtor = ctor;
|
|
91512
91636
|
activeRenderer = renderer;
|
|
91637
|
+
bodyWidth = ctx?.width;
|
|
91513
91638
|
if (tabId === "tools") {
|
|
91514
91639
|
toolsBody = target;
|
|
91515
|
-
toolsScroll =
|
|
91640
|
+
toolsScroll = Math.max(0, toolsScroll);
|
|
91516
91641
|
paintToolsRows();
|
|
91517
91642
|
return;
|
|
91518
91643
|
}
|
|
@@ -91560,7 +91685,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91560
91685
|
if (onMcp) {
|
|
91561
91686
|
moveMcpSelection(mcpSelected - 1);
|
|
91562
91687
|
} else {
|
|
91563
|
-
toolsScroll =
|
|
91688
|
+
toolsScroll = Math.max(0, toolsScroll - 1);
|
|
91564
91689
|
paint();
|
|
91565
91690
|
}
|
|
91566
91691
|
return;
|
|
@@ -91569,7 +91694,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91569
91694
|
if (onMcp) {
|
|
91570
91695
|
moveMcpSelection(mcpSelected + 1);
|
|
91571
91696
|
} else {
|
|
91572
|
-
toolsScroll
|
|
91697
|
+
toolsScroll += 1;
|
|
91573
91698
|
paint();
|
|
91574
91699
|
}
|
|
91575
91700
|
return;
|
|
@@ -91579,7 +91704,7 @@ function presentMcpTools(openModal, otui, chrome, options) {
|
|
|
91579
91704
|
if (onMcp) {
|
|
91580
91705
|
mcpScroll = clampScroll3(mcpScroll + step, runtimes.length, bodyRows);
|
|
91581
91706
|
} else {
|
|
91582
|
-
toolsScroll =
|
|
91707
|
+
toolsScroll = Math.max(0, toolsScroll + step);
|
|
91583
91708
|
}
|
|
91584
91709
|
paint();
|
|
91585
91710
|
}
|
|
@@ -91592,6 +91717,7 @@ function openMcpTools(otui, chrome, options) {
|
|
|
91592
91717
|
}
|
|
91593
91718
|
|
|
91594
91719
|
// src/tui/mcp-consumer.ts
|
|
91720
|
+
import { homedir as homedir9 } from "os";
|
|
91595
91721
|
var MCP_CONSUMER_COMMAND = "/mcp";
|
|
91596
91722
|
function isMcpConsumerCommand(line) {
|
|
91597
91723
|
return (line.trim().split(/\s+/)[0] ?? "") === MCP_CONSUMER_COMMAND;
|
|
@@ -91620,12 +91746,21 @@ function credentialNames(server) {
|
|
|
91620
91746
|
}
|
|
91621
91747
|
return [...names].sort();
|
|
91622
91748
|
}
|
|
91623
|
-
|
|
91749
|
+
var MAX_TARGET_CHARS = 240;
|
|
91750
|
+
function collapseHome2(text, home) {
|
|
91751
|
+
const trimmed = home.replace(/\/+$/, "");
|
|
91752
|
+
if (trimmed === "")
|
|
91753
|
+
return text;
|
|
91754
|
+
const escaped = trimmed.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
91755
|
+
return text.replace(new RegExp(`(^|[\\s="'])${escaped}(?=/|$|[\\s"'])`, "g"), "$1~");
|
|
91756
|
+
}
|
|
91757
|
+
function targetOf(server, home) {
|
|
91624
91758
|
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);
|
|
91759
|
+
const target = typeof raw.url === "string" && raw.url.length > 0 ? displayUrl(raw.url) : collapseHome2([raw.command, ...raw.args ?? []].filter(Boolean).join(" "), home);
|
|
91760
|
+
return sanitiseIdentifier(target, MAX_TARGET_CHARS);
|
|
91627
91761
|
}
|
|
91628
91762
|
function buildConsumerModel(input) {
|
|
91763
|
+
const home = input.home ?? homedir9();
|
|
91629
91764
|
const stateByName = new Map(input.states.map((s) => [s.name, s]));
|
|
91630
91765
|
const rows = input.configured.map((server) => {
|
|
91631
91766
|
const state = stateByName.get(server.name);
|
|
@@ -91637,7 +91772,7 @@ function buildConsumerModel(input) {
|
|
|
91637
91772
|
transport: transportOf(server),
|
|
91638
91773
|
status,
|
|
91639
91774
|
toolCount: state?.toolCount ?? 0,
|
|
91640
|
-
target: targetOf(server),
|
|
91775
|
+
target: targetOf(server, home),
|
|
91641
91776
|
credentials: credentialNames(server),
|
|
91642
91777
|
detail,
|
|
91643
91778
|
action: status === "needs-approval" ? `keryx mcp trust ${server.name}` : status === "needs_auth" ? "set the variable named above, then restart the session" : undefined
|
|
@@ -91645,10 +91780,10 @@ function buildConsumerModel(input) {
|
|
|
91645
91780
|
});
|
|
91646
91781
|
return {
|
|
91647
91782
|
rows,
|
|
91648
|
-
problems: input.problems.map((p) => `${p.file}: ${sanitiseForDisplay(p.message)}`),
|
|
91783
|
+
problems: input.problems.map((p) => `${collapseHome2(p.file, home)}: ${sanitiseForDisplay(p.message)}`),
|
|
91649
91784
|
emptyHint: rows.length > 0 ? undefined : `No MCP servers configured.
|
|
91650
|
-
user: ${input.userFile}
|
|
91651
|
-
project: ${input.projectFile}`
|
|
91785
|
+
user: ${collapseHome2(input.userFile, home)}
|
|
91786
|
+
project: ${collapseHome2(input.projectFile, home)}`
|
|
91652
91787
|
};
|
|
91653
91788
|
}
|
|
91654
91789
|
var MCP_CONSUMER_FOOTER = [
|
|
@@ -91677,7 +91812,7 @@ function consumerActionFor(status) {
|
|
|
91677
91812
|
function statusGlyph(status) {
|
|
91678
91813
|
return STATUS_GLYPH[status] ?? status;
|
|
91679
91814
|
}
|
|
91680
|
-
function formatConsumerModalRow(row, isSelected, status) {
|
|
91815
|
+
function formatConsumerModalRow(row, isSelected, status, width) {
|
|
91681
91816
|
const mark = isSelected ? ">" : " ";
|
|
91682
91817
|
const name = row.name.padEnd(18);
|
|
91683
91818
|
const source = row.source.padEnd(10);
|
|
@@ -91702,7 +91837,8 @@ function formatConsumerModalRow(row, isSelected, status) {
|
|
|
91702
91837
|
action = "";
|
|
91703
91838
|
}
|
|
91704
91839
|
const creds = row.credentials.length > 0 ? ` [reads ${row.credentials.join(", ")}]` : "";
|
|
91705
|
-
return `${mark} ${name} ${source} ${transport} ${glyph}
|
|
91840
|
+
return wrapHangingRow(`${mark} ${name} ${source} ${transport} ${glyph}`, `${tools}${action} ${row.target}${creds}`, width).join(`
|
|
91841
|
+
`);
|
|
91706
91842
|
}
|
|
91707
91843
|
function formatConsumerModalLines(model, selected, status) {
|
|
91708
91844
|
if (model === undefined) {
|
|
@@ -91743,6 +91879,7 @@ function presentMcpConsumer(openModalFn, otui, chrome, options) {
|
|
|
91743
91879
|
let rowCtor;
|
|
91744
91880
|
let activeRenderer;
|
|
91745
91881
|
let unsubscribeKey;
|
|
91882
|
+
let bodyWidth;
|
|
91746
91883
|
const rendererHint = options.renderer ?? chrome?.renderer;
|
|
91747
91884
|
const bodyRows = options.visibleRows ?? (typeof rendererHint?.width === "number" && typeof rendererHint.height === "number" ? modalBodyRows(resolveModalPanelSize(rendererHint.width, rendererHint.height).height) : 13);
|
|
91748
91885
|
const rowsOf = () => options.snapshot()?.rows ?? [];
|
|
@@ -91775,7 +91912,7 @@ function presentMcpConsumer(openModalFn, otui, chrome, options) {
|
|
|
91775
91912
|
const index = start + i;
|
|
91776
91913
|
body.add(new rowCtor(activeRenderer, {
|
|
91777
91914
|
id: `mcp-consumer-row-${row.name}`,
|
|
91778
|
-
content: formatConsumerModalRow(row, index === selected, status),
|
|
91915
|
+
content: formatConsumerModalRow(row, index === selected, status, bodyWidth),
|
|
91779
91916
|
onMouseDown: () => handleRowClick(row.name, index)
|
|
91780
91917
|
}));
|
|
91781
91918
|
}
|
|
@@ -91846,6 +91983,7 @@ function presentMcpConsumer(openModalFn, otui, chrome, options) {
|
|
|
91846
91983
|
rowCtor = ctor;
|
|
91847
91984
|
activeRenderer = renderer;
|
|
91848
91985
|
body = target;
|
|
91986
|
+
bodyWidth = ctx?.width;
|
|
91849
91987
|
paint();
|
|
91850
91988
|
},
|
|
91851
91989
|
onClose: () => {
|
|
@@ -97654,30 +97792,31 @@ var CUSTOM_ADD_ENTRY = {
|
|
|
97654
97792
|
label: "\uFF0B Add custom provider (OpenAI-compatible)",
|
|
97655
97793
|
note: "name \xB7 URL \xB7 key \xB7 models \u2192 saved to llm-providers.json"
|
|
97656
97794
|
};
|
|
97657
|
-
function promptCustomFieldStep(otui,
|
|
97795
|
+
function promptCustomFieldStep(otui, target, opts) {
|
|
97796
|
+
const r = stepRenderer(target);
|
|
97658
97797
|
return new Promise((resolve) => {
|
|
97659
|
-
const
|
|
97660
|
-
|
|
97661
|
-
|
|
97798
|
+
const surface = openStepSurface(otui, target, {
|
|
97799
|
+
id: "custom-field-picker",
|
|
97800
|
+
title: opts.title,
|
|
97801
|
+
tab: "Custom provider",
|
|
97802
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
97803
|
+
footer: inputStepFooter("back"),
|
|
97804
|
+
contentRows: opts.note !== undefined ? 4 : 2,
|
|
97805
|
+
onEscape: () => {
|
|
97806
|
+
input.blur();
|
|
97807
|
+
resolve({ kind: "back" });
|
|
97808
|
+
}
|
|
97809
|
+
});
|
|
97662
97810
|
if (opts.note !== undefined) {
|
|
97663
|
-
|
|
97811
|
+
surface.body.add(new otui.TextRenderable(r, { id: "cf-note", content: otui.t`${otui.dim(opts.note)}`, marginTop: 1 }));
|
|
97664
97812
|
}
|
|
97665
97813
|
const input = new otui.InputRenderable(r, { id: "cf-input", value: opts.value ?? "", marginTop: 1 });
|
|
97666
|
-
|
|
97814
|
+
surface.body.add(input);
|
|
97667
97815
|
input.focus();
|
|
97668
97816
|
const cleanup = () => {
|
|
97669
|
-
unsub();
|
|
97670
97817
|
input.blur();
|
|
97671
|
-
|
|
97818
|
+
surface.close();
|
|
97672
97819
|
};
|
|
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
97820
|
input.on(otui.InputRenderableEvents.ENTER, () => {
|
|
97682
97821
|
const entered = input.value.trim();
|
|
97683
97822
|
cleanup();
|
|
@@ -97697,9 +97836,9 @@ function parseOptionalPositiveWizardNumber(raw) {
|
|
|
97697
97836
|
const parsed = parseOptionalWizardNumber(raw);
|
|
97698
97837
|
return parsed !== undefined && parsed > 0 ? parsed : undefined;
|
|
97699
97838
|
}
|
|
97700
|
-
async function promptCustomProviderWizard(otui,
|
|
97839
|
+
async function promptCustomProviderWizard(otui, target) {
|
|
97701
97840
|
while (true) {
|
|
97702
|
-
const nameStep = await promptCustomFieldStep(otui,
|
|
97841
|
+
const nameStep = await promptCustomFieldStep(otui, target, {
|
|
97703
97842
|
title: "Provider name",
|
|
97704
97843
|
note: "unique id used in /provider (letters, digits, - _)"
|
|
97705
97844
|
});
|
|
@@ -97711,7 +97850,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97711
97850
|
continue;
|
|
97712
97851
|
}
|
|
97713
97852
|
while (true) {
|
|
97714
|
-
const urlStep = await promptCustomFieldStep(otui,
|
|
97853
|
+
const urlStep = await promptCustomFieldStep(otui, target, {
|
|
97715
97854
|
title: "Base URL",
|
|
97716
97855
|
note: "before the chat path \u2014 /v1/chat/completions is appended, e.g. http://10.110.43.19:8080",
|
|
97717
97856
|
value: "http://localhost:8000"
|
|
@@ -97733,7 +97872,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97733
97872
|
continue;
|
|
97734
97873
|
}
|
|
97735
97874
|
const baseUrl = baseUrlRaw.replace(/\/+$/, "");
|
|
97736
|
-
const keyStep = await promptCustomFieldStep(otui,
|
|
97875
|
+
const keyStep = await promptCustomFieldStep(otui, target, {
|
|
97737
97876
|
title: "API key (optional)",
|
|
97738
97877
|
note: "empty = no key \xB7 saved owner-only (0600) in your keryx config dir"
|
|
97739
97878
|
});
|
|
@@ -97741,7 +97880,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97741
97880
|
continue;
|
|
97742
97881
|
}
|
|
97743
97882
|
const apiKey = keyStep.value.length > 0 ? keyStep.value : undefined;
|
|
97744
|
-
const modelsStep = await promptCustomFieldStep(otui,
|
|
97883
|
+
const modelsStep = await promptCustomFieldStep(otui, target, {
|
|
97745
97884
|
title: "Models (optional)",
|
|
97746
97885
|
note: "comma-separated ids \xB7 empty = fetch the live /v1/models list"
|
|
97747
97886
|
});
|
|
@@ -97749,7 +97888,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97749
97888
|
continue;
|
|
97750
97889
|
}
|
|
97751
97890
|
const models = modelsStep.value.split(",").map((m) => m.trim()).filter((m) => m.length > 0);
|
|
97752
|
-
const temperatureStep = await promptCustomFieldStep(otui,
|
|
97891
|
+
const temperatureStep = await promptCustomFieldStep(otui, target, {
|
|
97753
97892
|
title: "Temperature (optional)",
|
|
97754
97893
|
note: "empty = provider default \xB7 e.g. 0.2"
|
|
97755
97894
|
});
|
|
@@ -97757,7 +97896,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97757
97896
|
continue;
|
|
97758
97897
|
}
|
|
97759
97898
|
const temperature = parseOptionalWizardNumber(temperatureStep.value);
|
|
97760
|
-
const maxOutputTokensStep = await promptCustomFieldStep(otui,
|
|
97899
|
+
const maxOutputTokensStep = await promptCustomFieldStep(otui, target, {
|
|
97761
97900
|
title: "Max output tokens (optional)",
|
|
97762
97901
|
note: "empty = default 1024 \xB7 e.g. 4096"
|
|
97763
97902
|
});
|
|
@@ -97765,7 +97904,7 @@ async function promptCustomProviderWizard(otui, r) {
|
|
|
97765
97904
|
continue;
|
|
97766
97905
|
}
|
|
97767
97906
|
const maxOutputTokens = parseOptionalPositiveWizardNumber(maxOutputTokensStep.value);
|
|
97768
|
-
const timeoutMsStep = await promptCustomFieldStep(otui,
|
|
97907
|
+
const timeoutMsStep = await promptCustomFieldStep(otui, target, {
|
|
97769
97908
|
title: "Request timeout ms (optional)",
|
|
97770
97909
|
note: "empty = no engine-internal timeout \xB7 e.g. 180000"
|
|
97771
97910
|
});
|
|
@@ -98120,6 +98259,78 @@ function onKeypress4(r, handler) {
|
|
|
98120
98259
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
98121
98260
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
98122
98261
|
}
|
|
98262
|
+
function isModalChrome(target) {
|
|
98263
|
+
return target !== null && typeof target === "object" && "renderer" in target && "focusComposer" in target;
|
|
98264
|
+
}
|
|
98265
|
+
function stepRenderer(target) {
|
|
98266
|
+
return isModalChrome(target) ? target.renderer : target;
|
|
98267
|
+
}
|
|
98268
|
+
function openStepSurface(otui, target, opts) {
|
|
98269
|
+
const r = stepRenderer(target);
|
|
98270
|
+
if (!isModalChrome(target)) {
|
|
98271
|
+
const box = overlayBox(otui, r, opts.id);
|
|
98272
|
+
r.root.add(box);
|
|
98273
|
+
box.add(new otui.TextRenderable(r, { id: `${opts.id}-title`, content: otui.t`${otui.bold(opts.title)} ${otui.dim(opts.hint)}` }));
|
|
98274
|
+
let closed = false;
|
|
98275
|
+
const close = () => {
|
|
98276
|
+
if (closed)
|
|
98277
|
+
return;
|
|
98278
|
+
closed = true;
|
|
98279
|
+
unsub();
|
|
98280
|
+
r.root.remove(box);
|
|
98281
|
+
};
|
|
98282
|
+
const unsub = onKeypress4(r, (key) => {
|
|
98283
|
+
if (key.name === "escape") {
|
|
98284
|
+
close();
|
|
98285
|
+
opts.onEscape();
|
|
98286
|
+
key.preventDefault();
|
|
98287
|
+
key.stopPropagation();
|
|
98288
|
+
}
|
|
98289
|
+
});
|
|
98290
|
+
return { body: box, modal: false, close };
|
|
98291
|
+
}
|
|
98292
|
+
let body;
|
|
98293
|
+
let closedByStep = false;
|
|
98294
|
+
const handle = openModal(otui, target, {
|
|
98295
|
+
title: opts.title,
|
|
98296
|
+
tabs: [{ id: opts.id, label: opts.tab }],
|
|
98297
|
+
footer: opts.footer,
|
|
98298
|
+
contentRows: opts.contentRows,
|
|
98299
|
+
renderTab: (_tabId, tabBody) => {
|
|
98300
|
+
body = tabBody;
|
|
98301
|
+
},
|
|
98302
|
+
onClose: () => {
|
|
98303
|
+
if (!closedByStep)
|
|
98304
|
+
opts.onEscape();
|
|
98305
|
+
}
|
|
98306
|
+
});
|
|
98307
|
+
if (handle === undefined || body === undefined) {
|
|
98308
|
+
return openStepSurface(otui, r, opts);
|
|
98309
|
+
}
|
|
98310
|
+
return {
|
|
98311
|
+
body,
|
|
98312
|
+
modal: true,
|
|
98313
|
+
close: () => {
|
|
98314
|
+
if (closedByStep)
|
|
98315
|
+
return;
|
|
98316
|
+
closedByStep = true;
|
|
98317
|
+
handle.close({ restoreFocus: false });
|
|
98318
|
+
}
|
|
98319
|
+
};
|
|
98320
|
+
}
|
|
98321
|
+
function selectStepFooter(escLabel) {
|
|
98322
|
+
return [
|
|
98323
|
+
{ key: "\u2191/\u2193", label: "select" },
|
|
98324
|
+
{ key: "Enter", label: "confirm" },
|
|
98325
|
+
{ key: "esc", label: escLabel }
|
|
98326
|
+
];
|
|
98327
|
+
}
|
|
98328
|
+
function inputStepFooter(escLabel) {
|
|
98329
|
+
return [
|
|
98330
|
+
{ key: "Enter", label: "confirm" },
|
|
98331
|
+
{ key: "esc", label: escLabel }
|
|
98332
|
+
];
|
|
98333
|
+
}
|
|
98123
98334
|
function parseSearchProviderArgs(line) {
|
|
98124
98335
|
const parts = line.trim().length === 0 ? [] : line.trim().split(/\s+/);
|
|
98125
98336
|
const [providerId, ...tail] = parts;
|
|
@@ -98166,27 +98377,28 @@ async function selectSearchProviderAndReport(controller, onSystem, providerId) {
|
|
|
98166
98377
|
onSystem?.(`Search provider '${providerId}' selected.
|
|
98167
98378
|
`);
|
|
98168
98379
|
}
|
|
98169
|
-
function promptSearchFieldStep(otui,
|
|
98380
|
+
function promptSearchFieldStep(otui, target, field, value) {
|
|
98381
|
+
const r = stepRenderer(target);
|
|
98170
98382
|
return new Promise((resolve) => {
|
|
98171
|
-
const
|
|
98172
|
-
|
|
98173
|
-
|
|
98383
|
+
const surface = openStepSurface(otui, target, {
|
|
98384
|
+
id: "search-field-picker",
|
|
98385
|
+
title: field.label,
|
|
98386
|
+
tab: field.required ? "Required" : "Optional",
|
|
98387
|
+
hint: `${field.required ? "required" : "optional"} \xB7 Enter \xB7 Esc to go back`,
|
|
98388
|
+
footer: inputStepFooter("back"),
|
|
98389
|
+
contentRows: 2,
|
|
98390
|
+
onEscape: () => {
|
|
98391
|
+
input.blur();
|
|
98392
|
+
resolve({ kind: "back" });
|
|
98393
|
+
}
|
|
98394
|
+
});
|
|
98174
98395
|
const input = new otui.InputRenderable(r, { id: "sf-input", value, marginTop: 1 });
|
|
98175
|
-
|
|
98396
|
+
surface.body.add(input);
|
|
98176
98397
|
input.focus();
|
|
98177
98398
|
const cleanup = () => {
|
|
98178
|
-
unsub();
|
|
98179
98399
|
input.blur();
|
|
98180
|
-
|
|
98400
|
+
surface.close();
|
|
98181
98401
|
};
|
|
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
98402
|
input.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98191
98403
|
const entered = input.value.trim();
|
|
98192
98404
|
cleanup();
|
|
@@ -98194,32 +98406,33 @@ function promptSearchFieldStep(otui, r, field, value) {
|
|
|
98194
98406
|
});
|
|
98195
98407
|
});
|
|
98196
98408
|
}
|
|
98197
|
-
function promptSearchCredentialStep(otui,
|
|
98409
|
+
function promptSearchCredentialStep(otui, target, opts) {
|
|
98410
|
+
const r = stepRenderer(target);
|
|
98198
98411
|
return new Promise((resolve) => {
|
|
98199
|
-
const
|
|
98200
|
-
|
|
98201
|
-
|
|
98202
|
-
|
|
98412
|
+
const surface = openStepSurface(otui, target, {
|
|
98413
|
+
id: "search-credential-picker",
|
|
98414
|
+
title: `Paste your ${opts.label}`,
|
|
98415
|
+
tab: "Credential",
|
|
98416
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
98417
|
+
footer: inputStepFooter("back"),
|
|
98418
|
+
contentRows: 4,
|
|
98419
|
+
onEscape: () => {
|
|
98420
|
+
keyInput.blur();
|
|
98421
|
+
resolve({ kind: "back" });
|
|
98422
|
+
}
|
|
98423
|
+
});
|
|
98424
|
+
surface.body.add(new otui.TextRenderable(r, {
|
|
98203
98425
|
id: "sc-note",
|
|
98204
98426
|
content: otui.t`${otui.dim("Saved to your keryx config dir (owner-only, 0600)")}`,
|
|
98205
98427
|
marginTop: 1
|
|
98206
98428
|
}));
|
|
98207
98429
|
const keyInput = new otui.InputRenderable(r, { id: "sc-input", placeholder: "...", marginTop: 1 });
|
|
98208
|
-
|
|
98430
|
+
surface.body.add(keyInput);
|
|
98209
98431
|
keyInput.focus();
|
|
98210
98432
|
const cleanup = () => {
|
|
98211
|
-
unsub();
|
|
98212
98433
|
keyInput.blur();
|
|
98213
|
-
|
|
98434
|
+
surface.close();
|
|
98214
98435
|
};
|
|
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
98436
|
keyInput.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98224
98437
|
const value = keyInput.value.trim();
|
|
98225
98438
|
cleanup();
|
|
@@ -98227,14 +98440,24 @@ function promptSearchCredentialStep(otui, r, opts) {
|
|
|
98227
98440
|
});
|
|
98228
98441
|
});
|
|
98229
98442
|
}
|
|
98230
|
-
function promptSetActiveProviderStep(otui,
|
|
98443
|
+
function promptSetActiveProviderStep(otui, target) {
|
|
98444
|
+
const r = stepRenderer(target);
|
|
98231
98445
|
return new Promise((resolve) => {
|
|
98232
|
-
const
|
|
98233
|
-
|
|
98234
|
-
|
|
98446
|
+
const surface = openStepSurface(otui, target, {
|
|
98447
|
+
id: "search-active-picker",
|
|
98448
|
+
title: "Set as active provider after a successful test?",
|
|
98449
|
+
tab: "Active",
|
|
98450
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to go back)",
|
|
98451
|
+
footer: selectStepFooter("back"),
|
|
98452
|
+
contentRows: selectBoxHeight(2, true),
|
|
98453
|
+
onEscape: () => {
|
|
98454
|
+
select.blur();
|
|
98455
|
+
resolve(undefined);
|
|
98456
|
+
}
|
|
98457
|
+
});
|
|
98235
98458
|
const select = new otui.SelectRenderable(r, {
|
|
98236
98459
|
id: "sa-select",
|
|
98237
|
-
width: 60,
|
|
98460
|
+
width: surface.modal ? "100%" : 60,
|
|
98238
98461
|
height: selectBoxHeight(2, true),
|
|
98239
98462
|
options: [
|
|
98240
98463
|
{ name: "Yes", description: "select it once the test passes" },
|
|
@@ -98242,21 +98465,12 @@ function promptSetActiveProviderStep(otui, r) {
|
|
|
98242
98465
|
],
|
|
98243
98466
|
selectedTextColor: "#ffd166"
|
|
98244
98467
|
});
|
|
98245
|
-
|
|
98468
|
+
surface.body.add(select);
|
|
98246
98469
|
select.focus();
|
|
98247
98470
|
const cleanup = () => {
|
|
98248
|
-
unsub();
|
|
98249
98471
|
select.blur();
|
|
98250
|
-
|
|
98472
|
+
surface.close();
|
|
98251
98473
|
};
|
|
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
98474
|
select.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98261
98475
|
const chosen = select.getSelectedOption();
|
|
98262
98476
|
cleanup();
|
|
@@ -98264,35 +98478,36 @@ function promptSetActiveProviderStep(otui, r) {
|
|
|
98264
98478
|
});
|
|
98265
98479
|
});
|
|
98266
98480
|
}
|
|
98267
|
-
function pickSearchProviderStep(otui,
|
|
98481
|
+
function pickSearchProviderStep(otui, target, providers) {
|
|
98482
|
+
const r = stepRenderer(target);
|
|
98268
98483
|
return new Promise((resolve) => {
|
|
98269
|
-
const
|
|
98270
|
-
|
|
98271
|
-
|
|
98484
|
+
const surface = openStepSurface(otui, target, {
|
|
98485
|
+
id: "search-provider-picker",
|
|
98486
|
+
title: "Select a search provider",
|
|
98487
|
+
tab: "Search providers",
|
|
98488
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to cancel)",
|
|
98489
|
+
footer: selectStepFooter("cancel"),
|
|
98490
|
+
contentRows: selectBoxHeight(providers.length, true),
|
|
98491
|
+
onEscape: () => {
|
|
98492
|
+
select.blur();
|
|
98493
|
+
resolve(undefined);
|
|
98494
|
+
}
|
|
98495
|
+
});
|
|
98272
98496
|
const labelOf = (p) => `${p.id} (${p.displayName})`;
|
|
98273
98497
|
const select = new otui.SelectRenderable(r, {
|
|
98274
98498
|
id: "spp-select",
|
|
98275
|
-
width: 60,
|
|
98499
|
+
width: surface.modal ? "100%" : 60,
|
|
98276
98500
|
height: selectBoxHeight(providers.length, true),
|
|
98277
98501
|
showScrollIndicator: true,
|
|
98278
98502
|
options: providers.map((p) => ({ name: labelOf(p), description: p.kind })),
|
|
98279
98503
|
selectedTextColor: "#ffd166"
|
|
98280
98504
|
});
|
|
98281
|
-
|
|
98505
|
+
surface.body.add(select);
|
|
98282
98506
|
select.focus();
|
|
98283
98507
|
const cleanup = () => {
|
|
98284
|
-
unsub();
|
|
98285
98508
|
select.blur();
|
|
98286
|
-
|
|
98509
|
+
surface.close();
|
|
98287
98510
|
};
|
|
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
98511
|
select.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98297
98512
|
const chosen = select.getSelectedOption();
|
|
98298
98513
|
cleanup();
|
|
@@ -98352,19 +98567,46 @@ async function runSearchProviderFieldsStep(otui, r, provider, seed) {
|
|
|
98352
98567
|
}
|
|
98353
98568
|
return { kind: "done", fields, credential, setActive };
|
|
98354
98569
|
}
|
|
98355
|
-
function runSearchProviderTestStep(otui,
|
|
98570
|
+
function runSearchProviderTestStep(otui, target, controller, provider, fields, credential, setActive) {
|
|
98571
|
+
const r = stepRenderer(target);
|
|
98356
98572
|
return new Promise((resolve) => {
|
|
98357
|
-
|
|
98358
|
-
|
|
98573
|
+
let settled;
|
|
98574
|
+
let left = false;
|
|
98575
|
+
const modal = isModalChrome(target);
|
|
98576
|
+
let surface;
|
|
98577
|
+
if (modal) {
|
|
98578
|
+
surface = openStepSurface(otui, target, {
|
|
98579
|
+
id: "search-test-picker",
|
|
98580
|
+
title: `Test '${provider.id}'`,
|
|
98581
|
+
tab: "Test",
|
|
98582
|
+
hint: "",
|
|
98583
|
+
footer: [
|
|
98584
|
+
{ key: "Enter", label: "close after success" },
|
|
98585
|
+
{ key: "esc", label: "back" }
|
|
98586
|
+
],
|
|
98587
|
+
contentRows: 2,
|
|
98588
|
+
onEscape: () => {
|
|
98589
|
+
left = true;
|
|
98590
|
+
unsub();
|
|
98591
|
+
resolve(settled === "success" ? "done" : "retry");
|
|
98592
|
+
}
|
|
98593
|
+
});
|
|
98594
|
+
}
|
|
98595
|
+
const box = surface?.body ?? overlayBox(otui, r, "search-test-picker");
|
|
98596
|
+
if (surface === undefined)
|
|
98597
|
+
r.root.add(box);
|
|
98359
98598
|
const status = new otui.TextRenderable(r, { id: "st-title", content: otui.t`${otui.bold(`Testing '${provider.id}'`)} ${otui.dim("...")}` });
|
|
98360
98599
|
box.add(status);
|
|
98361
|
-
let settled;
|
|
98362
98600
|
const cleanup = () => {
|
|
98601
|
+
left = true;
|
|
98363
98602
|
unsub();
|
|
98364
|
-
|
|
98603
|
+
if (surface !== undefined)
|
|
98604
|
+
surface.close();
|
|
98605
|
+
else
|
|
98606
|
+
r.root.remove(box);
|
|
98365
98607
|
};
|
|
98366
98608
|
const unsub = onKeypress4(r, (key) => {
|
|
98367
|
-
if (settled === "failure" && key.name === "escape") {
|
|
98609
|
+
if (!modal && settled === "failure" && key.name === "escape") {
|
|
98368
98610
|
cleanup();
|
|
98369
98611
|
resolve("retry");
|
|
98370
98612
|
key.preventDefault();
|
|
@@ -98379,6 +98621,9 @@ function runSearchProviderTestStep(otui, r, controller, provider, fields, creden
|
|
|
98379
98621
|
(async () => {
|
|
98380
98622
|
controller.configure(provider.id, { ...provider.defaults, ...fields }, credential);
|
|
98381
98623
|
const tested = await controller.test(provider.id);
|
|
98624
|
+
if (left) {
|
|
98625
|
+
return;
|
|
98626
|
+
}
|
|
98382
98627
|
if (!tested.ok) {
|
|
98383
98628
|
settled = "failure";
|
|
98384
98629
|
const reason = tested.reason === "missing-credential" ? "missing credential" : "connection validation failed";
|
|
@@ -98391,6 +98636,9 @@ function runSearchProviderTestStep(otui, r, controller, provider, fields, creden
|
|
|
98391
98636
|
return;
|
|
98392
98637
|
}
|
|
98393
98638
|
const selected = await controller.select(provider.id);
|
|
98639
|
+
if (left) {
|
|
98640
|
+
return;
|
|
98641
|
+
}
|
|
98394
98642
|
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
98643
|
})();
|
|
98396
98644
|
});
|
|
@@ -98417,11 +98665,22 @@ async function searchProviderWizardInTui(otui, r, controller) {
|
|
|
98417
98665
|
}
|
|
98418
98666
|
}
|
|
98419
98667
|
}
|
|
98420
|
-
function promptBaseUrlStep(otui,
|
|
98668
|
+
function promptBaseUrlStep(otui, target, label, baseUrl, notice) {
|
|
98669
|
+
const r = stepRenderer(target);
|
|
98421
98670
|
return new Promise((resolve) => {
|
|
98422
|
-
const
|
|
98423
|
-
|
|
98424
|
-
|
|
98671
|
+
const surface = openStepSurface(otui, target, {
|
|
98672
|
+
id: "base-url-picker",
|
|
98673
|
+
title: `${label} endpoint URL`,
|
|
98674
|
+
tab: "Endpoint",
|
|
98675
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
98676
|
+
footer: inputStepFooter("back"),
|
|
98677
|
+
contentRows: notice !== undefined ? 6 : 4,
|
|
98678
|
+
onEscape: () => {
|
|
98679
|
+
input.blur();
|
|
98680
|
+
resolve(undefined);
|
|
98681
|
+
}
|
|
98682
|
+
});
|
|
98683
|
+
const box = surface.body;
|
|
98425
98684
|
if (notice !== undefined) {
|
|
98426
98685
|
box.add(new otui.TextRenderable(r, { id: "bp-notice", content: otui.t`${otui.red("\u2717")} ${notice}`, marginTop: 1 }));
|
|
98427
98686
|
}
|
|
@@ -98430,17 +98689,9 @@ function promptBaseUrlStep(otui, r, label, baseUrl, notice) {
|
|
|
98430
98689
|
box.add(input);
|
|
98431
98690
|
input.focus();
|
|
98432
98691
|
const cleanup = () => {
|
|
98433
|
-
|
|
98434
|
-
|
|
98692
|
+
input.blur();
|
|
98693
|
+
surface.close();
|
|
98435
98694
|
};
|
|
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
98695
|
input.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98445
98696
|
const value = input.value.trim();
|
|
98446
98697
|
cleanup();
|
|
@@ -98448,11 +98699,25 @@ function promptBaseUrlStep(otui, r, label, baseUrl, notice) {
|
|
|
98448
98699
|
});
|
|
98449
98700
|
});
|
|
98450
98701
|
}
|
|
98451
|
-
function promptApiKeyStep(otui,
|
|
98702
|
+
function promptApiKeyStep(otui, target, opts) {
|
|
98703
|
+
const r = stepRenderer(target);
|
|
98452
98704
|
return new Promise((resolve) => {
|
|
98453
|
-
const
|
|
98454
|
-
|
|
98455
|
-
|
|
98705
|
+
const surface = openStepSurface(otui, target, {
|
|
98706
|
+
id: "key-picker",
|
|
98707
|
+
title: `Paste your ${opts.label} API key`,
|
|
98708
|
+
tab: "API key",
|
|
98709
|
+
hint: "(Enter \xB7 Esc to go back)",
|
|
98710
|
+
footer: [
|
|
98711
|
+
{ key: "Enter", label: "save (empty = skip)" },
|
|
98712
|
+
{ key: "esc", label: "back" }
|
|
98713
|
+
],
|
|
98714
|
+
contentRows: opts.notice !== undefined ? 6 : 4,
|
|
98715
|
+
onEscape: () => {
|
|
98716
|
+
keyInput.blur();
|
|
98717
|
+
resolve({ kind: "back" });
|
|
98718
|
+
}
|
|
98719
|
+
});
|
|
98720
|
+
const box = surface.body;
|
|
98456
98721
|
if (opts.notice !== undefined) {
|
|
98457
98722
|
box.add(new otui.TextRenderable(r, { id: "kp-notice", content: otui.t`${otui.red("\u2717")} ${opts.notice}`, marginTop: 1 }));
|
|
98458
98723
|
}
|
|
@@ -98464,18 +98729,9 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
98464
98729
|
const keyInput = new otui.InputRenderable(r, { id: "kp-input", placeholder: opts.placeholder ?? "sk-...", marginTop: 1 });
|
|
98465
98730
|
box.add(keyInput);
|
|
98466
98731
|
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
98732
|
const cleanup = () => {
|
|
98477
|
-
|
|
98478
|
-
|
|
98733
|
+
keyInput.blur();
|
|
98734
|
+
surface.close();
|
|
98479
98735
|
};
|
|
98480
98736
|
keyInput.on(otui.InputRenderableEvents.ENTER, () => {
|
|
98481
98737
|
const value = keyInput.value.trim();
|
|
@@ -98484,38 +98740,39 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
98484
98740
|
});
|
|
98485
98741
|
});
|
|
98486
98742
|
}
|
|
98487
|
-
function pickAuthMethodStep(otui,
|
|
98743
|
+
function pickAuthMethodStep(otui, target, providerLabel, methods) {
|
|
98744
|
+
const r = stepRenderer(target);
|
|
98488
98745
|
return new Promise((resolve) => {
|
|
98489
|
-
const
|
|
98490
|
-
|
|
98491
|
-
|
|
98746
|
+
const surface = openStepSurface(otui, target, {
|
|
98747
|
+
id: "auth-method-picker",
|
|
98748
|
+
title: `How to connect ${providerLabel}`,
|
|
98749
|
+
tab: "Sign-in",
|
|
98750
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to go back)",
|
|
98751
|
+
footer: selectStepFooter("back"),
|
|
98752
|
+
contentRows: selectBoxHeight(methods.length, true),
|
|
98753
|
+
onEscape: () => {
|
|
98754
|
+
select.blur();
|
|
98755
|
+
resolve(undefined);
|
|
98756
|
+
}
|
|
98757
|
+
});
|
|
98492
98758
|
const descriptions = {
|
|
98493
98759
|
"device-code": deviceCodeMethodLabel(providerLabel === "GitHub Copilot" ? "github-copilot" : providerLabel === "OpenAI" ? "openai" : "grok"),
|
|
98494
98760
|
"api-key": "Manually enter API Key"
|
|
98495
98761
|
};
|
|
98496
98762
|
const select = new otui.SelectRenderable(r, {
|
|
98497
98763
|
id: "amp-select",
|
|
98498
|
-
width: 60,
|
|
98764
|
+
width: surface.modal ? "100%" : 60,
|
|
98499
98765
|
height: selectBoxHeight(methods.length, true),
|
|
98500
98766
|
showScrollIndicator: true,
|
|
98501
98767
|
options: methods.map((m) => ({ name: m, description: descriptions[m] })),
|
|
98502
98768
|
selectedTextColor: "#ffd166"
|
|
98503
98769
|
});
|
|
98504
|
-
|
|
98770
|
+
surface.body.add(select);
|
|
98505
98771
|
select.focus();
|
|
98506
98772
|
const cleanup = () => {
|
|
98507
|
-
unsub();
|
|
98508
98773
|
select.blur();
|
|
98509
|
-
|
|
98774
|
+
surface.close();
|
|
98510
98775
|
};
|
|
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
98776
|
select.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98520
98777
|
const chosen = select.getSelectedOption();
|
|
98521
98778
|
cleanup();
|
|
@@ -98523,30 +98780,27 @@ function pickAuthMethodStep(otui, r, providerLabel, methods) {
|
|
|
98523
98780
|
});
|
|
98524
98781
|
});
|
|
98525
98782
|
}
|
|
98526
|
-
function runDeviceLoginInTui(otui,
|
|
98783
|
+
function runDeviceLoginInTui(otui, target, provider, dir) {
|
|
98784
|
+
const r = stepRenderer(target);
|
|
98527
98785
|
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
98786
|
const controller = new AbortController;
|
|
98537
|
-
const
|
|
98538
|
-
|
|
98539
|
-
|
|
98540
|
-
|
|
98541
|
-
|
|
98542
|
-
|
|
98787
|
+
const surface = openStepSurface(otui, target, {
|
|
98788
|
+
id: "device-login",
|
|
98789
|
+
title: deviceCodeMethodLabel(provider),
|
|
98790
|
+
tab: "Device login",
|
|
98791
|
+
hint: "(Esc to cancel)",
|
|
98792
|
+
footer: [{ key: "esc", label: "cancel" }],
|
|
98793
|
+
contentRows: 4,
|
|
98794
|
+
onEscape: () => {
|
|
98543
98795
|
controller.abort();
|
|
98544
|
-
cleanup();
|
|
98545
98796
|
resolve(false);
|
|
98546
|
-
key.preventDefault();
|
|
98547
|
-
key.stopPropagation();
|
|
98548
98797
|
}
|
|
98549
98798
|
});
|
|
98799
|
+
const status = new otui.TextRenderable(r, { id: "dl-status", content: otui.t`${otui.dim("Requesting a device code\u2026")}`, marginTop: 1 });
|
|
98800
|
+
surface.body.add(status);
|
|
98801
|
+
const cleanup = () => {
|
|
98802
|
+
surface.close();
|
|
98803
|
+
};
|
|
98550
98804
|
loginDeviceCode({
|
|
98551
98805
|
provider,
|
|
98552
98806
|
fetch: (input, init) => globalThis.fetch(input, init),
|
|
@@ -98588,15 +98842,26 @@ function modelPickerNotice(label, result) {
|
|
|
98588
98842
|
}
|
|
98589
98843
|
return modelsFailureLine(label, result.failure);
|
|
98590
98844
|
}
|
|
98591
|
-
function pickProviderStep(otui,
|
|
98845
|
+
function pickProviderStep(otui, target, detected) {
|
|
98846
|
+
const r = stepRenderer(target);
|
|
98592
98847
|
return new Promise((resolve) => {
|
|
98593
|
-
const
|
|
98594
|
-
|
|
98595
|
-
|
|
98848
|
+
const surface = openStepSurface(otui, target, {
|
|
98849
|
+
id: "picker",
|
|
98850
|
+
title: "Select a provider",
|
|
98851
|
+
tab: "Providers",
|
|
98852
|
+
hint: "(\u2191/\u2193, Enter \xB7 Esc to cancel)",
|
|
98853
|
+
footer: selectStepFooter("cancel"),
|
|
98854
|
+
contentRows: selectBoxHeight(detected.length, true),
|
|
98855
|
+
onEscape: () => {
|
|
98856
|
+
provSelect.blur();
|
|
98857
|
+
resolve(undefined);
|
|
98858
|
+
}
|
|
98859
|
+
});
|
|
98860
|
+
const box = surface.body;
|
|
98596
98861
|
const labelOf = (d) => d.label ?? d.name;
|
|
98597
98862
|
const provSelect = new otui.SelectRenderable(r, {
|
|
98598
98863
|
id: "picker-provider",
|
|
98599
|
-
width: 60,
|
|
98864
|
+
width: surface.modal ? "100%" : 60,
|
|
98600
98865
|
height: selectBoxHeight(detected.length, true),
|
|
98601
98866
|
showScrollIndicator: true,
|
|
98602
98867
|
options: detected.map((d) => ({ name: labelOf(d), description: d.note ?? `${d.models.length} model(s)` })),
|
|
@@ -98604,18 +98869,9 @@ function pickProviderStep(otui, r, detected) {
|
|
|
98604
98869
|
});
|
|
98605
98870
|
box.add(provSelect);
|
|
98606
98871
|
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
98872
|
const cleanup = () => {
|
|
98617
|
-
|
|
98618
|
-
|
|
98873
|
+
provSelect.blur();
|
|
98874
|
+
surface.close();
|
|
98619
98875
|
};
|
|
98620
98876
|
provSelect.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98621
98877
|
const chosen = provSelect.getSelectedOption();
|
|
@@ -98624,12 +98880,7 @@ function pickProviderStep(otui, r, detected) {
|
|
|
98624
98880
|
});
|
|
98625
98881
|
});
|
|
98626
98882
|
}
|
|
98627
|
-
function isModalChrome(target) {
|
|
98628
|
-
return target !== null && typeof target === "object" && "renderer" in target && "focusComposer" in target;
|
|
98629
|
-
}
|
|
98630
98883
|
function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
98631
|
-
const chrome = isModalChrome(rOrChrome) ? rOrChrome : undefined;
|
|
98632
|
-
const r = chrome !== undefined ? chrome.renderer : rOrChrome;
|
|
98633
98884
|
return new Promise((resolve) => {
|
|
98634
98885
|
if (detected.length === 0) {
|
|
98635
98886
|
resolve(undefined);
|
|
@@ -98647,13 +98898,13 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98647
98898
|
}
|
|
98648
98899
|
const allCandidates = options.onlyConnected ? candidates : [...candidates, CUSTOM_ADD_ENTRY];
|
|
98649
98900
|
while (true) {
|
|
98650
|
-
const prov = await pickProviderStep(otui,
|
|
98901
|
+
const prov = await pickProviderStep(otui, rOrChrome, allCandidates);
|
|
98651
98902
|
if (prov === undefined) {
|
|
98652
98903
|
resolve(undefined);
|
|
98653
98904
|
return;
|
|
98654
98905
|
}
|
|
98655
98906
|
if (prov.name === CUSTOM_PROVIDER_ADD_ID) {
|
|
98656
|
-
const created = await promptCustomProviderWizard(otui,
|
|
98907
|
+
const created = await promptCustomProviderWizard(otui, rOrChrome);
|
|
98657
98908
|
if (created !== undefined) {
|
|
98658
98909
|
saveCustomCompatProvider({
|
|
98659
98910
|
name: created.name,
|
|
@@ -98677,7 +98928,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98677
98928
|
continue;
|
|
98678
98929
|
}
|
|
98679
98930
|
const lockDiscoveredHost = prov.name === "github-copilot";
|
|
98680
|
-
let selectedBaseUrl = options.onlyConnected || prov.baseUrl === undefined || lockDiscoveredHost ? prov.baseUrl : await promptBaseUrlStep(otui,
|
|
98931
|
+
let selectedBaseUrl = options.onlyConnected || prov.baseUrl === undefined || lockDiscoveredHost ? prov.baseUrl : await promptBaseUrlStep(otui, rOrChrome, prov.label ?? prov.name, prov.baseUrl);
|
|
98681
98932
|
if (!options.onlyConnected && !lockDiscoveredHost && prov.baseUrl !== undefined && selectedBaseUrl === undefined) {
|
|
98682
98933
|
continue;
|
|
98683
98934
|
}
|
|
@@ -98705,13 +98956,13 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98705
98956
|
offered.push("api-key");
|
|
98706
98957
|
let method = offered.length === 1 ? offered[0] : undefined;
|
|
98707
98958
|
if (offered.length > 1) {
|
|
98708
|
-
method = await pickAuthMethodStep(otui,
|
|
98959
|
+
method = await pickAuthMethodStep(otui, rOrChrome, label, offered);
|
|
98709
98960
|
if (method === undefined) {
|
|
98710
98961
|
return "back";
|
|
98711
98962
|
}
|
|
98712
98963
|
}
|
|
98713
98964
|
if (method === "device-code") {
|
|
98714
|
-
if (!await runDeviceLoginInTui(otui,
|
|
98965
|
+
if (!await runDeviceLoginInTui(otui, rOrChrome, prov.name, options.configDir)) {
|
|
98715
98966
|
return "back";
|
|
98716
98967
|
}
|
|
98717
98968
|
const saved = loadShellConfig(options.configDir).baseUrls?.[prov.name];
|
|
@@ -98721,7 +98972,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98721
98972
|
}
|
|
98722
98973
|
return "ok";
|
|
98723
98974
|
}
|
|
98724
|
-
const kr = await promptApiKeyStep(otui,
|
|
98975
|
+
const kr = await promptApiKeyStep(otui, rOrChrome, {
|
|
98725
98976
|
label,
|
|
98726
98977
|
envKey,
|
|
98727
98978
|
...notice === undefined ? {} : { notice }
|
|
@@ -98751,7 +99002,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98751
99002
|
models = await modelsForPicker(selectedProvider, modelDeps);
|
|
98752
99003
|
}
|
|
98753
99004
|
if (!options.onlyConnected && selectedProvider.baseUrl !== undefined && endpointMayBeAtFault(models.failure)) {
|
|
98754
|
-
const corrected = await promptBaseUrlStep(otui,
|
|
99005
|
+
const corrected = await promptBaseUrlStep(otui, rOrChrome, label, selectedProvider.baseUrl, modelsFailureLine(label, models.failure));
|
|
98755
99006
|
if (corrected === undefined) {
|
|
98756
99007
|
continue;
|
|
98757
99008
|
}
|
|
@@ -98762,7 +99013,7 @@ function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
|
98762
99013
|
models = await modelsForPicker(selectedProvider, modelDeps);
|
|
98763
99014
|
}
|
|
98764
99015
|
}
|
|
98765
|
-
const model = await pickModelInTui(otui,
|
|
99016
|
+
const model = await pickModelInTui(otui, rOrChrome, models.models, modelPickerNotice(label, models), {
|
|
98766
99017
|
escLabel: "back"
|
|
98767
99018
|
});
|
|
98768
99019
|
if (model === undefined) {
|
|
@@ -98998,6 +99249,9 @@ function pickSessionInTui(otui, rOrChrome, sessions) {
|
|
|
98998
99249
|
});
|
|
98999
99250
|
});
|
|
99000
99251
|
}
|
|
99252
|
+
function describeModeRow(mode, readOnly) {
|
|
99253
|
+
return readOnly ? { mode, readOnly: "\xB7 read-only" } : { mode };
|
|
99254
|
+
}
|
|
99001
99255
|
var MODE_PICKER_DESCRIPTIONS = {
|
|
99002
99256
|
ask: "Every mutating action asks first (today's default)",
|
|
99003
99257
|
trust: "Auto-approves safe actions; still asks for destructive/credential ones",
|
|
@@ -99109,6 +99363,8 @@ async function launchTuiAgentShell(opts) {
|
|
|
99109
99363
|
sidebar.add(new otui.TextRenderable(r, { id: "sb-model-k", content: otui.t`${otui.dim("Model")}`, marginTop: 1 }));
|
|
99110
99364
|
const sbModelV = new otui.TextRenderable(r, { id: "sb-model-v", content: otui.t`${otui.dim(`${sel.provider}/${sel.model}`)}` });
|
|
99111
99365
|
sidebar.add(sbModelV);
|
|
99366
|
+
const sbModeV = new otui.TextRenderable(r, { id: "sb-mode-v", content: "" });
|
|
99367
|
+
sidebar.add(sbModeV);
|
|
99112
99368
|
sidebar.add(new otui.TextRenderable(r, { id: "sb-usage-k", content: otui.t`${otui.dim("Usage")}`, marginTop: 1 }));
|
|
99113
99369
|
const sbUsageV = new otui.TextRenderable(r, { id: "sb-usage-v", content: otui.t`${otui.dim("\u21910 \u21930")}` });
|
|
99114
99370
|
sidebar.add(sbUsageV);
|
|
@@ -99725,6 +99981,11 @@ async function launchTuiAgentShell(opts) {
|
|
|
99725
99981
|
io.permissionMode = () => permissionMode;
|
|
99726
99982
|
let readOnly = false;
|
|
99727
99983
|
io.readOnly = () => readOnly;
|
|
99984
|
+
const paintModeRow = () => {
|
|
99985
|
+
const row = describeModeRow(permissionMode, readOnly);
|
|
99986
|
+
sbModeV.content = row.readOnly === undefined ? otui.t`${otui.dim(`mode ${row.mode}`)}` : otui.t`${otui.dim(`mode ${row.mode}`)} ${otui.yellow(row.readOnly)}`;
|
|
99987
|
+
};
|
|
99988
|
+
paintModeRow();
|
|
99728
99989
|
io.onAutoApproved = (tool, input, meta) => {
|
|
99729
99990
|
const preview = tool === "shell_exec" ? parseShellExecCommand(input) : tool;
|
|
99730
99991
|
const label = meta.destructive ? `\u25C7 auto-approved (${permissionMode}) [destructive]` : `\u25C7 auto-approved (${permissionMode})`;
|
|
@@ -99752,7 +100013,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
99752
100013
|
};
|
|
99753
100014
|
deps = { ...deps, onContextCompaction };
|
|
99754
100015
|
liveDeps = deps;
|
|
100016
|
+
let removeSplash;
|
|
99755
100017
|
const applyOpened = (opened, previewHistory) => {
|
|
100018
|
+
if (opened.history.length > 0) {
|
|
100019
|
+
removeSplash?.();
|
|
100020
|
+
removeSplash = undefined;
|
|
100021
|
+
}
|
|
99756
100022
|
liveSession = opened.handle;
|
|
99757
100023
|
history = previewHistory === true ? opened.history.slice(-SESSION_PREVIEW_MESSAGE_COUNT) : opened.history;
|
|
99758
100024
|
archive = opened.archive.length > 0 ? [...opened.archive] : [...opened.history];
|
|
@@ -99868,6 +100134,9 @@ async function launchTuiAgentShell(opts) {
|
|
|
99868
100134
|
}));
|
|
99869
100135
|
}
|
|
99870
100136
|
slateSession = { dir: liveSession.dir, cwd: sessionCwd, opened: false };
|
|
100137
|
+
if (history.length === 0) {
|
|
100138
|
+
removeSplash = mountEmptyTranscriptSplash(otui, r, transcript);
|
|
100139
|
+
}
|
|
99871
100140
|
refreshWorkspaceSidebar();
|
|
99872
100141
|
refreshReviewSidebar();
|
|
99873
100142
|
const paintSessionHeader = () => {
|
|
@@ -100164,6 +100433,7 @@ Staying in the current session.
|
|
|
100164
100433
|
}
|
|
100165
100434
|
}
|
|
100166
100435
|
permissionMode = next;
|
|
100436
|
+
paintModeRow();
|
|
100167
100437
|
chrome.showToast(`Permission mode: ${next}`);
|
|
100168
100438
|
if (saveFlag) {
|
|
100169
100439
|
const saved = setProjectPermissionMode(sessionCwd, next);
|
|
@@ -100221,11 +100491,13 @@ Staying in the current session.
|
|
|
100221
100491
|
}
|
|
100222
100492
|
if (wanted === "on") {
|
|
100223
100493
|
readOnly = true;
|
|
100494
|
+
paintModeRow();
|
|
100224
100495
|
chrome.showToast("Read-only mode: on");
|
|
100225
100496
|
return;
|
|
100226
100497
|
}
|
|
100227
100498
|
if (wanted === "off") {
|
|
100228
100499
|
readOnly = false;
|
|
100500
|
+
paintModeRow();
|
|
100229
100501
|
chrome.showToast(`Read-only mode: off (permission mode stays: ${permissionMode})`);
|
|
100230
100502
|
return;
|
|
100231
100503
|
}
|
|
@@ -100605,6 +100877,8 @@ Staying in the current session.
|
|
|
100605
100877
|
suggestionGate.cancel("new turn started");
|
|
100606
100878
|
if (origin === "operator") {
|
|
100607
100879
|
consecutiveAutoWakes = 0;
|
|
100880
|
+
removeSplash?.();
|
|
100881
|
+
removeSplash = undefined;
|
|
100608
100882
|
}
|
|
100609
100883
|
const displayLine = summarizeSubmittedLine(line);
|
|
100610
100884
|
if (chrome.isBusy()) {
|
|
@@ -100910,7 +101184,7 @@ Staying in the current session.
|
|
|
100910
101184
|
const args = parseSearchProviderArgs(line.slice(16));
|
|
100911
101185
|
const all = searchProviderController.configurable();
|
|
100912
101186
|
if (args.providerId === undefined) {
|
|
100913
|
-
await chrome.withOverlay(() => searchProviderWizardInTui(otui,
|
|
101187
|
+
await chrome.withOverlay(() => searchProviderWizardInTui(otui, chrome, searchProviderController));
|
|
100914
101188
|
input.focus();
|
|
100915
101189
|
return;
|
|
100916
101190
|
}
|
|
@@ -100946,7 +101220,7 @@ Staying in the current session.
|
|
|
100946
101220
|
`);
|
|
100947
101221
|
return;
|
|
100948
101222
|
}
|
|
100949
|
-
const picked = await chrome.withOverlay(() => pickSearchProviderStep(otui,
|
|
101223
|
+
const picked = await chrome.withOverlay(() => pickSearchProviderStep(otui, chrome, selectable));
|
|
100950
101224
|
input.focus();
|
|
100951
101225
|
if (picked === undefined) {
|
|
100952
101226
|
return;
|
|
@@ -101136,12 +101410,10 @@ Usage: /reasoning <${REASONING_EFFORT_LEVELS.join("|")}>
|
|
|
101136
101410
|
const ns = await chrome.withOverlay(() => command.name === "/connect" ? selectProviderModelInTui(otui, chrome, detected, { onlyConnected: true, env: process.env }) : selectProviderModelInTui(otui, chrome, detected));
|
|
101137
101411
|
if (ns !== undefined) {
|
|
101138
101412
|
await switchTo(ns);
|
|
101139
|
-
} else {
|
|
101140
|
-
|
|
101141
|
-
chrome.showToast("No connected providers found. Run /provider to configure one first.");
|
|
101142
|
-
}
|
|
101143
|
-
input.focus();
|
|
101413
|
+
} else if (command.name === "/connect") {
|
|
101414
|
+
chrome.showToast("No connected providers found. Run /provider to configure one first.");
|
|
101144
101415
|
}
|
|
101416
|
+
input.focus();
|
|
101145
101417
|
})();
|
|
101146
101418
|
return;
|
|
101147
101419
|
}
|
|
@@ -106956,7 +107228,7 @@ import { readFileSync as readFileSync9 } from "fs";
|
|
|
106956
107228
|
|
|
106957
107229
|
// src/agents/bootstrap.ts
|
|
106958
107230
|
import { mkdir as mkdir64, readFile as readFile101, writeFile as writeFile55 } from "fs/promises";
|
|
106959
|
-
import { homedir as
|
|
107231
|
+
import { homedir as homedir10 } from "os";
|
|
106960
107232
|
import path200 from "path";
|
|
106961
107233
|
init_fs();
|
|
106962
107234
|
var AGENT_BOOTSTRAP_START = "<!-- keryx:global-bootstrap -->";
|
|
@@ -107025,7 +107297,7 @@ function resolveAgentBootstrapRuntimes(ids) {
|
|
|
107025
107297
|
}
|
|
107026
107298
|
return { runtimes, unknown };
|
|
107027
107299
|
}
|
|
107028
|
-
async function agentBootstrapStatus(runtime, homeRoot =
|
|
107300
|
+
async function agentBootstrapStatus(runtime, homeRoot = homedir10()) {
|
|
107029
107301
|
const filePath = runtime.filePath(homeRoot);
|
|
107030
107302
|
const exists = await pathExists(filePath);
|
|
107031
107303
|
const content = exists ? await readFile101(filePath, "utf8") : "";
|
|
@@ -107035,7 +107307,7 @@ async function agentBootstrapStatus(runtime, homeRoot = homedir9()) {
|
|
|
107035
107307
|
return { runtime: runtime.id, label: runtime.label, filePath, exists, installed, current };
|
|
107036
107308
|
}
|
|
107037
107309
|
async function installAgentBootstrap(runtime, options = {}) {
|
|
107038
|
-
const homeRoot = options.homeRoot ??
|
|
107310
|
+
const homeRoot = options.homeRoot ?? homedir10();
|
|
107039
107311
|
const filePath = runtime.filePath(homeRoot);
|
|
107040
107312
|
const exists = await pathExists(filePath);
|
|
107041
107313
|
const current = exists ? await readFile101(filePath, "utf8") : "";
|
|
@@ -107050,7 +107322,7 @@ async function installAgentBootstrap(runtime, options = {}) {
|
|
|
107050
107322
|
return { ...status, wrote, dryRun };
|
|
107051
107323
|
}
|
|
107052
107324
|
async function uninstallAgentBootstrap(runtime, options = {}) {
|
|
107053
|
-
const homeRoot = options.homeRoot ??
|
|
107325
|
+
const homeRoot = options.homeRoot ?? homedir10();
|
|
107054
107326
|
const filePath = runtime.filePath(homeRoot);
|
|
107055
107327
|
const exists = await pathExists(filePath);
|
|
107056
107328
|
const current = exists ? await readFile101(filePath, "utf8") : "";
|