@mrciphersmith/keryx 0.3.114 → 0.3.115

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.
Files changed (2) hide show
  1. package/dist/cli.js +61 -32
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -23150,7 +23150,7 @@ var package_default;
23150
23150
  var init_package = __esm(() => {
23151
23151
  package_default = {
23152
23152
  name: "@mrciphersmith/keryx",
23153
- version: "0.3.114",
23153
+ version: "0.3.115",
23154
23154
  description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
23155
23155
  private: false,
23156
23156
  publishConfig: {
@@ -52419,6 +52419,7 @@ var init_codex_catalog_version = __esm(() => {
52419
52419
  });
52420
52420
 
52421
52421
  // src/commands/subscription-models.ts
52422
+ import { resolve as resolve2 } from "path";
52422
52423
  function positiveInt(value) {
52423
52424
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : undefined;
52424
52425
  }
@@ -52426,7 +52427,22 @@ async function fetchOpenAiCodexModels(fetchFn, opts = {}) {
52426
52427
  const { contextWindows: _windows, ...result } = await fetchOpenAiCodexCatalog(fetchFn, opts);
52427
52428
  return result;
52428
52429
  }
52429
- async function fetchOpenAiCodexCatalog(fetchFn, opts = {}) {
52430
+ function fetchOpenAiCodexCatalog(fetchFn, opts = {}) {
52431
+ let requests = catalogInFlight.get(fetchFn);
52432
+ if (requests === undefined) {
52433
+ requests = new Map;
52434
+ catalogInFlight.set(fetchFn, requests);
52435
+ }
52436
+ const key = JSON.stringify([resolve2(keryxConfigDir(opts.configDir)), opts.timeoutMs ?? 8000, opts.refreshCatalogVersion ?? false]);
52437
+ const existing = requests.get(key);
52438
+ if (existing !== undefined)
52439
+ return existing;
52440
+ const scope = requests;
52441
+ const request = requestOpenAiCodexCatalog(fetchFn, opts).finally(() => scope.delete(key));
52442
+ scope.set(key, request);
52443
+ return request;
52444
+ }
52445
+ async function requestOpenAiCodexCatalog(fetchFn, opts = {}) {
52430
52446
  const controller = new AbortController;
52431
52447
  const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 8000);
52432
52448
  let authenticated = false;
@@ -52476,8 +52492,9 @@ async function fetchOpenAiCodexCatalog(fetchFn, opts = {}) {
52476
52492
  clearTimeout(timer);
52477
52493
  }
52478
52494
  }
52479
- var OPENAI_CODEX_PICKER;
52495
+ var OPENAI_CODEX_PICKER, catalogInFlight;
52480
52496
  var init_subscription_models = __esm(() => {
52497
+ init_config_dir();
52481
52498
  init_openai_subscription();
52482
52499
  init_codex_catalog_version();
52483
52500
  OPENAI_CODEX_PICKER = {
@@ -52486,6 +52503,7 @@ var init_subscription_models = __esm(() => {
52486
52503
  baseUrl: "https://chatgpt.com/backend-api/codex",
52487
52504
  models: ["gpt-5.3-codex"]
52488
52505
  };
52506
+ catalogInFlight = new WeakMap;
52489
52507
  });
52490
52508
 
52491
52509
  // src/commands/live-codex-models.ts
@@ -60559,7 +60577,7 @@ var init_output_spill = __esm(() => {
60559
60577
 
60560
60578
  // src/harness/tool/builtin/interactive-tools.ts
60561
60579
  import { readdir as readdir24 } from "fs/promises";
60562
- import { basename, dirname, isAbsolute, join as join3, relative, resolve as resolve2, sep } from "path";
60580
+ import { basename, dirname, isAbsolute, join as join3, relative, resolve as resolve3, sep } from "path";
60563
60581
  import { lstatSync as lstatSync5, realpathSync as realpathSync4 } from "fs";
60564
60582
  async function readFromLine(file, startLine, cap) {
60565
60583
  const reader = file.stream().getReader();
@@ -60617,7 +60635,7 @@ async function readFromLine(file, startLine, cap) {
60617
60635
  }
60618
60636
  function confineToRoot(root, candidate) {
60619
60637
  const rootReal = realpathOr(root);
60620
- const target = resolve2(rootReal, candidate ?? ".");
60638
+ const target = resolve3(rootReal, candidate ?? ".");
60621
60639
  const effective = realpathThroughAncestors(target);
60622
60640
  if (effective === undefined) {
60623
60641
  return null;
@@ -60635,7 +60653,7 @@ function realpathOr(candidate) {
60635
60653
  try {
60636
60654
  return realpathSync4(candidate);
60637
60655
  } catch {
60638
- return resolve2(candidate);
60656
+ return resolve3(candidate);
60639
60657
  }
60640
60658
  }
60641
60659
  function realpathThroughAncestors(absolute) {
@@ -60652,7 +60670,7 @@ function realpathThroughAncestors(absolute) {
60652
60670
  } catch {}
60653
60671
  const parent = dirname(current);
60654
60672
  if (parent === current) {
60655
- return resolve2(absolute);
60673
+ return resolve3(absolute);
60656
60674
  }
60657
60675
  missing.push(basename(current));
60658
60676
  current = parent;
@@ -75020,7 +75038,7 @@ var init_github = __esm(() => {
75020
75038
 
75021
75039
  // src/harness/tool/metaproject-adapter.ts
75022
75040
  import { lstat as lstat10, readdir as readdir32, readFile as readFile92, realpath as realpath17, stat as stat25 } from "fs/promises";
75023
- import { isAbsolute as isAbsolute2, join as join4, relative as relative2, resolve as resolve3 } from "path";
75041
+ import { isAbsolute as isAbsolute2, join as join4, relative as relative2, resolve as resolve4 } from "path";
75024
75042
  function isMissingExecutable(cause) {
75025
75043
  const message = cause instanceof Error ? cause.message : String(cause);
75026
75044
  return /Executable not found|\bENOENT\b|not found in \$?PATH/i.test(message);
@@ -75062,7 +75080,7 @@ function portableMemoryPath(candidate) {
75062
75080
  }
75063
75081
  function confineToWiki(cwd, candidate) {
75064
75082
  const wikiRoot = join4(cwd, ".metaproject", "wiki");
75065
- const target = resolve3(wikiRoot, candidate);
75083
+ const target = resolve4(wikiRoot, candidate);
75066
75084
  const rel = relative2(wikiRoot, target);
75067
75085
  if (rel === "") {
75068
75086
  return null;
@@ -75119,7 +75137,7 @@ async function detectMemoryStoreUnreadable(cwd) {
75119
75137
  }
75120
75138
  function confineToSkills(cwd, candidate) {
75121
75139
  const skillsRoot = join4(cwd, ".metaproject", "skills", "gdskills");
75122
- const target = resolve3(cwd, candidate);
75140
+ const target = resolve4(cwd, candidate);
75123
75141
  const rel = relative2(skillsRoot, target);
75124
75142
  if (rel === "") {
75125
75143
  return null;
@@ -95188,6 +95206,9 @@ ${block}
95188
95206
  function asksForAutomaticReview(deps, options, userLine) {
95189
95207
  return options.automaticReview ?? ((options.origin ?? "operator") === "operator" && deps.subagentBudget === undefined && isAutomaticReviewRequest(userLine));
95190
95208
  }
95209
+ function agentContextWindow(deps) {
95210
+ return deps.getContextWindow !== undefined ? deps.getContextWindow() : deps.contextWindow;
95211
+ }
95191
95212
  async function runAgentTurn(io, deps, history, userLine, options = {}) {
95192
95213
  const controlNonce = deps.controlNonce ?? generateControlNonce();
95193
95214
  recordBunfigBaseline();
@@ -95420,7 +95441,7 @@ async function pruneHistory(io, deps, history, sessionDir, minSavingTokens, shou
95420
95441
  return { pruned: 0, collapsed: 0, reasoningStripped: 0, savedTokens: 0 };
95421
95442
  }
95422
95443
  const lengthBefore = history.length;
95423
- const thresholds = pruneThresholdsForWindow(deps.contextWindow);
95444
+ const thresholds = pruneThresholdsForWindow(agentContextWindow(deps));
95424
95445
  const result = await pruneToolOutputs(history, {
95425
95446
  sessionDir,
95426
95447
  protectTokens: thresholds.protectTokens,
@@ -95458,7 +95479,7 @@ async function pruneOrRewriteHistory(input) {
95458
95479
  round: input.round,
95459
95480
  maxRounds: input.maxRounds
95460
95481
  });
95461
- const forced = needsCompaction(estimateRequestTokens(history, input.systemInstruction, input.toolDefs), deps.contextWindow);
95482
+ const forced = needsCompaction(estimateRequestTokens(history, input.systemInstruction, input.toolDefs), agentContextWindow(deps));
95462
95483
  const logDecision = (d) => {
95463
95484
  const key = `${d.kind}:${d.reason}`;
95464
95485
  if (d.apply) {
@@ -95503,7 +95524,7 @@ ${describeRewriteDecision(d)}
95503
95524
  sessionDir: wmDir,
95504
95525
  slate,
95505
95526
  frame: { nonce: input.controlNonce, scrub, ts: input.now() },
95506
- ...deps.contextWindow !== undefined ? { contextWindow: deps.contextWindow } : {},
95527
+ ...agentContextWindow(deps) !== undefined ? { contextWindow: agentContextWindow(deps) } : {},
95507
95528
  providerId: deps.providerId,
95508
95529
  remainingRounds,
95509
95530
  atPlanBoundary: boundary,
@@ -95577,13 +95598,13 @@ async function pruneThenCompact(io, deps, history, systemInstruction, toolDefs,
95577
95598
  usageAnchors.delete(history);
95578
95599
  }
95579
95600
  const estimate = estimateRequestTokens(history, systemInstruction, toolDefs);
95580
- if (!needsCompaction(estimate, deps.contextWindow)) {
95601
+ if (!needsCompaction(estimate, agentContextWindow(deps))) {
95581
95602
  return;
95582
95603
  }
95583
95604
  await firePreCompactBestEffort(deps, estimate);
95584
95605
  const compacted = compactWithFallback(history, {
95585
95606
  keepLastUserTurns: 3,
95586
- fits: (ctx) => !needsCompaction(estimateRequestTokens(ctx, systemInstruction, toolDefs), deps.contextWindow)
95607
+ fits: (ctx) => !needsCompaction(estimateRequestTokens(ctx, systemInstruction, toolDefs), agentContextWindow(deps))
95587
95608
  });
95588
95609
  if (!compacted.noop) {
95589
95610
  history.splice(0, history.length, ...compacted.context);
@@ -95969,11 +95990,11 @@ ${planSnapshot}`;
95969
95990
  `);
95970
95991
  }
95971
95992
  const preRequestEstimate = pruneResult.pruned + pruneResult.reasoningStripped > 0 ? estimateRequestTokens(history, roundSystemInstruction, toolDefs) : estimateWithUsageAnchor(history, roundSystemInstruction, toolDefs, liveAnchor);
95972
- if (needsCompaction(preRequestEstimate, deps.contextWindow)) {
95993
+ if (needsCompaction(preRequestEstimate, agentContextWindow(deps))) {
95973
95994
  await firePreCompactBestEffort(deps, preRequestEstimate);
95974
95995
  const compacted = compactWithFallback(history, {
95975
95996
  keepLastUserTurns: 3,
95976
- fits: (ctx) => !needsCompaction(estimateRequestTokens(ctx, roundSystemInstruction, toolDefs), deps.contextWindow)
95997
+ fits: (ctx) => !needsCompaction(estimateRequestTokens(ctx, roundSystemInstruction, toolDefs), agentContextWindow(deps))
95977
95998
  });
95978
95999
  if (!compacted.noop) {
95979
96000
  history.splice(0, history.length, ...compacted.context);
@@ -96287,7 +96308,7 @@ ${planSnapshot}`;
96287
96308
  usageAnchors.delete(history);
96288
96309
  forgetHiddenHashes();
96289
96310
  }
96290
- const overflowTarget = overflowTargetTokens(parseOverflowLimits(pendingOverflowError.message), deps.contextWindow, overflowEstimate);
96311
+ const overflowTarget = overflowTargetTokens(parseOverflowLimits(pendingOverflowError.message), agentContextWindow(deps), overflowEstimate);
96291
96312
  const compacted = compactWithFallback(history, {
96292
96313
  keepLastUserTurns: 3,
96293
96314
  fits: (ctx) => overflowTarget !== undefined && estimateRequestTokens(ctx, roundSystemInstruction, toolDefs) <= overflowTarget
@@ -105361,7 +105382,7 @@ var init_metaproject_operations = __esm(() => {
105361
105382
 
105362
105383
  // src/harness/tool/builtin/metaproject-tools.ts
105363
105384
  import { existsSync as existsSync43 } from "fs";
105364
- import { resolve as resolve4 } from "path";
105385
+ import { resolve as resolve5 } from "path";
105365
105386
  function normalizeSearchResult(result) {
105366
105387
  if (result.isError && RG_UNAVAILABLE_SIGNATURE.test(result.output)) {
105367
105388
  return { output: SEARCH_CODE_RG_UNAVAILABLE_MESSAGE, isError: true };
@@ -105369,7 +105390,7 @@ function normalizeSearchResult(result) {
105369
105390
  return result;
105370
105391
  }
105371
105392
  function keryxSelfCommand(main = Bun.main, execPath = process.execPath, exists = existsSync43, entries = KERYX_ENTRIES) {
105372
- if (entries.includes(resolve4(main)) && exists(main)) {
105393
+ if (entries.includes(resolve5(main)) && exists(main)) {
105373
105394
  return [execPath, ...SAFE_BUN_SPAWN_ARGS, main];
105374
105395
  }
105375
105396
  if (isCompiledBinaryEntry(main)) {
@@ -105525,8 +105546,8 @@ var init_metaproject_tools = __esm(() => {
105525
105546
  RG_UNAVAILABLE_SIGNATURE = /ripgrep \(rg\) is not installed|Executable not found[^\n]*\brg\b|\brg\b[^\n]*\bENOENT\b|\bENOENT\b[^\n]*\brg\b/i;
105526
105547
  SEARCH_CODE_RG_UNAVAILABLE_MESSAGE = "ripgrep (rg) is not installed or not on PATH, and search_code needs it. Install it " + "(`brew install ripgrep` / `apt install ripgrep`), or use read_file and list_dir to " + "inspect files directly instead of retrying search_code.";
105527
105548
  KERYX_ENTRIES = [
105528
- resolve4(import.meta.dir, "..", "..", "..", "cli.ts"),
105529
- resolve4(import.meta.dir, "cli.js")
105549
+ resolve5(import.meta.dir, "..", "..", "..", "cli.ts"),
105550
+ resolve5(import.meta.dir, "cli.js")
105530
105551
  ];
105531
105552
  });
105532
105553
 
@@ -146663,6 +146684,7 @@ function mountStartupIndicator(otui, r, initialLabel, opts = {}) {
146663
146684
  return;
146664
146685
  }
146665
146686
  text.content = otui.t`${dimChunk(otui, `${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ${label}`)}`;
146687
+ r.requestRender();
146666
146688
  };
146667
146689
  paint();
146668
146690
  const schedule = opts.setInterval ?? ((fn, ms) => setInterval(fn, ms));
@@ -146684,6 +146706,7 @@ function mountStartupIndicator(otui, r, initialLabel, opts = {}) {
146684
146706
  removed = true;
146685
146707
  unschedule(timer);
146686
146708
  r.root.remove(box);
146709
+ r.requestRender();
146687
146710
  }
146688
146711
  };
146689
146712
  }
@@ -158396,6 +158419,15 @@ async function fetchCodexLimits(fetchFn, model, configDir, timeoutMs) {
158396
158419
  return {};
158397
158420
  }
158398
158421
  }
158422
+ function startSessionLimits(input, load = loadSessionLimits) {
158423
+ let contextWindow;
158424
+ const ready = new Promise((resolve) => setTimeout(resolve, 0)).then(async () => {
158425
+ try {
158426
+ contextWindow = (await load(input)).contextWindow;
158427
+ } catch {}
158428
+ });
158429
+ return { getContextWindow: () => contextWindow, ready };
158430
+ }
158399
158431
  async function loadSessionLimits(input) {
158400
158432
  const fetchFn = input.fetch ?? globalThis.fetch;
158401
158433
  const env = envWithSavedApiKeys(input.env ?? process.env);
@@ -180411,15 +180443,12 @@ Example: keryx shell --provider ollama --model llama3.1:latest`);
180411
180443
  steerable: true
180412
180444
  })
180413
180445
  });
180414
- let contextWindow;
180415
- try {
180416
- const limits = await loadSessionLimits({
180417
- provider: sel.provider,
180418
- model: sel.model,
180419
- ...sel.baseUrl !== undefined ? { baseUrl: sel.baseUrl } : {}
180420
- });
180421
- contextWindow = limits.contextWindow;
180422
- } catch {}
180446
+ const limits = startSessionLimits({
180447
+ provider: sel.provider,
180448
+ model: sel.model,
180449
+ ...sel.baseUrl !== undefined ? { baseUrl: sel.baseUrl } : {},
180450
+ ...runtime.cacheDir !== undefined ? { configDir: runtime.cacheDir } : {}
180451
+ });
180423
180452
  const deps = {
180424
180453
  provider: agentProvider,
180425
180454
  providerId: sel.provider,
@@ -180451,7 +180480,7 @@ Example: keryx shell --provider ollama --model llama3.1:latest`);
180451
180480
  sweepBackgroundJobs: () => jobRegistry.sweepAll(),
180452
180481
  jobRegistry,
180453
180482
  ...resetSubagentBudget !== undefined ? { resetSubagentBudget } : {},
180454
- ...contextWindow !== undefined ? { contextWindow } : {},
180483
+ getContextWindow: limits.getContextWindow,
180455
180484
  ...Object.keys(resolvedModelParams).length > 0 ? { modelParams: resolvedModelParams } : {},
180456
180485
  ...(() => {
180457
180486
  const h = getShellHooks();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.3.114",
3
+ "version": "0.3.115",
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": {