@mrciphersmith/keryx 0.2.62 → 0.2.64

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 +106 -28
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -53556,7 +53556,7 @@ import { spawnSync as spawnSync2 } from "child_process";
53556
53556
  // package.json
53557
53557
  var package_default = {
53558
53558
  name: "@mrciphersmith/keryx",
53559
- version: "0.2.62",
53559
+ version: "0.2.64",
53560
53560
  description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
53561
53561
  private: false,
53562
53562
  publishConfig: {
@@ -57576,10 +57576,10 @@ function formatTokens(n) {
57576
57576
  // src/tui/games/constants.ts
57577
57577
  var GAME_MODEL_TIMEOUT_MS = 60000;
57578
57578
  var GAMES_FOOTER = [
57579
- { key: "h/l", label: "move" },
57579
+ { key: "arrows", label: "move" },
57580
57580
  { key: "enter", label: "place" },
57581
57581
  { key: "r", label: "new game" },
57582
- { key: "\u2190/\u2192", label: "games" },
57582
+ { key: "tab", label: "games" },
57583
57583
  { key: "esc", label: "minimize" }
57584
57584
  ];
57585
57585
 
@@ -57906,34 +57906,89 @@ async function runGameModelTurn(game, state, opts) {
57906
57906
  }
57907
57907
 
57908
57908
  // src/tui/games/agent-panel.ts
57909
+ var MODEL_MAX = 22;
57910
+ function truncate4(value, max) {
57911
+ return value.length > max ? `${value.slice(0, max - 1)}\u2026` : value;
57912
+ }
57909
57913
  function renderAgentPanel(game, parent, core, renderer, args2) {
57910
57914
  const theme = getTheme();
57911
- const line = (content, fg, id) => {
57912
- parent.add(new core.TextRenderable(renderer, { content, fg, ...id !== undefined ? { id } : {} }));
57913
- };
57914
- if (args2.modelBusy) {
57915
- line("agent is thinking\u2026", theme.focus, "game-notice");
57916
- } else {
57917
- line(args2.notice ?? "", theme.error, "game-notice");
57918
- }
57919
- const sys = game.systemPrompt().split(`
57920
- `);
57921
- line(`system: ${sys.join(" \xB7 ")}`, theme.muted, "game-system");
57915
+ const box = (opts) => new core.BoxRenderable(renderer, opts);
57916
+ const text = (opts) => new core.TextRenderable(renderer, opts);
57917
+ const card = (id, extra = {}) => box({
57918
+ id,
57919
+ flexDirection: "column",
57920
+ border: true,
57921
+ borderStyle: "rounded",
57922
+ borderColor: theme.border,
57923
+ backgroundColor: theme.panel,
57924
+ paddingLeft: 1,
57925
+ paddingRight: 1,
57926
+ ...extra
57927
+ });
57928
+ const statRow = (owner, label, value, id, valueFg = theme.text) => {
57929
+ const rowBox = box({ flexDirection: "row", gap: 1 });
57930
+ rowBox.add(text({ content: label, fg: theme.muted }));
57931
+ rowBox.add(text({ id, content: value, fg: valueFg }));
57932
+ owner.add(rowBox);
57933
+ };
57934
+ const idle = args2.notice === undefined || args2.notice === "";
57935
+ const statusCard = card("game-status-card", { width: "100%", marginTop: 1 });
57936
+ statusCard.add(text({
57937
+ id: "game-notice",
57938
+ content: args2.modelBusy ? "agent is thinking\u2026" : idle ? "waiting for your move" : args2.notice,
57939
+ fg: args2.modelBusy ? theme.focus : idle ? theme.text : theme.error
57940
+ }));
57941
+ parent.add(statusCard);
57942
+ const sysCard = new core.ScrollBoxRenderable(renderer, {
57943
+ id: "game-system-card",
57944
+ width: "100%",
57945
+ flexGrow: 1,
57946
+ minHeight: 0,
57947
+ marginTop: 1,
57948
+ border: true,
57949
+ borderStyle: "rounded",
57950
+ borderColor: theme.border,
57951
+ backgroundColor: theme.panel,
57952
+ paddingLeft: 1,
57953
+ paddingRight: 1,
57954
+ scrollY: true,
57955
+ contentOptions: { flexDirection: "column" }
57956
+ });
57957
+ sysCard.add(text({ id: "game-system-title", content: "system prompt", fg: theme.muted }));
57958
+ sysCard.add(text({ id: "game-system", content: game.systemPrompt(), fg: theme.muted }));
57959
+ parent.add(sysCard);
57922
57960
  const lt = args2.lastTurn;
57923
57961
  const tot = args2.totals;
57924
- const model = lt === undefined ? "\u2013" : `${lt.provider}/${lt.model}`;
57925
- const parts = [
57926
- `model: ${model}`,
57927
- `first byte ${formatMs(lt?.latencyMs)}`,
57928
- `total ${formatMs(lt?.totalMs)}`,
57929
- `in ${formatTokens(lt?.inputTokens)}`,
57930
- `out ${formatTokens(lt?.outputTokens)}`,
57931
- lt?.reasoning === true ? "reasoning" : undefined,
57932
- `turns ${tot.turns}`,
57933
- `fallbacks ${tot.localFallbacks}`,
57934
- tot.errors > 0 ? `errors ${tot.errors}` : undefined
57935
- ];
57936
- line(parts.filter((p) => p !== undefined).join(" \xB7 "), theme.muted, "game-stats");
57962
+ const statsRow = box({ id: "game-stats-row", width: "100%", flexDirection: "row", gap: 1, marginTop: 1 });
57963
+ const lastTurnCard = card("game-last-turn", { flexGrow: 1, flexShrink: 0 });
57964
+ lastTurnCard.add(text({ id: "game-last-turn-title", content: "last turn", fg: theme.muted }));
57965
+ if (lt === undefined) {
57966
+ lastTurnCard.add(text({ id: "game-stats-empty", content: "no turns yet", fg: theme.muted }));
57967
+ } else {
57968
+ const model = lt.provider === "\u2013" ? "\u2013" : truncate4(`${lt.provider}/${lt.model}`, MODEL_MAX);
57969
+ statRow(lastTurnCard, "model", model, "game-stats-model");
57970
+ statRow(lastTurnCard, "first byte", formatMs(lt.latencyMs), "game-stats-latency");
57971
+ statRow(lastTurnCard, "total", formatMs(lt.totalMs), "game-stats-total");
57972
+ statRow(lastTurnCard, "tokens", `in ${formatTokens(lt.inputTokens)} \xB7 out ${formatTokens(lt.outputTokens)}`, "game-stats-tokens");
57973
+ if (lt.reasoning) {
57974
+ statRow(lastTurnCard, "reasoning", "yes", "game-stats-reasoning", theme.focus);
57975
+ }
57976
+ if (lt.localFallback) {
57977
+ statRow(lastTurnCard, "fallback", "local", "game-stats-fallback", theme.error);
57978
+ }
57979
+ if (lt.error) {
57980
+ statRow(lastTurnCard, "error", "yes", "game-stats-error", theme.error);
57981
+ }
57982
+ }
57983
+ const sessionCard = card("game-session", { flexGrow: 1, flexShrink: 0 });
57984
+ sessionCard.add(text({ id: "game-session-title", content: "session", fg: theme.muted }));
57985
+ statRow(sessionCard, "turns", String(tot.turns), "game-session-turns");
57986
+ statRow(sessionCard, "fallbacks", String(tot.localFallbacks), "game-session-fallbacks");
57987
+ statRow(sessionCard, "errors", String(tot.errors), "game-session-errors");
57988
+ statRow(sessionCard, "tokens", `in ${formatTokens(tot.inputTokens)} \xB7 out ${formatTokens(tot.outputTokens)}`, "game-session-tokens");
57989
+ statsRow.add(lastTurnCard);
57990
+ statsRow.add(sessionCard);
57991
+ parent.add(statsRow);
57937
57992
  }
57938
57993
 
57939
57994
  // src/tui/games/otui.ts
@@ -58103,6 +58158,14 @@ function presentGamesModal(openModalFn, otui, chrome, options = {}, registry = c
58103
58158
  title: "/game",
58104
58159
  tabs: games.map((game) => ({ id: game.id, label: game.label })),
58105
58160
  footer: GAMES_FOOTER,
58161
+ onArrowKeys: (key, _direction) => {
58162
+ const game = registry.get(activeId);
58163
+ if (game === undefined || modelBusy) {
58164
+ return false;
58165
+ }
58166
+ const state = stateOf(activeId);
58167
+ return game.onKey(state, { name: key.name, sequence: key.sequence }) !== undefined;
58168
+ },
58106
58169
  renderTab: (_tabId, body, ctx) => {
58107
58170
  if (body === undefined || body === null) {
58108
58171
  return;
@@ -59034,6 +59097,18 @@ async function createShellChrome(otui, renderer, opts) {
59034
59097
  });
59035
59098
  main.add(scroll);
59036
59099
  const transcript = scroll.content;
59100
+ let liveStatus;
59101
+ const originalTranscriptAdd = transcript.add.bind(transcript);
59102
+ const originalTranscriptRemove = transcript.remove.bind(transcript);
59103
+ transcript.add = (child, index) => {
59104
+ if (liveStatus !== undefined && child !== liveStatus) {
59105
+ originalTranscriptRemove(liveStatus);
59106
+ const added = originalTranscriptAdd(child, index);
59107
+ originalTranscriptAdd(liveStatus);
59108
+ return added;
59109
+ }
59110
+ return originalTranscriptAdd(child, index);
59111
+ };
59037
59112
  const queueDock = new otui.BoxRenderable(r, {
59038
59113
  id: "queue-dock",
59039
59114
  flexShrink: 0,
@@ -59208,7 +59283,6 @@ async function createShellChrome(otui, renderer, opts) {
59208
59283
  const footerRight = new otui.TextRenderable(r, { id: "footer-right", content: otui.t`${otui.dim(opts.status)}` });
59209
59284
  footer.add(footerRight);
59210
59285
  main.add(footer);
59211
- let liveStatus;
59212
59286
  let busyPhase = "waiting for model";
59213
59287
  let busyStartedAt = 0;
59214
59288
  let spinIdx = 0;
@@ -59223,12 +59297,15 @@ async function createShellChrome(otui, renderer, opts) {
59223
59297
  }
59224
59298
  if (!busy) {
59225
59299
  footerLeft.content = otui.t`${otui.dim(opts.footerHint)}`;
59300
+ footerRight.content = otui.t`${otui.dim(opts.status)}`;
59226
59301
  return;
59227
59302
  }
59228
59303
  const frame = SPINNER[spinIdx % SPINNER.length] ?? "\u280B";
59229
59304
  const secs = ((Date.now() - busyStartedAt) / 1000).toFixed(1);
59230
59305
  const line = `${frame} ${busyPhase} \xB7 ${secs}s`;
59231
59306
  footerLeft.content = otui.t`${otui.yellow(line)}`;
59307
+ const perm = opts.permissionMode?.();
59308
+ footerRight.content = otui.t`${otui.dim(perm !== undefined && perm.length > 0 ? `mode ${perm}` : opts.status)}`;
59232
59309
  if (liveStatus !== undefined) {
59233
59310
  liveStatus.content = otui.t`${otui.dim(line)}`;
59234
59311
  }
@@ -62565,6 +62642,7 @@ async function launchTuiAgentShell(opts) {
62565
62642
  placeholder: "type a task or / for commands \xB7 Enter send \xB7 Shift+Enter newline",
62566
62643
  commands: commandsForMode("agent"),
62567
62644
  headerMeta: "\u21910 \u21930",
62645
+ permissionMode: () => permissionMode,
62568
62646
  filterCommands: (query) => filterCommands(query, "agent"),
62569
62647
  ...opts.versionCheck !== undefined ? { versionCheck: opts.versionCheck } : {}
62570
62648
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.2.62",
3
+ "version": "0.2.64",
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": {