@mrciphersmith/keryx 0.2.35 → 0.2.36
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 +573 -87
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -44796,6 +44796,492 @@ class LiveMarkdownBlock {
|
|
|
44796
44796
|
|
|
44797
44797
|
// src/tui/tui-shell.ts
|
|
44798
44798
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
44799
|
+
// package.json
|
|
44800
|
+
var package_default = {
|
|
44801
|
+
name: "@mrciphersmith/keryx",
|
|
44802
|
+
version: "0.2.36",
|
|
44803
|
+
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
44804
|
+
private: false,
|
|
44805
|
+
publishConfig: {
|
|
44806
|
+
access: "public"
|
|
44807
|
+
},
|
|
44808
|
+
license: "MIT",
|
|
44809
|
+
type: "module",
|
|
44810
|
+
repository: {
|
|
44811
|
+
type: "git",
|
|
44812
|
+
url: "git+ssh://git@github.com/MrCipherSmith/keryx.git"
|
|
44813
|
+
},
|
|
44814
|
+
keywords: [
|
|
44815
|
+
"ai-agents",
|
|
44816
|
+
"coding-agents",
|
|
44817
|
+
"agent-harness",
|
|
44818
|
+
"agent-context",
|
|
44819
|
+
"repository-context",
|
|
44820
|
+
"code-graph",
|
|
44821
|
+
"project-memory",
|
|
44822
|
+
"test-impact-analysis",
|
|
44823
|
+
"developer-tools",
|
|
44824
|
+
"model-context-protocol",
|
|
44825
|
+
"mcp",
|
|
44826
|
+
"claude-code",
|
|
44827
|
+
"cursor",
|
|
44828
|
+
"codex",
|
|
44829
|
+
"cli",
|
|
44830
|
+
"bun"
|
|
44831
|
+
],
|
|
44832
|
+
bin: {
|
|
44833
|
+
keryx: "./dist/cli.js"
|
|
44834
|
+
},
|
|
44835
|
+
scripts: {
|
|
44836
|
+
keryx: "bun ./src/cli.ts",
|
|
44837
|
+
build: "bun build ./src/cli.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core && bun build ./src/harness/process/sandbox/proxy-worker.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core",
|
|
44838
|
+
prepare: "bun run build",
|
|
44839
|
+
typecheck: "tsc --noEmit",
|
|
44840
|
+
test: "bun test",
|
|
44841
|
+
check: "tsc --noEmit && bun test",
|
|
44842
|
+
"check:doc-links": "bun scripts/check-doc-links.ts",
|
|
44843
|
+
"test:guards": "bun test src/lib/config-dir.ast.test.ts src/lib/config-dir.readers.test.ts src/lib/production-graph.test.ts src/harness/policy/profiles.test.ts src/lib/serve-server.test.ts"
|
|
44844
|
+
},
|
|
44845
|
+
files: [
|
|
44846
|
+
"dist",
|
|
44847
|
+
"docs/requirements/shared-agent-context/schemas",
|
|
44848
|
+
"src/gdgraph",
|
|
44849
|
+
"src/gdskills/bundled",
|
|
44850
|
+
"src/gdskills/contracts",
|
|
44851
|
+
"LICENSE",
|
|
44852
|
+
"README.md",
|
|
44853
|
+
"package.json"
|
|
44854
|
+
],
|
|
44855
|
+
dependencies: {},
|
|
44856
|
+
optionalDependencies: {
|
|
44857
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
44858
|
+
"@opentui/core": "^0.4.5",
|
|
44859
|
+
"web-tree-sitter": "^0.22.0"
|
|
44860
|
+
},
|
|
44861
|
+
devDependencies: {
|
|
44862
|
+
"@types/bun": "latest",
|
|
44863
|
+
"@xenova/transformers": "^2.17.2",
|
|
44864
|
+
"bun-types": "latest",
|
|
44865
|
+
typescript: "^5"
|
|
44866
|
+
},
|
|
44867
|
+
engines: {
|
|
44868
|
+
bun: ">=1.1.0"
|
|
44869
|
+
},
|
|
44870
|
+
trustedDependencies: [
|
|
44871
|
+
"protobufjs",
|
|
44872
|
+
"sharp"
|
|
44873
|
+
]
|
|
44874
|
+
};
|
|
44875
|
+
|
|
44876
|
+
// src/tui/modal-host.ts
|
|
44877
|
+
function onKeypress(r, handler) {
|
|
44878
|
+
r._internalKeyInput.onInternal("keypress", handler);
|
|
44879
|
+
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
44880
|
+
}
|
|
44881
|
+
var BACKDROP_ID = "modal-backdrop";
|
|
44882
|
+
var PANEL_ID = "modal-panel";
|
|
44883
|
+
var BACKDROP_OPACITY = 0.45;
|
|
44884
|
+
var hosts = new WeakMap;
|
|
44885
|
+
function clearChildren(box) {
|
|
44886
|
+
for (const child of [...box.getChildren()]) {
|
|
44887
|
+
box.remove(child);
|
|
44888
|
+
}
|
|
44889
|
+
}
|
|
44890
|
+
function containsNode(root, node) {
|
|
44891
|
+
if (root === node) {
|
|
44892
|
+
return true;
|
|
44893
|
+
}
|
|
44894
|
+
for (const child of root.getChildren()) {
|
|
44895
|
+
if (containsNode(child, node)) {
|
|
44896
|
+
return true;
|
|
44897
|
+
}
|
|
44898
|
+
}
|
|
44899
|
+
return false;
|
|
44900
|
+
}
|
|
44901
|
+
function resolveInitialTab(tabs, initialTab) {
|
|
44902
|
+
const first = tabs[0];
|
|
44903
|
+
if (first === undefined) {
|
|
44904
|
+
return "";
|
|
44905
|
+
}
|
|
44906
|
+
if (initialTab !== undefined && tabs.some((tab) => tab.id === initialTab)) {
|
|
44907
|
+
return initialTab;
|
|
44908
|
+
}
|
|
44909
|
+
return first.id;
|
|
44910
|
+
}
|
|
44911
|
+
function paintTabs(state) {
|
|
44912
|
+
clearChildren(state.tabStrip);
|
|
44913
|
+
const labels = state.tabs.map((tab) => tab.id === state.active ? `[${tab.label}]` : ` ${tab.label} `).join(" ");
|
|
44914
|
+
state.tabStrip.add(new state.otui.TextRenderable(state.chrome.renderer, {
|
|
44915
|
+
id: "modal-tabs",
|
|
44916
|
+
content: state.otui.t`${state.otui.dim(labels)}`
|
|
44917
|
+
}));
|
|
44918
|
+
}
|
|
44919
|
+
function unmountActiveTab(state) {
|
|
44920
|
+
const cleanup = state.tabCleanup;
|
|
44921
|
+
state.tabCleanup = undefined;
|
|
44922
|
+
if (cleanup !== undefined) {
|
|
44923
|
+
cleanup();
|
|
44924
|
+
}
|
|
44925
|
+
clearChildren(state.body);
|
|
44926
|
+
}
|
|
44927
|
+
function mountTab(state, input2, tabId) {
|
|
44928
|
+
unmountActiveTab(state);
|
|
44929
|
+
state.active = tabId;
|
|
44930
|
+
paintTabs(state);
|
|
44931
|
+
const cleanup = input2.renderTab(tabId, state.body);
|
|
44932
|
+
state.tabCleanup = typeof cleanup === "function" ? cleanup : undefined;
|
|
44933
|
+
}
|
|
44934
|
+
function closeHost(state, opts) {
|
|
44935
|
+
if (!state.open) {
|
|
44936
|
+
return;
|
|
44937
|
+
}
|
|
44938
|
+
unmountActiveTab(state);
|
|
44939
|
+
state.open = false;
|
|
44940
|
+
state.input = undefined;
|
|
44941
|
+
state.backdrop.visible = false;
|
|
44942
|
+
const onClose = state.onClose;
|
|
44943
|
+
state.onClose = undefined;
|
|
44944
|
+
if (opts.restoreFocus) {
|
|
44945
|
+
const scroll = state.chrome.scroll;
|
|
44946
|
+
if (state.savedScrollTop !== undefined && scroll !== undefined) {
|
|
44947
|
+
scroll.scrollTop = state.savedScrollTop;
|
|
44948
|
+
}
|
|
44949
|
+
state.chrome.focusComposer();
|
|
44950
|
+
}
|
|
44951
|
+
if (opts.runOnClose && onClose !== undefined) {
|
|
44952
|
+
onClose();
|
|
44953
|
+
}
|
|
44954
|
+
}
|
|
44955
|
+
function ensureHost(otui, chrome) {
|
|
44956
|
+
const existing = hosts.get(chrome.renderer);
|
|
44957
|
+
if (existing !== undefined) {
|
|
44958
|
+
return existing;
|
|
44959
|
+
}
|
|
44960
|
+
const r = chrome.renderer;
|
|
44961
|
+
const backdrop = new otui.BoxRenderable(r, {
|
|
44962
|
+
id: BACKDROP_ID,
|
|
44963
|
+
position: "absolute",
|
|
44964
|
+
top: 0,
|
|
44965
|
+
left: 0,
|
|
44966
|
+
width: "100%",
|
|
44967
|
+
height: "100%",
|
|
44968
|
+
backgroundColor: "#000000",
|
|
44969
|
+
opacity: BACKDROP_OPACITY,
|
|
44970
|
+
zIndex: 100,
|
|
44971
|
+
flexDirection: "column",
|
|
44972
|
+
justifyContent: "center",
|
|
44973
|
+
alignItems: "center",
|
|
44974
|
+
visible: false
|
|
44975
|
+
});
|
|
44976
|
+
const panel = new otui.BoxRenderable(r, {
|
|
44977
|
+
id: PANEL_ID,
|
|
44978
|
+
width: "80%",
|
|
44979
|
+
maxWidth: 72,
|
|
44980
|
+
maxHeight: "80%",
|
|
44981
|
+
flexShrink: 0,
|
|
44982
|
+
flexDirection: "column",
|
|
44983
|
+
borderStyle: "rounded",
|
|
44984
|
+
border: true,
|
|
44985
|
+
borderColor: "#3a4a4a",
|
|
44986
|
+
backgroundColor: "#0f1b1b",
|
|
44987
|
+
paddingLeft: 1,
|
|
44988
|
+
paddingRight: 1,
|
|
44989
|
+
zIndex: 101
|
|
44990
|
+
});
|
|
44991
|
+
const titleText = new otui.TextRenderable(r, {
|
|
44992
|
+
id: "modal-title",
|
|
44993
|
+
content: ""
|
|
44994
|
+
});
|
|
44995
|
+
const tabStrip = new otui.BoxRenderable(r, {
|
|
44996
|
+
id: "modal-tab-strip",
|
|
44997
|
+
flexShrink: 0,
|
|
44998
|
+
width: "100%",
|
|
44999
|
+
flexDirection: "row",
|
|
45000
|
+
focusable: true
|
|
45001
|
+
});
|
|
45002
|
+
const body = new otui.BoxRenderable(r, {
|
|
45003
|
+
id: "modal-body",
|
|
45004
|
+
width: "100%",
|
|
45005
|
+
minHeight: 1,
|
|
45006
|
+
flexDirection: "column"
|
|
45007
|
+
});
|
|
45008
|
+
panel.add(titleText);
|
|
45009
|
+
panel.add(tabStrip);
|
|
45010
|
+
panel.add(body);
|
|
45011
|
+
backdrop.add(panel);
|
|
45012
|
+
r.root.add(backdrop);
|
|
45013
|
+
const state = {
|
|
45014
|
+
otui,
|
|
45015
|
+
chrome,
|
|
45016
|
+
backdrop,
|
|
45017
|
+
panel,
|
|
45018
|
+
titleText,
|
|
45019
|
+
tabStrip,
|
|
45020
|
+
body,
|
|
45021
|
+
open: false,
|
|
45022
|
+
generation: 0,
|
|
45023
|
+
tabs: [],
|
|
45024
|
+
active: "",
|
|
45025
|
+
tabCleanup: undefined,
|
|
45026
|
+
onClose: undefined,
|
|
45027
|
+
input: undefined,
|
|
45028
|
+
releaseOverlay: undefined,
|
|
45029
|
+
unsubKeys: undefined,
|
|
45030
|
+
savedScrollTop: undefined
|
|
45031
|
+
};
|
|
45032
|
+
state.releaseOverlay = chrome.addOverlaySource(() => state.open);
|
|
45033
|
+
state.unsubKeys = onKeypress(r, (key) => {
|
|
45034
|
+
if (!state.open || state.input === undefined) {
|
|
45035
|
+
return;
|
|
45036
|
+
}
|
|
45037
|
+
if (key.name === "escape") {
|
|
45038
|
+
closeHost(state, { restoreFocus: true, runOnClose: true });
|
|
45039
|
+
key.preventDefault();
|
|
45040
|
+
key.stopPropagation();
|
|
45041
|
+
return;
|
|
45042
|
+
}
|
|
45043
|
+
const idx = state.tabs.findIndex((tab) => tab.id === state.active);
|
|
45044
|
+
const focused = r.currentFocusedRenderable;
|
|
45045
|
+
const onStrip = focused !== null && containsNode(state.tabStrip, focused);
|
|
45046
|
+
if (key.name === "left" || onStrip && key.name === "tab" && key.shift === true) {
|
|
45047
|
+
const prev = idx > 0 ? state.tabs[idx - 1] : undefined;
|
|
45048
|
+
if (prev !== undefined) {
|
|
45049
|
+
mountTab(state, state.input, prev.id);
|
|
45050
|
+
}
|
|
45051
|
+
key.preventDefault();
|
|
45052
|
+
key.stopPropagation();
|
|
45053
|
+
return;
|
|
45054
|
+
}
|
|
45055
|
+
if (key.name === "right" || onStrip && key.name === "tab") {
|
|
45056
|
+
const next = state.tabs[idx + 1];
|
|
45057
|
+
if (next !== undefined) {
|
|
45058
|
+
mountTab(state, state.input, next.id);
|
|
45059
|
+
}
|
|
45060
|
+
key.preventDefault();
|
|
45061
|
+
key.stopPropagation();
|
|
45062
|
+
return;
|
|
45063
|
+
}
|
|
45064
|
+
if (focused !== null && containsNode(state.body, focused)) {
|
|
45065
|
+
return;
|
|
45066
|
+
}
|
|
45067
|
+
const digit = key.sequence.length === 1 ? key.sequence : key.name;
|
|
45068
|
+
if (digit.length === 1 && digit >= "1" && digit <= "9") {
|
|
45069
|
+
const jump = state.tabs[Number(digit) - 1];
|
|
45070
|
+
if (jump !== undefined) {
|
|
45071
|
+
mountTab(state, state.input, jump.id);
|
|
45072
|
+
key.preventDefault();
|
|
45073
|
+
key.stopPropagation();
|
|
45074
|
+
}
|
|
45075
|
+
}
|
|
45076
|
+
});
|
|
45077
|
+
hosts.set(r, state);
|
|
45078
|
+
return state;
|
|
45079
|
+
}
|
|
45080
|
+
function makeHandle(state, generation) {
|
|
45081
|
+
return {
|
|
45082
|
+
close() {
|
|
45083
|
+
if (state.generation !== generation) {
|
|
45084
|
+
return;
|
|
45085
|
+
}
|
|
45086
|
+
closeHost(state, { restoreFocus: true, runOnClose: true });
|
|
45087
|
+
},
|
|
45088
|
+
setTab(id) {
|
|
45089
|
+
if (state.generation !== generation || !state.open || state.input === undefined) {
|
|
45090
|
+
return;
|
|
45091
|
+
}
|
|
45092
|
+
if (!state.tabs.some((tab) => tab.id === id) || id === state.active) {
|
|
45093
|
+
return;
|
|
45094
|
+
}
|
|
45095
|
+
mountTab(state, state.input, id);
|
|
45096
|
+
},
|
|
45097
|
+
activeTab() {
|
|
45098
|
+
return state.active;
|
|
45099
|
+
}
|
|
45100
|
+
};
|
|
45101
|
+
}
|
|
45102
|
+
function openModal(otui, chrome, input2) {
|
|
45103
|
+
if (otui === undefined || chrome === undefined || input2.tabs.length < 1) {
|
|
45104
|
+
return;
|
|
45105
|
+
}
|
|
45106
|
+
const state = ensureHost(otui, chrome);
|
|
45107
|
+
if (state.open) {
|
|
45108
|
+
unmountActiveTab(state);
|
|
45109
|
+
const previousClose = state.onClose;
|
|
45110
|
+
state.onClose = undefined;
|
|
45111
|
+
previousClose?.();
|
|
45112
|
+
} else {
|
|
45113
|
+
state.savedScrollTop = chrome.scroll.scrollTop;
|
|
45114
|
+
chrome.hideMenu();
|
|
45115
|
+
chrome.blurComposer();
|
|
45116
|
+
state.backdrop.visible = true;
|
|
45117
|
+
state.open = true;
|
|
45118
|
+
}
|
|
45119
|
+
state.generation += 1;
|
|
45120
|
+
const generation = state.generation;
|
|
45121
|
+
state.input = input2;
|
|
45122
|
+
state.tabs = input2.tabs;
|
|
45123
|
+
state.onClose = input2.onClose;
|
|
45124
|
+
state.titleText.content = otui.t`${otui.bold(input2.title)}`;
|
|
45125
|
+
mountTab(state, input2, resolveInitialTab(input2.tabs, input2.initialTab));
|
|
45126
|
+
state.tabStrip.focus();
|
|
45127
|
+
return makeHandle(state, generation);
|
|
45128
|
+
}
|
|
45129
|
+
|
|
45130
|
+
// src/tui/session-info.ts
|
|
45131
|
+
var SESSION_INFO_COMMANDS = ["/session-info", "/status", "/info"];
|
|
45132
|
+
var MISSING = "\u2014";
|
|
45133
|
+
function isSessionInfoCommand(line) {
|
|
45134
|
+
const token = line.trim().split(/\s+/)[0] ?? "";
|
|
45135
|
+
return SESSION_INFO_COMMANDS.includes(token);
|
|
45136
|
+
}
|
|
45137
|
+
function displayOrMissing(value) {
|
|
45138
|
+
return value !== undefined && value.length > 0 ? value : MISSING;
|
|
45139
|
+
}
|
|
45140
|
+
function formatUtc(iso) {
|
|
45141
|
+
if (iso === undefined || iso.length === 0) {
|
|
45142
|
+
return MISSING;
|
|
45143
|
+
}
|
|
45144
|
+
const date = new Date(iso);
|
|
45145
|
+
if (Number.isNaN(date.getTime())) {
|
|
45146
|
+
return MISSING;
|
|
45147
|
+
}
|
|
45148
|
+
return `${date.toISOString()} UTC`;
|
|
45149
|
+
}
|
|
45150
|
+
function formatCount(value) {
|
|
45151
|
+
return value === undefined ? MISSING : String(value);
|
|
45152
|
+
}
|
|
45153
|
+
function usageUsed(usage) {
|
|
45154
|
+
if (usage === undefined) {
|
|
45155
|
+
return;
|
|
45156
|
+
}
|
|
45157
|
+
if (usage.totalTokens !== undefined) {
|
|
45158
|
+
return usage.totalTokens;
|
|
45159
|
+
}
|
|
45160
|
+
if (usage.inputTokens === undefined && usage.outputTokens === undefined) {
|
|
45161
|
+
return;
|
|
45162
|
+
}
|
|
45163
|
+
return (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
|
|
45164
|
+
}
|
|
45165
|
+
function contextRow(source) {
|
|
45166
|
+
const used = usageUsed(source.usage);
|
|
45167
|
+
if (used !== undefined) {
|
|
45168
|
+
return `${used} tokens`;
|
|
45169
|
+
}
|
|
45170
|
+
if (source.estimateTokens !== undefined) {
|
|
45171
|
+
return `${source.estimateTokens} tokens (estimate)`;
|
|
45172
|
+
}
|
|
45173
|
+
return MISSING;
|
|
45174
|
+
}
|
|
45175
|
+
function buildSessionInfoSnapshot(source) {
|
|
45176
|
+
const id = source.summary?.id ?? "";
|
|
45177
|
+
const provider = source.selection?.provider ?? source.summary?.provider;
|
|
45178
|
+
const model = source.selection?.model ?? source.summary?.model;
|
|
45179
|
+
const sessionRows = [
|
|
45180
|
+
{ label: "Title", value: displayOrMissing(source.summary?.title) },
|
|
45181
|
+
{ label: "Version", value: displayOrMissing(source.version) },
|
|
45182
|
+
{ label: "Session id", value: displayOrMissing(source.summary?.id) },
|
|
45183
|
+
{ label: "Project", value: displayOrMissing(source.summary?.projectPath) },
|
|
45184
|
+
{ label: "Provider", value: displayOrMissing(provider) },
|
|
45185
|
+
{ label: "Model", value: displayOrMissing(model) }
|
|
45186
|
+
];
|
|
45187
|
+
if (source.summary?.parentSessionId !== undefined && source.summary.parentSessionId.length > 0) {
|
|
45188
|
+
sessionRows.push({ label: "Parent", value: source.summary.parentSessionId });
|
|
45189
|
+
}
|
|
45190
|
+
const messages = source.summary?.messageCount === undefined && source.summary?.archiveMessageCount === undefined ? MISSING : `${formatCount(source.summary.messageCount)} / ${formatCount(source.summary.archiveMessageCount)}`;
|
|
45191
|
+
sessionRows.push({ label: "Created", value: formatUtc(source.summary?.createdAt) }, { label: "Updated", value: formatUtc(source.summary?.updatedAt) }, { label: "Messages", value: messages }, { label: "Compactions", value: formatCount(source.summary?.compactCount) }, { label: "Context", value: contextRow(source) });
|
|
45192
|
+
const estimate = source.estimateTokens === undefined ? MISSING : `${source.estimateTokens} tokens (estimate)`;
|
|
45193
|
+
const usageRows = [
|
|
45194
|
+
{
|
|
45195
|
+
label: "Last turn input",
|
|
45196
|
+
value: source.usage?.inputTokens === undefined ? MISSING : String(source.usage.inputTokens)
|
|
45197
|
+
},
|
|
45198
|
+
{
|
|
45199
|
+
label: "Last turn output",
|
|
45200
|
+
value: source.usage?.outputTokens === undefined ? MISSING : String(source.usage.outputTokens)
|
|
45201
|
+
},
|
|
45202
|
+
{ label: "Context estimate", value: estimate }
|
|
45203
|
+
];
|
|
45204
|
+
return { sessionId: id, sessionRows, usageRows };
|
|
45205
|
+
}
|
|
45206
|
+
function formatSection(title, rows) {
|
|
45207
|
+
const width = rows.reduce((max, row) => Math.max(max, row.label.length), 0);
|
|
45208
|
+
return [title, ...rows.map((row) => ` ${row.label.padEnd(width)} ${row.value}`)].join(`
|
|
45209
|
+
`);
|
|
45210
|
+
}
|
|
45211
|
+
function formatSessionInfoText(snapshot) {
|
|
45212
|
+
return `${formatSection("Session", snapshot.sessionRows)}
|
|
45213
|
+
|
|
45214
|
+
${formatSection("Usage", snapshot.usageRows)}
|
|
45215
|
+
`;
|
|
45216
|
+
}
|
|
45217
|
+
function sessionIdCopyText(snapshot) {
|
|
45218
|
+
return snapshot.sessionId;
|
|
45219
|
+
}
|
|
45220
|
+
function sessionBlockCopyText(snapshot) {
|
|
45221
|
+
return formatSessionInfoText(snapshot);
|
|
45222
|
+
}
|
|
45223
|
+
function paintRows(otui, renderer, body, rows) {
|
|
45224
|
+
if (otui === undefined || otui === null || body === undefined || body === null) {
|
|
45225
|
+
return;
|
|
45226
|
+
}
|
|
45227
|
+
const parent = body;
|
|
45228
|
+
const ctor = otui.TextRenderable;
|
|
45229
|
+
if (parent.add === undefined || ctor === undefined) {
|
|
45230
|
+
return;
|
|
45231
|
+
}
|
|
45232
|
+
const width = rows.reduce((max, row) => Math.max(max, row.label.length), 0);
|
|
45233
|
+
parent.add(new ctor(renderer, {
|
|
45234
|
+
id: "session-info-body",
|
|
45235
|
+
content: rows.map((row) => `${row.label.padEnd(width)} ${row.value}`).join(`
|
|
45236
|
+
`)
|
|
45237
|
+
}));
|
|
45238
|
+
}
|
|
45239
|
+
function presentSessionInfo(openModal2, otui, chrome, options) {
|
|
45240
|
+
const { snapshot, toast } = options;
|
|
45241
|
+
const copy = (text) => {
|
|
45242
|
+
if (text.length === 0) {
|
|
45243
|
+
return;
|
|
45244
|
+
}
|
|
45245
|
+
try {
|
|
45246
|
+
options.copyText(text);
|
|
45247
|
+
toast("Copied to clipboard");
|
|
45248
|
+
} catch {}
|
|
45249
|
+
};
|
|
45250
|
+
let unsubscribeKey;
|
|
45251
|
+
const handle = openModal2(otui, chrome, {
|
|
45252
|
+
title: "Session",
|
|
45253
|
+
tabs: [
|
|
45254
|
+
{ id: "session", label: "Session" },
|
|
45255
|
+
{ id: "usage", label: "Usage" }
|
|
45256
|
+
],
|
|
45257
|
+
initialTab: "session",
|
|
45258
|
+
renderTab: (tabId, body) => {
|
|
45259
|
+
const rows = tabId === "usage" ? snapshot.usageRows : snapshot.sessionRows;
|
|
45260
|
+
const renderer = options.renderer ?? chrome?.renderer;
|
|
45261
|
+
paintRows(otui, renderer, body, rows);
|
|
45262
|
+
},
|
|
45263
|
+
onClose: () => {
|
|
45264
|
+
unsubscribeKey?.();
|
|
45265
|
+
}
|
|
45266
|
+
});
|
|
45267
|
+
if (handle === undefined) {
|
|
45268
|
+
return;
|
|
45269
|
+
}
|
|
45270
|
+
if (options.onKeypress !== undefined) {
|
|
45271
|
+
unsubscribeKey = options.onKeypress((key) => {
|
|
45272
|
+
const token = key.name || key.sequence;
|
|
45273
|
+
if (token === "c") {
|
|
45274
|
+
copy(sessionIdCopyText(snapshot));
|
|
45275
|
+
} else if (token === "y") {
|
|
45276
|
+
copy(sessionBlockCopyText(snapshot));
|
|
45277
|
+
}
|
|
45278
|
+
});
|
|
45279
|
+
}
|
|
45280
|
+
return handle;
|
|
45281
|
+
}
|
|
45282
|
+
function openSessionInfo(otui, chrome, options) {
|
|
45283
|
+
return presentSessionInfo((hostOtui, hostChrome, input2) => openModal(hostOtui, hostChrome, input2), otui, chrome, options);
|
|
45284
|
+
}
|
|
44799
45285
|
|
|
44800
45286
|
// src/commands/agent-commands.ts
|
|
44801
45287
|
var CHAT_ONLY = ["chat"];
|
|
@@ -44854,6 +45340,13 @@ var AGENT_SLASH_COMMANDS = [
|
|
|
44854
45340
|
{ name: "/new", description: "Start a new session (old kept on disk)", modes: BOTH },
|
|
44855
45341
|
{ name: "/resume", description: "Resume a prior session in this project", modes: AGENT_ONLY },
|
|
44856
45342
|
{ name: "/sessions", description: "Open the session list and switch to one", modes: AGENT_ONLY },
|
|
45343
|
+
{
|
|
45344
|
+
name: "/session-info",
|
|
45345
|
+
description: "Show session identity and context usage",
|
|
45346
|
+
modes: BOTH
|
|
45347
|
+
},
|
|
45348
|
+
{ name: "/status", description: "Alias of /session-info", modes: BOTH },
|
|
45349
|
+
{ name: "/info", description: "Alias of /session-info", modes: BOTH },
|
|
44857
45350
|
{
|
|
44858
45351
|
name: "/compact",
|
|
44859
45352
|
description: "Compact model context \u2014 /compact [focus] (archive kept)",
|
|
@@ -45334,7 +45827,7 @@ function selectBoxHeight(count, withDescription) {
|
|
|
45334
45827
|
const per = withDescription ? 2 : 1;
|
|
45335
45828
|
return Math.min(Math.max(count * per, per), 16);
|
|
45336
45829
|
}
|
|
45337
|
-
function
|
|
45830
|
+
function onKeypress2(r, handler) {
|
|
45338
45831
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
45339
45832
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
45340
45833
|
}
|
|
@@ -45435,7 +45928,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
45435
45928
|
key.stopPropagation();
|
|
45436
45929
|
}
|
|
45437
45930
|
};
|
|
45438
|
-
const unsub =
|
|
45931
|
+
const unsub = onKeypress2(r, onKey);
|
|
45439
45932
|
sel.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
45440
45933
|
const chosen = sel.getSelectedOption();
|
|
45441
45934
|
const value = chosen?.value;
|
|
@@ -45723,7 +46216,7 @@ async function checkVersion(options) {
|
|
|
45723
46216
|
}
|
|
45724
46217
|
|
|
45725
46218
|
// src/tui/shell-chrome.ts
|
|
45726
|
-
function
|
|
46219
|
+
function onKeypress3(r, handler) {
|
|
45727
46220
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
45728
46221
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
45729
46222
|
}
|
|
@@ -46153,7 +46646,7 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
46153
46646
|
syncComposerHeight();
|
|
46154
46647
|
emitSubmit(line);
|
|
46155
46648
|
};
|
|
46156
|
-
const unsubscribeMenuKeys =
|
|
46649
|
+
const unsubscribeMenuKeys = onKeypress3(r, (key) => {
|
|
46157
46650
|
if (!menu.visible || !menuNav || overlayActive()) {
|
|
46158
46651
|
return;
|
|
46159
46652
|
}
|
|
@@ -47601,7 +48094,7 @@ function overlayBox(otui, r, id) {
|
|
|
47601
48094
|
padding: 1
|
|
47602
48095
|
});
|
|
47603
48096
|
}
|
|
47604
|
-
function
|
|
48097
|
+
function onKeypress4(r, handler) {
|
|
47605
48098
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
47606
48099
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
47607
48100
|
}
|
|
@@ -47646,7 +48139,7 @@ function promptBaseUrlStep(otui, r, label, baseUrl2) {
|
|
|
47646
48139
|
unsub();
|
|
47647
48140
|
r.root.remove(box);
|
|
47648
48141
|
};
|
|
47649
|
-
const unsub =
|
|
48142
|
+
const unsub = onKeypress4(r, (key) => {
|
|
47650
48143
|
if (key.name === "escape") {
|
|
47651
48144
|
cleanup();
|
|
47652
48145
|
resolve3(undefined);
|
|
@@ -47682,7 +48175,7 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
47682
48175
|
key.stopPropagation();
|
|
47683
48176
|
}
|
|
47684
48177
|
};
|
|
47685
|
-
const unsub =
|
|
48178
|
+
const unsub = onKeypress4(r, onKey);
|
|
47686
48179
|
const cleanup = () => {
|
|
47687
48180
|
unsub();
|
|
47688
48181
|
r.root.remove(box);
|
|
@@ -47722,7 +48215,7 @@ function pickProviderStep(otui, r, detected) {
|
|
|
47722
48215
|
key.stopPropagation();
|
|
47723
48216
|
}
|
|
47724
48217
|
};
|
|
47725
|
-
const unsub =
|
|
48218
|
+
const unsub = onKeypress4(r, onKey);
|
|
47726
48219
|
const cleanup = () => {
|
|
47727
48220
|
unsub();
|
|
47728
48221
|
r.root.remove(box);
|
|
@@ -47840,7 +48333,7 @@ function pickModelInTui(otui, r, models) {
|
|
|
47840
48333
|
key.stopPropagation();
|
|
47841
48334
|
}
|
|
47842
48335
|
};
|
|
47843
|
-
const unsub =
|
|
48336
|
+
const unsub = onKeypress4(r, onKey);
|
|
47844
48337
|
const cleanup = () => {
|
|
47845
48338
|
unsub();
|
|
47846
48339
|
r.root.remove(box);
|
|
@@ -47932,7 +48425,7 @@ function pickSessionInTui(otui, r, sessions) {
|
|
|
47932
48425
|
key.stopPropagation();
|
|
47933
48426
|
}
|
|
47934
48427
|
};
|
|
47935
|
-
const unsub =
|
|
48428
|
+
const unsub = onKeypress4(r, onKey);
|
|
47936
48429
|
const cleanup = () => {
|
|
47937
48430
|
unsub();
|
|
47938
48431
|
r.root.remove(box);
|
|
@@ -48117,6 +48610,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
48117
48610
|
hasExactUsage = true;
|
|
48118
48611
|
}
|
|
48119
48612
|
});
|
|
48613
|
+
let lastUsage;
|
|
48614
|
+
const recordedUsage = io.onUsage?.bind(io);
|
|
48615
|
+
io.onUsage = (usage) => {
|
|
48616
|
+
lastUsage = usage;
|
|
48617
|
+
recordedUsage?.(usage);
|
|
48618
|
+
};
|
|
48120
48619
|
attachBlockIo(io, addBlock, {
|
|
48121
48620
|
onReasoning: () => {
|
|
48122
48621
|
setBusyPhase("thinking");
|
|
@@ -48513,6 +49012,22 @@ Staying in the current session.
|
|
|
48513
49012
|
`);
|
|
48514
49013
|
};
|
|
48515
49014
|
paintSessionHeader();
|
|
49015
|
+
const showSessionInfo = () => {
|
|
49016
|
+
const snapshot = buildSessionInfoSnapshot({
|
|
49017
|
+
summary: liveSession.summary,
|
|
49018
|
+
selection: currentSel,
|
|
49019
|
+
version: package_default.version,
|
|
49020
|
+
usage: lastUsage,
|
|
49021
|
+
estimateTokens: estimateContextTokens(history)
|
|
49022
|
+
});
|
|
49023
|
+
openSessionInfo(otui, chrome, {
|
|
49024
|
+
snapshot,
|
|
49025
|
+
copyText: (text) => r.copyToClipboardOSC52(text),
|
|
49026
|
+
toast: (message2) => chrome.showToast(message2),
|
|
49027
|
+
renderer: r,
|
|
49028
|
+
onKeypress: (handler) => onKeypress4(r, (key) => handler(key))
|
|
49029
|
+
});
|
|
49030
|
+
};
|
|
48516
49031
|
const updateModelLabels = () => {
|
|
48517
49032
|
paintSessionHeader();
|
|
48518
49033
|
const label = `${currentSel.provider}/${currentSel.model}`;
|
|
@@ -48718,6 +49233,10 @@ Staying in the current session.
|
|
|
48718
49233
|
`);
|
|
48719
49234
|
return;
|
|
48720
49235
|
}
|
|
49236
|
+
if (command2 !== undefined && isSessionInfoCommand(command2.name)) {
|
|
49237
|
+
showSessionInfo();
|
|
49238
|
+
return;
|
|
49239
|
+
}
|
|
48721
49240
|
if (command2 !== undefined || line.startsWith("/")) {
|
|
48722
49241
|
transcript.add(new otui.TextRenderable(r, {
|
|
48723
49242
|
id: `c${uid++}`,
|
|
@@ -48859,6 +49378,10 @@ Staying in the current session.
|
|
|
48859
49378
|
}
|
|
48860
49379
|
return;
|
|
48861
49380
|
}
|
|
49381
|
+
if (isSessionInfoCommand(command.name)) {
|
|
49382
|
+
showSessionInfo();
|
|
49383
|
+
return;
|
|
49384
|
+
}
|
|
48862
49385
|
if (command.name === "/copy") {
|
|
48863
49386
|
const target = newestBlock();
|
|
48864
49387
|
if (target === undefined || !copyBlock(target.id)) {
|
|
@@ -49078,7 +49601,7 @@ Staying in the current session.
|
|
|
49078
49601
|
focusComposer();
|
|
49079
49602
|
});
|
|
49080
49603
|
};
|
|
49081
|
-
|
|
49604
|
+
onKeypress4(r, (key) => {
|
|
49082
49605
|
nav.handleKey(key);
|
|
49083
49606
|
});
|
|
49084
49607
|
chrome.onSubmit((line) => {
|
|
@@ -49204,6 +49727,9 @@ function createChatBridge(hooks = {}) {
|
|
|
49204
49727
|
close();
|
|
49205
49728
|
return "exit";
|
|
49206
49729
|
}
|
|
49730
|
+
if (isSessionInfoCommand(value)) {
|
|
49731
|
+
return "local";
|
|
49732
|
+
}
|
|
49207
49733
|
if ((turn || queue.length > 0) && value.startsWith("/")) {
|
|
49208
49734
|
return "deferred";
|
|
49209
49735
|
}
|
|
@@ -49327,6 +49853,22 @@ async function mountChatShell(otui, renderer, opts) {
|
|
|
49327
49853
|
opts.onExit?.();
|
|
49328
49854
|
return;
|
|
49329
49855
|
}
|
|
49856
|
+
if (result === "local") {
|
|
49857
|
+
const snapshot = buildSessionInfoSnapshot({
|
|
49858
|
+
summary: opts.deps.session !== undefined ? latestSession(opts.deps.session.cwd) : undefined,
|
|
49859
|
+
selection,
|
|
49860
|
+
version: package_default.version,
|
|
49861
|
+
estimateTokens: estimateContextTokens(seen)
|
|
49862
|
+
});
|
|
49863
|
+
openSessionInfo(otui, chrome, {
|
|
49864
|
+
snapshot,
|
|
49865
|
+
copyText: (text) => r.copyToClipboardOSC52(text),
|
|
49866
|
+
toast: (message2) => chrome.showToast(message2),
|
|
49867
|
+
renderer: r,
|
|
49868
|
+
onKeypress: (handler) => onKeypress4(r, (key) => handler(key))
|
|
49869
|
+
});
|
|
49870
|
+
return;
|
|
49871
|
+
}
|
|
49330
49872
|
if (result === "deferred") {
|
|
49331
49873
|
append(otui.t`${otui.yellow("\u25C7 a reply is still streaming \u2014 command deferred. Wait for it to finish.")}`);
|
|
49332
49874
|
}
|
|
@@ -49413,82 +49955,6 @@ async function launchTuiChatShell(opts) {
|
|
|
49413
49955
|
|
|
49414
49956
|
// src/commands/shell.ts
|
|
49415
49957
|
init_shell_config();
|
|
49416
|
-
// package.json
|
|
49417
|
-
var package_default = {
|
|
49418
|
-
name: "@mrciphersmith/keryx",
|
|
49419
|
-
version: "0.2.35",
|
|
49420
|
-
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
49421
|
-
private: false,
|
|
49422
|
-
publishConfig: {
|
|
49423
|
-
access: "public"
|
|
49424
|
-
},
|
|
49425
|
-
license: "MIT",
|
|
49426
|
-
type: "module",
|
|
49427
|
-
repository: {
|
|
49428
|
-
type: "git",
|
|
49429
|
-
url: "git+ssh://git@github.com/MrCipherSmith/keryx.git"
|
|
49430
|
-
},
|
|
49431
|
-
keywords: [
|
|
49432
|
-
"ai-agents",
|
|
49433
|
-
"coding-agents",
|
|
49434
|
-
"agent-harness",
|
|
49435
|
-
"agent-context",
|
|
49436
|
-
"repository-context",
|
|
49437
|
-
"code-graph",
|
|
49438
|
-
"project-memory",
|
|
49439
|
-
"test-impact-analysis",
|
|
49440
|
-
"developer-tools",
|
|
49441
|
-
"model-context-protocol",
|
|
49442
|
-
"mcp",
|
|
49443
|
-
"claude-code",
|
|
49444
|
-
"cursor",
|
|
49445
|
-
"codex",
|
|
49446
|
-
"cli",
|
|
49447
|
-
"bun"
|
|
49448
|
-
],
|
|
49449
|
-
bin: {
|
|
49450
|
-
keryx: "./dist/cli.js"
|
|
49451
|
-
},
|
|
49452
|
-
scripts: {
|
|
49453
|
-
keryx: "bun ./src/cli.ts",
|
|
49454
|
-
build: "bun build ./src/cli.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core && bun build ./src/harness/process/sandbox/proxy-worker.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core",
|
|
49455
|
-
prepare: "bun run build",
|
|
49456
|
-
typecheck: "tsc --noEmit",
|
|
49457
|
-
test: "bun test",
|
|
49458
|
-
check: "tsc --noEmit && bun test",
|
|
49459
|
-
"check:doc-links": "bun scripts/check-doc-links.ts",
|
|
49460
|
-
"test:guards": "bun test src/lib/config-dir.ast.test.ts src/lib/config-dir.readers.test.ts src/lib/production-graph.test.ts src/harness/policy/profiles.test.ts src/lib/serve-server.test.ts"
|
|
49461
|
-
},
|
|
49462
|
-
files: [
|
|
49463
|
-
"dist",
|
|
49464
|
-
"docs/requirements/shared-agent-context/schemas",
|
|
49465
|
-
"src/gdgraph",
|
|
49466
|
-
"src/gdskills/bundled",
|
|
49467
|
-
"src/gdskills/contracts",
|
|
49468
|
-
"LICENSE",
|
|
49469
|
-
"README.md",
|
|
49470
|
-
"package.json"
|
|
49471
|
-
],
|
|
49472
|
-
dependencies: {},
|
|
49473
|
-
optionalDependencies: {
|
|
49474
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49475
|
-
"@opentui/core": "^0.4.5",
|
|
49476
|
-
"web-tree-sitter": "^0.22.0"
|
|
49477
|
-
},
|
|
49478
|
-
devDependencies: {
|
|
49479
|
-
"@types/bun": "latest",
|
|
49480
|
-
"@xenova/transformers": "^2.17.2",
|
|
49481
|
-
"bun-types": "latest",
|
|
49482
|
-
typescript: "^5"
|
|
49483
|
-
},
|
|
49484
|
-
engines: {
|
|
49485
|
-
bun: ">=1.1.0"
|
|
49486
|
-
},
|
|
49487
|
-
trustedDependencies: [
|
|
49488
|
-
"protobufjs",
|
|
49489
|
-
"sharp"
|
|
49490
|
-
]
|
|
49491
|
-
};
|
|
49492
49958
|
|
|
49493
49959
|
// src/commands/select.ts
|
|
49494
49960
|
init_guard2();
|
|
@@ -49727,6 +50193,9 @@ var READLINE_AGENT_COMMANDS = [
|
|
|
49727
50193
|
"/new",
|
|
49728
50194
|
"/clear",
|
|
49729
50195
|
"/compact",
|
|
50196
|
+
"/session-info",
|
|
50197
|
+
"/status",
|
|
50198
|
+
"/info",
|
|
49730
50199
|
"/exit"
|
|
49731
50200
|
];
|
|
49732
50201
|
function readlineAgentHelpText() {
|
|
@@ -49815,6 +50284,15 @@ Starting a new session.
|
|
|
49815
50284
|
system(HELP_TEXT);
|
|
49816
50285
|
continue;
|
|
49817
50286
|
}
|
|
50287
|
+
if (isSessionInfoCommand(command)) {
|
|
50288
|
+
system(formatSessionInfoText(buildSessionInfoSnapshot({
|
|
50289
|
+
summary: live?.summary,
|
|
50290
|
+
selection: { provider: providerName, model: modelName },
|
|
50291
|
+
version: package_default.version,
|
|
50292
|
+
estimateTokens: estimateContextTokens(history)
|
|
50293
|
+
})));
|
|
50294
|
+
continue;
|
|
50295
|
+
}
|
|
49818
50296
|
if (command === "/clear" || command === "/new") {
|
|
49819
50297
|
if (sessionsOn) {
|
|
49820
50298
|
live = createSession({ cwd: sessionCwd, provider: providerName, model: modelName });
|
|
@@ -50462,6 +50940,14 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
50462
50940
|
}
|
|
50463
50941
|
if (command === "/help") {
|
|
50464
50942
|
agentIo.onSystem?.(readlineAgentHelpText());
|
|
50943
|
+
} else if (isSessionInfoCommand(command)) {
|
|
50944
|
+
agentIo.onSystem?.(formatSessionInfoText(buildSessionInfoSnapshot({
|
|
50945
|
+
summary: live?.summary,
|
|
50946
|
+
selection: { provider: deps.providerId, model: deps.modelId },
|
|
50947
|
+
version: package_default.version,
|
|
50948
|
+
usage: lastUsage,
|
|
50949
|
+
estimateTokens: estimateContextTokens(history)
|
|
50950
|
+
})));
|
|
50465
50951
|
} else if (command === "/expand") {
|
|
50466
50952
|
const expanded = expandedToolOutput(lastToolName, lastToolOutput);
|
|
50467
50953
|
if (expanded !== undefined) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.36",
|
|
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": {
|