@mrciphersmith/keryx 0.2.34 → 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 +735 -116
- package/docs/requirements/shared-agent-context/schemas/README.md +65 -0
- package/docs/requirements/shared-agent-context/schemas/access-receipt.schema.json +13 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-accepted-transition-failed-gate.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-accepted-transition-no-target-write.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-bound-work-no-flow-ref.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-duplicate-roles.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-evidence-missing-revision.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-proposal.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-resource-egress.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-spoofed-viewer-mutation.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-stale-evidence.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-time-order.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-unsafe-uri.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/invalid-workspace.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/replay-idempotency-corpus.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/valid-accepted-transition.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/valid-access-receipt.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/valid-fwk-receipt.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/valid-proposal.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/valid-review-decision.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fixtures/valid-workspace.json +1 -0
- package/docs/requirements/shared-agent-context/schemas/fwk-receipt.schema.json +28 -0
- package/docs/requirements/shared-agent-context/schemas/review-decision.schema.json +18 -0
- package/docs/requirements/shared-agent-context/schemas/workspace-manifest.schema.json +37 -0
- package/docs/requirements/shared-agent-context/schemas/workspace-proposal.schema.json +22 -0
- package/package.json +8 -2
package/dist/cli.js
CHANGED
|
@@ -34772,9 +34772,10 @@ function traceRefFor(traceId) {
|
|
|
34772
34772
|
}
|
|
34773
34773
|
|
|
34774
34774
|
// src/sac/index.ts
|
|
34775
|
-
import { readFile as readFile62, realpath as realpath3 } from "fs/promises";
|
|
34775
|
+
import { access as access3, readFile as readFile62, realpath as realpath3 } from "fs/promises";
|
|
34776
34776
|
import { createHash as createHash10 } from "crypto";
|
|
34777
34777
|
import path115 from "path";
|
|
34778
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
34778
34779
|
var idPattern = /^[a-z][a-z0-9-]{2,63}$/;
|
|
34779
34780
|
var subjectPattern = /^(?:user|team|service|agent):[a-z0-9][a-z0-9._-]{0,127}$/;
|
|
34780
34781
|
var revisionPattern = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/;
|
|
@@ -34791,6 +34792,28 @@ var normativeSchemaFiles = {
|
|
|
34791
34792
|
"review-decision": "review-decision.schema.json"
|
|
34792
34793
|
};
|
|
34793
34794
|
var normativeSchemas = new Map;
|
|
34795
|
+
var NORMATIVE_SCHEMA_DIR = path115.join("docs", "requirements", "shared-agent-context", "schemas");
|
|
34796
|
+
async function resolveSacNormativeSchemaPath(fileName, searchFrom = [fileURLToPath6(new URL(".", import.meta.url)), process.cwd()]) {
|
|
34797
|
+
const seen = new Set;
|
|
34798
|
+
for (const start of searchFrom) {
|
|
34799
|
+
let dir = path115.resolve(start);
|
|
34800
|
+
for (let i = 0;i < 10; i++) {
|
|
34801
|
+
if (seen.has(dir))
|
|
34802
|
+
break;
|
|
34803
|
+
seen.add(dir);
|
|
34804
|
+
const candidate = path115.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
|
|
34805
|
+
try {
|
|
34806
|
+
await access3(candidate);
|
|
34807
|
+
return candidate;
|
|
34808
|
+
} catch {}
|
|
34809
|
+
const parent = path115.dirname(dir);
|
|
34810
|
+
if (parent === dir)
|
|
34811
|
+
break;
|
|
34812
|
+
dir = parent;
|
|
34813
|
+
}
|
|
34814
|
+
}
|
|
34815
|
+
throw new Error(`SAC normative schema not found: ${fileName}`);
|
|
34816
|
+
}
|
|
34794
34817
|
function parseStrictRfc3339Utc(value) {
|
|
34795
34818
|
if (typeof value !== "string")
|
|
34796
34819
|
return;
|
|
@@ -34829,7 +34852,7 @@ function isRecord2(value) {
|
|
|
34829
34852
|
async function loadNormativeSchema(schema) {
|
|
34830
34853
|
let pending = normativeSchemas.get(schema);
|
|
34831
34854
|
if (!pending) {
|
|
34832
|
-
pending =
|
|
34855
|
+
pending = resolveSacNormativeSchemaPath(normativeSchemaFiles[schema]).then((file) => readFile62(file, "utf8")).then((source) => JSON.parse(source));
|
|
34833
34856
|
normativeSchemas.set(schema, pending);
|
|
34834
34857
|
}
|
|
34835
34858
|
return pending;
|
|
@@ -44773,6 +44796,492 @@ class LiveMarkdownBlock {
|
|
|
44773
44796
|
|
|
44774
44797
|
// src/tui/tui-shell.ts
|
|
44775
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
|
+
}
|
|
44776
45285
|
|
|
44777
45286
|
// src/commands/agent-commands.ts
|
|
44778
45287
|
var CHAT_ONLY = ["chat"];
|
|
@@ -44800,7 +45309,7 @@ var AGENT_SLASH_COMMANDS = [
|
|
|
44800
45309
|
modes: BOTH,
|
|
44801
45310
|
modeDescriptions: {
|
|
44802
45311
|
agent: "Connect to an already configured provider (interactive picker)",
|
|
44803
|
-
chat: "
|
|
45312
|
+
chat: "Switch to a connected provider (picker when available)"
|
|
44804
45313
|
}
|
|
44805
45314
|
},
|
|
44806
45315
|
{
|
|
@@ -44831,6 +45340,13 @@ var AGENT_SLASH_COMMANDS = [
|
|
|
44831
45340
|
{ name: "/new", description: "Start a new session (old kept on disk)", modes: BOTH },
|
|
44832
45341
|
{ name: "/resume", description: "Resume a prior session in this project", modes: AGENT_ONLY },
|
|
44833
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 },
|
|
44834
45350
|
{
|
|
44835
45351
|
name: "/compact",
|
|
44836
45352
|
description: "Compact model context \u2014 /compact [focus] (archive kept)",
|
|
@@ -45311,7 +45827,7 @@ function selectBoxHeight(count, withDescription) {
|
|
|
45311
45827
|
const per = withDescription ? 2 : 1;
|
|
45312
45828
|
return Math.min(Math.max(count * per, per), 16);
|
|
45313
45829
|
}
|
|
45314
|
-
function
|
|
45830
|
+
function onKeypress2(r, handler) {
|
|
45315
45831
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
45316
45832
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
45317
45833
|
}
|
|
@@ -45412,7 +45928,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
45412
45928
|
key.stopPropagation();
|
|
45413
45929
|
}
|
|
45414
45930
|
};
|
|
45415
|
-
const unsub =
|
|
45931
|
+
const unsub = onKeypress2(r, onKey);
|
|
45416
45932
|
sel.on(otui.SelectRenderableEvents.ITEM_SELECTED, () => {
|
|
45417
45933
|
const chosen = sel.getSelectedOption();
|
|
45418
45934
|
const value = chosen?.value;
|
|
@@ -45700,12 +46216,13 @@ async function checkVersion(options) {
|
|
|
45700
46216
|
}
|
|
45701
46217
|
|
|
45702
46218
|
// src/tui/shell-chrome.ts
|
|
45703
|
-
function
|
|
46219
|
+
function onKeypress3(r, handler) {
|
|
45704
46220
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
45705
46221
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
45706
46222
|
}
|
|
45707
46223
|
var COMPOSER_MIN_ROWS = 1;
|
|
45708
46224
|
var COMPOSER_MAX_ROWS = 6;
|
|
46225
|
+
var COMPOSER_BORDER_ROWS = 2;
|
|
45709
46226
|
var MENU_HEIGHT = 10;
|
|
45710
46227
|
var SIDEBAR_WIDTH = 30;
|
|
45711
46228
|
var SIDEBAR_BORDER_LEFT = 1;
|
|
@@ -45723,9 +46240,29 @@ ${result.installCommand.slice(split)}`);
|
|
|
45723
46240
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
45724
46241
|
var SPINNER_MS = 120;
|
|
45725
46242
|
var TOAST_MS = 5000;
|
|
45726
|
-
function composerHeightForLines(visualLines) {
|
|
46243
|
+
function composerHeightForLines(visualLines, maxRows = COMPOSER_MAX_ROWS) {
|
|
46244
|
+
const cap = Number.isFinite(maxRows) && maxRows >= COMPOSER_MIN_ROWS ? Math.floor(maxRows) : COMPOSER_MAX_ROWS;
|
|
45727
46245
|
const n = Number.isFinite(visualLines) ? Math.floor(visualLines) : COMPOSER_MIN_ROWS;
|
|
45728
|
-
return Math.min(
|
|
46246
|
+
return Math.min(cap, Math.max(COMPOSER_MIN_ROWS, n < 1 ? COMPOSER_MIN_ROWS : n));
|
|
46247
|
+
}
|
|
46248
|
+
function composerMaxRowsForViewport(viewportRows) {
|
|
46249
|
+
if (!Number.isFinite(viewportRows) || viewportRows < 1) {
|
|
46250
|
+
return COMPOSER_MAX_ROWS;
|
|
46251
|
+
}
|
|
46252
|
+
return Math.max(COMPOSER_MIN_ROWS, Math.floor(viewportRows / 3));
|
|
46253
|
+
}
|
|
46254
|
+
function wrappedLineCount(text, width) {
|
|
46255
|
+
const inner = Number.isFinite(width) ? Math.floor(width) : 0;
|
|
46256
|
+
const paragraphs = text.length === 0 ? [""] : text.split(`
|
|
46257
|
+
`);
|
|
46258
|
+
if (inner < 1) {
|
|
46259
|
+
return Math.max(COMPOSER_MIN_ROWS, paragraphs.length);
|
|
46260
|
+
}
|
|
46261
|
+
let total = 0;
|
|
46262
|
+
for (const paragraph of paragraphs) {
|
|
46263
|
+
total += Math.max(1, Math.ceil(Math.max(paragraph.length, 1) / inner));
|
|
46264
|
+
}
|
|
46265
|
+
return total;
|
|
45729
46266
|
}
|
|
45730
46267
|
function prefixFilter(commands, query) {
|
|
45731
46268
|
const q = query.trim().toLowerCase();
|
|
@@ -45903,6 +46440,9 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
45903
46440
|
const composer = new otui.BoxRenderable(r, {
|
|
45904
46441
|
id: "composer",
|
|
45905
46442
|
flexShrink: 0,
|
|
46443
|
+
minWidth: 0,
|
|
46444
|
+
width: "100%",
|
|
46445
|
+
flexDirection: "column",
|
|
45906
46446
|
borderStyle: "rounded",
|
|
45907
46447
|
border: true,
|
|
45908
46448
|
paddingLeft: 1,
|
|
@@ -45912,10 +46452,12 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
45912
46452
|
id: "prompt",
|
|
45913
46453
|
placeholder: opts.placeholder,
|
|
45914
46454
|
wrapMode: "word",
|
|
46455
|
+
minWidth: 0,
|
|
46456
|
+
width: "100%",
|
|
45915
46457
|
minHeight: COMPOSER_MIN_ROWS,
|
|
45916
|
-
maxHeight: COMPOSER_MAX_ROWS,
|
|
45917
46458
|
height: COMPOSER_MIN_ROWS,
|
|
45918
|
-
|
|
46459
|
+
flexShrink: 0,
|
|
46460
|
+
overflow: "scroll",
|
|
45919
46461
|
keyBindings: [
|
|
45920
46462
|
{ name: "return", action: "submit" },
|
|
45921
46463
|
{ name: "kpenter", action: "submit" },
|
|
@@ -45929,17 +46471,28 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
45929
46471
|
});
|
|
45930
46472
|
composer.add(textarea);
|
|
45931
46473
|
main.add(composer);
|
|
46474
|
+
const viewportRows = () => {
|
|
46475
|
+
const h = r.height;
|
|
46476
|
+
return typeof h === "number" && h > 0 ? h : COMPOSER_MAX_ROWS * 3;
|
|
46477
|
+
};
|
|
45932
46478
|
const syncComposerHeight = () => {
|
|
46479
|
+
const cap = composerMaxRowsForViewport(viewportRows());
|
|
45933
46480
|
let lines = 1;
|
|
45934
46481
|
try {
|
|
45935
|
-
|
|
46482
|
+
const wrapWidth = typeof textarea.width === "number" && textarea.width > 0 ? textarea.width : 0;
|
|
46483
|
+
lines = Math.max(textarea.virtualLineCount || 0, textarea.lineCount || 0, wrappedLineCount(textarea.plainText, wrapWidth), 1);
|
|
45936
46484
|
} catch {
|
|
45937
|
-
lines =
|
|
46485
|
+
lines = wrappedLineCount(textarea.plainText, 0);
|
|
45938
46486
|
}
|
|
45939
|
-
const h = composerHeightForLines(lines);
|
|
46487
|
+
const h = composerHeightForLines(lines, cap);
|
|
45940
46488
|
if (textarea.height !== h) {
|
|
45941
46489
|
textarea.height = h;
|
|
45942
46490
|
}
|
|
46491
|
+
const boxH = h + COMPOSER_BORDER_ROWS;
|
|
46492
|
+
if (composer.height !== boxH) {
|
|
46493
|
+
composer.height = boxH;
|
|
46494
|
+
}
|
|
46495
|
+
textarea.maxHeight = cap;
|
|
45943
46496
|
};
|
|
45944
46497
|
const input2 = {
|
|
45945
46498
|
get value() {
|
|
@@ -46067,6 +46620,10 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
46067
46620
|
syncComposerHeight();
|
|
46068
46621
|
refilter();
|
|
46069
46622
|
};
|
|
46623
|
+
const onComposerResized = () => {
|
|
46624
|
+
syncComposerHeight();
|
|
46625
|
+
};
|
|
46626
|
+
textarea.on(otui.LayoutEvents.RESIZED, onComposerResized);
|
|
46070
46627
|
textarea.focus();
|
|
46071
46628
|
syncComposerHeight();
|
|
46072
46629
|
const submitHandlers = new Set;
|
|
@@ -46089,7 +46646,7 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
46089
46646
|
syncComposerHeight();
|
|
46090
46647
|
emitSubmit(line);
|
|
46091
46648
|
};
|
|
46092
|
-
const unsubscribeMenuKeys =
|
|
46649
|
+
const unsubscribeMenuKeys = onKeypress3(r, (key) => {
|
|
46093
46650
|
if (!menu.visible || !menuNav || overlayActive()) {
|
|
46094
46651
|
return;
|
|
46095
46652
|
}
|
|
@@ -46167,6 +46724,9 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
46167
46724
|
clearBusyTimer();
|
|
46168
46725
|
clearToastTimer();
|
|
46169
46726
|
unsubscribeMenuKeys();
|
|
46727
|
+
try {
|
|
46728
|
+
textarea.off(otui.LayoutEvents.RESIZED, onComposerResized);
|
|
46729
|
+
} catch {}
|
|
46170
46730
|
try {
|
|
46171
46731
|
r.off(otui.CliRenderEvents.SELECTION, onSelection);
|
|
46172
46732
|
} catch {}
|
|
@@ -47266,12 +47826,8 @@ async function filterConnectedDetectedProviders(detected, options = {}) {
|
|
|
47266
47826
|
}
|
|
47267
47827
|
const requiresApiKey = registry.requiresApiKey ?? true;
|
|
47268
47828
|
const envKey = prov.envKey ?? registry.envKey;
|
|
47269
|
-
|
|
47270
|
-
|
|
47271
|
-
continue;
|
|
47272
|
-
}
|
|
47273
|
-
const raw = env[envKey];
|
|
47274
|
-
if (raw === undefined || raw.length === 0) {
|
|
47829
|
+
const raw = envKey !== undefined ? env[envKey] : undefined;
|
|
47830
|
+
if (requiresApiKey && (raw === undefined || raw.length === 0)) {
|
|
47275
47831
|
continue;
|
|
47276
47832
|
}
|
|
47277
47833
|
const compat = {
|
|
@@ -47280,13 +47836,13 @@ async function filterConnectedDetectedProviders(detected, options = {}) {
|
|
|
47280
47836
|
...prov.chatPath !== undefined ? { chatPath: prov.chatPath } : {},
|
|
47281
47837
|
...prov.modelsPath !== undefined ? { modelsPath: prov.modelsPath } : {}
|
|
47282
47838
|
};
|
|
47283
|
-
const result = await fetchOpenAiCompatModelsDetailed(fetchFn, compat, raw, {
|
|
47839
|
+
const result = await fetchOpenAiCompatModelsDetailed(fetchFn, compat, raw ?? "", {
|
|
47284
47840
|
timeoutMs: MODELS_FETCH_TIMEOUT_MS
|
|
47285
47841
|
});
|
|
47286
47842
|
if (result.source !== "live" || result.models.length === 0) {
|
|
47287
47843
|
continue;
|
|
47288
47844
|
}
|
|
47289
|
-
connected.push(prov);
|
|
47845
|
+
connected.push({ ...prov, models: result.models });
|
|
47290
47846
|
}
|
|
47291
47847
|
return connected;
|
|
47292
47848
|
}
|
|
@@ -47538,7 +48094,7 @@ function overlayBox(otui, r, id) {
|
|
|
47538
48094
|
padding: 1
|
|
47539
48095
|
});
|
|
47540
48096
|
}
|
|
47541
|
-
function
|
|
48097
|
+
function onKeypress4(r, handler) {
|
|
47542
48098
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
47543
48099
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
47544
48100
|
}
|
|
@@ -47583,7 +48139,7 @@ function promptBaseUrlStep(otui, r, label, baseUrl2) {
|
|
|
47583
48139
|
unsub();
|
|
47584
48140
|
r.root.remove(box);
|
|
47585
48141
|
};
|
|
47586
|
-
const unsub =
|
|
48142
|
+
const unsub = onKeypress4(r, (key) => {
|
|
47587
48143
|
if (key.name === "escape") {
|
|
47588
48144
|
cleanup();
|
|
47589
48145
|
resolve3(undefined);
|
|
@@ -47619,7 +48175,7 @@ function promptApiKeyStep(otui, r, opts) {
|
|
|
47619
48175
|
key.stopPropagation();
|
|
47620
48176
|
}
|
|
47621
48177
|
};
|
|
47622
|
-
const unsub =
|
|
48178
|
+
const unsub = onKeypress4(r, onKey);
|
|
47623
48179
|
const cleanup = () => {
|
|
47624
48180
|
unsub();
|
|
47625
48181
|
r.root.remove(box);
|
|
@@ -47659,7 +48215,7 @@ function pickProviderStep(otui, r, detected) {
|
|
|
47659
48215
|
key.stopPropagation();
|
|
47660
48216
|
}
|
|
47661
48217
|
};
|
|
47662
|
-
const unsub =
|
|
48218
|
+
const unsub = onKeypress4(r, onKey);
|
|
47663
48219
|
const cleanup = () => {
|
|
47664
48220
|
unsub();
|
|
47665
48221
|
r.root.remove(box);
|
|
@@ -47693,11 +48249,11 @@ function selectProviderModelInTui(otui, r, detected, options = {}) {
|
|
|
47693
48249
|
resolve3(undefined);
|
|
47694
48250
|
return;
|
|
47695
48251
|
}
|
|
47696
|
-
const selectedBaseUrl = prov.baseUrl
|
|
47697
|
-
if (prov.baseUrl !== undefined && selectedBaseUrl === undefined) {
|
|
48252
|
+
const selectedBaseUrl = options.onlyConnected || prov.baseUrl === undefined ? prov.baseUrl : await promptBaseUrlStep(otui, r, prov.label ?? prov.name, prov.baseUrl);
|
|
48253
|
+
if (!options.onlyConnected && prov.baseUrl !== undefined && selectedBaseUrl === undefined) {
|
|
47698
48254
|
continue;
|
|
47699
48255
|
}
|
|
47700
|
-
if (selectedBaseUrl !== undefined)
|
|
48256
|
+
if (!options.onlyConnected && selectedBaseUrl !== undefined)
|
|
47701
48257
|
saveProviderBaseUrl(prov.name, selectedBaseUrl);
|
|
47702
48258
|
const selectedProvider = selectedBaseUrl === undefined ? prov : { ...prov, baseUrl: selectedBaseUrl };
|
|
47703
48259
|
const envKey = prov.envKey;
|
|
@@ -47777,7 +48333,7 @@ function pickModelInTui(otui, r, models) {
|
|
|
47777
48333
|
key.stopPropagation();
|
|
47778
48334
|
}
|
|
47779
48335
|
};
|
|
47780
|
-
const unsub =
|
|
48336
|
+
const unsub = onKeypress4(r, onKey);
|
|
47781
48337
|
const cleanup = () => {
|
|
47782
48338
|
unsub();
|
|
47783
48339
|
r.root.remove(box);
|
|
@@ -47869,7 +48425,7 @@ function pickSessionInTui(otui, r, sessions) {
|
|
|
47869
48425
|
key.stopPropagation();
|
|
47870
48426
|
}
|
|
47871
48427
|
};
|
|
47872
|
-
const unsub =
|
|
48428
|
+
const unsub = onKeypress4(r, onKey);
|
|
47873
48429
|
const cleanup = () => {
|
|
47874
48430
|
unsub();
|
|
47875
48431
|
r.root.remove(box);
|
|
@@ -48054,6 +48610,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
48054
48610
|
hasExactUsage = true;
|
|
48055
48611
|
}
|
|
48056
48612
|
});
|
|
48613
|
+
let lastUsage;
|
|
48614
|
+
const recordedUsage = io.onUsage?.bind(io);
|
|
48615
|
+
io.onUsage = (usage) => {
|
|
48616
|
+
lastUsage = usage;
|
|
48617
|
+
recordedUsage?.(usage);
|
|
48618
|
+
};
|
|
48057
48619
|
attachBlockIo(io, addBlock, {
|
|
48058
48620
|
onReasoning: () => {
|
|
48059
48621
|
setBusyPhase("thinking");
|
|
@@ -48450,6 +49012,22 @@ Staying in the current session.
|
|
|
48450
49012
|
`);
|
|
48451
49013
|
};
|
|
48452
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
|
+
};
|
|
48453
49031
|
const updateModelLabels = () => {
|
|
48454
49032
|
paintSessionHeader();
|
|
48455
49033
|
const label = `${currentSel.provider}/${currentSel.model}`;
|
|
@@ -48655,6 +49233,10 @@ Staying in the current session.
|
|
|
48655
49233
|
`);
|
|
48656
49234
|
return;
|
|
48657
49235
|
}
|
|
49236
|
+
if (command2 !== undefined && isSessionInfoCommand(command2.name)) {
|
|
49237
|
+
showSessionInfo();
|
|
49238
|
+
return;
|
|
49239
|
+
}
|
|
48658
49240
|
if (command2 !== undefined || line.startsWith("/")) {
|
|
48659
49241
|
transcript.add(new otui.TextRenderable(r, {
|
|
48660
49242
|
id: `c${uid++}`,
|
|
@@ -48796,6 +49378,10 @@ Staying in the current session.
|
|
|
48796
49378
|
}
|
|
48797
49379
|
return;
|
|
48798
49380
|
}
|
|
49381
|
+
if (isSessionInfoCommand(command.name)) {
|
|
49382
|
+
showSessionInfo();
|
|
49383
|
+
return;
|
|
49384
|
+
}
|
|
48799
49385
|
if (command.name === "/copy") {
|
|
48800
49386
|
const target = newestBlock();
|
|
48801
49387
|
if (target === undefined || !copyBlock(target.id)) {
|
|
@@ -49015,7 +49601,7 @@ Staying in the current session.
|
|
|
49015
49601
|
focusComposer();
|
|
49016
49602
|
});
|
|
49017
49603
|
};
|
|
49018
|
-
|
|
49604
|
+
onKeypress4(r, (key) => {
|
|
49019
49605
|
nav.handleKey(key);
|
|
49020
49606
|
});
|
|
49021
49607
|
chrome.onSubmit((line) => {
|
|
@@ -49141,6 +49727,9 @@ function createChatBridge(hooks = {}) {
|
|
|
49141
49727
|
close();
|
|
49142
49728
|
return "exit";
|
|
49143
49729
|
}
|
|
49730
|
+
if (isSessionInfoCommand(value)) {
|
|
49731
|
+
return "local";
|
|
49732
|
+
}
|
|
49144
49733
|
if ((turn || queue.length > 0) && value.startsWith("/")) {
|
|
49145
49734
|
return "deferred";
|
|
49146
49735
|
}
|
|
@@ -49264,6 +49853,22 @@ async function mountChatShell(otui, renderer, opts) {
|
|
|
49264
49853
|
opts.onExit?.();
|
|
49265
49854
|
return;
|
|
49266
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
|
+
}
|
|
49267
49872
|
if (result === "deferred") {
|
|
49268
49873
|
append(otui.t`${otui.yellow("\u25C7 a reply is still streaming \u2014 command deferred. Wait for it to finish.")}`);
|
|
49269
49874
|
}
|
|
@@ -49315,6 +49920,12 @@ async function launchTuiChatShell(opts) {
|
|
|
49315
49920
|
runShell: opts.runShell,
|
|
49316
49921
|
pickSelection: async (pickOpts) => {
|
|
49317
49922
|
const detected = opts.redetect !== undefined ? await opts.redetect() : opts.detected;
|
|
49923
|
+
if (pickOpts?.onlyConnected === true) {
|
|
49924
|
+
return await selectProviderModelInTui(otui, r, detected, {
|
|
49925
|
+
onlyConnected: true,
|
|
49926
|
+
env: process.env
|
|
49927
|
+
});
|
|
49928
|
+
}
|
|
49318
49929
|
const only = pickOpts?.onlyProvider;
|
|
49319
49930
|
if (only === undefined) {
|
|
49320
49931
|
return await selectProviderModelInTui(otui, r, detected);
|
|
@@ -49344,76 +49955,6 @@ async function launchTuiChatShell(opts) {
|
|
|
49344
49955
|
|
|
49345
49956
|
// src/commands/shell.ts
|
|
49346
49957
|
init_shell_config();
|
|
49347
|
-
// package.json
|
|
49348
|
-
var package_default = {
|
|
49349
|
-
name: "@mrciphersmith/keryx",
|
|
49350
|
-
version: "0.2.34",
|
|
49351
|
-
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
49352
|
-
private: false,
|
|
49353
|
-
publishConfig: {
|
|
49354
|
-
access: "public"
|
|
49355
|
-
},
|
|
49356
|
-
license: "MIT",
|
|
49357
|
-
type: "module",
|
|
49358
|
-
repository: {
|
|
49359
|
-
type: "git",
|
|
49360
|
-
url: "git+ssh://git@github.com/MrCipherSmith/keryx.git"
|
|
49361
|
-
},
|
|
49362
|
-
keywords: [
|
|
49363
|
-
"ai-agents",
|
|
49364
|
-
"coding-agents",
|
|
49365
|
-
"agent-harness",
|
|
49366
|
-
"agent-context",
|
|
49367
|
-
"repository-context",
|
|
49368
|
-
"code-graph",
|
|
49369
|
-
"project-memory",
|
|
49370
|
-
"test-impact-analysis",
|
|
49371
|
-
"developer-tools",
|
|
49372
|
-
"model-context-protocol",
|
|
49373
|
-
"mcp",
|
|
49374
|
-
"claude-code",
|
|
49375
|
-
"cursor",
|
|
49376
|
-
"codex",
|
|
49377
|
-
"cli",
|
|
49378
|
-
"bun"
|
|
49379
|
-
],
|
|
49380
|
-
bin: {
|
|
49381
|
-
keryx: "./dist/cli.js"
|
|
49382
|
-
},
|
|
49383
|
-
scripts: {
|
|
49384
|
-
keryx: "bun ./src/cli.ts",
|
|
49385
|
-
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",
|
|
49386
|
-
prepare: "bun run build",
|
|
49387
|
-
typecheck: "tsc --noEmit",
|
|
49388
|
-
test: "bun test",
|
|
49389
|
-
check: "tsc --noEmit && bun test",
|
|
49390
|
-
"check:doc-links": "bun scripts/check-doc-links.ts",
|
|
49391
|
-
"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"
|
|
49392
|
-
},
|
|
49393
|
-
files: [
|
|
49394
|
-
"dist",
|
|
49395
|
-
"src/gdgraph",
|
|
49396
|
-
"src/gdskills/bundled",
|
|
49397
|
-
"src/gdskills/contracts",
|
|
49398
|
-
"LICENSE",
|
|
49399
|
-
"README.md",
|
|
49400
|
-
"package.json"
|
|
49401
|
-
],
|
|
49402
|
-
dependencies: {},
|
|
49403
|
-
optionalDependencies: {
|
|
49404
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49405
|
-
"@opentui/core": "^0.4.5",
|
|
49406
|
-
"web-tree-sitter": "^0.22.0"
|
|
49407
|
-
},
|
|
49408
|
-
devDependencies: {
|
|
49409
|
-
"@types/bun": "latest",
|
|
49410
|
-
"bun-types": "latest",
|
|
49411
|
-
typescript: "^5"
|
|
49412
|
-
},
|
|
49413
|
-
engines: {
|
|
49414
|
-
bun: ">=1.1.0"
|
|
49415
|
-
}
|
|
49416
|
-
};
|
|
49417
49958
|
|
|
49418
49959
|
// src/commands/select.ts
|
|
49419
49960
|
init_guard2();
|
|
@@ -49652,6 +50193,9 @@ var READLINE_AGENT_COMMANDS = [
|
|
|
49652
50193
|
"/new",
|
|
49653
50194
|
"/clear",
|
|
49654
50195
|
"/compact",
|
|
50196
|
+
"/session-info",
|
|
50197
|
+
"/status",
|
|
50198
|
+
"/info",
|
|
49655
50199
|
"/exit"
|
|
49656
50200
|
];
|
|
49657
50201
|
function readlineAgentHelpText() {
|
|
@@ -49740,6 +50284,15 @@ Starting a new session.
|
|
|
49740
50284
|
system(HELP_TEXT);
|
|
49741
50285
|
continue;
|
|
49742
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
|
+
}
|
|
49743
50296
|
if (command === "/clear" || command === "/new") {
|
|
49744
50297
|
if (sessionsOn) {
|
|
49745
50298
|
live = createSession({ cwd: sessionCwd, provider: providerName, model: modelName });
|
|
@@ -49809,7 +50362,12 @@ Starting a new session.
|
|
|
49809
50362
|
continue;
|
|
49810
50363
|
}
|
|
49811
50364
|
if (command === "/connect") {
|
|
49812
|
-
|
|
50365
|
+
if (deps.selectProviderModel === undefined) {
|
|
50366
|
+
system(CONNECT_GUIDANCE);
|
|
50367
|
+
continue;
|
|
50368
|
+
}
|
|
50369
|
+
const picked = await deps.selectProviderModel(io, { onlyConnected: true });
|
|
50370
|
+
applySelection(picked);
|
|
49813
50371
|
continue;
|
|
49814
50372
|
}
|
|
49815
50373
|
const wrongMode = describeUnavailableCommand(command, "chat");
|
|
@@ -50382,6 +50940,14 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
50382
50940
|
}
|
|
50383
50941
|
if (command === "/help") {
|
|
50384
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
|
+
})));
|
|
50385
50951
|
} else if (command === "/expand") {
|
|
50386
50952
|
const expanded = expandedToolOutput(lastToolName, lastToolOutput);
|
|
50387
50953
|
if (expanded !== undefined) {
|
|
@@ -53020,9 +53586,9 @@ function printHelp17() {
|
|
|
53020
53586
|
// src/commands/update.ts
|
|
53021
53587
|
import { spawn as spawn5 } from "child_process";
|
|
53022
53588
|
import { chmod as chmod4, mkdir as mkdir52, readFile as readFile75, readdir as readdir22, writeFile as writeFile47 } from "fs/promises";
|
|
53023
|
-
import { access as
|
|
53589
|
+
import { access as access4, constants as constants2, existsSync as existsSync29 } from "fs";
|
|
53024
53590
|
import path141 from "path";
|
|
53025
|
-
import { fileURLToPath as
|
|
53591
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
53026
53592
|
init_config();
|
|
53027
53593
|
init_config2();
|
|
53028
53594
|
init_templates2();
|
|
@@ -54118,7 +54684,7 @@ async function runPostUpdateHooks(projectRoot) {
|
|
|
54118
54684
|
}
|
|
54119
54685
|
async function accessExecutable(filePath) {
|
|
54120
54686
|
await new Promise((resolve3, reject) => {
|
|
54121
|
-
|
|
54687
|
+
access4(filePath, constants2.X_OK, (error2) => {
|
|
54122
54688
|
if (error2) {
|
|
54123
54689
|
reject(error2);
|
|
54124
54690
|
return;
|
|
@@ -54166,12 +54732,12 @@ async function copyFileIfChanged2(from, to) {
|
|
|
54166
54732
|
await writeFile47(to, next, "utf8");
|
|
54167
54733
|
}
|
|
54168
54734
|
function runtimeSourcePath2(relativePath) {
|
|
54169
|
-
const directPath =
|
|
54735
|
+
const directPath = fileURLToPath7(new URL(relativePath, import.meta.url));
|
|
54170
54736
|
if (existsSync29(directPath)) {
|
|
54171
54737
|
return directPath;
|
|
54172
54738
|
}
|
|
54173
54739
|
if (relativePath.startsWith("../")) {
|
|
54174
|
-
const packagedSourcePath = path141.join(path141.dirname(
|
|
54740
|
+
const packagedSourcePath = path141.join(path141.dirname(fileURLToPath7(import.meta.url)), "..", "src", relativePath.slice(3));
|
|
54175
54741
|
if (existsSync29(packagedSourcePath)) {
|
|
54176
54742
|
return packagedSourcePath;
|
|
54177
54743
|
}
|
|
@@ -56564,6 +57130,53 @@ async function versionCommand(args2, deps = {}) {
|
|
|
56564
57130
|
init_args();
|
|
56565
57131
|
import { randomUUID as randomUUID21 } from "crypto";
|
|
56566
57132
|
import { writeFile as writeFile50 } from "fs/promises";
|
|
57133
|
+
|
|
57134
|
+
// src/sac/fwk-explain.ts
|
|
57135
|
+
function isOverflow(result) {
|
|
57136
|
+
return "code" in result;
|
|
57137
|
+
}
|
|
57138
|
+
function formatFwkExplain(result) {
|
|
57139
|
+
if (isOverflow(result)) {
|
|
57140
|
+
return [`SAC explain: context_overflow (${result.code})`, "No successful manifest/receipt. Shrink the scope or raise the budget."].join(`
|
|
57141
|
+
`);
|
|
57142
|
+
}
|
|
57143
|
+
const facts = Array.isArray(result.manifest.facts) ? result.manifest.facts : [];
|
|
57144
|
+
const knowHow = Array.isArray(result.manifest.knowHow) ? result.manifest.knowHow : [];
|
|
57145
|
+
const work = result.manifest.work;
|
|
57146
|
+
const byKind = { wiki: 0, memory: 0, skill: 0, other: 0 };
|
|
57147
|
+
const knowHowLines = knowHow.map((item) => {
|
|
57148
|
+
const row = item;
|
|
57149
|
+
const kind = row.kind === "wiki" || row.kind === "memory" || row.kind === "skill" ? row.kind : "other";
|
|
57150
|
+
byKind[kind] += 1;
|
|
57151
|
+
return ` - ${kind} ${row.uri ?? "?"} revision=${row.revision ?? "?"} status=${row.status ?? "?"}`;
|
|
57152
|
+
});
|
|
57153
|
+
const workState = work?.state ?? "unbound";
|
|
57154
|
+
const lines = [
|
|
57155
|
+
"SAC explain (FWK \u2014 Facts / Work / Know-how)",
|
|
57156
|
+
` freshness: ${result.manifest.freshness}`,
|
|
57157
|
+
` receipt: ${result.receipt.id} decision=${result.receipt.decision}`,
|
|
57158
|
+
` Facts (${facts.length}) \u2014 evidence-linked, task-local; not durable knowledge`,
|
|
57159
|
+
...facts.map((fact) => {
|
|
57160
|
+
const row = fact;
|
|
57161
|
+
const ev = row.evidence?.[0];
|
|
57162
|
+
return ` - ${row.statement ?? "(no statement)"} uri=${ev?.uri ?? "?"} revision=${ev?.revision ?? "?"} freshness=${row.freshness ?? "?"}`;
|
|
57163
|
+
}),
|
|
57164
|
+
` Work (${workState}) \u2014 Flow projection only; SAC does not write flow.json`,
|
|
57165
|
+
...workState === "bound" ? [
|
|
57166
|
+
` - flow=${work?.flowRef?.uri ?? "?"} snapshot=${work?.flowRef?.snapshot ?? "?"} revision=${work?.flowRef?.revision ?? "?"}`,
|
|
57167
|
+
` - completed=${(work?.completed ?? []).join(",") || "(none)"} next=${(work?.next ?? []).join(",") || "(none)"} blocked=${(work?.blocked ?? []).join(",") || "(none)"}`
|
|
57168
|
+
] : [" - no flow resource bound on this workspace"],
|
|
57169
|
+
` Know-how (${knowHow.length}: wiki=${byKind.wiki} memory=${byKind.memory} skill=${byKind.skill}) \u2014 references to owning stores, not SAC copies`,
|
|
57170
|
+
...knowHowLines.length > 0 ? knowHowLines : [" - (none accepted/visible in this budget)"],
|
|
57171
|
+
" Not written here: graph nodes/edges (navigation only), session transcripts, hidden reasoning."
|
|
57172
|
+
];
|
|
57173
|
+
if (result.partial)
|
|
57174
|
+
lines.push(` partial: omitted optional ${result.omittedOptional.join(", ") || "(none)"}`);
|
|
57175
|
+
return lines.join(`
|
|
57176
|
+
`);
|
|
57177
|
+
}
|
|
57178
|
+
|
|
57179
|
+
// src/commands/workspace.ts
|
|
56567
57180
|
var PROPOSAL_KINDS = ["decision", "wiki-update", "memory-entry", "follow-up", "contract-change", "risk"];
|
|
56568
57181
|
function service4() {
|
|
56569
57182
|
return new WorkspaceService({
|
|
@@ -56612,30 +57225,36 @@ async function workspaceCommand(args2) {
|
|
|
56612
57225
|
return;
|
|
56613
57226
|
}
|
|
56614
57227
|
if (subcommand === "overview") {
|
|
56615
|
-
rejectUnknownOptions(args2.slice(2), new Set(["--max-items", "--max-tokens"]));
|
|
57228
|
+
rejectUnknownOptions(args2.slice(2), new Set(["--max-items", "--max-tokens", "--explain"]));
|
|
56616
57229
|
const workspaceId = args2[1];
|
|
56617
57230
|
if (!workspaceId)
|
|
56618
|
-
throw new Error("Usage: keryx workspace overview <workspace-id> [--max-items N] [--max-tokens N]");
|
|
57231
|
+
throw new Error("Usage: keryx workspace overview <workspace-id> [--max-items N] [--max-tokens N] [--explain]");
|
|
56619
57232
|
const maxItems = Number(optionValue(args2, "--max-items") ?? "32");
|
|
56620
57233
|
const maxTokens = Number(optionValue(args2, "--max-tokens") ?? "4096");
|
|
56621
57234
|
if (!Number.isInteger(maxItems) || !Number.isInteger(maxTokens) || maxItems < 0 || maxTokens < 0)
|
|
56622
57235
|
throw new Error("--max-items and --max-tokens must be non-negative integers");
|
|
56623
57236
|
const result = await createLocalFwkReadService(process.cwd()).overview({ workspaceId, request: undefined, requestCorrelationId: randomUUID21(), budget: { maxItems, maxTokens } });
|
|
56624
|
-
|
|
57237
|
+
const normalized = normalizeFwkResult(result);
|
|
57238
|
+
console.log(JSON.stringify(normalized, null, 2));
|
|
57239
|
+
if (args2.includes("--explain"))
|
|
57240
|
+
console.error(formatFwkExplain(normalized));
|
|
56625
57241
|
return;
|
|
56626
57242
|
}
|
|
56627
57243
|
if (subcommand === "read") {
|
|
56628
|
-
rejectUnknownOptions(args2.slice(3), new Set(["--max-items", "--max-tokens"]));
|
|
57244
|
+
rejectUnknownOptions(args2.slice(3), new Set(["--max-items", "--max-tokens", "--explain"]));
|
|
56629
57245
|
const workspaceId = args2[1];
|
|
56630
57246
|
const itemId = args2[2];
|
|
56631
57247
|
if (!workspaceId || !itemId)
|
|
56632
|
-
throw new Error("Usage: keryx workspace read <workspace-id> <item-id> [--max-items N] [--max-tokens N]");
|
|
57248
|
+
throw new Error("Usage: keryx workspace read <workspace-id> <item-id> [--max-items N] [--max-tokens N] [--explain]");
|
|
56633
57249
|
const maxItems = Number(optionValue(args2, "--max-items") ?? "1");
|
|
56634
57250
|
const maxTokens = Number(optionValue(args2, "--max-tokens") ?? "4096");
|
|
56635
57251
|
if (!Number.isInteger(maxItems) || !Number.isInteger(maxTokens) || maxItems < 0 || maxTokens < 0)
|
|
56636
57252
|
throw new Error("--max-items and --max-tokens must be non-negative integers");
|
|
56637
57253
|
const result = await createLocalFwkReadService(process.cwd()).read({ workspaceId, itemId, request: undefined, requestCorrelationId: randomUUID21(), budget: { maxItems, maxTokens } });
|
|
56638
|
-
|
|
57254
|
+
const normalized = normalizeFwkResult(result);
|
|
57255
|
+
console.log(JSON.stringify(normalized, null, 2));
|
|
57256
|
+
if (args2.includes("--explain"))
|
|
57257
|
+
console.error(formatFwkExplain(normalized));
|
|
56639
57258
|
return;
|
|
56640
57259
|
}
|
|
56641
57260
|
if (subcommand === "propose") {
|
|
@@ -56714,8 +57333,8 @@ function printHelp20() {
|
|
|
56714
57333
|
keryx workspace list
|
|
56715
57334
|
keryx workspace show <workspace-id>
|
|
56716
57335
|
keryx workspace add-resource <workspace-id> --kind <kind> --uri <workspace-relative-ref> [--revision <revision>]
|
|
56717
|
-
keryx workspace overview <workspace-id> [--max-items N] [--max-tokens N]
|
|
56718
|
-
keryx workspace read <workspace-id> <item-id> [--max-items N] [--max-tokens N]
|
|
57336
|
+
keryx workspace overview <workspace-id> [--max-items N] [--max-tokens N] [--explain]
|
|
57337
|
+
keryx workspace read <workspace-id> <item-id> [--max-items N] [--max-tokens N] [--explain]
|
|
56719
57338
|
keryx workspace propose <workspace-id> --kind <` + PROPOSAL_KINDS.join("|") + `> --session <session-id> [--note <one-line note>]
|
|
56720
57339
|
keryx workspace review <workspace-id> <proposal-id> --decision <accepted|rejected|dismissed> [--reason <reason>] [--idempotency-key <key>]
|
|
56721
57340
|
keryx workspace collaboration <workspace-id>
|