@mrciphersmith/keryx 0.2.35 → 0.2.37
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 +1091 -114
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -41726,7 +41726,7 @@ function harnessWave(args, deps) {
|
|
|
41726
41726
|
// src/commands/shell.ts
|
|
41727
41727
|
init_make_provider();
|
|
41728
41728
|
init_orient();
|
|
41729
|
-
import { randomUUID as
|
|
41729
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
41730
41730
|
import * as readline2 from "readline";
|
|
41731
41731
|
|
|
41732
41732
|
// src/harness/tool/builtin/ask-user-tool.ts
|
|
@@ -44796,6 +44796,906 @@ 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.37",
|
|
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 MODAL_PANEL_WIDTH = 72;
|
|
44885
|
+
var MODAL_PANEL_HEIGHT = 18;
|
|
44886
|
+
var MODAL_PANEL_INNER_WIDTH = MODAL_PANEL_WIDTH - 4;
|
|
44887
|
+
var CLOSE_HINT = "[x] esc";
|
|
44888
|
+
var DEFAULT_FOOTER = [
|
|
44889
|
+
{ key: "\u2190/\u2192", label: "tabs" },
|
|
44890
|
+
{ key: "esc", label: "close" }
|
|
44891
|
+
];
|
|
44892
|
+
function formatModalFooter(actions) {
|
|
44893
|
+
return actions.map((action) => `${action.key} ${action.label}`).join(" \xB7 ");
|
|
44894
|
+
}
|
|
44895
|
+
var hosts = new WeakMap;
|
|
44896
|
+
function clearChildren(box) {
|
|
44897
|
+
for (const child of [...box.getChildren()]) {
|
|
44898
|
+
box.remove(child);
|
|
44899
|
+
}
|
|
44900
|
+
}
|
|
44901
|
+
function containsNode(root, node) {
|
|
44902
|
+
if (root === node) {
|
|
44903
|
+
return true;
|
|
44904
|
+
}
|
|
44905
|
+
for (const child of root.getChildren()) {
|
|
44906
|
+
if (containsNode(child, node)) {
|
|
44907
|
+
return true;
|
|
44908
|
+
}
|
|
44909
|
+
}
|
|
44910
|
+
return false;
|
|
44911
|
+
}
|
|
44912
|
+
function resolveInitialTab(tabs, initialTab) {
|
|
44913
|
+
const first = tabs[0];
|
|
44914
|
+
if (first === undefined) {
|
|
44915
|
+
return "";
|
|
44916
|
+
}
|
|
44917
|
+
if (initialTab !== undefined && tabs.some((tab) => tab.id === initialTab)) {
|
|
44918
|
+
return initialTab;
|
|
44919
|
+
}
|
|
44920
|
+
return first.id;
|
|
44921
|
+
}
|
|
44922
|
+
function paintTabs(state) {
|
|
44923
|
+
clearChildren(state.tabStrip);
|
|
44924
|
+
const labels = state.tabs.map((tab) => tab.id === state.active ? `[${tab.label}]` : ` ${tab.label} `).join(" ");
|
|
44925
|
+
state.tabStrip.add(new state.otui.TextRenderable(state.chrome.renderer, {
|
|
44926
|
+
id: "modal-tabs",
|
|
44927
|
+
content: state.otui.t`${state.otui.dim(labels)}`
|
|
44928
|
+
}));
|
|
44929
|
+
}
|
|
44930
|
+
function paintHeader(state, title) {
|
|
44931
|
+
state.titleText.content = state.otui.t`${state.otui.bold(title)}`;
|
|
44932
|
+
state.closeText.content = state.otui.t`${state.otui.dim(CLOSE_HINT)}`;
|
|
44933
|
+
}
|
|
44934
|
+
function paintFooter(state, actions) {
|
|
44935
|
+
const items = actions !== undefined && actions.length > 0 ? actions : DEFAULT_FOOTER;
|
|
44936
|
+
state.footerText.content = state.otui.t`${state.otui.dim(formatModalFooter(items))}`;
|
|
44937
|
+
}
|
|
44938
|
+
function unmountActiveTab(state) {
|
|
44939
|
+
const cleanup = state.tabCleanup;
|
|
44940
|
+
state.tabCleanup = undefined;
|
|
44941
|
+
if (cleanup !== undefined) {
|
|
44942
|
+
cleanup();
|
|
44943
|
+
}
|
|
44944
|
+
clearChildren(state.body);
|
|
44945
|
+
}
|
|
44946
|
+
function mountTab(state, input2, tabId) {
|
|
44947
|
+
unmountActiveTab(state);
|
|
44948
|
+
state.active = tabId;
|
|
44949
|
+
paintTabs(state);
|
|
44950
|
+
const cleanup = input2.renderTab(tabId, state.body);
|
|
44951
|
+
state.tabCleanup = typeof cleanup === "function" ? cleanup : undefined;
|
|
44952
|
+
}
|
|
44953
|
+
function closeHost(state, opts) {
|
|
44954
|
+
if (!state.open) {
|
|
44955
|
+
return;
|
|
44956
|
+
}
|
|
44957
|
+
unmountActiveTab(state);
|
|
44958
|
+
state.open = false;
|
|
44959
|
+
state.input = undefined;
|
|
44960
|
+
state.backdrop.visible = false;
|
|
44961
|
+
const onClose = state.onClose;
|
|
44962
|
+
state.onClose = undefined;
|
|
44963
|
+
if (opts.restoreFocus) {
|
|
44964
|
+
const scroll = state.chrome.scroll;
|
|
44965
|
+
if (state.savedScrollTop !== undefined && scroll !== undefined) {
|
|
44966
|
+
scroll.scrollTop = state.savedScrollTop;
|
|
44967
|
+
}
|
|
44968
|
+
state.chrome.focusComposer();
|
|
44969
|
+
}
|
|
44970
|
+
if (opts.runOnClose && onClose !== undefined) {
|
|
44971
|
+
onClose();
|
|
44972
|
+
}
|
|
44973
|
+
}
|
|
44974
|
+
function ensureHost(otui, chrome) {
|
|
44975
|
+
const existing = hosts.get(chrome.renderer);
|
|
44976
|
+
if (existing !== undefined) {
|
|
44977
|
+
return existing;
|
|
44978
|
+
}
|
|
44979
|
+
const r = chrome.renderer;
|
|
44980
|
+
const backdrop = new otui.BoxRenderable(r, {
|
|
44981
|
+
id: BACKDROP_ID,
|
|
44982
|
+
position: "absolute",
|
|
44983
|
+
top: 0,
|
|
44984
|
+
left: 0,
|
|
44985
|
+
width: "100%",
|
|
44986
|
+
height: "100%",
|
|
44987
|
+
backgroundColor: "#000000",
|
|
44988
|
+
opacity: BACKDROP_OPACITY,
|
|
44989
|
+
zIndex: 100,
|
|
44990
|
+
flexDirection: "column",
|
|
44991
|
+
justifyContent: "center",
|
|
44992
|
+
alignItems: "center",
|
|
44993
|
+
visible: false
|
|
44994
|
+
});
|
|
44995
|
+
const panel = new otui.BoxRenderable(r, {
|
|
44996
|
+
id: PANEL_ID,
|
|
44997
|
+
width: MODAL_PANEL_WIDTH,
|
|
44998
|
+
height: MODAL_PANEL_HEIGHT,
|
|
44999
|
+
flexShrink: 0,
|
|
45000
|
+
flexGrow: 0,
|
|
45001
|
+
flexDirection: "column",
|
|
45002
|
+
borderStyle: "rounded",
|
|
45003
|
+
border: true,
|
|
45004
|
+
borderColor: "#3a4a4a",
|
|
45005
|
+
backgroundColor: "#0f1b1b",
|
|
45006
|
+
paddingLeft: 1,
|
|
45007
|
+
paddingRight: 1,
|
|
45008
|
+
zIndex: 101
|
|
45009
|
+
});
|
|
45010
|
+
const header3 = new otui.BoxRenderable(r, {
|
|
45011
|
+
id: "modal-header",
|
|
45012
|
+
width: "100%",
|
|
45013
|
+
height: 1,
|
|
45014
|
+
flexShrink: 0,
|
|
45015
|
+
flexDirection: "row",
|
|
45016
|
+
justifyContent: "space-between"
|
|
45017
|
+
});
|
|
45018
|
+
const titleText = new otui.TextRenderable(r, {
|
|
45019
|
+
id: "modal-title",
|
|
45020
|
+
content: "",
|
|
45021
|
+
flexGrow: 1
|
|
45022
|
+
});
|
|
45023
|
+
const closeText = new otui.TextRenderable(r, {
|
|
45024
|
+
id: "modal-close",
|
|
45025
|
+
content: "",
|
|
45026
|
+
flexShrink: 0
|
|
45027
|
+
});
|
|
45028
|
+
header3.add(titleText);
|
|
45029
|
+
header3.add(closeText);
|
|
45030
|
+
const tabStrip = new otui.BoxRenderable(r, {
|
|
45031
|
+
id: "modal-tab-strip",
|
|
45032
|
+
flexShrink: 0,
|
|
45033
|
+
width: "100%",
|
|
45034
|
+
height: 1,
|
|
45035
|
+
flexDirection: "row",
|
|
45036
|
+
focusable: true
|
|
45037
|
+
});
|
|
45038
|
+
const body = new otui.BoxRenderable(r, {
|
|
45039
|
+
id: "modal-body",
|
|
45040
|
+
width: "100%",
|
|
45041
|
+
flexGrow: 1,
|
|
45042
|
+
minHeight: 1,
|
|
45043
|
+
flexDirection: "column"
|
|
45044
|
+
});
|
|
45045
|
+
const footer = new otui.BoxRenderable(r, {
|
|
45046
|
+
id: "modal-footer",
|
|
45047
|
+
width: "100%",
|
|
45048
|
+
height: 1,
|
|
45049
|
+
flexShrink: 0,
|
|
45050
|
+
flexDirection: "row"
|
|
45051
|
+
});
|
|
45052
|
+
const footerText = new otui.TextRenderable(r, {
|
|
45053
|
+
id: "modal-footer-text",
|
|
45054
|
+
content: ""
|
|
45055
|
+
});
|
|
45056
|
+
footer.add(footerText);
|
|
45057
|
+
panel.add(header3);
|
|
45058
|
+
panel.add(tabStrip);
|
|
45059
|
+
panel.add(body);
|
|
45060
|
+
panel.add(footer);
|
|
45061
|
+
backdrop.add(panel);
|
|
45062
|
+
r.root.add(backdrop);
|
|
45063
|
+
const state = {
|
|
45064
|
+
otui,
|
|
45065
|
+
chrome,
|
|
45066
|
+
backdrop,
|
|
45067
|
+
panel,
|
|
45068
|
+
header: header3,
|
|
45069
|
+
titleText,
|
|
45070
|
+
closeText,
|
|
45071
|
+
tabStrip,
|
|
45072
|
+
body,
|
|
45073
|
+
footer,
|
|
45074
|
+
footerText,
|
|
45075
|
+
open: false,
|
|
45076
|
+
generation: 0,
|
|
45077
|
+
tabs: [],
|
|
45078
|
+
active: "",
|
|
45079
|
+
tabCleanup: undefined,
|
|
45080
|
+
onClose: undefined,
|
|
45081
|
+
input: undefined,
|
|
45082
|
+
releaseOverlay: undefined,
|
|
45083
|
+
unsubKeys: undefined,
|
|
45084
|
+
savedScrollTop: undefined
|
|
45085
|
+
};
|
|
45086
|
+
state.releaseOverlay = chrome.addOverlaySource(() => state.open);
|
|
45087
|
+
state.unsubKeys = onKeypress(r, (key) => {
|
|
45088
|
+
if (!state.open || state.input === undefined) {
|
|
45089
|
+
return;
|
|
45090
|
+
}
|
|
45091
|
+
if (key.name === "escape" || key.name === "x" || key.sequence === "x") {
|
|
45092
|
+
closeHost(state, { restoreFocus: true, runOnClose: true });
|
|
45093
|
+
key.preventDefault();
|
|
45094
|
+
key.stopPropagation();
|
|
45095
|
+
return;
|
|
45096
|
+
}
|
|
45097
|
+
const idx = state.tabs.findIndex((tab) => tab.id === state.active);
|
|
45098
|
+
const focused = r.currentFocusedRenderable;
|
|
45099
|
+
const onStrip = focused !== null && containsNode(state.tabStrip, focused);
|
|
45100
|
+
if (key.name === "left" || onStrip && key.name === "tab" && key.shift === true) {
|
|
45101
|
+
const prev = idx > 0 ? state.tabs[idx - 1] : undefined;
|
|
45102
|
+
if (prev !== undefined) {
|
|
45103
|
+
mountTab(state, state.input, prev.id);
|
|
45104
|
+
}
|
|
45105
|
+
key.preventDefault();
|
|
45106
|
+
key.stopPropagation();
|
|
45107
|
+
return;
|
|
45108
|
+
}
|
|
45109
|
+
if (key.name === "right" || onStrip && key.name === "tab") {
|
|
45110
|
+
const next = state.tabs[idx + 1];
|
|
45111
|
+
if (next !== undefined) {
|
|
45112
|
+
mountTab(state, state.input, next.id);
|
|
45113
|
+
}
|
|
45114
|
+
key.preventDefault();
|
|
45115
|
+
key.stopPropagation();
|
|
45116
|
+
return;
|
|
45117
|
+
}
|
|
45118
|
+
if (focused !== null && containsNode(state.body, focused)) {
|
|
45119
|
+
return;
|
|
45120
|
+
}
|
|
45121
|
+
const digit = key.sequence.length === 1 ? key.sequence : key.name;
|
|
45122
|
+
if (digit.length === 1 && digit >= "1" && digit <= "9") {
|
|
45123
|
+
const jump = state.tabs[Number(digit) - 1];
|
|
45124
|
+
if (jump !== undefined) {
|
|
45125
|
+
mountTab(state, state.input, jump.id);
|
|
45126
|
+
key.preventDefault();
|
|
45127
|
+
key.stopPropagation();
|
|
45128
|
+
}
|
|
45129
|
+
}
|
|
45130
|
+
});
|
|
45131
|
+
hosts.set(r, state);
|
|
45132
|
+
return state;
|
|
45133
|
+
}
|
|
45134
|
+
function makeHandle(state, generation) {
|
|
45135
|
+
return {
|
|
45136
|
+
close() {
|
|
45137
|
+
if (state.generation !== generation) {
|
|
45138
|
+
return;
|
|
45139
|
+
}
|
|
45140
|
+
closeHost(state, { restoreFocus: true, runOnClose: true });
|
|
45141
|
+
},
|
|
45142
|
+
setTab(id) {
|
|
45143
|
+
if (state.generation !== generation || !state.open || state.input === undefined) {
|
|
45144
|
+
return;
|
|
45145
|
+
}
|
|
45146
|
+
if (!state.tabs.some((tab) => tab.id === id) || id === state.active) {
|
|
45147
|
+
return;
|
|
45148
|
+
}
|
|
45149
|
+
mountTab(state, state.input, id);
|
|
45150
|
+
},
|
|
45151
|
+
activeTab() {
|
|
45152
|
+
return state.active;
|
|
45153
|
+
}
|
|
45154
|
+
};
|
|
45155
|
+
}
|
|
45156
|
+
function openModal(otui, chrome, input2) {
|
|
45157
|
+
if (otui === undefined || chrome === undefined || input2.tabs.length < 1) {
|
|
45158
|
+
return;
|
|
45159
|
+
}
|
|
45160
|
+
const state = ensureHost(otui, chrome);
|
|
45161
|
+
if (state.open) {
|
|
45162
|
+
unmountActiveTab(state);
|
|
45163
|
+
const previousClose = state.onClose;
|
|
45164
|
+
state.onClose = undefined;
|
|
45165
|
+
previousClose?.();
|
|
45166
|
+
} else {
|
|
45167
|
+
state.savedScrollTop = chrome.scroll.scrollTop;
|
|
45168
|
+
chrome.hideMenu();
|
|
45169
|
+
chrome.blurComposer();
|
|
45170
|
+
state.backdrop.visible = true;
|
|
45171
|
+
state.open = true;
|
|
45172
|
+
}
|
|
45173
|
+
state.generation += 1;
|
|
45174
|
+
const generation = state.generation;
|
|
45175
|
+
state.input = input2;
|
|
45176
|
+
state.tabs = input2.tabs;
|
|
45177
|
+
state.onClose = input2.onClose;
|
|
45178
|
+
paintHeader(state, input2.title);
|
|
45179
|
+
paintFooter(state, input2.footer);
|
|
45180
|
+
mountTab(state, input2, resolveInitialTab(input2.tabs, input2.initialTab));
|
|
45181
|
+
state.tabStrip.focus();
|
|
45182
|
+
return makeHandle(state, generation);
|
|
45183
|
+
}
|
|
45184
|
+
|
|
45185
|
+
// src/tui/flow-inspector.ts
|
|
45186
|
+
var FLOWS_COMMAND = "/flows";
|
|
45187
|
+
var FLOWS_FOOTER = [
|
|
45188
|
+
{ key: "\u2191/\u2193", label: "select" },
|
|
45189
|
+
{ key: "\u2190/\u2192", label: "tabs" },
|
|
45190
|
+
{ key: "esc", label: "close" }
|
|
45191
|
+
];
|
|
45192
|
+
function isFlowsCommand(line) {
|
|
45193
|
+
const token = line.trim().split(/\s+/)[0] ?? "";
|
|
45194
|
+
return token === FLOWS_COMMAND;
|
|
45195
|
+
}
|
|
45196
|
+
function findFlowItem(items, query) {
|
|
45197
|
+
const needle = query.trim();
|
|
45198
|
+
if (needle.length === 0) {
|
|
45199
|
+
return;
|
|
45200
|
+
}
|
|
45201
|
+
const padded = /^\d+$/.test(needle) ? needle.padStart(3, "0") : needle;
|
|
45202
|
+
return items.find((item) => item.id === needle || item.id === padded || item.dir === needle || item.dir.endsWith(`/${needle}`)) ?? items.find((item) => item.slug === needle);
|
|
45203
|
+
}
|
|
45204
|
+
function formatFlowListLines(items, selected) {
|
|
45205
|
+
if (items.length === 0) {
|
|
45206
|
+
return ["No flows in this project."];
|
|
45207
|
+
}
|
|
45208
|
+
return items.map((item, index) => {
|
|
45209
|
+
const mark = index === selected ? ">" : " ";
|
|
45210
|
+
return `${mark} ${item.id} ${item.status} ${item.tasksDone}/${item.tasksTotal} ${item.title}`;
|
|
45211
|
+
});
|
|
45212
|
+
}
|
|
45213
|
+
function formatFlowDetailLines(item) {
|
|
45214
|
+
const taskLines = item.tasks.length === 0 ? [" (no tasks)"] : item.tasks.map((task) => ` ${task.id} ${task.status} ${task.title}`);
|
|
45215
|
+
return [
|
|
45216
|
+
`${item.id} ${item.title}`,
|
|
45217
|
+
`Status ${item.status}`,
|
|
45218
|
+
`Dir ${item.dir}`,
|
|
45219
|
+
`Tasks ${item.tasksDone}/${item.tasksTotal}`,
|
|
45220
|
+
`PR ${item.prUrl ?? "\u2014"}`,
|
|
45221
|
+
`Source ${item.source}`,
|
|
45222
|
+
`Created ${item.createdAt}`,
|
|
45223
|
+
`Updated ${item.updatedAt}`,
|
|
45224
|
+
"",
|
|
45225
|
+
"Tasks",
|
|
45226
|
+
...taskLines
|
|
45227
|
+
];
|
|
45228
|
+
}
|
|
45229
|
+
function formatFlowListText(items) {
|
|
45230
|
+
if (items.length === 0) {
|
|
45231
|
+
return `Flows
|
|
45232
|
+
No flows in this project.
|
|
45233
|
+
`;
|
|
45234
|
+
}
|
|
45235
|
+
return [
|
|
45236
|
+
"Flows",
|
|
45237
|
+
...items.map((item) => ` ${item.id} ${item.status} ${item.tasksDone}/${item.tasksTotal} ${item.title}`),
|
|
45238
|
+
""
|
|
45239
|
+
].join(`
|
|
45240
|
+
`);
|
|
45241
|
+
}
|
|
45242
|
+
function formatFlowDetailText(item) {
|
|
45243
|
+
return `${formatFlowDetailLines(item).join(`
|
|
45244
|
+
`)}
|
|
45245
|
+
`;
|
|
45246
|
+
}
|
|
45247
|
+
function paintLines(otui, renderer, body, lines) {
|
|
45248
|
+
if (otui === undefined || otui === null || body === undefined || body === null) {
|
|
45249
|
+
return;
|
|
45250
|
+
}
|
|
45251
|
+
const parent = body;
|
|
45252
|
+
const ctor = otui.TextRenderable;
|
|
45253
|
+
if (parent.add === undefined || ctor === undefined) {
|
|
45254
|
+
return;
|
|
45255
|
+
}
|
|
45256
|
+
const node = new ctor(renderer, { id: "flows-body", content: lines.join(`
|
|
45257
|
+
`) });
|
|
45258
|
+
parent.add(node);
|
|
45259
|
+
return node;
|
|
45260
|
+
}
|
|
45261
|
+
function presentFlows(openModal2, otui, chrome, options) {
|
|
45262
|
+
const items = options.items;
|
|
45263
|
+
let selected = 0;
|
|
45264
|
+
let listNode;
|
|
45265
|
+
let detailNode;
|
|
45266
|
+
let unsubscribeKey;
|
|
45267
|
+
const paintSelection = () => {
|
|
45268
|
+
if (listNode !== undefined) {
|
|
45269
|
+
listNode.content = formatFlowListLines(items, selected).join(`
|
|
45270
|
+
`);
|
|
45271
|
+
}
|
|
45272
|
+
if (detailNode !== undefined) {
|
|
45273
|
+
const item = items[selected];
|
|
45274
|
+
detailNode.content = item !== undefined ? formatFlowDetailLines(item).join(`
|
|
45275
|
+
`) : "No flow selected.";
|
|
45276
|
+
}
|
|
45277
|
+
};
|
|
45278
|
+
const handle = openModal2(otui, chrome, {
|
|
45279
|
+
title: "/flows",
|
|
45280
|
+
tabs: [
|
|
45281
|
+
{ id: "list", label: "Flows" },
|
|
45282
|
+
{ id: "detail", label: "Detail" }
|
|
45283
|
+
],
|
|
45284
|
+
initialTab: "list",
|
|
45285
|
+
footer: FLOWS_FOOTER,
|
|
45286
|
+
renderTab: (tabId, body) => {
|
|
45287
|
+
const renderer = options.renderer ?? chrome?.renderer;
|
|
45288
|
+
if (tabId === "list") {
|
|
45289
|
+
listNode = paintLines(otui, renderer, body, formatFlowListLines(items, selected));
|
|
45290
|
+
return;
|
|
45291
|
+
}
|
|
45292
|
+
const item = items[selected];
|
|
45293
|
+
detailNode = paintLines(otui, renderer, body, item !== undefined ? formatFlowDetailLines(item) : ["No flow selected."]);
|
|
45294
|
+
},
|
|
45295
|
+
onClose: () => {
|
|
45296
|
+
unsubscribeKey?.();
|
|
45297
|
+
}
|
|
45298
|
+
});
|
|
45299
|
+
if (handle === undefined) {
|
|
45300
|
+
return;
|
|
45301
|
+
}
|
|
45302
|
+
if (options.onKeypress !== undefined) {
|
|
45303
|
+
unsubscribeKey = options.onKeypress((key) => {
|
|
45304
|
+
const token = key.name || key.sequence;
|
|
45305
|
+
if (items.length === 0) {
|
|
45306
|
+
return;
|
|
45307
|
+
}
|
|
45308
|
+
if (token === "up" || token === "k") {
|
|
45309
|
+
selected = selected > 0 ? selected - 1 : 0;
|
|
45310
|
+
paintSelection();
|
|
45311
|
+
} else if (token === "down" || token === "j") {
|
|
45312
|
+
selected = selected < items.length - 1 ? selected + 1 : selected;
|
|
45313
|
+
paintSelection();
|
|
45314
|
+
} else if (token === "return" || token === "enter") {
|
|
45315
|
+
handle.setTab("detail");
|
|
45316
|
+
}
|
|
45317
|
+
});
|
|
45318
|
+
}
|
|
45319
|
+
return handle;
|
|
45320
|
+
}
|
|
45321
|
+
function openFlows(otui, chrome, options) {
|
|
45322
|
+
return presentFlows((hostOtui, hostChrome, input2) => openModal(hostOtui, hostChrome, input2), otui, chrome, options);
|
|
45323
|
+
}
|
|
45324
|
+
|
|
45325
|
+
// src/tui/inspector-sources.ts
|
|
45326
|
+
init_store2();
|
|
45327
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
45328
|
+
function workspaceFromManifest(manifest) {
|
|
45329
|
+
return {
|
|
45330
|
+
id: manifest.id,
|
|
45331
|
+
title: manifest.title,
|
|
45332
|
+
status: manifest.status,
|
|
45333
|
+
resources: manifest.resources.map((resource) => ({ kind: resource.kind, uri: resource.uri }))
|
|
45334
|
+
};
|
|
45335
|
+
}
|
|
45336
|
+
function workspacesInSession(workspaces, opts) {
|
|
45337
|
+
const text = opts.sessionText ?? "";
|
|
45338
|
+
const sessionId = opts.sessionId ?? "";
|
|
45339
|
+
return workspaces.filter((workspace) => {
|
|
45340
|
+
if (text.includes(workspace.id)) {
|
|
45341
|
+
return true;
|
|
45342
|
+
}
|
|
45343
|
+
return workspace.resources.some((resource) => resource.kind === "session" && sessionId.length > 0 && resource.uri.includes(sessionId));
|
|
45344
|
+
});
|
|
45345
|
+
}
|
|
45346
|
+
function explicitFlowMention(item, text) {
|
|
45347
|
+
if (text.length === 0) {
|
|
45348
|
+
return false;
|
|
45349
|
+
}
|
|
45350
|
+
const id = item.id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
45351
|
+
const slug2 = item.slug.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
45352
|
+
const pattern = new RegExp(`(?:flow\\s+#?|/flows\\s+|\\.metaproject/flows/)${id}\\b` + (slug2.length > 0 ? `|(?:flow\\s+)${slug2}\\b` : ""), "i");
|
|
45353
|
+
return pattern.test(text);
|
|
45354
|
+
}
|
|
45355
|
+
function flowsInSession(flows, opts) {
|
|
45356
|
+
const sessionId = opts.sessionId ?? "";
|
|
45357
|
+
const text = opts.sessionText ?? "";
|
|
45358
|
+
return flows.filter((flow) => {
|
|
45359
|
+
if (sessionId.length > 0 && flow.sessionIds.includes(sessionId)) {
|
|
45360
|
+
return true;
|
|
45361
|
+
}
|
|
45362
|
+
return explicitFlowMention(flow, text);
|
|
45363
|
+
});
|
|
45364
|
+
}
|
|
45365
|
+
function flowItemFromState(flow, dir) {
|
|
45366
|
+
const sessionIds = [
|
|
45367
|
+
...new Set(flow.tasks.map((task) => task.runLink?.sessionId).filter((id) => typeof id === "string" && id.length > 0))
|
|
45368
|
+
];
|
|
45369
|
+
return {
|
|
45370
|
+
id: flow.id,
|
|
45371
|
+
slug: flow.slug,
|
|
45372
|
+
title: flow.title,
|
|
45373
|
+
status: flow.status,
|
|
45374
|
+
dir: `.metaproject/flows/${dir}`,
|
|
45375
|
+
tasksDone: flow.tasks.filter((task) => task.status === "done").length,
|
|
45376
|
+
tasksTotal: flow.tasks.length,
|
|
45377
|
+
sessionIds,
|
|
45378
|
+
prUrl: flow.pr.url,
|
|
45379
|
+
createdAt: flow.createdAt,
|
|
45380
|
+
updatedAt: flow.updatedAt,
|
|
45381
|
+
source: flow.source.ref ?? flow.source.type,
|
|
45382
|
+
tasks: flow.tasks.map((task) => ({ id: task.id, title: task.title, status: task.status }))
|
|
45383
|
+
};
|
|
45384
|
+
}
|
|
45385
|
+
async function loadInspectorWorkspaces(cwd) {
|
|
45386
|
+
try {
|
|
45387
|
+
const service4 = new WorkspaceService({
|
|
45388
|
+
workspaceRoot: cwd,
|
|
45389
|
+
authorizationServer: localWorkspaceAuthorizationServer(),
|
|
45390
|
+
strictGuard: {
|
|
45391
|
+
mode: "strict",
|
|
45392
|
+
availability: "available",
|
|
45393
|
+
decision: "pass",
|
|
45394
|
+
policyRevision: "local-offline-v1"
|
|
45395
|
+
}
|
|
45396
|
+
});
|
|
45397
|
+
const listed = await service4.list({ request: undefined, requestCorrelationId: randomUUID17() });
|
|
45398
|
+
return listed.map(workspaceFromManifest);
|
|
45399
|
+
} catch {
|
|
45400
|
+
return [];
|
|
45401
|
+
}
|
|
45402
|
+
}
|
|
45403
|
+
async function loadInspectorFlows(cwd) {
|
|
45404
|
+
try {
|
|
45405
|
+
const dirs = await listFlowDirs(cwd);
|
|
45406
|
+
const items = [];
|
|
45407
|
+
for (const dir of dirs) {
|
|
45408
|
+
try {
|
|
45409
|
+
items.push(flowItemFromState(await readFlow(cwd, dir), dir));
|
|
45410
|
+
} catch {}
|
|
45411
|
+
}
|
|
45412
|
+
return items;
|
|
45413
|
+
} catch {
|
|
45414
|
+
return [];
|
|
45415
|
+
}
|
|
45416
|
+
}
|
|
45417
|
+
function formatWorkspaceLines(workspaces) {
|
|
45418
|
+
if (workspaces.length === 0) {
|
|
45419
|
+
return ["No workspaces recorded in this session."];
|
|
45420
|
+
}
|
|
45421
|
+
const width = workspaces.reduce((max, workspace) => Math.max(max, workspace.id.length), 0);
|
|
45422
|
+
return workspaces.map((workspace) => `${workspace.id.padEnd(width)} ${workspace.status} ${workspace.title}`);
|
|
45423
|
+
}
|
|
45424
|
+
function formatSessionFlowLines(flows) {
|
|
45425
|
+
if (flows.length === 0) {
|
|
45426
|
+
return ["No flows recorded in this session."];
|
|
45427
|
+
}
|
|
45428
|
+
return flows.map((flow) => `${flow.id} ${flow.status} ${flow.tasksDone}/${flow.tasksTotal} ${flow.title}`);
|
|
45429
|
+
}
|
|
45430
|
+
|
|
45431
|
+
// src/tui/context-usage.ts
|
|
45432
|
+
var CONTEXT_BAR_WIDTH = 28;
|
|
45433
|
+
function lastTurnUsed(usage) {
|
|
45434
|
+
if (usage === undefined) {
|
|
45435
|
+
return;
|
|
45436
|
+
}
|
|
45437
|
+
if (usage.totalTokens !== undefined) {
|
|
45438
|
+
return usage.totalTokens;
|
|
45439
|
+
}
|
|
45440
|
+
if (usage.inputTokens === undefined && usage.outputTokens === undefined) {
|
|
45441
|
+
return;
|
|
45442
|
+
}
|
|
45443
|
+
return (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
|
|
45444
|
+
}
|
|
45445
|
+
function renderUsageBar(filled, width = CONTEXT_BAR_WIDTH) {
|
|
45446
|
+
const n = Math.max(0, Math.min(width, filled > 0 ? width : 0));
|
|
45447
|
+
return `[${"\u2588".repeat(n)}${"\u2591".repeat(width - n)}]`;
|
|
45448
|
+
}
|
|
45449
|
+
function buildContextUsage(source) {
|
|
45450
|
+
const lastIn = source.usage?.inputTokens;
|
|
45451
|
+
const lastOut = source.usage?.outputTokens;
|
|
45452
|
+
const last = lastTurnUsed(source.usage);
|
|
45453
|
+
const hasEstimate = source.estimateTokens !== undefined;
|
|
45454
|
+
const total = hasEstimate ? source.estimateTokens ?? 0 : last ?? 0;
|
|
45455
|
+
const estimated = hasEstimate || last === undefined;
|
|
45456
|
+
const segments2 = [];
|
|
45457
|
+
if (hasEstimate) {
|
|
45458
|
+
segments2.push({ id: "history", label: "history (est.)", tokens: source.estimateTokens ?? 0 });
|
|
45459
|
+
}
|
|
45460
|
+
if (lastIn !== undefined) {
|
|
45461
|
+
segments2.push({ id: "last-in", label: "last in", tokens: lastIn });
|
|
45462
|
+
}
|
|
45463
|
+
if (lastOut !== undefined) {
|
|
45464
|
+
segments2.push({ id: "last-out", label: "last out", tokens: lastOut });
|
|
45465
|
+
}
|
|
45466
|
+
return {
|
|
45467
|
+
total,
|
|
45468
|
+
estimated,
|
|
45469
|
+
segments: segments2,
|
|
45470
|
+
bar: renderUsageBar(total),
|
|
45471
|
+
note: total === 0 ? "No context usage yet." : "No model context window is known. The bar is relative to used tokens, not a billed limit."
|
|
45472
|
+
};
|
|
45473
|
+
}
|
|
45474
|
+
function formatContextUsageText(view) {
|
|
45475
|
+
if (view.total === 0 && view.segments.every((segment) => segment.tokens === 0)) {
|
|
45476
|
+
return `Context
|
|
45477
|
+
${view.note}
|
|
45478
|
+
`;
|
|
45479
|
+
}
|
|
45480
|
+
const kind = view.estimated ? "tokens (estimate)" : "tokens";
|
|
45481
|
+
const width = view.segments.reduce((max, segment) => Math.max(max, segment.label.length), 0);
|
|
45482
|
+
const rows = view.segments.map((segment) => ` ${segment.label.padEnd(width)} ${segment.tokens}`);
|
|
45483
|
+
return [`Context`, ` Used ${view.total} ${kind}`, ` ${view.bar}`, ...rows, "", ` ${view.note}`, ""].join(`
|
|
45484
|
+
`);
|
|
45485
|
+
}
|
|
45486
|
+
|
|
45487
|
+
// src/tui/session-info.ts
|
|
45488
|
+
var SESSION_INFO_COMMANDS = ["/status"];
|
|
45489
|
+
var MISSING = "\u2014";
|
|
45490
|
+
var SESSION_INFO_FOOTER = [
|
|
45491
|
+
{ key: "c", label: "copy id" },
|
|
45492
|
+
{ key: "\u2190/\u2192", label: "tabs" },
|
|
45493
|
+
{ key: "esc", label: "close" }
|
|
45494
|
+
];
|
|
45495
|
+
function isSessionInfoCommand(line) {
|
|
45496
|
+
const token = line.trim().split(/\s+/)[0] ?? "";
|
|
45497
|
+
return SESSION_INFO_COMMANDS.includes(token);
|
|
45498
|
+
}
|
|
45499
|
+
function displayOrMissing(value) {
|
|
45500
|
+
return value !== undefined && value.length > 0 ? value : MISSING;
|
|
45501
|
+
}
|
|
45502
|
+
function formatUtc(iso) {
|
|
45503
|
+
if (iso === undefined || iso.length === 0) {
|
|
45504
|
+
return MISSING;
|
|
45505
|
+
}
|
|
45506
|
+
const date = new Date(iso);
|
|
45507
|
+
if (Number.isNaN(date.getTime())) {
|
|
45508
|
+
return MISSING;
|
|
45509
|
+
}
|
|
45510
|
+
return `${date.toISOString()} UTC`;
|
|
45511
|
+
}
|
|
45512
|
+
function formatCount(value) {
|
|
45513
|
+
return value === undefined ? MISSING : String(value);
|
|
45514
|
+
}
|
|
45515
|
+
function usageUsed(usage) {
|
|
45516
|
+
if (usage === undefined) {
|
|
45517
|
+
return;
|
|
45518
|
+
}
|
|
45519
|
+
if (usage.totalTokens !== undefined) {
|
|
45520
|
+
return usage.totalTokens;
|
|
45521
|
+
}
|
|
45522
|
+
if (usage.inputTokens === undefined && usage.outputTokens === undefined) {
|
|
45523
|
+
return;
|
|
45524
|
+
}
|
|
45525
|
+
return (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
|
|
45526
|
+
}
|
|
45527
|
+
function contextRow(source) {
|
|
45528
|
+
const used = usageUsed(source.usage);
|
|
45529
|
+
if (used !== undefined) {
|
|
45530
|
+
return `${used} tokens`;
|
|
45531
|
+
}
|
|
45532
|
+
if (source.estimateTokens !== undefined) {
|
|
45533
|
+
return `${source.estimateTokens} tokens (estimate)`;
|
|
45534
|
+
}
|
|
45535
|
+
return MISSING;
|
|
45536
|
+
}
|
|
45537
|
+
function buildSessionInfoSnapshot(source) {
|
|
45538
|
+
const id = source.summary?.id ?? "";
|
|
45539
|
+
const provider = source.selection?.provider ?? source.summary?.provider;
|
|
45540
|
+
const model = source.selection?.model ?? source.summary?.model;
|
|
45541
|
+
const sessionRows = [
|
|
45542
|
+
{ label: "Title", value: displayOrMissing(source.summary?.title) },
|
|
45543
|
+
{ label: "Version", value: displayOrMissing(source.version) },
|
|
45544
|
+
{ label: "Session id", value: displayOrMissing(source.summary?.id) },
|
|
45545
|
+
{ label: "Project", value: displayOrMissing(source.summary?.projectPath) },
|
|
45546
|
+
{ label: "Provider", value: displayOrMissing(provider) },
|
|
45547
|
+
{ label: "Model", value: displayOrMissing(model) }
|
|
45548
|
+
];
|
|
45549
|
+
if (source.summary?.parentSessionId !== undefined && source.summary.parentSessionId.length > 0) {
|
|
45550
|
+
sessionRows.push({ label: "Parent", value: source.summary.parentSessionId });
|
|
45551
|
+
}
|
|
45552
|
+
const messages = source.summary?.messageCount === undefined && source.summary?.archiveMessageCount === undefined ? MISSING : `${formatCount(source.summary.messageCount)} / ${formatCount(source.summary.archiveMessageCount)}`;
|
|
45553
|
+
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) });
|
|
45554
|
+
const estimate = source.estimateTokens === undefined ? MISSING : `${source.estimateTokens} tokens (estimate)`;
|
|
45555
|
+
const usageRows = [
|
|
45556
|
+
{
|
|
45557
|
+
label: "Last turn input",
|
|
45558
|
+
value: source.usage?.inputTokens === undefined ? MISSING : String(source.usage.inputTokens)
|
|
45559
|
+
},
|
|
45560
|
+
{
|
|
45561
|
+
label: "Last turn output",
|
|
45562
|
+
value: source.usage?.outputTokens === undefined ? MISSING : String(source.usage.outputTokens)
|
|
45563
|
+
},
|
|
45564
|
+
{ label: "Context estimate", value: estimate }
|
|
45565
|
+
];
|
|
45566
|
+
const context = buildContextUsage({
|
|
45567
|
+
estimateTokens: source.estimateTokens,
|
|
45568
|
+
usage: source.usage
|
|
45569
|
+
});
|
|
45570
|
+
const sessionWorkspaces = workspacesInSession(source.workspaces ?? [], {
|
|
45571
|
+
sessionId: id,
|
|
45572
|
+
...source.sessionText !== undefined ? { sessionText: source.sessionText } : {}
|
|
45573
|
+
});
|
|
45574
|
+
const sessionFlows = flowsInSession(source.flows ?? [], {
|
|
45575
|
+
sessionId: id,
|
|
45576
|
+
...source.sessionText !== undefined ? { sessionText: source.sessionText } : {}
|
|
45577
|
+
});
|
|
45578
|
+
return {
|
|
45579
|
+
sessionId: id,
|
|
45580
|
+
sessionRows,
|
|
45581
|
+
usageRows,
|
|
45582
|
+
context,
|
|
45583
|
+
workspaceLines: formatWorkspaceLines(sessionWorkspaces),
|
|
45584
|
+
flowLines: formatSessionFlowLines(sessionFlows),
|
|
45585
|
+
hasWorkspaces: sessionWorkspaces.length > 0,
|
|
45586
|
+
hasFlows: sessionFlows.length > 0
|
|
45587
|
+
};
|
|
45588
|
+
}
|
|
45589
|
+
function formatSection(title, rows) {
|
|
45590
|
+
const width = rows.reduce((max, row) => Math.max(max, row.label.length), 0);
|
|
45591
|
+
return [title, ...rows.map((row) => ` ${row.label.padEnd(width)} ${row.value}`)].join(`
|
|
45592
|
+
`);
|
|
45593
|
+
}
|
|
45594
|
+
function formatSessionInfoText(snapshot) {
|
|
45595
|
+
const extra = [];
|
|
45596
|
+
extra.push(formatContextUsageText(snapshot.context));
|
|
45597
|
+
if (snapshot.hasWorkspaces) {
|
|
45598
|
+
extra.push(["Workspaces", ...snapshot.workspaceLines.map((line) => ` ${line}`), ""].join(`
|
|
45599
|
+
`));
|
|
45600
|
+
}
|
|
45601
|
+
if (snapshot.hasFlows) {
|
|
45602
|
+
extra.push(["Flow", ...snapshot.flowLines.map((line) => ` ${line}`), ""].join(`
|
|
45603
|
+
`));
|
|
45604
|
+
}
|
|
45605
|
+
return `${formatSection("Session", snapshot.sessionRows)}
|
|
45606
|
+
|
|
45607
|
+
${formatSection("Usage", snapshot.usageRows)}
|
|
45608
|
+
|
|
45609
|
+
${extra.join(`
|
|
45610
|
+
`)}`;
|
|
45611
|
+
}
|
|
45612
|
+
function sessionIdCopyText(snapshot) {
|
|
45613
|
+
return snapshot.sessionId;
|
|
45614
|
+
}
|
|
45615
|
+
function statusModalTabs(snapshot) {
|
|
45616
|
+
const tabs = [
|
|
45617
|
+
{ id: "status", label: "Status" },
|
|
45618
|
+
{ id: "context", label: "Context" }
|
|
45619
|
+
];
|
|
45620
|
+
if (snapshot.hasWorkspaces) {
|
|
45621
|
+
tabs.push({ id: "workspaces", label: "Workspaces" });
|
|
45622
|
+
}
|
|
45623
|
+
if (snapshot.hasFlows) {
|
|
45624
|
+
tabs.push({ id: "flow", label: "Flow" });
|
|
45625
|
+
}
|
|
45626
|
+
return tabs;
|
|
45627
|
+
}
|
|
45628
|
+
function paintContent(otui, renderer, body, content) {
|
|
45629
|
+
if (otui === undefined || otui === null || body === undefined || body === null) {
|
|
45630
|
+
return;
|
|
45631
|
+
}
|
|
45632
|
+
const parent = body;
|
|
45633
|
+
const ctor = otui.TextRenderable;
|
|
45634
|
+
if (parent.add === undefined || ctor === undefined) {
|
|
45635
|
+
return;
|
|
45636
|
+
}
|
|
45637
|
+
parent.add(new ctor(renderer, { id: "session-info-body", content }));
|
|
45638
|
+
}
|
|
45639
|
+
function paintRows(otui, renderer, body, rows) {
|
|
45640
|
+
const width = rows.reduce((max, row) => Math.max(max, row.label.length), 0);
|
|
45641
|
+
paintContent(otui, renderer, body, rows.map((row) => `${row.label.padEnd(width)} ${row.value}`).join(`
|
|
45642
|
+
`));
|
|
45643
|
+
}
|
|
45644
|
+
function presentSessionInfo(openModal2, otui, chrome, options) {
|
|
45645
|
+
const { snapshot, toast } = options;
|
|
45646
|
+
const copy = (text) => {
|
|
45647
|
+
if (text.length === 0) {
|
|
45648
|
+
return;
|
|
45649
|
+
}
|
|
45650
|
+
try {
|
|
45651
|
+
options.copyText(text);
|
|
45652
|
+
toast("Copied to clipboard");
|
|
45653
|
+
} catch {}
|
|
45654
|
+
};
|
|
45655
|
+
let unsubscribeKey;
|
|
45656
|
+
const handle = openModal2(otui, chrome, {
|
|
45657
|
+
title: "/status",
|
|
45658
|
+
tabs: statusModalTabs(snapshot),
|
|
45659
|
+
initialTab: "status",
|
|
45660
|
+
footer: SESSION_INFO_FOOTER,
|
|
45661
|
+
renderTab: (tabId, body) => {
|
|
45662
|
+
const renderer = options.renderer ?? chrome?.renderer;
|
|
45663
|
+
if (tabId === "context") {
|
|
45664
|
+
paintContent(otui, renderer, body, formatContextUsageText(snapshot.context).trimEnd());
|
|
45665
|
+
return;
|
|
45666
|
+
}
|
|
45667
|
+
if (tabId === "workspaces") {
|
|
45668
|
+
paintContent(otui, renderer, body, snapshot.workspaceLines.join(`
|
|
45669
|
+
`));
|
|
45670
|
+
return;
|
|
45671
|
+
}
|
|
45672
|
+
if (tabId === "flow") {
|
|
45673
|
+
paintContent(otui, renderer, body, snapshot.flowLines.join(`
|
|
45674
|
+
`));
|
|
45675
|
+
return;
|
|
45676
|
+
}
|
|
45677
|
+
paintRows(otui, renderer, body, snapshot.sessionRows);
|
|
45678
|
+
},
|
|
45679
|
+
onClose: () => {
|
|
45680
|
+
unsubscribeKey?.();
|
|
45681
|
+
}
|
|
45682
|
+
});
|
|
45683
|
+
if (handle === undefined) {
|
|
45684
|
+
return;
|
|
45685
|
+
}
|
|
45686
|
+
if (options.onKeypress !== undefined) {
|
|
45687
|
+
unsubscribeKey = options.onKeypress((key) => {
|
|
45688
|
+
const token = key.name || key.sequence;
|
|
45689
|
+
if (token === "c") {
|
|
45690
|
+
copy(sessionIdCopyText(snapshot));
|
|
45691
|
+
}
|
|
45692
|
+
});
|
|
45693
|
+
}
|
|
45694
|
+
return handle;
|
|
45695
|
+
}
|
|
45696
|
+
function openSessionInfo(otui, chrome, options) {
|
|
45697
|
+
return presentSessionInfo((hostOtui, hostChrome, input2) => openModal(hostOtui, hostChrome, input2), otui, chrome, options);
|
|
45698
|
+
}
|
|
44799
45699
|
|
|
44800
45700
|
// src/commands/agent-commands.ts
|
|
44801
45701
|
var CHAT_ONLY = ["chat"];
|
|
@@ -44854,6 +45754,12 @@ var AGENT_SLASH_COMMANDS = [
|
|
|
44854
45754
|
{ name: "/new", description: "Start a new session (old kept on disk)", modes: BOTH },
|
|
44855
45755
|
{ name: "/resume", description: "Resume a prior session in this project", modes: AGENT_ONLY },
|
|
44856
45756
|
{ name: "/sessions", description: "Open the session list and switch to one", modes: AGENT_ONLY },
|
|
45757
|
+
{
|
|
45758
|
+
name: "/status",
|
|
45759
|
+
description: "Show session identity, context, workspaces, and flows",
|
|
45760
|
+
modes: BOTH
|
|
45761
|
+
},
|
|
45762
|
+
{ name: "/flows", description: "Browse project flows and inspect one", modes: BOTH },
|
|
44857
45763
|
{
|
|
44858
45764
|
name: "/compact",
|
|
44859
45765
|
description: "Compact model context \u2014 /compact [focus] (archive kept)",
|
|
@@ -45334,7 +46240,7 @@ function selectBoxHeight(count, withDescription) {
|
|
|
45334
46240
|
const per = withDescription ? 2 : 1;
|
|
45335
46241
|
return Math.min(Math.max(count * per, per), 16);
|
|
45336
46242
|
}
|
|
45337
|
-
function
|
|
46243
|
+
function onKeypress2(r, handler) {
|
|
45338
46244
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
45339
46245
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
45340
46246
|
}
|
|
@@ -45435,7 +46341,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
45435
46341
|
key.stopPropagation();
|
|
45436
46342
|
}
|
|
45437
46343
|
};
|
|
45438
|
-
const unsub =
|
|
46344
|
+
const unsub = onKeypress2(r, onKey);
|
|
45439
46345
|
sel.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
45440
46346
|
const chosen = sel.getSelectedOption();
|
|
45441
46347
|
const value = chosen?.value;
|
|
@@ -45723,7 +46629,7 @@ async function checkVersion(options) {
|
|
|
45723
46629
|
}
|
|
45724
46630
|
|
|
45725
46631
|
// src/tui/shell-chrome.ts
|
|
45726
|
-
function
|
|
46632
|
+
function onKeypress3(r, handler) {
|
|
45727
46633
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
45728
46634
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
45729
46635
|
}
|
|
@@ -46153,7 +47059,7 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
46153
47059
|
syncComposerHeight();
|
|
46154
47060
|
emitSubmit(line);
|
|
46155
47061
|
};
|
|
46156
|
-
const unsubscribeMenuKeys =
|
|
47062
|
+
const unsubscribeMenuKeys = onKeypress3(r, (key) => {
|
|
46157
47063
|
if (!menu.visible || !menuNav || overlayActive()) {
|
|
46158
47064
|
return;
|
|
46159
47065
|
}
|
|
@@ -46958,7 +47864,7 @@ function createBlockView(otui, renderer, parent, block, options = {}) {
|
|
|
46958
47864
|
let body;
|
|
46959
47865
|
let bodyText;
|
|
46960
47866
|
let painted;
|
|
46961
|
-
const
|
|
47867
|
+
const paintHeader2 = (state, focused) => {
|
|
46962
47868
|
const hint = state.collapsed ? options.hint : options.expandedHint ?? options.hint;
|
|
46963
47869
|
const label = blockLabel({
|
|
46964
47870
|
kind: state.kind,
|
|
@@ -47019,7 +47925,7 @@ function createBlockView(otui, renderer, parent, block, options = {}) {
|
|
|
47019
47925
|
return {
|
|
47020
47926
|
id: block.id,
|
|
47021
47927
|
render: (state, opts = {}) => {
|
|
47022
|
-
|
|
47928
|
+
paintHeader2(state, opts.focused === true);
|
|
47023
47929
|
if (state.collapsed) {
|
|
47024
47930
|
dropBody();
|
|
47025
47931
|
return;
|
|
@@ -47601,7 +48507,7 @@ function overlayBox(otui, r, id) {
|
|
|
47601
48507
|
padding: 1
|
|
47602
48508
|
});
|
|
47603
48509
|
}
|
|
47604
|
-
function
|
|
48510
|
+
function onKeypress4(r, handler) {
|
|
47605
48511
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
47606
48512
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
47607
48513
|
}
|
|
@@ -47646,7 +48552,7 @@ function promptBaseUrlStep(otui, r, label, baseUrl2) {
|
|
|
47646
48552
|
unsub();
|
|
47647
48553
|
r.root.remove(box);
|
|
47648
48554
|
};
|
|
47649
|
-
const unsub =
|
|
48555
|
+
const unsub = onKeypress4(r, (key) => {
|
|
47650
48556
|
if (key.name === "escape") {
|
|
47651
48557
|
cleanup();
|
|
47652
48558
|
resolve3(undefined);
|
|
@@ -47682,7 +48588,7 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
47682
48588
|
key.stopPropagation();
|
|
47683
48589
|
}
|
|
47684
48590
|
};
|
|
47685
|
-
const unsub =
|
|
48591
|
+
const unsub = onKeypress4(r, onKey);
|
|
47686
48592
|
const cleanup = () => {
|
|
47687
48593
|
unsub();
|
|
47688
48594
|
r.root.remove(box);
|
|
@@ -47722,7 +48628,7 @@ function pickProviderStep(otui, r, detected) {
|
|
|
47722
48628
|
key.stopPropagation();
|
|
47723
48629
|
}
|
|
47724
48630
|
};
|
|
47725
|
-
const unsub =
|
|
48631
|
+
const unsub = onKeypress4(r, onKey);
|
|
47726
48632
|
const cleanup = () => {
|
|
47727
48633
|
unsub();
|
|
47728
48634
|
r.root.remove(box);
|
|
@@ -47840,7 +48746,7 @@ function pickModelInTui(otui, r, models) {
|
|
|
47840
48746
|
key.stopPropagation();
|
|
47841
48747
|
}
|
|
47842
48748
|
};
|
|
47843
|
-
const unsub =
|
|
48749
|
+
const unsub = onKeypress4(r, onKey);
|
|
47844
48750
|
const cleanup = () => {
|
|
47845
48751
|
unsub();
|
|
47846
48752
|
r.root.remove(box);
|
|
@@ -47932,7 +48838,7 @@ function pickSessionInTui(otui, r, sessions) {
|
|
|
47932
48838
|
key.stopPropagation();
|
|
47933
48839
|
}
|
|
47934
48840
|
};
|
|
47935
|
-
const unsub =
|
|
48841
|
+
const unsub = onKeypress4(r, onKey);
|
|
47936
48842
|
const cleanup = () => {
|
|
47937
48843
|
unsub();
|
|
47938
48844
|
r.root.remove(box);
|
|
@@ -48117,6 +49023,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
48117
49023
|
hasExactUsage = true;
|
|
48118
49024
|
}
|
|
48119
49025
|
});
|
|
49026
|
+
let lastUsage;
|
|
49027
|
+
const recordedUsage = io.onUsage?.bind(io);
|
|
49028
|
+
io.onUsage = (usage) => {
|
|
49029
|
+
lastUsage = usage;
|
|
49030
|
+
recordedUsage?.(usage);
|
|
49031
|
+
};
|
|
48120
49032
|
attachBlockIo(io, addBlock, {
|
|
48121
49033
|
onReasoning: () => {
|
|
48122
49034
|
setBusyPhase("thinking");
|
|
@@ -48513,6 +49425,42 @@ Staying in the current session.
|
|
|
48513
49425
|
`);
|
|
48514
49426
|
};
|
|
48515
49427
|
paintSessionHeader();
|
|
49428
|
+
const inspectorKeys = { onKeypress: (handler) => onKeypress4(r, (key) => handler(key)) };
|
|
49429
|
+
const inspectorCwd = () => opts.session?.cwd ?? liveSession.summary.projectPath;
|
|
49430
|
+
const showSessionInfo = () => {
|
|
49431
|
+
(async () => {
|
|
49432
|
+
const cwd = inspectorCwd();
|
|
49433
|
+
const [workspaces, flows] = await Promise.all([loadInspectorWorkspaces(cwd), loadInspectorFlows(cwd)]);
|
|
49434
|
+
const snapshot = buildSessionInfoSnapshot({
|
|
49435
|
+
summary: liveSession.summary,
|
|
49436
|
+
selection: currentSel,
|
|
49437
|
+
version: package_default.version,
|
|
49438
|
+
usage: lastUsage,
|
|
49439
|
+
estimateTokens: estimateContextTokens(history),
|
|
49440
|
+
sessionText: history.map((message2) => message2.content).join(`
|
|
49441
|
+
`),
|
|
49442
|
+
workspaces,
|
|
49443
|
+
flows
|
|
49444
|
+
});
|
|
49445
|
+
openSessionInfo(otui, chrome, {
|
|
49446
|
+
snapshot,
|
|
49447
|
+
copyText: (text) => r.copyToClipboardOSC52(text),
|
|
49448
|
+
toast: (message2) => chrome.showToast(message2),
|
|
49449
|
+
renderer: r,
|
|
49450
|
+
...inspectorKeys
|
|
49451
|
+
});
|
|
49452
|
+
})();
|
|
49453
|
+
};
|
|
49454
|
+
const showFlows = () => {
|
|
49455
|
+
(async () => {
|
|
49456
|
+
const items = await loadInspectorFlows(inspectorCwd());
|
|
49457
|
+
openFlows(otui, chrome, {
|
|
49458
|
+
items,
|
|
49459
|
+
renderer: r,
|
|
49460
|
+
...inspectorKeys
|
|
49461
|
+
});
|
|
49462
|
+
})();
|
|
49463
|
+
};
|
|
48516
49464
|
const updateModelLabels = () => {
|
|
48517
49465
|
paintSessionHeader();
|
|
48518
49466
|
const label = `${currentSel.provider}/${currentSel.model}`;
|
|
@@ -48718,6 +49666,14 @@ Staying in the current session.
|
|
|
48718
49666
|
`);
|
|
48719
49667
|
return;
|
|
48720
49668
|
}
|
|
49669
|
+
if (command2 !== undefined && isSessionInfoCommand(command2.name)) {
|
|
49670
|
+
showSessionInfo();
|
|
49671
|
+
return;
|
|
49672
|
+
}
|
|
49673
|
+
if (command2 !== undefined && isFlowsCommand(command2.name)) {
|
|
49674
|
+
showFlows();
|
|
49675
|
+
return;
|
|
49676
|
+
}
|
|
48721
49677
|
if (command2 !== undefined || line.startsWith("/")) {
|
|
48722
49678
|
transcript.add(new otui.TextRenderable(r, {
|
|
48723
49679
|
id: `c${uid++}`,
|
|
@@ -48859,6 +49815,14 @@ Staying in the current session.
|
|
|
48859
49815
|
}
|
|
48860
49816
|
return;
|
|
48861
49817
|
}
|
|
49818
|
+
if (isSessionInfoCommand(command.name)) {
|
|
49819
|
+
showSessionInfo();
|
|
49820
|
+
return;
|
|
49821
|
+
}
|
|
49822
|
+
if (isFlowsCommand(command.name)) {
|
|
49823
|
+
showFlows();
|
|
49824
|
+
return;
|
|
49825
|
+
}
|
|
48862
49826
|
if (command.name === "/copy") {
|
|
48863
49827
|
const target = newestBlock();
|
|
48864
49828
|
if (target === undefined || !copyBlock(target.id)) {
|
|
@@ -49078,7 +50042,7 @@ Staying in the current session.
|
|
|
49078
50042
|
focusComposer();
|
|
49079
50043
|
});
|
|
49080
50044
|
};
|
|
49081
|
-
|
|
50045
|
+
onKeypress4(r, (key) => {
|
|
49082
50046
|
nav.handleKey(key);
|
|
49083
50047
|
});
|
|
49084
50048
|
chrome.onSubmit((line) => {
|
|
@@ -49204,6 +50168,9 @@ function createChatBridge(hooks = {}) {
|
|
|
49204
50168
|
close();
|
|
49205
50169
|
return "exit";
|
|
49206
50170
|
}
|
|
50171
|
+
if (isSessionInfoCommand(value) || isFlowsCommand(value)) {
|
|
50172
|
+
return "local";
|
|
50173
|
+
}
|
|
49207
50174
|
if ((turn || queue.length > 0) && value.startsWith("/")) {
|
|
49208
50175
|
return "deferred";
|
|
49209
50176
|
}
|
|
@@ -49327,6 +50294,36 @@ async function mountChatShell(otui, renderer, opts) {
|
|
|
49327
50294
|
opts.onExit?.();
|
|
49328
50295
|
return;
|
|
49329
50296
|
}
|
|
50297
|
+
if (result === "local") {
|
|
50298
|
+
const cwd = opts.deps.session?.cwd;
|
|
50299
|
+
const keys = { onKeypress: (handler) => onKeypress4(r, (key) => handler(key)) };
|
|
50300
|
+
(async () => {
|
|
50301
|
+
const [workspaces, flows] = cwd === undefined ? [[], []] : await Promise.all([loadInspectorWorkspaces(cwd), loadInspectorFlows(cwd)]);
|
|
50302
|
+
if (isFlowsCommand(line)) {
|
|
50303
|
+
openFlows(otui, chrome, { items: flows, renderer: r, ...keys });
|
|
50304
|
+
return;
|
|
50305
|
+
}
|
|
50306
|
+
const summary = cwd !== undefined ? latestSession(cwd) : undefined;
|
|
50307
|
+
const snapshot = buildSessionInfoSnapshot({
|
|
50308
|
+
summary,
|
|
50309
|
+
selection,
|
|
50310
|
+
version: package_default.version,
|
|
50311
|
+
estimateTokens: estimateContextTokens(seen),
|
|
50312
|
+
sessionText: seen.map((message2) => message2.content).join(`
|
|
50313
|
+
`),
|
|
50314
|
+
workspaces,
|
|
50315
|
+
flows
|
|
50316
|
+
});
|
|
50317
|
+
openSessionInfo(otui, chrome, {
|
|
50318
|
+
snapshot,
|
|
50319
|
+
copyText: (text) => r.copyToClipboardOSC52(text),
|
|
50320
|
+
toast: (message2) => chrome.showToast(message2),
|
|
50321
|
+
renderer: r,
|
|
50322
|
+
...keys
|
|
50323
|
+
});
|
|
50324
|
+
})();
|
|
50325
|
+
return;
|
|
50326
|
+
}
|
|
49330
50327
|
if (result === "deferred") {
|
|
49331
50328
|
append(otui.t`${otui.yellow("\u25C7 a reply is still streaming \u2014 command deferred. Wait for it to finish.")}`);
|
|
49332
50329
|
}
|
|
@@ -49413,82 +50410,6 @@ async function launchTuiChatShell(opts) {
|
|
|
49413
50410
|
|
|
49414
50411
|
// src/commands/shell.ts
|
|
49415
50412
|
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
50413
|
|
|
49493
50414
|
// src/commands/select.ts
|
|
49494
50415
|
init_guard2();
|
|
@@ -49727,6 +50648,8 @@ var READLINE_AGENT_COMMANDS = [
|
|
|
49727
50648
|
"/new",
|
|
49728
50649
|
"/clear",
|
|
49729
50650
|
"/compact",
|
|
50651
|
+
"/status",
|
|
50652
|
+
"/flows",
|
|
49730
50653
|
"/exit"
|
|
49731
50654
|
];
|
|
49732
50655
|
function readlineAgentHelpText() {
|
|
@@ -49815,6 +50738,34 @@ Starting a new session.
|
|
|
49815
50738
|
system(HELP_TEXT);
|
|
49816
50739
|
continue;
|
|
49817
50740
|
}
|
|
50741
|
+
if (isSessionInfoCommand(command)) {
|
|
50742
|
+
const cwd = deps.session?.cwd;
|
|
50743
|
+
const [workspaces, flows] = cwd === undefined ? [[], []] : await Promise.all([loadInspectorWorkspaces(cwd), loadInspectorFlows(cwd)]);
|
|
50744
|
+
system(formatSessionInfoText(buildSessionInfoSnapshot({
|
|
50745
|
+
summary: live?.summary,
|
|
50746
|
+
selection: { provider: providerName, model: modelName },
|
|
50747
|
+
version: package_default.version,
|
|
50748
|
+
estimateTokens: estimateContextTokens(history),
|
|
50749
|
+
sessionText: history.map((message2) => message2.content).join(`
|
|
50750
|
+
`),
|
|
50751
|
+
workspaces,
|
|
50752
|
+
flows
|
|
50753
|
+
})));
|
|
50754
|
+
continue;
|
|
50755
|
+
}
|
|
50756
|
+
if (isFlowsCommand(command)) {
|
|
50757
|
+
const cwd = deps.session?.cwd;
|
|
50758
|
+
const items = cwd === undefined ? [] : await loadInspectorFlows(cwd);
|
|
50759
|
+
const query = argument.trim();
|
|
50760
|
+
if (query.length > 0) {
|
|
50761
|
+
const found = findFlowItem(items, query);
|
|
50762
|
+
system(found !== undefined ? formatFlowDetailText(found) : `No flow matching '${query}'.
|
|
50763
|
+
`);
|
|
50764
|
+
continue;
|
|
50765
|
+
}
|
|
50766
|
+
system(formatFlowListText(items));
|
|
50767
|
+
continue;
|
|
50768
|
+
}
|
|
49818
50769
|
if (command === "/clear" || command === "/new") {
|
|
49819
50770
|
if (sessionsOn) {
|
|
49820
50771
|
live = createSession({ cwd: sessionCwd, provider: providerName, model: modelName });
|
|
@@ -50462,6 +51413,32 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
50462
51413
|
}
|
|
50463
51414
|
if (command === "/help") {
|
|
50464
51415
|
agentIo.onSystem?.(readlineAgentHelpText());
|
|
51416
|
+
} else if (isSessionInfoCommand(command)) {
|
|
51417
|
+
const cwd = sessionCwd;
|
|
51418
|
+
const [workspaces, flows] = await Promise.all([
|
|
51419
|
+
loadInspectorWorkspaces(cwd),
|
|
51420
|
+
loadInspectorFlows(cwd)
|
|
51421
|
+
]);
|
|
51422
|
+
agentIo.onSystem?.(formatSessionInfoText(buildSessionInfoSnapshot({
|
|
51423
|
+
summary: live?.summary,
|
|
51424
|
+
selection: { provider: deps.providerId, model: deps.modelId },
|
|
51425
|
+
version: package_default.version,
|
|
51426
|
+
usage: lastUsage,
|
|
51427
|
+
estimateTokens: estimateContextTokens(history),
|
|
51428
|
+
sessionText: history.map((message2) => message2.content).join(`
|
|
51429
|
+
`),
|
|
51430
|
+
workspaces,
|
|
51431
|
+
flows
|
|
51432
|
+
})));
|
|
51433
|
+
} else if (isFlowsCommand(command)) {
|
|
51434
|
+
const items = await loadInspectorFlows(sessionCwd);
|
|
51435
|
+
if (rest.length > 0) {
|
|
51436
|
+
const found = findFlowItem(items, rest);
|
|
51437
|
+
agentIo.onSystem?.(found !== undefined ? formatFlowDetailText(found) : `No flow matching '${rest}'.
|
|
51438
|
+
`);
|
|
51439
|
+
} else {
|
|
51440
|
+
agentIo.onSystem?.(formatFlowListText(items));
|
|
51441
|
+
}
|
|
50465
51442
|
} else if (command === "/expand") {
|
|
50466
51443
|
const expanded = expandedToolOutput(lastToolName, lastToolOutput);
|
|
50467
51444
|
if (expanded !== undefined) {
|
|
@@ -50748,7 +51725,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
50748
51725
|
modelId: sel.model
|
|
50749
51726
|
}),
|
|
50750
51727
|
maxToolCalls: resolveAgentMaxToolCalls(),
|
|
50751
|
-
idSeq: () =>
|
|
51728
|
+
idSeq: () => randomUUID18()
|
|
50752
51729
|
};
|
|
50753
51730
|
};
|
|
50754
51731
|
const redetect = () => detectProviders({
|
|
@@ -50779,7 +51756,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
50779
51756
|
makeShellDeps: (sel) => ({
|
|
50780
51757
|
makeProvider: chatFactory,
|
|
50781
51758
|
clock: () => new Date().toISOString(),
|
|
50782
|
-
idSeq: () =>
|
|
51759
|
+
idSeq: () => randomUUID18(),
|
|
50783
51760
|
initial: sel,
|
|
50784
51761
|
session: {
|
|
50785
51762
|
cwd,
|
|
@@ -50849,7 +51826,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
50849
51826
|
const deps = {
|
|
50850
51827
|
makeProvider: baseFactory,
|
|
50851
51828
|
clock: () => new Date().toISOString(),
|
|
50852
|
-
idSeq: () =>
|
|
51829
|
+
idSeq: () => randomUUID18(),
|
|
50853
51830
|
initial: baseUrl2 === undefined ? { provider, model } : { provider, model, baseUrl: baseUrl2 },
|
|
50854
51831
|
selectProviderModel: realSelectProviderModel(baseUrl2)
|
|
50855
51832
|
};
|
|
@@ -50897,7 +51874,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
50897
51874
|
modelId: model
|
|
50898
51875
|
}),
|
|
50899
51876
|
maxToolCalls: resolveAgentMaxToolCalls(),
|
|
50900
|
-
idSeq: () =>
|
|
51877
|
+
idSeq: () => randomUUID18()
|
|
50901
51878
|
};
|
|
50902
51879
|
let resumeId = flags.resumeId;
|
|
50903
51880
|
if (flags.resumePick === true && resumeId === undefined) {
|
|
@@ -51229,7 +52206,7 @@ function printHelp16() {
|
|
|
51229
52206
|
}
|
|
51230
52207
|
|
|
51231
52208
|
// src/commands/serve.ts
|
|
51232
|
-
import { randomUUID as
|
|
52209
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
51233
52210
|
|
|
51234
52211
|
// src/lib/serve-config.ts
|
|
51235
52212
|
init_config_dir();
|
|
@@ -51556,7 +52533,7 @@ function saveServeConfig(config, dir, onWarn) {
|
|
|
51556
52533
|
|
|
51557
52534
|
// src/lib/serve-credential.ts
|
|
51558
52535
|
init_config_dir();
|
|
51559
|
-
import { createHash as createHash29, randomBytes as randomBytes2, randomUUID as
|
|
52536
|
+
import { createHash as createHash29, randomBytes as randomBytes2, randomUUID as randomUUID19 } from "crypto";
|
|
51560
52537
|
import {
|
|
51561
52538
|
chmodSync as chmodSync4,
|
|
51562
52539
|
closeSync as closeSync3,
|
|
@@ -51640,7 +52617,7 @@ function readServeCredential(dir) {
|
|
|
51640
52617
|
}
|
|
51641
52618
|
function writeStore(store, dir) {
|
|
51642
52619
|
const file = serveCredentialPath(dir);
|
|
51643
|
-
const temp = `${file}.${
|
|
52620
|
+
const temp = `${file}.${randomUUID19()}.tmp`;
|
|
51644
52621
|
try {
|
|
51645
52622
|
ensureKeryxConfigDir(dir);
|
|
51646
52623
|
const handle = openSync3(temp, "wx", 384);
|
|
@@ -51680,7 +52657,7 @@ function mintRecord(now) {
|
|
|
51680
52657
|
const salt = randomBytes2(32).toString("hex");
|
|
51681
52658
|
return {
|
|
51682
52659
|
token,
|
|
51683
|
-
record: { id:
|
|
52660
|
+
record: { id: randomUUID19(), algorithm: "sha256", salt, hash: hashToken(salt, token), createdAt: now }
|
|
51684
52661
|
};
|
|
51685
52662
|
}
|
|
51686
52663
|
function issueServeToken(dir, now = () => new Date().toISOString(), onWaiting) {
|
|
@@ -51994,7 +52971,7 @@ function releaseIdempotencyKey(project, idempotencyKey, turnId, dir) {
|
|
|
51994
52971
|
}
|
|
51995
52972
|
|
|
51996
52973
|
// src/lib/serve-turn.ts
|
|
51997
|
-
import { randomUUID as
|
|
52974
|
+
import { randomUUID as randomUUID20 } from "crypto";
|
|
51998
52975
|
import path140 from "path";
|
|
51999
52976
|
init_service();
|
|
52000
52977
|
var REMOTE_ORIGIN = "remote:http";
|
|
@@ -52113,7 +53090,7 @@ async function redactOut(security, text) {
|
|
|
52113
53090
|
async function runRemoteTurn(input2) {
|
|
52114
53091
|
const scanRoot = input2.scanRoot;
|
|
52115
53092
|
const security = createSecurityService(scanRoot);
|
|
52116
|
-
const newId = input2.newId ?? (() =>
|
|
53093
|
+
const newId = input2.newId ?? (() => randomUUID20());
|
|
52117
53094
|
const clock = input2.clock ?? (() => new Date().toISOString());
|
|
52118
53095
|
const turnId = input2.turnId ?? newId();
|
|
52119
53096
|
const sessionId = input2.request.sessionId ?? newId();
|
|
@@ -52256,7 +53233,7 @@ function outcomeOf(status, gate, unresolvedBlockerIds) {
|
|
|
52256
53233
|
}
|
|
52257
53234
|
function createSubmitTurn(deps) {
|
|
52258
53235
|
return async (request, project) => {
|
|
52259
|
-
const turnId = (deps.newId ?? (() =>
|
|
53236
|
+
const turnId = (deps.newId ?? (() => randomUUID20()))();
|
|
52260
53237
|
const scanned = await scanPrompt(deps.dir, request.prompt);
|
|
52261
53238
|
if (scanned.rejected) {
|
|
52262
53239
|
return { kind: "rejected" };
|
|
@@ -52943,7 +53920,7 @@ function runConfig(args2) {
|
|
|
52943
53920
|
return;
|
|
52944
53921
|
}
|
|
52945
53922
|
const credential2 = readServeCredential();
|
|
52946
|
-
const credentialId = credential2.status === "ok" ? credential2.record.id :
|
|
53923
|
+
const credentialId = credential2.status === "ok" ? credential2.record.id : randomUUID21();
|
|
52947
53924
|
const config = defaultServeConfig(credentialId, {
|
|
52948
53925
|
address: parsed.parsed.values.get("--bind") ?? DEFAULT_SERVE_BIND_ADDRESS,
|
|
52949
53926
|
port: port ?? DEFAULT_SERVE_PORT,
|
|
@@ -56642,7 +57619,7 @@ async function versionCommand(args2, deps = {}) {
|
|
|
56642
57619
|
|
|
56643
57620
|
// src/commands/workspace.ts
|
|
56644
57621
|
init_args();
|
|
56645
|
-
import { randomUUID as
|
|
57622
|
+
import { randomUUID as randomUUID22 } from "crypto";
|
|
56646
57623
|
import { writeFile as writeFile50 } from "fs/promises";
|
|
56647
57624
|
|
|
56648
57625
|
// src/sac/fwk-explain.ts
|
|
@@ -56710,13 +57687,13 @@ async function workspaceCommand(args2) {
|
|
|
56710
57687
|
const component = optionValue(args2, "--component");
|
|
56711
57688
|
if (!title)
|
|
56712
57689
|
throw new Error("Usage: keryx workspace create --title <title> [--component <workspace-relative-ref>]");
|
|
56713
|
-
const workspace = await service4().create({ request: undefined, requestCorrelationId:
|
|
57690
|
+
const workspace = await service4().create({ request: undefined, requestCorrelationId: randomUUID22(), id: newWorkspaceId(), title, ...component ? { component: { kind: "component", uri: component } } : {} });
|
|
56714
57691
|
console.log(JSON.stringify(workspace, null, 2));
|
|
56715
57692
|
return;
|
|
56716
57693
|
}
|
|
56717
57694
|
if (subcommand === "list") {
|
|
56718
57695
|
rejectUnknownOptions(args2.slice(1), new Set);
|
|
56719
|
-
console.log(JSON.stringify(await service4().list({ request: undefined, requestCorrelationId:
|
|
57696
|
+
console.log(JSON.stringify(await service4().list({ request: undefined, requestCorrelationId: randomUUID22() }), null, 2));
|
|
56720
57697
|
return;
|
|
56721
57698
|
}
|
|
56722
57699
|
if (subcommand === "show") {
|
|
@@ -56724,7 +57701,7 @@ async function workspaceCommand(args2) {
|
|
|
56724
57701
|
const id = args2[1];
|
|
56725
57702
|
if (!id)
|
|
56726
57703
|
throw new Error("Usage: keryx workspace show <workspace-id>");
|
|
56727
|
-
console.log(JSON.stringify(await service4().show({ request: undefined, requestCorrelationId:
|
|
57704
|
+
console.log(JSON.stringify(await service4().show({ request: undefined, requestCorrelationId: randomUUID22(), workspaceId: id }), null, 2));
|
|
56728
57705
|
return;
|
|
56729
57706
|
}
|
|
56730
57707
|
if (subcommand === "add-resource") {
|
|
@@ -56735,7 +57712,7 @@ async function workspaceCommand(args2) {
|
|
|
56735
57712
|
const revision = optionValue(args2, "--revision");
|
|
56736
57713
|
if (!workspaceId || !kind || !uri)
|
|
56737
57714
|
throw new Error("Usage: keryx workspace add-resource <workspace-id> --kind <kind> --uri <workspace-relative-ref> [--revision <revision>]");
|
|
56738
|
-
console.log(JSON.stringify(await service4().addResource({ request: undefined, requestCorrelationId:
|
|
57715
|
+
console.log(JSON.stringify(await service4().addResource({ request: undefined, requestCorrelationId: randomUUID22(), workspaceId, resource: { kind, uri, ...revision ? { revision } : {} } }), null, 2));
|
|
56739
57716
|
return;
|
|
56740
57717
|
}
|
|
56741
57718
|
if (subcommand === "overview") {
|
|
@@ -56747,7 +57724,7 @@ async function workspaceCommand(args2) {
|
|
|
56747
57724
|
const maxTokens = Number(optionValue(args2, "--max-tokens") ?? "4096");
|
|
56748
57725
|
if (!Number.isInteger(maxItems) || !Number.isInteger(maxTokens) || maxItems < 0 || maxTokens < 0)
|
|
56749
57726
|
throw new Error("--max-items and --max-tokens must be non-negative integers");
|
|
56750
|
-
const result = await createLocalFwkReadService(process.cwd()).overview({ workspaceId, request: undefined, requestCorrelationId:
|
|
57727
|
+
const result = await createLocalFwkReadService(process.cwd()).overview({ workspaceId, request: undefined, requestCorrelationId: randomUUID22(), budget: { maxItems, maxTokens } });
|
|
56751
57728
|
const normalized = normalizeFwkResult(result);
|
|
56752
57729
|
console.log(JSON.stringify(normalized, null, 2));
|
|
56753
57730
|
if (args2.includes("--explain"))
|
|
@@ -56764,7 +57741,7 @@ async function workspaceCommand(args2) {
|
|
|
56764
57741
|
const maxTokens = Number(optionValue(args2, "--max-tokens") ?? "4096");
|
|
56765
57742
|
if (!Number.isInteger(maxItems) || !Number.isInteger(maxTokens) || maxItems < 0 || maxTokens < 0)
|
|
56766
57743
|
throw new Error("--max-items and --max-tokens must be non-negative integers");
|
|
56767
|
-
const result = await createLocalFwkReadService(process.cwd()).read({ workspaceId, itemId, request: undefined, requestCorrelationId:
|
|
57744
|
+
const result = await createLocalFwkReadService(process.cwd()).read({ workspaceId, itemId, request: undefined, requestCorrelationId: randomUUID22(), budget: { maxItems, maxTokens } });
|
|
56768
57745
|
const normalized = normalizeFwkResult(result);
|
|
56769
57746
|
console.log(JSON.stringify(normalized, null, 2));
|
|
56770
57747
|
if (args2.includes("--explain"))
|
|
@@ -56787,12 +57764,12 @@ async function workspaceCommand(args2) {
|
|
|
56787
57764
|
if (!session)
|
|
56788
57765
|
throw new Error(`no session matching "${sessionRef}" in this project \u2014 use \`keryx sessions list\``);
|
|
56789
57766
|
const { service: service5, wrapUpAuthority, authorizationServer } = createHarnessProposalLifecycleService(cwd, { workspaceId, ...note2 ? { note: note2 } : {} });
|
|
56790
|
-
const requestCorrelationId =
|
|
57767
|
+
const requestCorrelationId = randomUUID22();
|
|
56791
57768
|
const actor = await authorizationServer.actorContextFor(undefined, requestCorrelationId);
|
|
56792
57769
|
if (!actor)
|
|
56793
57770
|
throw new Error("trusted ActorContext is required");
|
|
56794
57771
|
const wrapUp = await wrapUpAuthority.issue({ actor, source: "session", sourceRef: sessionEvidenceRef(workspaceId, session.id) });
|
|
56795
|
-
const proposal = await service5.create({ request: undefined, requestCorrelationId, workspaceId, id: `proposal-${
|
|
57772
|
+
const proposal = await service5.create({ request: undefined, requestCorrelationId, workspaceId, id: `proposal-${randomUUID22().replace(/-/g, "").slice(0, 16)}`, proposalRevision, kind, wrapUp });
|
|
56796
57773
|
if (note2)
|
|
56797
57774
|
await writeFile50(proposalNotePath(cwd, workspaceId, proposal.id), note2, "utf8");
|
|
56798
57775
|
console.log(JSON.stringify(normalizeProposalLifecycleResult(proposal), null, 2));
|
|
@@ -56804,10 +57781,10 @@ async function workspaceCommand(args2) {
|
|
|
56804
57781
|
const proposalId = args2[2];
|
|
56805
57782
|
const decision = optionValue(args2, "--decision");
|
|
56806
57783
|
const reason = optionValue(args2, "--reason");
|
|
56807
|
-
const idempotencyKey = optionValue(args2, "--idempotency-key") ??
|
|
57784
|
+
const idempotencyKey = optionValue(args2, "--idempotency-key") ?? randomUUID22();
|
|
56808
57785
|
if (!workspaceId || !proposalId || !decision)
|
|
56809
57786
|
throw new Error("Usage: keryx workspace review <workspace-id> <proposal-id> --decision <accepted|rejected|dismissed> [--reason <reason>] [--idempotency-key <key>]");
|
|
56810
|
-
const result = await createHarnessProposalLifecycleService(process.cwd(), { workspaceId }).service.review({ request: undefined, requestCorrelationId:
|
|
57787
|
+
const result = await createHarnessProposalLifecycleService(process.cwd(), { workspaceId }).service.review({ request: undefined, requestCorrelationId: randomUUID22(), workspaceId, proposalId, decision, idempotencyKey, ...reason ? { reason } : {} });
|
|
56811
57788
|
console.log(JSON.stringify(normalizeProposalLifecycleResult(result), null, 2));
|
|
56812
57789
|
return;
|
|
56813
57790
|
}
|
|
@@ -56816,7 +57793,7 @@ async function workspaceCommand(args2) {
|
|
|
56816
57793
|
const workspaceId = args2[1];
|
|
56817
57794
|
if (!workspaceId)
|
|
56818
57795
|
throw new Error("Usage: keryx workspace collaboration <workspace-id>");
|
|
56819
|
-
console.log(JSON.stringify(await createLocalCollaborationService(process.cwd()).overview({ workspaceId, request: undefined, requestCorrelationId:
|
|
57796
|
+
console.log(JSON.stringify(await createLocalCollaborationService(process.cwd()).overview({ workspaceId, request: undefined, requestCorrelationId: randomUUID22() }), null, 2));
|
|
56820
57797
|
return;
|
|
56821
57798
|
}
|
|
56822
57799
|
if (subcommand === "policy-readiness") {
|