@mrciphersmith/keryx 0.2.114 → 0.2.116
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 +271 -142
- 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.116",
|
|
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: {
|
|
@@ -88889,7 +88889,6 @@ function createBlockNavController(options) {
|
|
|
88889
88889
|
const schedule = options.schedule ?? ((run) => void setTimeout(run, 0));
|
|
88890
88890
|
const onChange = options.onChange ?? (() => {});
|
|
88891
88891
|
let focusOwner = "composer";
|
|
88892
|
-
let savedScrollTop = 0;
|
|
88893
88892
|
const active = () => focusOwner === "blocks";
|
|
88894
88893
|
const paint = (id) => {
|
|
88895
88894
|
const state = registry.get(id);
|
|
@@ -88977,7 +88976,6 @@ function createBlockNavController(options) {
|
|
|
88977
88976
|
}
|
|
88978
88977
|
focusOwner = "blocks";
|
|
88979
88978
|
registry.focus(target.id);
|
|
88980
|
-
savedScrollTop = scroll.scrollTop;
|
|
88981
88979
|
scroll.stickyScroll = false;
|
|
88982
88980
|
blurComposer();
|
|
88983
88981
|
paintAll();
|
|
@@ -88990,8 +88988,12 @@ function createBlockNavController(options) {
|
|
|
88990
88988
|
}
|
|
88991
88989
|
focusOwner = "composer";
|
|
88992
88990
|
paintAll();
|
|
88993
|
-
scroll.
|
|
88994
|
-
|
|
88991
|
+
if (typeof scroll.scrollHeight === "number" && typeof scroll.height === "number") {
|
|
88992
|
+
const atBottom = scroll.scrollTop >= scroll.scrollHeight - scroll.height - 3;
|
|
88993
|
+
scroll.stickyScroll = atBottom;
|
|
88994
|
+
} else {
|
|
88995
|
+
scroll.stickyScroll = true;
|
|
88996
|
+
}
|
|
88995
88997
|
focusComposer();
|
|
88996
88998
|
onChange();
|
|
88997
88999
|
};
|
|
@@ -89073,7 +89075,7 @@ function onKeypress(r, handler) {
|
|
|
89073
89075
|
}
|
|
89074
89076
|
var BACKDROP_ID = "modal-backdrop";
|
|
89075
89077
|
var PANEL_ID = "modal-panel";
|
|
89076
|
-
var BACKDROP_ALPHA =
|
|
89078
|
+
var BACKDROP_ALPHA = 1;
|
|
89077
89079
|
function backdropFillColor(otui) {
|
|
89078
89080
|
const color = otui.RGBA.fromHex(getTheme().bg);
|
|
89079
89081
|
color.a = BACKDROP_ALPHA;
|
|
@@ -89084,13 +89086,23 @@ var MODAL_PANEL_CHROME_X = 4;
|
|
|
89084
89086
|
var MODAL_PANEL_MIN_WIDTH = 72;
|
|
89085
89087
|
var MODAL_PANEL_MIN_HEIGHT = 18;
|
|
89086
89088
|
var MODAL_PANEL_SIZE_RATIO = 0.95;
|
|
89089
|
+
var MODAL_PANEL_MAX_HEIGHT_RATIO = 0.85;
|
|
89087
89090
|
var MODAL_CHROME_ROWS = 5;
|
|
89088
89091
|
var MODAL_PANEL_WIDTH = MODAL_PANEL_MIN_WIDTH;
|
|
89089
89092
|
var MODAL_PANEL_HEIGHT = MODAL_PANEL_MIN_HEIGHT;
|
|
89090
89093
|
var MODAL_PANEL_INNER_WIDTH = MODAL_PANEL_MIN_WIDTH - MODAL_PANEL_CHROME_X;
|
|
89091
|
-
function resolveModalPanelSize(cols, rows) {
|
|
89094
|
+
function resolveModalPanelSize(cols, rows, contentRows) {
|
|
89095
|
+
const width = Math.max(MODAL_PANEL_MIN_WIDTH, Math.round(cols * MODAL_PANEL_SIZE_RATIO));
|
|
89096
|
+
if (contentRows !== undefined) {
|
|
89097
|
+
const maxHeight = Math.max(6, Math.round(rows * MODAL_PANEL_MAX_HEIGHT_RATIO));
|
|
89098
|
+
const needed = Math.max(6, contentRows + MODAL_CHROME_ROWS);
|
|
89099
|
+
return {
|
|
89100
|
+
width,
|
|
89101
|
+
height: Math.min(maxHeight, needed)
|
|
89102
|
+
};
|
|
89103
|
+
}
|
|
89092
89104
|
return {
|
|
89093
|
-
width
|
|
89105
|
+
width,
|
|
89094
89106
|
height: Math.max(MODAL_PANEL_MIN_HEIGHT, Math.round(rows * MODAL_PANEL_SIZE_RATIO))
|
|
89095
89107
|
};
|
|
89096
89108
|
}
|
|
@@ -89098,6 +89110,19 @@ function modalBodyRows(panelHeight) {
|
|
|
89098
89110
|
return Math.max(1, panelHeight - MODAL_CHROME_ROWS);
|
|
89099
89111
|
}
|
|
89100
89112
|
var CLOSE_HINT = "[x] esc";
|
|
89113
|
+
var UNMEASURED_SIDEBAR_WIDTH = 30;
|
|
89114
|
+
function resolveModalAvailableWidth(chrome) {
|
|
89115
|
+
const rWidth = chrome.renderer.width;
|
|
89116
|
+
const mainWidth = chrome.main?.width ?? 0;
|
|
89117
|
+
if (mainWidth > 0) {
|
|
89118
|
+
return Math.min(rWidth, mainWidth);
|
|
89119
|
+
}
|
|
89120
|
+
if (chrome.sidebar !== undefined) {
|
|
89121
|
+
const sidebarWidth = chrome.sidebar.width > 0 ? chrome.sidebar.width : UNMEASURED_SIDEBAR_WIDTH;
|
|
89122
|
+
return Math.max(20, rWidth - sidebarWidth);
|
|
89123
|
+
}
|
|
89124
|
+
return rWidth;
|
|
89125
|
+
}
|
|
89101
89126
|
function resolveModalInnerWidth(availableWidth) {
|
|
89102
89127
|
return Math.max(20, availableWidth - MODAL_PANEL_CHROME_X);
|
|
89103
89128
|
}
|
|
@@ -89181,9 +89206,11 @@ function mountTab(state, input, tabId) {
|
|
|
89181
89206
|
unmountActiveTab(state);
|
|
89182
89207
|
state.active = tabId;
|
|
89183
89208
|
paintTabs(state);
|
|
89184
|
-
const
|
|
89209
|
+
const availWidth = resolveModalAvailableWidth(state.chrome);
|
|
89210
|
+
const size = resolveModalPanelSize(availWidth, state.chrome.renderer.height, input.contentRows);
|
|
89211
|
+
const panelWidth = Math.min(availWidth, size.width);
|
|
89185
89212
|
const cleanup = input.renderTab(tabId, state.body, {
|
|
89186
|
-
width: resolveModalInnerWidth(
|
|
89213
|
+
width: resolveModalInnerWidth(panelWidth),
|
|
89187
89214
|
height: modalBodyRows(size.height)
|
|
89188
89215
|
});
|
|
89189
89216
|
state.tabCleanup = typeof cleanup === "function" ? cleanup : undefined;
|
|
@@ -89305,7 +89332,8 @@ function ensureHost(otui, chrome) {
|
|
|
89305
89332
|
panel.add(scroll);
|
|
89306
89333
|
panel.add(footer);
|
|
89307
89334
|
backdrop.add(panel);
|
|
89308
|
-
r.root
|
|
89335
|
+
const mountTarget = chrome.main ?? r.root;
|
|
89336
|
+
mountTarget.add(backdrop);
|
|
89309
89337
|
const state = {
|
|
89310
89338
|
otui,
|
|
89311
89339
|
chrome,
|
|
@@ -89425,8 +89453,9 @@ function openModal(otui, chrome, input) {
|
|
|
89425
89453
|
return;
|
|
89426
89454
|
}
|
|
89427
89455
|
const state = ensureHost(otui, chrome);
|
|
89428
|
-
const
|
|
89429
|
-
|
|
89456
|
+
const availWidth = resolveModalAvailableWidth(chrome);
|
|
89457
|
+
const size = resolveModalPanelSize(availWidth, chrome.renderer.height, input.contentRows);
|
|
89458
|
+
state.panel.width = Math.min(availWidth, size.width);
|
|
89430
89459
|
state.panel.height = size.height;
|
|
89431
89460
|
if (state.open) {
|
|
89432
89461
|
unmountActiveTab(state);
|
|
@@ -89448,7 +89477,10 @@ function openModal(otui, chrome, input) {
|
|
|
89448
89477
|
paintHeader(state, input.title);
|
|
89449
89478
|
paintFooter(state, input.footer);
|
|
89450
89479
|
mountTab(state, input, resolveInitialTab(input.tabs, input.initialTab));
|
|
89451
|
-
|
|
89480
|
+
const focused = chrome.renderer.currentFocusedRenderable;
|
|
89481
|
+
if (focused === null || !containsNode(state.scroll, focused)) {
|
|
89482
|
+
state.tabStrip.focus();
|
|
89483
|
+
}
|
|
89452
89484
|
return makeHandle(state, generation);
|
|
89453
89485
|
}
|
|
89454
89486
|
|
|
@@ -90760,6 +90792,10 @@ var REVIEW_FOOTER = [
|
|
|
90760
90792
|
{ key: "\u2191/\u2193", label: "scroll" },
|
|
90761
90793
|
{ key: "esc", label: "close" }
|
|
90762
90794
|
];
|
|
90795
|
+
var REVIEW_EMPTY_FOOTER = [
|
|
90796
|
+
{ key: "\u2190/\u2192", label: "tabs" },
|
|
90797
|
+
{ key: "esc", label: "close" }
|
|
90798
|
+
];
|
|
90763
90799
|
function isReviewCommand(line) {
|
|
90764
90800
|
const token = line.trim().split(/\s+/)[0] ?? "";
|
|
90765
90801
|
return token === REVIEW_COMMAND;
|
|
@@ -91061,6 +91097,7 @@ function presentReview(openModal, otui, chrome, options) {
|
|
|
91061
91097
|
paintSelection();
|
|
91062
91098
|
});
|
|
91063
91099
|
};
|
|
91100
|
+
const isCompactEmpty = items.length === 0;
|
|
91064
91101
|
const handle = openModal(otui, chrome, {
|
|
91065
91102
|
title: REVIEW_COMMAND,
|
|
91066
91103
|
tabs: [
|
|
@@ -91068,7 +91105,8 @@ function presentReview(openModal, otui, chrome, options) {
|
|
|
91068
91105
|
{ id: "detail", label: "Detail" }
|
|
91069
91106
|
],
|
|
91070
91107
|
initialTab: "list",
|
|
91071
|
-
footer: REVIEW_FOOTER,
|
|
91108
|
+
footer: isCompactEmpty ? REVIEW_EMPTY_FOOTER : REVIEW_FOOTER,
|
|
91109
|
+
...isCompactEmpty ? { contentRows: 3 } : {},
|
|
91072
91110
|
onArrowKeys: (key, direction) => {
|
|
91073
91111
|
if (items[selected]?.type === "proposal" && status.kind !== "running" && status.kind !== "done" && handle?.activeTab() === "detail") {
|
|
91074
91112
|
focusedAction = direction === "left" ? "accept" : "decline";
|
|
@@ -92740,14 +92778,36 @@ function describeUnavailableCommand(line, mode) {
|
|
|
92740
92778
|
return `${command.name} is only available in ${where} \u2014 this is ${mode} mode. ` + `Type /help for the commands available here.
|
|
92741
92779
|
`;
|
|
92742
92780
|
}
|
|
92743
|
-
function renderCommandHelp(mode, only) {
|
|
92781
|
+
function renderCommandHelp(mode, only, maxColumns) {
|
|
92744
92782
|
const allow = only === undefined ? undefined : new Set(only);
|
|
92745
92783
|
const options = commandsForMode(mode).filter((c) => allow === undefined || allow.has(c.name));
|
|
92746
92784
|
const width = options.reduce((w, c) => Math.max(w, c.name.length), 0);
|
|
92747
|
-
|
|
92785
|
+
const descColumn = width + 4;
|
|
92786
|
+
const wrapBudget = maxColumns !== undefined && maxColumns - descColumn >= MIN_HELP_WRAP_COLUMNS ? maxColumns - descColumn : undefined;
|
|
92787
|
+
const rows = options.flatMap((c) => {
|
|
92788
|
+
const lines = c.description.split(`
|
|
92789
|
+
`).flatMap((line) => wrapBudget === undefined ? [line] : wrapWords(line, wrapBudget));
|
|
92790
|
+
return lines.map((line, i) => (i === 0 ? ` ${c.name.padEnd(width)} ${line}` : `${" ".repeat(descColumn)}${line}`).trimEnd());
|
|
92791
|
+
});
|
|
92792
|
+
return ["Commands:", ...rows].join(`
|
|
92748
92793
|
`) + `
|
|
92749
92794
|
`;
|
|
92750
92795
|
}
|
|
92796
|
+
var MIN_HELP_WRAP_COLUMNS = 10;
|
|
92797
|
+
function wrapWords(line, budget) {
|
|
92798
|
+
const out = [];
|
|
92799
|
+
let cur = "";
|
|
92800
|
+
for (const word of line.split(/\s+/).filter(Boolean)) {
|
|
92801
|
+
if (cur.length > 0 && cur.length + 1 + word.length > budget) {
|
|
92802
|
+
out.push(cur);
|
|
92803
|
+
cur = word;
|
|
92804
|
+
} else {
|
|
92805
|
+
cur = cur.length > 0 ? `${cur} ${word}` : word;
|
|
92806
|
+
}
|
|
92807
|
+
}
|
|
92808
|
+
out.push(cur);
|
|
92809
|
+
return out;
|
|
92810
|
+
}
|
|
92751
92811
|
|
|
92752
92812
|
// src/tui/theme-picker.ts
|
|
92753
92813
|
function isThemeCommand(line) {
|
|
@@ -95100,6 +95160,10 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
95100
95160
|
syncComposerHeight();
|
|
95101
95161
|
const submitHandlers = new Set;
|
|
95102
95162
|
const emitSubmit = (line) => {
|
|
95163
|
+
if (line.length > 0) {
|
|
95164
|
+
scroll.scrollTop = scroll.scrollHeight;
|
|
95165
|
+
scroll.stickyScroll = true;
|
|
95166
|
+
}
|
|
95103
95167
|
for (const handler of [...submitHandlers]) {
|
|
95104
95168
|
handler(line);
|
|
95105
95169
|
}
|
|
@@ -98524,7 +98588,12 @@ function pickProviderStep(otui, r, detected) {
|
|
|
98524
98588
|
});
|
|
98525
98589
|
});
|
|
98526
98590
|
}
|
|
98527
|
-
function
|
|
98591
|
+
function isModalChrome(target) {
|
|
98592
|
+
return target !== null && typeof target === "object" && "renderer" in target && "focusComposer" in target;
|
|
98593
|
+
}
|
|
98594
|
+
function selectProviderModelInTui(otui, rOrChrome, detected, options = {}) {
|
|
98595
|
+
const chrome = isModalChrome(rOrChrome) ? rOrChrome : undefined;
|
|
98596
|
+
const r = chrome !== undefined ? chrome.renderer : rOrChrome;
|
|
98528
98597
|
return new Promise((resolve) => {
|
|
98529
98598
|
if (detected.length === 0) {
|
|
98530
98599
|
resolve(undefined);
|
|
@@ -98657,7 +98726,9 @@ function selectProviderModelInTui(otui, r, detected, options = {}) {
|
|
|
98657
98726
|
models = await modelsForPicker(selectedProvider, modelDeps);
|
|
98658
98727
|
}
|
|
98659
98728
|
}
|
|
98660
|
-
const model = await pickModelInTui(otui, r, models.models, modelPickerNotice(label, models)
|
|
98729
|
+
const model = await pickModelInTui(otui, chrome ?? r, models.models, modelPickerNotice(label, models), {
|
|
98730
|
+
escLabel: "back"
|
|
98731
|
+
});
|
|
98661
98732
|
if (model === undefined) {
|
|
98662
98733
|
continue;
|
|
98663
98734
|
}
|
|
@@ -98671,49 +98742,120 @@ function adaptiveSelectHeight(count, available, per = 1) {
|
|
|
98671
98742
|
const min = Math.max(1, Math.floor(available / 4));
|
|
98672
98743
|
return Math.min(available, Math.max(min, count * per));
|
|
98673
98744
|
}
|
|
98674
|
-
function pickModelInTui(otui,
|
|
98745
|
+
function pickModelInTui(otui, rOrChrome, models, notice, options = {}) {
|
|
98746
|
+
const chrome = isModalChrome(rOrChrome) ? rOrChrome : undefined;
|
|
98747
|
+
const r = chrome !== undefined ? chrome.renderer : rOrChrome;
|
|
98748
|
+
const showNotice = models.length === 0 && notice !== undefined;
|
|
98749
|
+
const noticeText = () => new otui.TextRenderable(r, { id: "mp-notice", content: otui.t`${otui.red("\u2717")} ${notice ?? ""}` });
|
|
98750
|
+
const listSpec = {
|
|
98751
|
+
idPrefix: "mp",
|
|
98752
|
+
items: models,
|
|
98753
|
+
toOption: (m) => ({ name: m, description: "" }),
|
|
98754
|
+
matches: (m, q) => m.toLowerCase().includes(q),
|
|
98755
|
+
emptyLabel: notice ?? "(no models found)",
|
|
98756
|
+
filterHint: (filter, shown, total) => `filter: ${filter} (${shown}/${total})`,
|
|
98757
|
+
showDescription: false
|
|
98758
|
+
};
|
|
98759
|
+
const fixedRows = 1 + (showNotice ? 1 : 0);
|
|
98760
|
+
if (chrome !== undefined) {
|
|
98761
|
+
return new Promise((resolve) => {
|
|
98762
|
+
let chosen;
|
|
98763
|
+
const handle = openModal(otui, chrome, {
|
|
98764
|
+
title: "Select a model",
|
|
98765
|
+
tabs: [{ id: "models", label: "Models" }],
|
|
98766
|
+
footer: [
|
|
98767
|
+
{ key: "\u2191/\u2193", label: "select" },
|
|
98768
|
+
{ key: "Enter", label: "confirm" },
|
|
98769
|
+
{ key: "esc", label: options.escLabel ?? "close" }
|
|
98770
|
+
],
|
|
98771
|
+
contentRows: fixedRows + Math.max(1, models.length),
|
|
98772
|
+
renderTab: (_tabId, body, ctx) => {
|
|
98773
|
+
const parent = body;
|
|
98774
|
+
if (showNotice) {
|
|
98775
|
+
parent.add(noticeText());
|
|
98776
|
+
}
|
|
98777
|
+
const list = mountFilterList(otui, r, parent, {
|
|
98778
|
+
...listSpec,
|
|
98779
|
+
idleHint: "type to filter by name",
|
|
98780
|
+
width: "100%",
|
|
98781
|
+
height: adaptiveSelectHeight(models.length, Math.max(1, ctx.height - fixedRows)),
|
|
98782
|
+
onPick: (m) => {
|
|
98783
|
+
chosen = m;
|
|
98784
|
+
handle?.close();
|
|
98785
|
+
}
|
|
98786
|
+
});
|
|
98787
|
+
return onKeypress4(r, list.onKey);
|
|
98788
|
+
},
|
|
98789
|
+
onClose: () => resolve(chosen)
|
|
98790
|
+
});
|
|
98791
|
+
if (handle === undefined) {
|
|
98792
|
+
resolve(undefined);
|
|
98793
|
+
}
|
|
98794
|
+
});
|
|
98795
|
+
}
|
|
98675
98796
|
return new Promise((resolve) => {
|
|
98676
|
-
const all = models;
|
|
98677
|
-
const NO_MODELS = notice ?? "(no models found)";
|
|
98678
98797
|
const box = overlayBox(otui, r, "model-picker");
|
|
98679
98798
|
r.root.add(box);
|
|
98680
98799
|
box.add(new otui.TextRenderable(r, { id: "mp-title", content: otui.t`${otui.bold("Select a model")}` }));
|
|
98681
|
-
if (
|
|
98682
|
-
box.add(
|
|
98800
|
+
if (showNotice) {
|
|
98801
|
+
box.add(noticeText());
|
|
98683
98802
|
}
|
|
98684
|
-
const filterLine = new otui.TextRenderable(r, { id: "mp-filter", content: otui.t`${otui.dim("type to filter \xB7 \u2191/\u2193 Enter \xB7 Esc to go back")}` });
|
|
98685
|
-
box.add(filterLine);
|
|
98686
|
-
const NO_MATCH = "(no match)";
|
|
98687
98803
|
const rHeight = r.height;
|
|
98688
98804
|
const available = typeof rHeight === "number" && rHeight > 0 ? Math.max(4, rHeight - 4) : 16;
|
|
98689
|
-
|
|
98690
|
-
const
|
|
98691
|
-
|
|
98805
|
+
let unsub = () => {};
|
|
98806
|
+
const finish = (m) => {
|
|
98807
|
+
unsub();
|
|
98808
|
+
r.root.remove(box);
|
|
98809
|
+
resolve(m);
|
|
98810
|
+
};
|
|
98811
|
+
const list = mountFilterList(otui, r, box, {
|
|
98812
|
+
...listSpec,
|
|
98813
|
+
idleHint: "type to filter \xB7 \u2191/\u2193 Enter \xB7 Esc to go back",
|
|
98692
98814
|
width: 72,
|
|
98693
|
-
|
|
98694
|
-
|
|
98695
|
-
showScrollIndicator: true,
|
|
98696
|
-
wrapSelection: true,
|
|
98697
|
-
options: (all.length > 0 ? all : [NO_MODELS]).map((m) => ({ name: m, description: "" })),
|
|
98698
|
-
selectedTextColor: "#ffd166"
|
|
98815
|
+
height: adaptiveSelectHeight(models.length, available),
|
|
98816
|
+
onPick: finish
|
|
98699
98817
|
});
|
|
98700
|
-
|
|
98701
|
-
sel.focus();
|
|
98702
|
-
let filter = "";
|
|
98703
|
-
const apply = () => {
|
|
98704
|
-
const q = filter.trim().toLowerCase();
|
|
98705
|
-
const matches = q.length > 0 ? all.filter((m) => m.toLowerCase().includes(q)) : all;
|
|
98706
|
-
sel.options = matches.length > 0 ? matches.map((m) => ({ name: m, description: "" })) : [{ name: NO_MATCH, description: "" }];
|
|
98707
|
-
filterLine.content = otui.t`${otui.dim(q.length > 0 ? `filter: ${filter} (${matches.length}/${all.length})` : "type to filter \xB7 \u2191/\u2193 Enter \xB7 Esc to go back")}`;
|
|
98708
|
-
};
|
|
98709
|
-
const onKey = (key) => {
|
|
98818
|
+
unsub = onKeypress4(r, (key) => {
|
|
98710
98819
|
if (key.name === "escape") {
|
|
98711
|
-
|
|
98712
|
-
resolve(undefined);
|
|
98820
|
+
finish(undefined);
|
|
98713
98821
|
key.preventDefault();
|
|
98714
98822
|
key.stopPropagation();
|
|
98715
98823
|
return;
|
|
98716
98824
|
}
|
|
98825
|
+
list.onKey(key);
|
|
98826
|
+
});
|
|
98827
|
+
});
|
|
98828
|
+
}
|
|
98829
|
+
function mountFilterList(otui, r, parent, spec) {
|
|
98830
|
+
const filterLine = new otui.TextRenderable(r, { id: `${spec.idPrefix}-filter`, content: "" });
|
|
98831
|
+
parent.add(filterLine);
|
|
98832
|
+
const sel = new otui.SelectRenderable(r, {
|
|
98833
|
+
id: `${spec.idPrefix}-sel`,
|
|
98834
|
+
width: spec.width,
|
|
98835
|
+
showDescription: spec.showDescription,
|
|
98836
|
+
height: spec.height,
|
|
98837
|
+
showScrollIndicator: true,
|
|
98838
|
+
wrapSelection: true,
|
|
98839
|
+
options: [],
|
|
98840
|
+
selectedTextColor: "#ffd166"
|
|
98841
|
+
});
|
|
98842
|
+
parent.add(sel);
|
|
98843
|
+
sel.focus();
|
|
98844
|
+
let filter = "";
|
|
98845
|
+
let shown = spec.items;
|
|
98846
|
+
const apply = () => {
|
|
98847
|
+
const q = filter.trim().toLowerCase();
|
|
98848
|
+
shown = q.length > 0 ? spec.items.filter((item) => spec.matches(item, q)) : spec.items;
|
|
98849
|
+
sel.options = shown.length > 0 ? shown.map(spec.toOption) : [{ name: spec.items.length === 0 ? spec.emptyLabel : "(no match)", description: "" }];
|
|
98850
|
+
sel.selectedIndex = 0;
|
|
98851
|
+
filterLine.content = otui.t`${otui.dim(q.length > 0 ? spec.filterHint(filter, shown.length, spec.items.length) : spec.idleHint)}`;
|
|
98852
|
+
};
|
|
98853
|
+
apply();
|
|
98854
|
+
sel.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98855
|
+
spec.onPick(shown[sel.getSelectedIndex()]);
|
|
98856
|
+
});
|
|
98857
|
+
return {
|
|
98858
|
+
onKey: (key) => {
|
|
98717
98859
|
if (key.name === "backspace") {
|
|
98718
98860
|
filter = filter.slice(0, -1);
|
|
98719
98861
|
apply();
|
|
@@ -98728,113 +98870,95 @@ function pickModelInTui(otui, r, models, notice) {
|
|
|
98728
98870
|
key.preventDefault();
|
|
98729
98871
|
key.stopPropagation();
|
|
98730
98872
|
}
|
|
98731
|
-
}
|
|
98732
|
-
|
|
98733
|
-
const cleanup = () => {
|
|
98734
|
-
unsub();
|
|
98735
|
-
r.root.remove(box);
|
|
98736
|
-
};
|
|
98737
|
-
sel.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98738
|
-
const chosen = sel.getSelectedOption();
|
|
98739
|
-
cleanup();
|
|
98740
|
-
resolve(chosen === null || chosen.name === NO_MATCH || chosen.name === NO_MODELS ? undefined : chosen.name);
|
|
98741
|
-
});
|
|
98742
|
-
});
|
|
98873
|
+
}
|
|
98874
|
+
};
|
|
98743
98875
|
}
|
|
98744
98876
|
function formatSessionDate(iso) {
|
|
98745
98877
|
const short = iso.trim().replace("T", " ");
|
|
98746
98878
|
return short.length >= 16 ? short.slice(0, 16) : short;
|
|
98747
98879
|
}
|
|
98748
|
-
function pickSessionInTui(otui,
|
|
98749
|
-
|
|
98750
|
-
|
|
98751
|
-
|
|
98752
|
-
|
|
98753
|
-
|
|
98754
|
-
|
|
98755
|
-
|
|
98756
|
-
|
|
98757
|
-
|
|
98758
|
-
|
|
98759
|
-
|
|
98760
|
-
}
|
|
98880
|
+
function pickSessionInTui(otui, rOrChrome, sessions) {
|
|
98881
|
+
const chrome = isModalChrome(rOrChrome) ? rOrChrome : undefined;
|
|
98882
|
+
const r = chrome !== undefined ? chrome.renderer : rOrChrome;
|
|
98883
|
+
const all = sessions.map((s) => {
|
|
98884
|
+
const created = formatSessionDate(s.createdAt);
|
|
98885
|
+
const updated = formatSessionDate(s.updatedAt);
|
|
98886
|
+
const short = shortSessionId(s.id);
|
|
98887
|
+
const title = s.title.length > 52 ? `${s.title.slice(0, 49)}\u2026` : s.title;
|
|
98888
|
+
return {
|
|
98889
|
+
value: s.id,
|
|
98890
|
+
label: `${short} \xB7 ${title}`,
|
|
98891
|
+
description: `${s.projectPath} \xB7 created ${created} \xB7 updated ${updated}`,
|
|
98892
|
+
search: `${s.id} ${short} ${s.projectPath} ${s.title} ${created} ${updated}`.toLowerCase()
|
|
98893
|
+
};
|
|
98894
|
+
});
|
|
98895
|
+
const listSpec = {
|
|
98896
|
+
idPrefix: "sp",
|
|
98897
|
+
items: all,
|
|
98898
|
+
toOption: (row) => ({ name: row.label, description: row.description }),
|
|
98899
|
+
matches: (row, q) => row.search.includes(q),
|
|
98900
|
+
emptyLabel: "(no match)",
|
|
98901
|
+
filterHint: (filter, shown) => `filter: ${filter} (${shown})`,
|
|
98902
|
+
showDescription: true
|
|
98903
|
+
};
|
|
98904
|
+
const ROWS_PER_SESSION = 2;
|
|
98905
|
+
if (chrome !== undefined) {
|
|
98906
|
+
return new Promise((resolve) => {
|
|
98907
|
+
let chosen;
|
|
98908
|
+
const handle = openModal(otui, chrome, {
|
|
98909
|
+
title: "Session Switcher",
|
|
98910
|
+
tabs: [{ id: "sessions", label: "Sessions" }],
|
|
98911
|
+
footer: [
|
|
98912
|
+
{ key: "\u2191/\u2193", label: "select" },
|
|
98913
|
+
{ key: "Enter", label: "open" },
|
|
98914
|
+
{ key: "esc", label: "cancel" }
|
|
98915
|
+
],
|
|
98916
|
+
contentRows: 1 + Math.max(1, all.length) * ROWS_PER_SESSION,
|
|
98917
|
+
renderTab: (_tabId, body, ctx) => {
|
|
98918
|
+
const list = mountFilterList(otui, r, body, {
|
|
98919
|
+
...listSpec,
|
|
98920
|
+
idleHint: "type to filter by id, title, project, created, updated",
|
|
98921
|
+
width: "100%",
|
|
98922
|
+
height: adaptiveSelectHeight(all.length, Math.max(1, ctx.height - 1), ROWS_PER_SESSION),
|
|
98923
|
+
onPick: (row) => {
|
|
98924
|
+
chosen = row?.value;
|
|
98925
|
+
handle?.close();
|
|
98926
|
+
}
|
|
98927
|
+
});
|
|
98928
|
+
return onKeypress4(r, list.onKey);
|
|
98929
|
+
},
|
|
98930
|
+
onClose: () => resolve(chosen)
|
|
98931
|
+
});
|
|
98932
|
+
if (handle === undefined) {
|
|
98933
|
+
resolve(undefined);
|
|
98934
|
+
}
|
|
98761
98935
|
});
|
|
98936
|
+
}
|
|
98937
|
+
return new Promise((resolve) => {
|
|
98762
98938
|
const box = overlayBox(otui, r, "session-picker");
|
|
98763
98939
|
r.root.add(box);
|
|
98764
98940
|
box.add(new otui.TextRenderable(r, { id: "sp-title", content: otui.t`${otui.bold("Open session")} ${otui.dim("\u2191/\u2193 Enter \xB7 Esc to cancel")}` }));
|
|
98765
|
-
|
|
98766
|
-
|
|
98767
|
-
|
|
98768
|
-
|
|
98769
|
-
|
|
98770
|
-
|
|
98771
|
-
const
|
|
98772
|
-
|
|
98941
|
+
let unsub = () => {};
|
|
98942
|
+
const finish = (row) => {
|
|
98943
|
+
unsub();
|
|
98944
|
+
r.root.remove(box);
|
|
98945
|
+
resolve(row?.value);
|
|
98946
|
+
};
|
|
98947
|
+
const list = mountFilterList(otui, r, box, {
|
|
98948
|
+
...listSpec,
|
|
98949
|
+
idleHint: "type to filter \xB7 \u2191/\u2193 Enter \xB7 Esc to cancel",
|
|
98773
98950
|
width: "100%",
|
|
98774
|
-
showDescription: true,
|
|
98775
98951
|
height: 14,
|
|
98776
|
-
|
|
98777
|
-
wrapSelection: true,
|
|
98778
|
-
options: [],
|
|
98779
|
-
selectedTextColor: "#ffd166"
|
|
98952
|
+
onPick: finish
|
|
98780
98953
|
});
|
|
98781
|
-
|
|
98782
|
-
sel.focus();
|
|
98783
|
-
let filter = "";
|
|
98784
|
-
let matches = all;
|
|
98785
|
-
const apply = () => {
|
|
98786
|
-
const q = filter.trim().toLowerCase();
|
|
98787
|
-
matches = q.length > 0 ? all.filter((row) => row.search.includes(q)) : all;
|
|
98788
|
-
const items = matches.length > 0 ? matches : [
|
|
98789
|
-
{
|
|
98790
|
-
value: "",
|
|
98791
|
-
label: NO_MATCH,
|
|
98792
|
-
description: "",
|
|
98793
|
-
search: ""
|
|
98794
|
-
}
|
|
98795
|
-
];
|
|
98796
|
-
sel.options = items.map((row) => ({ name: row.label, description: row.description, value: row.value }));
|
|
98797
|
-
filterLine.content = otui.t`${otui.dim(q.length > 0 ? `filter: ${filter} (${matches.length})` : "type to filter \xB7 \u2191/\u2193 Enter \xB7 Esc to cancel")}`;
|
|
98798
|
-
sel.selectedIndex = 0;
|
|
98799
|
-
};
|
|
98800
|
-
apply();
|
|
98801
|
-
const onKey = (key) => {
|
|
98954
|
+
unsub = onKeypress4(r, (key) => {
|
|
98802
98955
|
if (key.name === "escape") {
|
|
98803
|
-
|
|
98804
|
-
resolve(undefined);
|
|
98805
|
-
key.preventDefault();
|
|
98806
|
-
key.stopPropagation();
|
|
98807
|
-
return;
|
|
98808
|
-
}
|
|
98809
|
-
if (key.name === "backspace") {
|
|
98810
|
-
filter = filter.slice(0, -1);
|
|
98811
|
-
apply();
|
|
98812
|
-
key.preventDefault();
|
|
98813
|
-
key.stopPropagation();
|
|
98814
|
-
return;
|
|
98815
|
-
}
|
|
98816
|
-
const ch = key.sequence;
|
|
98817
|
-
if (!key.ctrl && !key.meta && typeof ch === "string" && ch.length === 1 && ch >= " ") {
|
|
98818
|
-
filter += ch;
|
|
98819
|
-
apply();
|
|
98956
|
+
finish(undefined);
|
|
98820
98957
|
key.preventDefault();
|
|
98821
98958
|
key.stopPropagation();
|
|
98822
|
-
}
|
|
98823
|
-
};
|
|
98824
|
-
const unsub = onKeypress4(r, onKey);
|
|
98825
|
-
const cleanup = () => {
|
|
98826
|
-
unsub();
|
|
98827
|
-
r.root.remove(box);
|
|
98828
|
-
};
|
|
98829
|
-
sel.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
98830
|
-
const chosen = sel.getSelectedOption();
|
|
98831
|
-
cleanup();
|
|
98832
|
-
if (chosen === null || chosen.value === "" || chosen.name === NO_MATCH) {
|
|
98833
|
-
resolve(undefined);
|
|
98834
98959
|
return;
|
|
98835
98960
|
}
|
|
98836
|
-
|
|
98837
|
-
resolve(matched?.value);
|
|
98961
|
+
list.onKey(key);
|
|
98838
98962
|
});
|
|
98839
98963
|
});
|
|
98840
98964
|
}
|
|
@@ -99554,7 +99678,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
99554
99678
|
return chosen;
|
|
99555
99679
|
};
|
|
99556
99680
|
setAskUserHost(askUserInteractive);
|
|
99557
|
-
const
|
|
99681
|
+
const TRANSCRIPT_CHROME_COLS = 4;
|
|
99682
|
+
const HELP_MIN_COLS = 40;
|
|
99683
|
+
const helpText = () => {
|
|
99684
|
+
const mainWidth = chrome.main.width > 0 ? chrome.main.width : r.width - SIDEBAR_WIDTH;
|
|
99685
|
+
return renderCommandHelp("agent", undefined, Math.max(HELP_MIN_COLS, mainWidth - TRANSCRIPT_CHROME_COLS));
|
|
99686
|
+
};
|
|
99558
99687
|
const sessionCwd = opts.session?.cwd ?? process.cwd();
|
|
99559
99688
|
let permissionMode = opts.initialPermissionMode ?? getProjectPermissionMode(sessionCwd) ?? DEFAULT_PERMISSION_MODE;
|
|
99560
99689
|
io.permissionMode = () => permissionMode;
|
|
@@ -99601,7 +99730,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
99601
99730
|
return;
|
|
99602
99731
|
}
|
|
99603
99732
|
chrome.hideMenu();
|
|
99604
|
-
const pickId = await chrome.withOverlay(() => pickSessionInTui(otui,
|
|
99733
|
+
const pickId = await chrome.withOverlay(() => pickSessionInTui(otui, chrome, rows));
|
|
99605
99734
|
input.focus();
|
|
99606
99735
|
if (pickId === undefined) {
|
|
99607
99736
|
return;
|
|
@@ -100931,7 +101060,7 @@ Usage: /reasoning <${REASONING_EFFORT_LEVELS.join("|")}>
|
|
|
100931
101060
|
const prov = detected.find((d) => d.name === currentSel.provider);
|
|
100932
101061
|
const models = prov !== undefined ? await modelsForPicker(prov) : undefined;
|
|
100933
101062
|
const notice = prov === undefined || models === undefined ? undefined : modelPickerNotice(prov.label ?? prov.name, models);
|
|
100934
|
-
const chosen = await chrome.withOverlay(() => pickModelInTui(otui,
|
|
101063
|
+
const chosen = await chrome.withOverlay(() => pickModelInTui(otui, chrome, models?.models ?? [], notice));
|
|
100935
101064
|
if (chosen !== undefined) {
|
|
100936
101065
|
await switchTo(currentSel.baseUrl === undefined ? { provider: currentSel.provider, model: chosen } : { provider: currentSel.provider, model: chosen, baseUrl: currentSel.baseUrl });
|
|
100937
101066
|
try {
|
|
@@ -100968,7 +101097,7 @@ Usage: /reasoning <${REASONING_EFFORT_LEVELS.join("|")}>
|
|
|
100968
101097
|
if (command.name === "/connect" || command.name === "/provider") {
|
|
100969
101098
|
(async () => {
|
|
100970
101099
|
const detected = opts.redetect !== undefined ? await opts.redetect() : opts.detected;
|
|
100971
|
-
const ns = await chrome.withOverlay(() => command.name === "/connect" ? selectProviderModelInTui(otui,
|
|
101100
|
+
const ns = await chrome.withOverlay(() => command.name === "/connect" ? selectProviderModelInTui(otui, chrome, detected, { onlyConnected: true, env: process.env }) : selectProviderModelInTui(otui, chrome, detected));
|
|
100972
101101
|
if (ns !== undefined) {
|
|
100973
101102
|
await switchTo(ns);
|
|
100974
101103
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.116",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|