@mrciphersmith/keryx 0.2.21 → 0.2.23
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 +108 -21
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8045,6 +8045,23 @@ function isProviderPlatformSupported(provider, platform = process.platform) {
|
|
|
8045
8045
|
}
|
|
8046
8046
|
return provider.platforms.includes(platform);
|
|
8047
8047
|
}
|
|
8048
|
+
function providerBaseUrlEnvKey(providerName) {
|
|
8049
|
+
return `KERYX_${providerName.replace(/[^a-zA-Z0-9]+/g, "_").toUpperCase()}_BASE_URL`;
|
|
8050
|
+
}
|
|
8051
|
+
function resolveProviderBaseUrl(provider, env = process.env) {
|
|
8052
|
+
const override = env[providerBaseUrlEnvKey(provider.name)]?.trim();
|
|
8053
|
+
if (override === undefined || override.length === 0)
|
|
8054
|
+
return provider.baseUrl;
|
|
8055
|
+
try {
|
|
8056
|
+
const url = new URL(override);
|
|
8057
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.username.length > 0 || url.password.length > 0) {
|
|
8058
|
+
return provider.baseUrl;
|
|
8059
|
+
}
|
|
8060
|
+
return override.replace(/\/+$/, "");
|
|
8061
|
+
} catch {
|
|
8062
|
+
return provider.baseUrl;
|
|
8063
|
+
}
|
|
8064
|
+
}
|
|
8048
8065
|
function providerByName(name) {
|
|
8049
8066
|
return OPENAI_COMPAT_PROVIDERS.find((p) => p.name === name);
|
|
8050
8067
|
}
|
|
@@ -8091,7 +8108,7 @@ async function resolveModelsForPicker(fetchFn, provider, env = process.env, opts
|
|
|
8091
8108
|
const envKey = provider.envKey ?? compat.envKey;
|
|
8092
8109
|
const raw = envKey === undefined ? undefined : env[envKey];
|
|
8093
8110
|
const apiKey = typeof raw === "string" && raw.length > 0 ? raw : undefined;
|
|
8094
|
-
return fetchOpenAiCompatModelsDetailed(fetchFn, compat, apiKey, opts);
|
|
8111
|
+
return fetchOpenAiCompatModelsDetailed(fetchFn, { ...compat, ...provider.baseUrl !== undefined ? { baseUrl: provider.baseUrl } : {} }, apiKey, opts);
|
|
8095
8112
|
}
|
|
8096
8113
|
var DEFAULT_MODELS_PATH = "/v1/models", OPENAI_COMPAT_PROVIDERS, MODELS_FETCH_TIMEOUT_MS = 1e4;
|
|
8097
8114
|
var init_providers = __esm(() => {
|
|
@@ -9867,7 +9884,7 @@ function makeProvider(name, _model, opts) {
|
|
|
9867
9884
|
}
|
|
9868
9885
|
const grant = {
|
|
9869
9886
|
network: true,
|
|
9870
|
-
baseUrl: opts.baseUrl ?? compat
|
|
9887
|
+
baseUrl: opts.baseUrl ?? resolveProviderBaseUrl(compat, env),
|
|
9871
9888
|
...compat.allowLoopback === true ? { allowLoopback: true } : {},
|
|
9872
9889
|
...compat.chatPath !== undefined ? { chatPath: compat.chatPath } : {},
|
|
9873
9890
|
...apiKey !== undefined ? { apiKey } : {}
|
|
@@ -39576,6 +39593,7 @@ function reserveToolAttempt(state, name, input2, risk) {
|
|
|
39576
39593
|
}
|
|
39577
39594
|
async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
39578
39595
|
history.push({ role: "user", content: userLine, provenance: "project" });
|
|
39596
|
+
io.onHistoryChange?.("user");
|
|
39579
39597
|
const signal = options.signal;
|
|
39580
39598
|
const isAborted = () => signal?.aborted === true;
|
|
39581
39599
|
if (isAborted()) {
|
|
@@ -39628,6 +39646,7 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39628
39646
|
};
|
|
39629
39647
|
const request = signal === undefined ? { ...baseRequest } : { ...baseRequest, signal };
|
|
39630
39648
|
let assistantText = "";
|
|
39649
|
+
let assistantMessage;
|
|
39631
39650
|
let reasoningText = "";
|
|
39632
39651
|
let reasoningFlushed = false;
|
|
39633
39652
|
const flushReasoning = () => {
|
|
@@ -39655,6 +39674,13 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39655
39674
|
const text = event.text ?? "";
|
|
39656
39675
|
io.write(text);
|
|
39657
39676
|
assistantText += text;
|
|
39677
|
+
if (assistantMessage === undefined) {
|
|
39678
|
+
assistantMessage = { role: "assistant", content: text, provenance: "model" };
|
|
39679
|
+
history.push(assistantMessage);
|
|
39680
|
+
} else {
|
|
39681
|
+
assistantMessage.content += text;
|
|
39682
|
+
}
|
|
39683
|
+
io.onHistoryChange?.("assistant_delta");
|
|
39658
39684
|
} else if (event.kind === "tool_call_start") {
|
|
39659
39685
|
if (event.toolCallId !== undefined && event.toolName !== undefined) {
|
|
39660
39686
|
nameById.set(event.toolCallId, event.toolName);
|
|
@@ -39695,8 +39721,8 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39695
39721
|
}
|
|
39696
39722
|
flushReasoning();
|
|
39697
39723
|
if (assistantText.length > 0) {
|
|
39698
|
-
history.push({ role: "assistant", content: assistantText, provenance: "model" });
|
|
39699
39724
|
io.onAssistantText?.(assistantText);
|
|
39725
|
+
io.onHistoryChange?.("assistant_final");
|
|
39700
39726
|
}
|
|
39701
39727
|
if (isAborted()) {
|
|
39702
39728
|
system(`
|
|
@@ -39719,6 +39745,7 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39719
39745
|
content: "[system] You were asked to execute or inspect, but you replied with text and no tool call. " + "Resend a single compliant tool call now (with fully populated required arguments).",
|
|
39720
39746
|
provenance: "project"
|
|
39721
39747
|
});
|
|
39748
|
+
io.onHistoryChange?.("tool");
|
|
39722
39749
|
continue;
|
|
39723
39750
|
}
|
|
39724
39751
|
if (shouldReprompt) {
|
|
@@ -39749,6 +39776,7 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39749
39776
|
const result2 = { output: reservation.reason, isError: true };
|
|
39750
39777
|
io.onToolResult?.(call.name, result2);
|
|
39751
39778
|
history.push({ role: "tool", content: result2.output, provenance: "tool" });
|
|
39779
|
+
io.onHistoryChange?.("tool");
|
|
39752
39780
|
toolLog.push(`${call.name}: skipped (${reservation.reason.split(";")[0] ?? "budget"})`);
|
|
39753
39781
|
if (reservation.kind === "total_budget") {
|
|
39754
39782
|
exhaustedBudget = "total";
|
|
@@ -39763,6 +39791,7 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39763
39791
|
const result = await executeCall(call, toolByName, io.requestApproval);
|
|
39764
39792
|
io.onToolResult?.(call.name, result);
|
|
39765
39793
|
history.push({ role: "tool", content: redactSensitiveText(result.output), provenance: "tool" });
|
|
39794
|
+
io.onHistoryChange?.("tool");
|
|
39766
39795
|
const shortIn = call.input.length > 80 ? `${call.input.slice(0, 77)}\u2026` : call.input;
|
|
39767
39796
|
const riskUsage = risk === "read" ? `, read ${readBudgetUsed(budget)}/${maxReadToolCalls}` : `, non-read ${nonReadBudgetUsed(budget)}/${maxNonReadToolCalls}`;
|
|
39768
39797
|
toolLog.push(`${call.name}(${shortIn}) \u2192 ${result.isError ? "error" : "ok"} [attempt ${reservation.attempt}/${maxAttempts}, unique ${budgetUsed(budget)}/${maxToolCalls}${riskUsage}]`);
|
|
@@ -39778,6 +39807,7 @@ async function runAgentTurn(io, deps, history, userLine, options = {}) {
|
|
|
39778
39807
|
${hint}
|
|
39779
39808
|
`);
|
|
39780
39809
|
history.push({ role: "user", content: hint, provenance: "project" });
|
|
39810
|
+
io.onHistoryChange?.("tool");
|
|
39781
39811
|
}
|
|
39782
39812
|
} else {
|
|
39783
39813
|
lastErrorByHash.delete(reservation.hash);
|
|
@@ -44131,10 +44161,13 @@ async function launchTuiAgentShell(opts) {
|
|
|
44131
44161
|
let liveSession;
|
|
44132
44162
|
let history = [];
|
|
44133
44163
|
let archive = [];
|
|
44164
|
+
let nextArchiveIndex = 0;
|
|
44165
|
+
let sessionPersistTimer;
|
|
44134
44166
|
const applyOpened = (opened, previewHistory) => {
|
|
44135
44167
|
liveSession = opened.handle;
|
|
44136
44168
|
history = previewHistory === true ? opened.history.slice(-SESSION_PREVIEW_MESSAGE_COUNT) : opened.history;
|
|
44137
44169
|
archive = opened.archive.length > 0 ? [...opened.archive] : [...opened.history];
|
|
44170
|
+
nextArchiveIndex = history.length;
|
|
44138
44171
|
};
|
|
44139
44172
|
const pickRecentSession = async () => {
|
|
44140
44173
|
const rows = listSessions(sessionCwd);
|
|
@@ -44260,6 +44293,36 @@ async function launchTuiAgentShell(opts) {
|
|
|
44260
44293
|
});
|
|
44261
44294
|
paintSessionHeader();
|
|
44262
44295
|
};
|
|
44296
|
+
const syncArchive = () => {
|
|
44297
|
+
while (nextArchiveIndex < history.length) {
|
|
44298
|
+
const message2 = history[nextArchiveIndex];
|
|
44299
|
+
if (message2 !== undefined) {
|
|
44300
|
+
archive.push(message2);
|
|
44301
|
+
}
|
|
44302
|
+
nextArchiveIndex += 1;
|
|
44303
|
+
}
|
|
44304
|
+
};
|
|
44305
|
+
const flushSessionCheckpoint = () => {
|
|
44306
|
+
if (sessionPersistTimer !== undefined) {
|
|
44307
|
+
clearTimeout(sessionPersistTimer);
|
|
44308
|
+
sessionPersistTimer = undefined;
|
|
44309
|
+
}
|
|
44310
|
+
syncArchive();
|
|
44311
|
+
saveSession();
|
|
44312
|
+
};
|
|
44313
|
+
io.onHistoryChange = (kind) => {
|
|
44314
|
+
syncArchive();
|
|
44315
|
+
if (kind === "assistant_delta") {
|
|
44316
|
+
if (sessionPersistTimer === undefined) {
|
|
44317
|
+
sessionPersistTimer = setTimeout(() => {
|
|
44318
|
+
sessionPersistTimer = undefined;
|
|
44319
|
+
saveSession();
|
|
44320
|
+
}, 300);
|
|
44321
|
+
}
|
|
44322
|
+
return;
|
|
44323
|
+
}
|
|
44324
|
+
flushSessionCheckpoint();
|
|
44325
|
+
};
|
|
44263
44326
|
const startNewSession = (note2) => {
|
|
44264
44327
|
liveSession = createSession({
|
|
44265
44328
|
cwd: sessionCwd,
|
|
@@ -44268,6 +44331,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
44268
44331
|
});
|
|
44269
44332
|
history = [];
|
|
44270
44333
|
archive = [];
|
|
44334
|
+
nextArchiveIndex = 0;
|
|
44271
44335
|
paintSessionHeader();
|
|
44272
44336
|
if (note2 !== undefined && note2.length > 0) {
|
|
44273
44337
|
io.onSystem?.(`${note2}
|
|
@@ -44558,6 +44622,7 @@ Staying in the current session.
|
|
|
44558
44622
|
});
|
|
44559
44623
|
liveSession = packed.handle;
|
|
44560
44624
|
history = packed.context;
|
|
44625
|
+
nextArchiveIndex = history.length;
|
|
44561
44626
|
paintSessionHeader();
|
|
44562
44627
|
if (packed.result.noop) {
|
|
44563
44628
|
io.onSystem?.(`Nothing to compact (context already small).
|
|
@@ -44779,7 +44844,6 @@ Staying in the current session.
|
|
|
44779
44844
|
}
|
|
44780
44845
|
prevOnSystem?.(text);
|
|
44781
44846
|
};
|
|
44782
|
-
const beforeLen = history.length;
|
|
44783
44847
|
const controller = new AbortController;
|
|
44784
44848
|
mainTurnAbortController = controller;
|
|
44785
44849
|
runAgentTurn(io, deps, history, line, { signal: controller.signal }).finally(() => {
|
|
@@ -44787,14 +44851,8 @@ Staying in the current session.
|
|
|
44787
44851
|
const secs = ((Date.now() - startedAt) / 1000).toFixed(1);
|
|
44788
44852
|
stopBusy();
|
|
44789
44853
|
setMainAgent(turnFailed ? "failed" : "done", turnFailed ? "error" : "idle");
|
|
44790
|
-
for (let i = beforeLen;i < history.length; i++) {
|
|
44791
|
-
const m = history[i];
|
|
44792
|
-
if (m !== undefined) {
|
|
44793
|
-
archive.push(m);
|
|
44794
|
-
}
|
|
44795
|
-
}
|
|
44796
44854
|
try {
|
|
44797
|
-
|
|
44855
|
+
flushSessionCheckpoint();
|
|
44798
44856
|
} catch {}
|
|
44799
44857
|
transcript.add(new otui.TextRenderable(r, { id: `w${uid++}`, content: otui.t`${otui.dim(`worked for ${secs}s`)}`, marginTop: 1 }));
|
|
44800
44858
|
if (!hasExactUsage) {
|
|
@@ -45137,7 +45195,7 @@ init_shell_config();
|
|
|
45137
45195
|
// package.json
|
|
45138
45196
|
var package_default = {
|
|
45139
45197
|
name: "@mrciphersmith/keryx",
|
|
45140
|
-
version: "0.2.
|
|
45198
|
+
version: "0.2.23",
|
|
45141
45199
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
45142
45200
|
private: false,
|
|
45143
45201
|
publishConfig: {
|
|
@@ -45277,7 +45335,7 @@ async function detectProviders(deps) {
|
|
|
45277
45335
|
detected.push({
|
|
45278
45336
|
name: p.name,
|
|
45279
45337
|
models: [...p.models],
|
|
45280
|
-
baseUrl: p.
|
|
45338
|
+
baseUrl: resolveProviderBaseUrl(p, deps.env),
|
|
45281
45339
|
label: p.label,
|
|
45282
45340
|
...p.chatPath !== undefined ? { chatPath: p.chatPath } : {},
|
|
45283
45341
|
...p.modelsPath !== undefined ? { modelsPath: p.modelsPath } : {},
|
|
@@ -46048,6 +46106,8 @@ ${GUTTER}${style.cyan(`\u2699 ${call}`)}
|
|
|
46048
46106
|
let live;
|
|
46049
46107
|
let history = [];
|
|
46050
46108
|
let archive = [];
|
|
46109
|
+
let nextArchiveIndex = 0;
|
|
46110
|
+
let sessionPersistTimer;
|
|
46051
46111
|
if (sessionsOn) {
|
|
46052
46112
|
try {
|
|
46053
46113
|
let resumeId = sessionOpts?.resumeId;
|
|
@@ -46062,6 +46122,7 @@ ${GUTTER}${style.cyan(`\u2699 ${call}`)}
|
|
|
46062
46122
|
live = opened.handle;
|
|
46063
46123
|
history = opened.history;
|
|
46064
46124
|
archive = opened.archive.length > 0 ? [...opened.archive] : [...opened.history];
|
|
46125
|
+
nextArchiveIndex = history.length;
|
|
46065
46126
|
if (opened.resumed) {
|
|
46066
46127
|
agentIo.onSystem?.(`Resumed session ${shortSessionId(live.summary.id)} \xB7 ${live.summary.title} (${history.length} context \xB7 archive ${archive.length})
|
|
46067
46128
|
`);
|
|
@@ -46077,6 +46138,7 @@ ${GUTTER}${style.cyan(`\u2699 ${call}`)}
|
|
|
46077
46138
|
});
|
|
46078
46139
|
history = [];
|
|
46079
46140
|
archive = [];
|
|
46141
|
+
nextArchiveIndex = 0;
|
|
46080
46142
|
agentIo.onSystem?.(`${cause instanceof Error ? cause.message : String(cause)}
|
|
46081
46143
|
New session ${shortSessionId(live.summary.id)}.
|
|
46082
46144
|
`);
|
|
@@ -46094,6 +46156,36 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
46094
46156
|
});
|
|
46095
46157
|
} catch {}
|
|
46096
46158
|
};
|
|
46159
|
+
const syncArchive = () => {
|
|
46160
|
+
while (nextArchiveIndex < history.length) {
|
|
46161
|
+
const message2 = history[nextArchiveIndex];
|
|
46162
|
+
if (message2 !== undefined) {
|
|
46163
|
+
archive.push(message2);
|
|
46164
|
+
}
|
|
46165
|
+
nextArchiveIndex += 1;
|
|
46166
|
+
}
|
|
46167
|
+
};
|
|
46168
|
+
const flushSessionCheckpoint = () => {
|
|
46169
|
+
if (sessionPersistTimer !== undefined) {
|
|
46170
|
+
clearTimeout(sessionPersistTimer);
|
|
46171
|
+
sessionPersistTimer = undefined;
|
|
46172
|
+
}
|
|
46173
|
+
syncArchive();
|
|
46174
|
+
save();
|
|
46175
|
+
};
|
|
46176
|
+
agentIo.onHistoryChange = (kind) => {
|
|
46177
|
+
syncArchive();
|
|
46178
|
+
if (kind === "assistant_delta") {
|
|
46179
|
+
if (sessionPersistTimer === undefined) {
|
|
46180
|
+
sessionPersistTimer = setTimeout(() => {
|
|
46181
|
+
sessionPersistTimer = undefined;
|
|
46182
|
+
save();
|
|
46183
|
+
}, 300);
|
|
46184
|
+
}
|
|
46185
|
+
return;
|
|
46186
|
+
}
|
|
46187
|
+
flushSessionCheckpoint();
|
|
46188
|
+
};
|
|
46097
46189
|
for (;; ) {
|
|
46098
46190
|
const line = await readLine();
|
|
46099
46191
|
if (line === undefined) {
|
|
@@ -46127,6 +46219,7 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
46127
46219
|
});
|
|
46128
46220
|
history = [];
|
|
46129
46221
|
archive = [];
|
|
46222
|
+
nextArchiveIndex = 0;
|
|
46130
46223
|
agentIo.onSystem?.(`New session ${shortSessionId(live.summary.id)} (previous kept on disk)
|
|
46131
46224
|
`);
|
|
46132
46225
|
} else {
|
|
@@ -46148,6 +46241,7 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
46148
46241
|
});
|
|
46149
46242
|
live = packed.handle;
|
|
46150
46243
|
history = packed.context;
|
|
46244
|
+
nextArchiveIndex = history.length;
|
|
46151
46245
|
if (packed.result.noop) {
|
|
46152
46246
|
agentIo.onSystem?.(`Nothing to compact (context already small).
|
|
46153
46247
|
`);
|
|
@@ -46171,7 +46265,6 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
46171
46265
|
${GUTTER}${style.cyan("\u25CF")} ${style.bold("keryx")}
|
|
46172
46266
|
`);
|
|
46173
46267
|
lastUsage = undefined;
|
|
46174
|
-
const before = history.length;
|
|
46175
46268
|
startSpinner();
|
|
46176
46269
|
try {
|
|
46177
46270
|
await runAgentTurn(agentIo, deps, history, line);
|
|
@@ -46179,13 +46272,7 @@ ${GUTTER}${style.cyan("\u25CF")} ${style.bold("keryx")}
|
|
|
46179
46272
|
endBlock();
|
|
46180
46273
|
stopSpinner();
|
|
46181
46274
|
}
|
|
46182
|
-
|
|
46183
|
-
const m = history[i];
|
|
46184
|
-
if (m !== undefined) {
|
|
46185
|
-
archive.push(m);
|
|
46186
|
-
}
|
|
46187
|
-
}
|
|
46188
|
-
save();
|
|
46275
|
+
flushSessionCheckpoint();
|
|
46189
46276
|
const usageLine = formatUsage(lastUsage);
|
|
46190
46277
|
if (usageLine.length > 0) {
|
|
46191
46278
|
out(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.23",
|
|
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": {
|