@mrciphersmith/keryx 0.2.36 → 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 +583 -92
- 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
|
|
@@ -44799,7 +44799,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
44799
44799
|
// package.json
|
|
44800
44800
|
var package_default = {
|
|
44801
44801
|
name: "@mrciphersmith/keryx",
|
|
44802
|
-
version: "0.2.
|
|
44802
|
+
version: "0.2.37",
|
|
44803
44803
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
44804
44804
|
private: false,
|
|
44805
44805
|
publishConfig: {
|
|
@@ -44881,6 +44881,17 @@ function onKeypress(r, handler) {
|
|
|
44881
44881
|
var BACKDROP_ID = "modal-backdrop";
|
|
44882
44882
|
var PANEL_ID = "modal-panel";
|
|
44883
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
|
+
}
|
|
44884
44895
|
var hosts = new WeakMap;
|
|
44885
44896
|
function clearChildren(box) {
|
|
44886
44897
|
for (const child of [...box.getChildren()]) {
|
|
@@ -44916,6 +44927,14 @@ function paintTabs(state) {
|
|
|
44916
44927
|
content: state.otui.t`${state.otui.dim(labels)}`
|
|
44917
44928
|
}));
|
|
44918
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
|
+
}
|
|
44919
44938
|
function unmountActiveTab(state) {
|
|
44920
44939
|
const cleanup = state.tabCleanup;
|
|
44921
44940
|
state.tabCleanup = undefined;
|
|
@@ -44975,10 +44994,10 @@ function ensureHost(otui, chrome) {
|
|
|
44975
44994
|
});
|
|
44976
44995
|
const panel = new otui.BoxRenderable(r, {
|
|
44977
44996
|
id: PANEL_ID,
|
|
44978
|
-
width:
|
|
44979
|
-
|
|
44980
|
-
maxHeight: "80%",
|
|
44997
|
+
width: MODAL_PANEL_WIDTH,
|
|
44998
|
+
height: MODAL_PANEL_HEIGHT,
|
|
44981
44999
|
flexShrink: 0,
|
|
45000
|
+
flexGrow: 0,
|
|
44982
45001
|
flexDirection: "column",
|
|
44983
45002
|
borderStyle: "rounded",
|
|
44984
45003
|
border: true,
|
|
@@ -44988,26 +45007,57 @@ function ensureHost(otui, chrome) {
|
|
|
44988
45007
|
paddingRight: 1,
|
|
44989
45008
|
zIndex: 101
|
|
44990
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
|
+
});
|
|
44991
45018
|
const titleText = new otui.TextRenderable(r, {
|
|
44992
45019
|
id: "modal-title",
|
|
44993
|
-
content: ""
|
|
45020
|
+
content: "",
|
|
45021
|
+
flexGrow: 1
|
|
44994
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);
|
|
44995
45030
|
const tabStrip = new otui.BoxRenderable(r, {
|
|
44996
45031
|
id: "modal-tab-strip",
|
|
44997
45032
|
flexShrink: 0,
|
|
44998
45033
|
width: "100%",
|
|
45034
|
+
height: 1,
|
|
44999
45035
|
flexDirection: "row",
|
|
45000
45036
|
focusable: true
|
|
45001
45037
|
});
|
|
45002
45038
|
const body = new otui.BoxRenderable(r, {
|
|
45003
45039
|
id: "modal-body",
|
|
45004
45040
|
width: "100%",
|
|
45041
|
+
flexGrow: 1,
|
|
45005
45042
|
minHeight: 1,
|
|
45006
45043
|
flexDirection: "column"
|
|
45007
45044
|
});
|
|
45008
|
-
|
|
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);
|
|
45009
45058
|
panel.add(tabStrip);
|
|
45010
45059
|
panel.add(body);
|
|
45060
|
+
panel.add(footer);
|
|
45011
45061
|
backdrop.add(panel);
|
|
45012
45062
|
r.root.add(backdrop);
|
|
45013
45063
|
const state = {
|
|
@@ -45015,9 +45065,13 @@ function ensureHost(otui, chrome) {
|
|
|
45015
45065
|
chrome,
|
|
45016
45066
|
backdrop,
|
|
45017
45067
|
panel,
|
|
45068
|
+
header: header3,
|
|
45018
45069
|
titleText,
|
|
45070
|
+
closeText,
|
|
45019
45071
|
tabStrip,
|
|
45020
45072
|
body,
|
|
45073
|
+
footer,
|
|
45074
|
+
footerText,
|
|
45021
45075
|
open: false,
|
|
45022
45076
|
generation: 0,
|
|
45023
45077
|
tabs: [],
|
|
@@ -45034,7 +45088,7 @@ function ensureHost(otui, chrome) {
|
|
|
45034
45088
|
if (!state.open || state.input === undefined) {
|
|
45035
45089
|
return;
|
|
45036
45090
|
}
|
|
45037
|
-
if (key.name === "escape") {
|
|
45091
|
+
if (key.name === "escape" || key.name === "x" || key.sequence === "x") {
|
|
45038
45092
|
closeHost(state, { restoreFocus: true, runOnClose: true });
|
|
45039
45093
|
key.preventDefault();
|
|
45040
45094
|
key.stopPropagation();
|
|
@@ -45121,15 +45175,323 @@ function openModal(otui, chrome, input2) {
|
|
|
45121
45175
|
state.input = input2;
|
|
45122
45176
|
state.tabs = input2.tabs;
|
|
45123
45177
|
state.onClose = input2.onClose;
|
|
45124
|
-
state
|
|
45178
|
+
paintHeader(state, input2.title);
|
|
45179
|
+
paintFooter(state, input2.footer);
|
|
45125
45180
|
mountTab(state, input2, resolveInitialTab(input2.tabs, input2.initialTab));
|
|
45126
45181
|
state.tabStrip.focus();
|
|
45127
45182
|
return makeHandle(state, generation);
|
|
45128
45183
|
}
|
|
45129
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
|
+
|
|
45130
45487
|
// src/tui/session-info.ts
|
|
45131
|
-
var SESSION_INFO_COMMANDS = ["/
|
|
45488
|
+
var SESSION_INFO_COMMANDS = ["/status"];
|
|
45132
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
|
+
];
|
|
45133
45495
|
function isSessionInfoCommand(line) {
|
|
45134
45496
|
const token = line.trim().split(/\s+/)[0] ?? "";
|
|
45135
45497
|
return SESSION_INFO_COMMANDS.includes(token);
|
|
@@ -45201,7 +45563,28 @@ function buildSessionInfoSnapshot(source) {
|
|
|
45201
45563
|
},
|
|
45202
45564
|
{ label: "Context estimate", value: estimate }
|
|
45203
45565
|
];
|
|
45204
|
-
|
|
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
|
+
};
|
|
45205
45588
|
}
|
|
45206
45589
|
function formatSection(title, rows) {
|
|
45207
45590
|
const width = rows.reduce((max, row) => Math.max(max, row.label.length), 0);
|
|
@@ -45209,18 +45592,40 @@ function formatSection(title, rows) {
|
|
|
45209
45592
|
`);
|
|
45210
45593
|
}
|
|
45211
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
|
+
}
|
|
45212
45605
|
return `${formatSection("Session", snapshot.sessionRows)}
|
|
45213
45606
|
|
|
45214
45607
|
${formatSection("Usage", snapshot.usageRows)}
|
|
45215
|
-
|
|
45608
|
+
|
|
45609
|
+
${extra.join(`
|
|
45610
|
+
`)}`;
|
|
45216
45611
|
}
|
|
45217
45612
|
function sessionIdCopyText(snapshot) {
|
|
45218
45613
|
return snapshot.sessionId;
|
|
45219
45614
|
}
|
|
45220
|
-
function
|
|
45221
|
-
|
|
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;
|
|
45222
45627
|
}
|
|
45223
|
-
function
|
|
45628
|
+
function paintContent(otui, renderer, body, content) {
|
|
45224
45629
|
if (otui === undefined || otui === null || body === undefined || body === null) {
|
|
45225
45630
|
return;
|
|
45226
45631
|
}
|
|
@@ -45229,12 +45634,12 @@ function paintRows(otui, renderer, body, rows) {
|
|
|
45229
45634
|
if (parent.add === undefined || ctor === undefined) {
|
|
45230
45635
|
return;
|
|
45231
45636
|
}
|
|
45637
|
+
parent.add(new ctor(renderer, { id: "session-info-body", content }));
|
|
45638
|
+
}
|
|
45639
|
+
function paintRows(otui, renderer, body, rows) {
|
|
45232
45640
|
const width = rows.reduce((max, row) => Math.max(max, row.label.length), 0);
|
|
45233
|
-
|
|
45234
|
-
|
|
45235
|
-
content: rows.map((row) => `${row.label.padEnd(width)} ${row.value}`).join(`
|
|
45236
|
-
`)
|
|
45237
|
-
}));
|
|
45641
|
+
paintContent(otui, renderer, body, rows.map((row) => `${row.label.padEnd(width)} ${row.value}`).join(`
|
|
45642
|
+
`));
|
|
45238
45643
|
}
|
|
45239
45644
|
function presentSessionInfo(openModal2, otui, chrome, options) {
|
|
45240
45645
|
const { snapshot, toast } = options;
|
|
@@ -45249,16 +45654,27 @@ function presentSessionInfo(openModal2, otui, chrome, options) {
|
|
|
45249
45654
|
};
|
|
45250
45655
|
let unsubscribeKey;
|
|
45251
45656
|
const handle = openModal2(otui, chrome, {
|
|
45252
|
-
title: "
|
|
45253
|
-
tabs:
|
|
45254
|
-
|
|
45255
|
-
|
|
45256
|
-
],
|
|
45257
|
-
initialTab: "session",
|
|
45657
|
+
title: "/status",
|
|
45658
|
+
tabs: statusModalTabs(snapshot),
|
|
45659
|
+
initialTab: "status",
|
|
45660
|
+
footer: SESSION_INFO_FOOTER,
|
|
45258
45661
|
renderTab: (tabId, body) => {
|
|
45259
|
-
const rows = tabId === "usage" ? snapshot.usageRows : snapshot.sessionRows;
|
|
45260
45662
|
const renderer = options.renderer ?? chrome?.renderer;
|
|
45261
|
-
|
|
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);
|
|
45262
45678
|
},
|
|
45263
45679
|
onClose: () => {
|
|
45264
45680
|
unsubscribeKey?.();
|
|
@@ -45272,8 +45688,6 @@ function presentSessionInfo(openModal2, otui, chrome, options) {
|
|
|
45272
45688
|
const token = key.name || key.sequence;
|
|
45273
45689
|
if (token === "c") {
|
|
45274
45690
|
copy(sessionIdCopyText(snapshot));
|
|
45275
|
-
} else if (token === "y") {
|
|
45276
|
-
copy(sessionBlockCopyText(snapshot));
|
|
45277
45691
|
}
|
|
45278
45692
|
});
|
|
45279
45693
|
}
|
|
@@ -45341,12 +45755,11 @@ var AGENT_SLASH_COMMANDS = [
|
|
|
45341
45755
|
{ name: "/resume", description: "Resume a prior session in this project", modes: AGENT_ONLY },
|
|
45342
45756
|
{ name: "/sessions", description: "Open the session list and switch to one", modes: AGENT_ONLY },
|
|
45343
45757
|
{
|
|
45344
|
-
name: "/
|
|
45345
|
-
description: "Show session identity and
|
|
45758
|
+
name: "/status",
|
|
45759
|
+
description: "Show session identity, context, workspaces, and flows",
|
|
45346
45760
|
modes: BOTH
|
|
45347
45761
|
},
|
|
45348
|
-
{ name: "/
|
|
45349
|
-
{ name: "/info", description: "Alias of /session-info", modes: BOTH },
|
|
45762
|
+
{ name: "/flows", description: "Browse project flows and inspect one", modes: BOTH },
|
|
45350
45763
|
{
|
|
45351
45764
|
name: "/compact",
|
|
45352
45765
|
description: "Compact model context \u2014 /compact [focus] (archive kept)",
|
|
@@ -47451,7 +47864,7 @@ function createBlockView(otui, renderer, parent, block, options = {}) {
|
|
|
47451
47864
|
let body;
|
|
47452
47865
|
let bodyText;
|
|
47453
47866
|
let painted;
|
|
47454
|
-
const
|
|
47867
|
+
const paintHeader2 = (state, focused) => {
|
|
47455
47868
|
const hint = state.collapsed ? options.hint : options.expandedHint ?? options.hint;
|
|
47456
47869
|
const label = blockLabel({
|
|
47457
47870
|
kind: state.kind,
|
|
@@ -47512,7 +47925,7 @@ function createBlockView(otui, renderer, parent, block, options = {}) {
|
|
|
47512
47925
|
return {
|
|
47513
47926
|
id: block.id,
|
|
47514
47927
|
render: (state, opts = {}) => {
|
|
47515
|
-
|
|
47928
|
+
paintHeader2(state, opts.focused === true);
|
|
47516
47929
|
if (state.collapsed) {
|
|
47517
47930
|
dropBody();
|
|
47518
47931
|
return;
|
|
@@ -49012,21 +49425,41 @@ Staying in the current session.
|
|
|
49012
49425
|
`);
|
|
49013
49426
|
};
|
|
49014
49427
|
paintSessionHeader();
|
|
49428
|
+
const inspectorKeys = { onKeypress: (handler) => onKeypress4(r, (key) => handler(key)) };
|
|
49429
|
+
const inspectorCwd = () => opts.session?.cwd ?? liveSession.summary.projectPath;
|
|
49015
49430
|
const showSessionInfo = () => {
|
|
49016
|
-
|
|
49017
|
-
|
|
49018
|
-
|
|
49019
|
-
|
|
49020
|
-
|
|
49021
|
-
|
|
49022
|
-
|
|
49023
|
-
|
|
49024
|
-
|
|
49025
|
-
|
|
49026
|
-
|
|
49027
|
-
|
|
49028
|
-
|
|
49029
|
-
|
|
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
|
+
})();
|
|
49030
49463
|
};
|
|
49031
49464
|
const updateModelLabels = () => {
|
|
49032
49465
|
paintSessionHeader();
|
|
@@ -49237,6 +49670,10 @@ Staying in the current session.
|
|
|
49237
49670
|
showSessionInfo();
|
|
49238
49671
|
return;
|
|
49239
49672
|
}
|
|
49673
|
+
if (command2 !== undefined && isFlowsCommand(command2.name)) {
|
|
49674
|
+
showFlows();
|
|
49675
|
+
return;
|
|
49676
|
+
}
|
|
49240
49677
|
if (command2 !== undefined || line.startsWith("/")) {
|
|
49241
49678
|
transcript.add(new otui.TextRenderable(r, {
|
|
49242
49679
|
id: `c${uid++}`,
|
|
@@ -49382,6 +49819,10 @@ Staying in the current session.
|
|
|
49382
49819
|
showSessionInfo();
|
|
49383
49820
|
return;
|
|
49384
49821
|
}
|
|
49822
|
+
if (isFlowsCommand(command.name)) {
|
|
49823
|
+
showFlows();
|
|
49824
|
+
return;
|
|
49825
|
+
}
|
|
49385
49826
|
if (command.name === "/copy") {
|
|
49386
49827
|
const target = newestBlock();
|
|
49387
49828
|
if (target === undefined || !copyBlock(target.id)) {
|
|
@@ -49727,7 +50168,7 @@ function createChatBridge(hooks = {}) {
|
|
|
49727
50168
|
close();
|
|
49728
50169
|
return "exit";
|
|
49729
50170
|
}
|
|
49730
|
-
if (isSessionInfoCommand(value)) {
|
|
50171
|
+
if (isSessionInfoCommand(value) || isFlowsCommand(value)) {
|
|
49731
50172
|
return "local";
|
|
49732
50173
|
}
|
|
49733
50174
|
if ((turn || queue.length > 0) && value.startsWith("/")) {
|
|
@@ -49854,19 +50295,33 @@ async function mountChatShell(otui, renderer, opts) {
|
|
|
49854
50295
|
return;
|
|
49855
50296
|
}
|
|
49856
50297
|
if (result === "local") {
|
|
49857
|
-
const
|
|
49858
|
-
|
|
49859
|
-
|
|
49860
|
-
|
|
49861
|
-
|
|
49862
|
-
|
|
49863
|
-
|
|
49864
|
-
|
|
49865
|
-
|
|
49866
|
-
|
|
49867
|
-
|
|
49868
|
-
|
|
49869
|
-
|
|
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
|
+
})();
|
|
49870
50325
|
return;
|
|
49871
50326
|
}
|
|
49872
50327
|
if (result === "deferred") {
|
|
@@ -50193,9 +50648,8 @@ var READLINE_AGENT_COMMANDS = [
|
|
|
50193
50648
|
"/new",
|
|
50194
50649
|
"/clear",
|
|
50195
50650
|
"/compact",
|
|
50196
|
-
"/session-info",
|
|
50197
50651
|
"/status",
|
|
50198
|
-
"/
|
|
50652
|
+
"/flows",
|
|
50199
50653
|
"/exit"
|
|
50200
50654
|
];
|
|
50201
50655
|
function readlineAgentHelpText() {
|
|
@@ -50285,14 +50739,33 @@ Starting a new session.
|
|
|
50285
50739
|
continue;
|
|
50286
50740
|
}
|
|
50287
50741
|
if (isSessionInfoCommand(command)) {
|
|
50742
|
+
const cwd = deps.session?.cwd;
|
|
50743
|
+
const [workspaces, flows] = cwd === undefined ? [[], []] : await Promise.all([loadInspectorWorkspaces(cwd), loadInspectorFlows(cwd)]);
|
|
50288
50744
|
system(formatSessionInfoText(buildSessionInfoSnapshot({
|
|
50289
50745
|
summary: live?.summary,
|
|
50290
50746
|
selection: { provider: providerName, model: modelName },
|
|
50291
50747
|
version: package_default.version,
|
|
50292
|
-
estimateTokens: estimateContextTokens(history)
|
|
50748
|
+
estimateTokens: estimateContextTokens(history),
|
|
50749
|
+
sessionText: history.map((message2) => message2.content).join(`
|
|
50750
|
+
`),
|
|
50751
|
+
workspaces,
|
|
50752
|
+
flows
|
|
50293
50753
|
})));
|
|
50294
50754
|
continue;
|
|
50295
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
|
+
}
|
|
50296
50769
|
if (command === "/clear" || command === "/new") {
|
|
50297
50770
|
if (sessionsOn) {
|
|
50298
50771
|
live = createSession({ cwd: sessionCwd, provider: providerName, model: modelName });
|
|
@@ -50941,13 +51414,31 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
50941
51414
|
if (command === "/help") {
|
|
50942
51415
|
agentIo.onSystem?.(readlineAgentHelpText());
|
|
50943
51416
|
} else if (isSessionInfoCommand(command)) {
|
|
51417
|
+
const cwd = sessionCwd;
|
|
51418
|
+
const [workspaces, flows] = await Promise.all([
|
|
51419
|
+
loadInspectorWorkspaces(cwd),
|
|
51420
|
+
loadInspectorFlows(cwd)
|
|
51421
|
+
]);
|
|
50944
51422
|
agentIo.onSystem?.(formatSessionInfoText(buildSessionInfoSnapshot({
|
|
50945
51423
|
summary: live?.summary,
|
|
50946
51424
|
selection: { provider: deps.providerId, model: deps.modelId },
|
|
50947
51425
|
version: package_default.version,
|
|
50948
51426
|
usage: lastUsage,
|
|
50949
|
-
estimateTokens: estimateContextTokens(history)
|
|
51427
|
+
estimateTokens: estimateContextTokens(history),
|
|
51428
|
+
sessionText: history.map((message2) => message2.content).join(`
|
|
51429
|
+
`),
|
|
51430
|
+
workspaces,
|
|
51431
|
+
flows
|
|
50950
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
|
+
}
|
|
50951
51442
|
} else if (command === "/expand") {
|
|
50952
51443
|
const expanded = expandedToolOutput(lastToolName, lastToolOutput);
|
|
50953
51444
|
if (expanded !== undefined) {
|
|
@@ -51234,7 +51725,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
51234
51725
|
modelId: sel.model
|
|
51235
51726
|
}),
|
|
51236
51727
|
maxToolCalls: resolveAgentMaxToolCalls(),
|
|
51237
|
-
idSeq: () =>
|
|
51728
|
+
idSeq: () => randomUUID18()
|
|
51238
51729
|
};
|
|
51239
51730
|
};
|
|
51240
51731
|
const redetect = () => detectProviders({
|
|
@@ -51265,7 +51756,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
51265
51756
|
makeShellDeps: (sel) => ({
|
|
51266
51757
|
makeProvider: chatFactory,
|
|
51267
51758
|
clock: () => new Date().toISOString(),
|
|
51268
|
-
idSeq: () =>
|
|
51759
|
+
idSeq: () => randomUUID18(),
|
|
51269
51760
|
initial: sel,
|
|
51270
51761
|
session: {
|
|
51271
51762
|
cwd,
|
|
@@ -51335,7 +51826,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
51335
51826
|
const deps = {
|
|
51336
51827
|
makeProvider: baseFactory,
|
|
51337
51828
|
clock: () => new Date().toISOString(),
|
|
51338
|
-
idSeq: () =>
|
|
51829
|
+
idSeq: () => randomUUID18(),
|
|
51339
51830
|
initial: baseUrl2 === undefined ? { provider, model } : { provider, model, baseUrl: baseUrl2 },
|
|
51340
51831
|
selectProviderModel: realSelectProviderModel(baseUrl2)
|
|
51341
51832
|
};
|
|
@@ -51383,7 +51874,7 @@ async function shellCommand(args2, runtime = {}) {
|
|
|
51383
51874
|
modelId: model
|
|
51384
51875
|
}),
|
|
51385
51876
|
maxToolCalls: resolveAgentMaxToolCalls(),
|
|
51386
|
-
idSeq: () =>
|
|
51877
|
+
idSeq: () => randomUUID18()
|
|
51387
51878
|
};
|
|
51388
51879
|
let resumeId = flags.resumeId;
|
|
51389
51880
|
if (flags.resumePick === true && resumeId === undefined) {
|
|
@@ -51715,7 +52206,7 @@ function printHelp16() {
|
|
|
51715
52206
|
}
|
|
51716
52207
|
|
|
51717
52208
|
// src/commands/serve.ts
|
|
51718
|
-
import { randomUUID as
|
|
52209
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
51719
52210
|
|
|
51720
52211
|
// src/lib/serve-config.ts
|
|
51721
52212
|
init_config_dir();
|
|
@@ -52042,7 +52533,7 @@ function saveServeConfig(config, dir, onWarn) {
|
|
|
52042
52533
|
|
|
52043
52534
|
// src/lib/serve-credential.ts
|
|
52044
52535
|
init_config_dir();
|
|
52045
|
-
import { createHash as createHash29, randomBytes as randomBytes2, randomUUID as
|
|
52536
|
+
import { createHash as createHash29, randomBytes as randomBytes2, randomUUID as randomUUID19 } from "crypto";
|
|
52046
52537
|
import {
|
|
52047
52538
|
chmodSync as chmodSync4,
|
|
52048
52539
|
closeSync as closeSync3,
|
|
@@ -52126,7 +52617,7 @@ function readServeCredential(dir) {
|
|
|
52126
52617
|
}
|
|
52127
52618
|
function writeStore(store, dir) {
|
|
52128
52619
|
const file = serveCredentialPath(dir);
|
|
52129
|
-
const temp = `${file}.${
|
|
52620
|
+
const temp = `${file}.${randomUUID19()}.tmp`;
|
|
52130
52621
|
try {
|
|
52131
52622
|
ensureKeryxConfigDir(dir);
|
|
52132
52623
|
const handle = openSync3(temp, "wx", 384);
|
|
@@ -52166,7 +52657,7 @@ function mintRecord(now) {
|
|
|
52166
52657
|
const salt = randomBytes2(32).toString("hex");
|
|
52167
52658
|
return {
|
|
52168
52659
|
token,
|
|
52169
|
-
record: { id:
|
|
52660
|
+
record: { id: randomUUID19(), algorithm: "sha256", salt, hash: hashToken(salt, token), createdAt: now }
|
|
52170
52661
|
};
|
|
52171
52662
|
}
|
|
52172
52663
|
function issueServeToken(dir, now = () => new Date().toISOString(), onWaiting) {
|
|
@@ -52480,7 +52971,7 @@ function releaseIdempotencyKey(project, idempotencyKey, turnId, dir) {
|
|
|
52480
52971
|
}
|
|
52481
52972
|
|
|
52482
52973
|
// src/lib/serve-turn.ts
|
|
52483
|
-
import { randomUUID as
|
|
52974
|
+
import { randomUUID as randomUUID20 } from "crypto";
|
|
52484
52975
|
import path140 from "path";
|
|
52485
52976
|
init_service();
|
|
52486
52977
|
var REMOTE_ORIGIN = "remote:http";
|
|
@@ -52599,7 +53090,7 @@ async function redactOut(security, text) {
|
|
|
52599
53090
|
async function runRemoteTurn(input2) {
|
|
52600
53091
|
const scanRoot = input2.scanRoot;
|
|
52601
53092
|
const security = createSecurityService(scanRoot);
|
|
52602
|
-
const newId = input2.newId ?? (() =>
|
|
53093
|
+
const newId = input2.newId ?? (() => randomUUID20());
|
|
52603
53094
|
const clock = input2.clock ?? (() => new Date().toISOString());
|
|
52604
53095
|
const turnId = input2.turnId ?? newId();
|
|
52605
53096
|
const sessionId = input2.request.sessionId ?? newId();
|
|
@@ -52742,7 +53233,7 @@ function outcomeOf(status, gate, unresolvedBlockerIds) {
|
|
|
52742
53233
|
}
|
|
52743
53234
|
function createSubmitTurn(deps) {
|
|
52744
53235
|
return async (request, project) => {
|
|
52745
|
-
const turnId = (deps.newId ?? (() =>
|
|
53236
|
+
const turnId = (deps.newId ?? (() => randomUUID20()))();
|
|
52746
53237
|
const scanned = await scanPrompt(deps.dir, request.prompt);
|
|
52747
53238
|
if (scanned.rejected) {
|
|
52748
53239
|
return { kind: "rejected" };
|
|
@@ -53429,7 +53920,7 @@ function runConfig(args2) {
|
|
|
53429
53920
|
return;
|
|
53430
53921
|
}
|
|
53431
53922
|
const credential2 = readServeCredential();
|
|
53432
|
-
const credentialId = credential2.status === "ok" ? credential2.record.id :
|
|
53923
|
+
const credentialId = credential2.status === "ok" ? credential2.record.id : randomUUID21();
|
|
53433
53924
|
const config = defaultServeConfig(credentialId, {
|
|
53434
53925
|
address: parsed.parsed.values.get("--bind") ?? DEFAULT_SERVE_BIND_ADDRESS,
|
|
53435
53926
|
port: port ?? DEFAULT_SERVE_PORT,
|
|
@@ -57128,7 +57619,7 @@ async function versionCommand(args2, deps = {}) {
|
|
|
57128
57619
|
|
|
57129
57620
|
// src/commands/workspace.ts
|
|
57130
57621
|
init_args();
|
|
57131
|
-
import { randomUUID as
|
|
57622
|
+
import { randomUUID as randomUUID22 } from "crypto";
|
|
57132
57623
|
import { writeFile as writeFile50 } from "fs/promises";
|
|
57133
57624
|
|
|
57134
57625
|
// src/sac/fwk-explain.ts
|
|
@@ -57196,13 +57687,13 @@ async function workspaceCommand(args2) {
|
|
|
57196
57687
|
const component = optionValue(args2, "--component");
|
|
57197
57688
|
if (!title)
|
|
57198
57689
|
throw new Error("Usage: keryx workspace create --title <title> [--component <workspace-relative-ref>]");
|
|
57199
|
-
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 } } : {} });
|
|
57200
57691
|
console.log(JSON.stringify(workspace, null, 2));
|
|
57201
57692
|
return;
|
|
57202
57693
|
}
|
|
57203
57694
|
if (subcommand === "list") {
|
|
57204
57695
|
rejectUnknownOptions(args2.slice(1), new Set);
|
|
57205
|
-
console.log(JSON.stringify(await service4().list({ request: undefined, requestCorrelationId:
|
|
57696
|
+
console.log(JSON.stringify(await service4().list({ request: undefined, requestCorrelationId: randomUUID22() }), null, 2));
|
|
57206
57697
|
return;
|
|
57207
57698
|
}
|
|
57208
57699
|
if (subcommand === "show") {
|
|
@@ -57210,7 +57701,7 @@ async function workspaceCommand(args2) {
|
|
|
57210
57701
|
const id = args2[1];
|
|
57211
57702
|
if (!id)
|
|
57212
57703
|
throw new Error("Usage: keryx workspace show <workspace-id>");
|
|
57213
|
-
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));
|
|
57214
57705
|
return;
|
|
57215
57706
|
}
|
|
57216
57707
|
if (subcommand === "add-resource") {
|
|
@@ -57221,7 +57712,7 @@ async function workspaceCommand(args2) {
|
|
|
57221
57712
|
const revision = optionValue(args2, "--revision");
|
|
57222
57713
|
if (!workspaceId || !kind || !uri)
|
|
57223
57714
|
throw new Error("Usage: keryx workspace add-resource <workspace-id> --kind <kind> --uri <workspace-relative-ref> [--revision <revision>]");
|
|
57224
|
-
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));
|
|
57225
57716
|
return;
|
|
57226
57717
|
}
|
|
57227
57718
|
if (subcommand === "overview") {
|
|
@@ -57233,7 +57724,7 @@ async function workspaceCommand(args2) {
|
|
|
57233
57724
|
const maxTokens = Number(optionValue(args2, "--max-tokens") ?? "4096");
|
|
57234
57725
|
if (!Number.isInteger(maxItems) || !Number.isInteger(maxTokens) || maxItems < 0 || maxTokens < 0)
|
|
57235
57726
|
throw new Error("--max-items and --max-tokens must be non-negative integers");
|
|
57236
|
-
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 } });
|
|
57237
57728
|
const normalized = normalizeFwkResult(result);
|
|
57238
57729
|
console.log(JSON.stringify(normalized, null, 2));
|
|
57239
57730
|
if (args2.includes("--explain"))
|
|
@@ -57250,7 +57741,7 @@ async function workspaceCommand(args2) {
|
|
|
57250
57741
|
const maxTokens = Number(optionValue(args2, "--max-tokens") ?? "4096");
|
|
57251
57742
|
if (!Number.isInteger(maxItems) || !Number.isInteger(maxTokens) || maxItems < 0 || maxTokens < 0)
|
|
57252
57743
|
throw new Error("--max-items and --max-tokens must be non-negative integers");
|
|
57253
|
-
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 } });
|
|
57254
57745
|
const normalized = normalizeFwkResult(result);
|
|
57255
57746
|
console.log(JSON.stringify(normalized, null, 2));
|
|
57256
57747
|
if (args2.includes("--explain"))
|
|
@@ -57273,12 +57764,12 @@ async function workspaceCommand(args2) {
|
|
|
57273
57764
|
if (!session)
|
|
57274
57765
|
throw new Error(`no session matching "${sessionRef}" in this project \u2014 use \`keryx sessions list\``);
|
|
57275
57766
|
const { service: service5, wrapUpAuthority, authorizationServer } = createHarnessProposalLifecycleService(cwd, { workspaceId, ...note2 ? { note: note2 } : {} });
|
|
57276
|
-
const requestCorrelationId =
|
|
57767
|
+
const requestCorrelationId = randomUUID22();
|
|
57277
57768
|
const actor = await authorizationServer.actorContextFor(undefined, requestCorrelationId);
|
|
57278
57769
|
if (!actor)
|
|
57279
57770
|
throw new Error("trusted ActorContext is required");
|
|
57280
57771
|
const wrapUp = await wrapUpAuthority.issue({ actor, source: "session", sourceRef: sessionEvidenceRef(workspaceId, session.id) });
|
|
57281
|
-
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 });
|
|
57282
57773
|
if (note2)
|
|
57283
57774
|
await writeFile50(proposalNotePath(cwd, workspaceId, proposal.id), note2, "utf8");
|
|
57284
57775
|
console.log(JSON.stringify(normalizeProposalLifecycleResult(proposal), null, 2));
|
|
@@ -57290,10 +57781,10 @@ async function workspaceCommand(args2) {
|
|
|
57290
57781
|
const proposalId = args2[2];
|
|
57291
57782
|
const decision = optionValue(args2, "--decision");
|
|
57292
57783
|
const reason = optionValue(args2, "--reason");
|
|
57293
|
-
const idempotencyKey = optionValue(args2, "--idempotency-key") ??
|
|
57784
|
+
const idempotencyKey = optionValue(args2, "--idempotency-key") ?? randomUUID22();
|
|
57294
57785
|
if (!workspaceId || !proposalId || !decision)
|
|
57295
57786
|
throw new Error("Usage: keryx workspace review <workspace-id> <proposal-id> --decision <accepted|rejected|dismissed> [--reason <reason>] [--idempotency-key <key>]");
|
|
57296
|
-
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 } : {} });
|
|
57297
57788
|
console.log(JSON.stringify(normalizeProposalLifecycleResult(result), null, 2));
|
|
57298
57789
|
return;
|
|
57299
57790
|
}
|
|
@@ -57302,7 +57793,7 @@ async function workspaceCommand(args2) {
|
|
|
57302
57793
|
const workspaceId = args2[1];
|
|
57303
57794
|
if (!workspaceId)
|
|
57304
57795
|
throw new Error("Usage: keryx workspace collaboration <workspace-id>");
|
|
57305
|
-
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));
|
|
57306
57797
|
return;
|
|
57307
57798
|
}
|
|
57308
57799
|
if (subcommand === "policy-readiness") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.37",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|