@mrciphersmith/keryx 0.2.62 → 0.2.63

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 +95 -27
  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.63",
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,79 @@ 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(`
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 sysLines = game.systemPrompt().split(`
57920
57943
  `);
57921
- line(`system: ${sys.join(" \xB7 ")}`, theme.muted, "game-system");
57944
+ const sysShown = sysLines.length > 6 ? [...sysLines.slice(0, 6), `\u2026 (+${sysLines.length - 6} more)`] : sysLines;
57945
+ const sysCard = card("game-system-card", { width: "100%", marginTop: 1 });
57946
+ sysCard.add(text({ id: "game-system-title", content: "system prompt", fg: theme.muted }));
57947
+ sysCard.add(text({ id: "game-system", content: sysShown.join(`
57948
+ `), fg: theme.muted }));
57949
+ parent.add(sysCard);
57922
57950
  const lt = args2.lastTurn;
57923
57951
  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");
57952
+ const statsRow = box({ id: "game-stats-row", width: "100%", flexDirection: "row", gap: 1, marginTop: 1 });
57953
+ const lastTurnCard = card("game-last-turn", { flexGrow: 1, flexShrink: 0 });
57954
+ lastTurnCard.add(text({ id: "game-last-turn-title", content: "last turn", fg: theme.muted }));
57955
+ if (lt === undefined) {
57956
+ lastTurnCard.add(text({ id: "game-stats-empty", content: "no turns yet", fg: theme.muted }));
57957
+ } else {
57958
+ const model = lt.provider === "\u2013" ? "\u2013" : truncate4(`${lt.provider}/${lt.model}`, MODEL_MAX);
57959
+ statRow(lastTurnCard, "model", model, "game-stats-model");
57960
+ statRow(lastTurnCard, "first byte", formatMs(lt.latencyMs), "game-stats-latency");
57961
+ statRow(lastTurnCard, "total", formatMs(lt.totalMs), "game-stats-total");
57962
+ statRow(lastTurnCard, "tokens", `in ${formatTokens(lt.inputTokens)} \xB7 out ${formatTokens(lt.outputTokens)}`, "game-stats-tokens");
57963
+ if (lt.reasoning) {
57964
+ statRow(lastTurnCard, "reasoning", "yes", "game-stats-reasoning", theme.focus);
57965
+ }
57966
+ if (lt.localFallback) {
57967
+ statRow(lastTurnCard, "fallback", "local", "game-stats-fallback", theme.error);
57968
+ }
57969
+ if (lt.error) {
57970
+ statRow(lastTurnCard, "error", "yes", "game-stats-error", theme.error);
57971
+ }
57972
+ }
57973
+ const sessionCard = card("game-session", { flexGrow: 1, flexShrink: 0 });
57974
+ sessionCard.add(text({ id: "game-session-title", content: "session", fg: theme.muted }));
57975
+ statRow(sessionCard, "turns", String(tot.turns), "game-session-turns");
57976
+ statRow(sessionCard, "fallbacks", String(tot.localFallbacks), "game-session-fallbacks");
57977
+ statRow(sessionCard, "errors", String(tot.errors), "game-session-errors");
57978
+ statRow(sessionCard, "tokens", `in ${formatTokens(tot.inputTokens)} \xB7 out ${formatTokens(tot.outputTokens)}`, "game-session-tokens");
57979
+ statsRow.add(lastTurnCard);
57980
+ statsRow.add(sessionCard);
57981
+ parent.add(statsRow);
57937
57982
  }
57938
57983
 
57939
57984
  // src/tui/games/otui.ts
@@ -58103,6 +58148,14 @@ function presentGamesModal(openModalFn, otui, chrome, options = {}, registry = c
58103
58148
  title: "/game",
58104
58149
  tabs: games.map((game) => ({ id: game.id, label: game.label })),
58105
58150
  footer: GAMES_FOOTER,
58151
+ onArrowKeys: (key, _direction) => {
58152
+ const game = registry.get(activeId);
58153
+ if (game === undefined || modelBusy) {
58154
+ return false;
58155
+ }
58156
+ const state = stateOf(activeId);
58157
+ return game.onKey(state, { name: key.name, sequence: key.sequence }) !== undefined;
58158
+ },
58106
58159
  renderTab: (_tabId, body, ctx) => {
58107
58160
  if (body === undefined || body === null) {
58108
58161
  return;
@@ -59034,6 +59087,18 @@ async function createShellChrome(otui, renderer, opts) {
59034
59087
  });
59035
59088
  main.add(scroll);
59036
59089
  const transcript = scroll.content;
59090
+ let liveStatus;
59091
+ const originalTranscriptAdd = transcript.add.bind(transcript);
59092
+ const originalTranscriptRemove = transcript.remove.bind(transcript);
59093
+ transcript.add = (child, index) => {
59094
+ if (liveStatus !== undefined && child !== liveStatus) {
59095
+ originalTranscriptRemove(liveStatus);
59096
+ const added = originalTranscriptAdd(child, index);
59097
+ originalTranscriptAdd(liveStatus);
59098
+ return added;
59099
+ }
59100
+ return originalTranscriptAdd(child, index);
59101
+ };
59037
59102
  const queueDock = new otui.BoxRenderable(r, {
59038
59103
  id: "queue-dock",
59039
59104
  flexShrink: 0,
@@ -59208,7 +59273,6 @@ async function createShellChrome(otui, renderer, opts) {
59208
59273
  const footerRight = new otui.TextRenderable(r, { id: "footer-right", content: otui.t`${otui.dim(opts.status)}` });
59209
59274
  footer.add(footerRight);
59210
59275
  main.add(footer);
59211
- let liveStatus;
59212
59276
  let busyPhase = "waiting for model";
59213
59277
  let busyStartedAt = 0;
59214
59278
  let spinIdx = 0;
@@ -59223,12 +59287,15 @@ async function createShellChrome(otui, renderer, opts) {
59223
59287
  }
59224
59288
  if (!busy) {
59225
59289
  footerLeft.content = otui.t`${otui.dim(opts.footerHint)}`;
59290
+ footerRight.content = otui.t`${otui.dim(opts.status)}`;
59226
59291
  return;
59227
59292
  }
59228
59293
  const frame = SPINNER[spinIdx % SPINNER.length] ?? "\u280B";
59229
59294
  const secs = ((Date.now() - busyStartedAt) / 1000).toFixed(1);
59230
59295
  const line = `${frame} ${busyPhase} \xB7 ${secs}s`;
59231
59296
  footerLeft.content = otui.t`${otui.yellow(line)}`;
59297
+ const perm = opts.permissionMode?.();
59298
+ footerRight.content = otui.t`${otui.dim(perm !== undefined && perm.length > 0 ? `mode ${perm}` : opts.status)}`;
59232
59299
  if (liveStatus !== undefined) {
59233
59300
  liveStatus.content = otui.t`${otui.dim(line)}`;
59234
59301
  }
@@ -62565,6 +62632,7 @@ async function launchTuiAgentShell(opts) {
62565
62632
  placeholder: "type a task or / for commands \xB7 Enter send \xB7 Shift+Enter newline",
62566
62633
  commands: commandsForMode("agent"),
62567
62634
  headerMeta: "\u21910 \u21930",
62635
+ permissionMode: () => permissionMode,
62568
62636
  filterCommands: (query) => filterCommands(query, "agent"),
62569
62637
  ...opts.versionCheck !== undefined ? { versionCheck: opts.versionCheck } : {}
62570
62638
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.2.62",
3
+ "version": "0.2.63",
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": {