@mrciphersmith/keryx 0.2.65 → 0.2.66

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 +400 -33
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -28105,6 +28105,332 @@ function looksLikeUnifiedDiff(text) {
28105
28105
  }
28106
28106
  return false;
28107
28107
  }
28108
+ var CODE_LANG_ALIASES = {
28109
+ js: "javascript",
28110
+ mjs: "javascript",
28111
+ cjs: "javascript",
28112
+ jsx: "javascript",
28113
+ ts: "typescript",
28114
+ tsx: "typescript",
28115
+ py: "python",
28116
+ py3: "python",
28117
+ sh: "bash",
28118
+ shell: "bash",
28119
+ zsh: "bash",
28120
+ console: "bash",
28121
+ yml: "yaml",
28122
+ rb: "ruby",
28123
+ rs: "rust",
28124
+ kt: "kotlin",
28125
+ cs: "csharp",
28126
+ "c++": "cpp",
28127
+ cc: "cpp",
28128
+ cxx: "cpp",
28129
+ hpp: "cpp"
28130
+ };
28131
+ var GENERIC_KEYWORDS = new Set([
28132
+ "if",
28133
+ "else",
28134
+ "for",
28135
+ "while",
28136
+ "return",
28137
+ "function",
28138
+ "class",
28139
+ "const",
28140
+ "let",
28141
+ "var",
28142
+ "import",
28143
+ "export",
28144
+ "from",
28145
+ "true",
28146
+ "false",
28147
+ "null",
28148
+ "new",
28149
+ "this",
28150
+ "try",
28151
+ "catch",
28152
+ "throw",
28153
+ "switch",
28154
+ "case",
28155
+ "break",
28156
+ "continue",
28157
+ "default",
28158
+ "static",
28159
+ "public",
28160
+ "private"
28161
+ ]);
28162
+ var CODE_LANG_KEYWORDS = {
28163
+ javascript: new Set([
28164
+ ...GENERIC_KEYWORDS,
28165
+ "async",
28166
+ "await",
28167
+ "yield",
28168
+ "typeof",
28169
+ "instanceof",
28170
+ "in",
28171
+ "of",
28172
+ "void",
28173
+ "undefined",
28174
+ "super",
28175
+ "extends",
28176
+ "finally",
28177
+ "do",
28178
+ "delete"
28179
+ ]),
28180
+ typescript: new Set([
28181
+ ...GENERIC_KEYWORDS,
28182
+ "async",
28183
+ "await",
28184
+ "yield",
28185
+ "typeof",
28186
+ "instanceof",
28187
+ "in",
28188
+ "of",
28189
+ "void",
28190
+ "undefined",
28191
+ "super",
28192
+ "extends",
28193
+ "implements",
28194
+ "interface",
28195
+ "type",
28196
+ "enum",
28197
+ "namespace",
28198
+ "declare",
28199
+ "readonly",
28200
+ "abstract",
28201
+ "as",
28202
+ "satisfies",
28203
+ "finally",
28204
+ "do",
28205
+ "delete"
28206
+ ]),
28207
+ python: new Set([
28208
+ "def",
28209
+ "return",
28210
+ "if",
28211
+ "elif",
28212
+ "else",
28213
+ "for",
28214
+ "while",
28215
+ "break",
28216
+ "continue",
28217
+ "class",
28218
+ "import",
28219
+ "from",
28220
+ "as",
28221
+ "try",
28222
+ "except",
28223
+ "finally",
28224
+ "raise",
28225
+ "with",
28226
+ "lambda",
28227
+ "yield",
28228
+ "pass",
28229
+ "None",
28230
+ "True",
28231
+ "False",
28232
+ "and",
28233
+ "or",
28234
+ "not",
28235
+ "in",
28236
+ "is",
28237
+ "global",
28238
+ "nonlocal",
28239
+ "assert",
28240
+ "async",
28241
+ "await",
28242
+ "del",
28243
+ "self"
28244
+ ]),
28245
+ bash: new Set([
28246
+ "if",
28247
+ "then",
28248
+ "else",
28249
+ "elif",
28250
+ "fi",
28251
+ "for",
28252
+ "while",
28253
+ "do",
28254
+ "done",
28255
+ "case",
28256
+ "esac",
28257
+ "function",
28258
+ "return",
28259
+ "local",
28260
+ "export",
28261
+ "exit",
28262
+ "break",
28263
+ "continue",
28264
+ "in",
28265
+ "select",
28266
+ "until"
28267
+ ]),
28268
+ go: new Set([
28269
+ "func",
28270
+ "return",
28271
+ "if",
28272
+ "else",
28273
+ "for",
28274
+ "range",
28275
+ "switch",
28276
+ "case",
28277
+ "default",
28278
+ "break",
28279
+ "continue",
28280
+ "package",
28281
+ "import",
28282
+ "var",
28283
+ "const",
28284
+ "type",
28285
+ "struct",
28286
+ "interface",
28287
+ "map",
28288
+ "chan",
28289
+ "go",
28290
+ "defer",
28291
+ "select",
28292
+ "fallthrough",
28293
+ "nil",
28294
+ "true",
28295
+ "false"
28296
+ ]),
28297
+ rust: new Set([
28298
+ "fn",
28299
+ "let",
28300
+ "mut",
28301
+ "return",
28302
+ "if",
28303
+ "else",
28304
+ "for",
28305
+ "while",
28306
+ "loop",
28307
+ "match",
28308
+ "struct",
28309
+ "enum",
28310
+ "impl",
28311
+ "trait",
28312
+ "pub",
28313
+ "use",
28314
+ "mod",
28315
+ "crate",
28316
+ "self",
28317
+ "Self",
28318
+ "super",
28319
+ "const",
28320
+ "static",
28321
+ "async",
28322
+ "await",
28323
+ "move",
28324
+ "ref",
28325
+ "dyn",
28326
+ "where",
28327
+ "unsafe",
28328
+ "true",
28329
+ "false",
28330
+ "None",
28331
+ "Some",
28332
+ "Ok",
28333
+ "Err"
28334
+ ]),
28335
+ json: new Set(["true", "false", "null"])
28336
+ };
28337
+ function codeCommentPrefix(normalizedLang) {
28338
+ switch (normalizedLang) {
28339
+ case "javascript":
28340
+ case "typescript":
28341
+ case "go":
28342
+ case "rust":
28343
+ case "java":
28344
+ case "c":
28345
+ case "cpp":
28346
+ case "csharp":
28347
+ case "swift":
28348
+ case "kotlin":
28349
+ case "scala":
28350
+ case "php":
28351
+ return "//";
28352
+ case "python":
28353
+ case "bash":
28354
+ case "ruby":
28355
+ case "yaml":
28356
+ case "toml":
28357
+ case "r":
28358
+ case "perl":
28359
+ return "#";
28360
+ case "sql":
28361
+ case "lua":
28362
+ case "haskell":
28363
+ return "--";
28364
+ default:
28365
+ return "";
28366
+ }
28367
+ }
28368
+ function normalizeCodeLang(lang) {
28369
+ const key = lang.trim().toLowerCase();
28370
+ return CODE_LANG_ALIASES[key] ?? key;
28371
+ }
28372
+ var CODE_WORD_OR_NUMBER = /[A-Za-z_$][A-Za-z0-9_$]*|\d+(?:\.\d+)?/g;
28373
+ function tokenizeCodeWords(text, keywords) {
28374
+ const tokens = [];
28375
+ let last = 0;
28376
+ CODE_WORD_OR_NUMBER.lastIndex = 0;
28377
+ let m;
28378
+ while ((m = CODE_WORD_OR_NUMBER.exec(text)) !== null) {
28379
+ if (m.index > last) {
28380
+ tokens.push({ kind: "plain", text: text.slice(last, m.index) });
28381
+ }
28382
+ const word = m[0];
28383
+ if (/^[0-9]/.test(word)) {
28384
+ tokens.push({ kind: "number", text: word });
28385
+ } else if (keywords.has(word)) {
28386
+ tokens.push({ kind: "keyword", text: word });
28387
+ } else {
28388
+ tokens.push({ kind: "plain", text: word });
28389
+ }
28390
+ last = m.index + word.length;
28391
+ }
28392
+ if (last < text.length) {
28393
+ tokens.push({ kind: "plain", text: text.slice(last) });
28394
+ }
28395
+ return tokens;
28396
+ }
28397
+ function tokenizeCodeLine(line, lang) {
28398
+ const normalized = normalizeCodeLang(lang);
28399
+ const keywords = CODE_LANG_KEYWORDS[normalized] ?? GENERIC_KEYWORDS;
28400
+ const commentPrefix = codeCommentPrefix(normalized);
28401
+ const tokens = [];
28402
+ let plainBuf = "";
28403
+ const flushPlain = () => {
28404
+ if (plainBuf.length > 0) {
28405
+ tokens.push(...tokenizeCodeWords(plainBuf, keywords));
28406
+ plainBuf = "";
28407
+ }
28408
+ };
28409
+ let i = 0;
28410
+ while (i < line.length) {
28411
+ if (commentPrefix.length > 0 && line.startsWith(commentPrefix, i)) {
28412
+ flushPlain();
28413
+ tokens.push({ kind: "comment", text: line.slice(i) });
28414
+ break;
28415
+ }
28416
+ const ch = line[i];
28417
+ if (ch === '"' || ch === "'" || ch === "`") {
28418
+ flushPlain();
28419
+ let j = i + 1;
28420
+ while (j < line.length && line[j] !== ch) {
28421
+ j += line[j] === "\\" ? 2 : 1;
28422
+ }
28423
+ j = Math.min(j + 1, line.length);
28424
+ tokens.push({ kind: "string", text: line.slice(i, j) });
28425
+ i = j;
28426
+ continue;
28427
+ }
28428
+ plainBuf += ch;
28429
+ i += 1;
28430
+ }
28431
+ flushPlain();
28432
+ return tokens;
28433
+ }
28108
28434
  function payloadKind(lang, _lineCount) {
28109
28435
  const normalized = lang.toLowerCase();
28110
28436
  if (MARKDOWN_LANGS.has(normalized)) {
@@ -28121,6 +28447,18 @@ function blockLabel({ kind, lineCount, collapsed, hint }) {
28121
28447
  const suffix = hint !== undefined && hint.length > 0 ? ` \xB7 ${hint}` : "";
28122
28448
  return `${marker} ${kind} (${lineCount} ${unit})${suffix}`;
28123
28449
  }
28450
+ function summarizeSubmittedLine(line) {
28451
+ const normalized = line.replace(/\r\n/g, `
28452
+ `).replace(/\r/g, `
28453
+ `);
28454
+ const nonEmpty = normalized.split(`
28455
+ `).filter((linePart) => linePart.length > 0);
28456
+ if (nonEmpty.length <= 1) {
28457
+ return line;
28458
+ }
28459
+ const [first, ...rest] = nonEmpty;
28460
+ return `${first} [+ ${rest.length} pasted line${rest.length === 1 ? "" : "s"}]`;
28461
+ }
28124
28462
  var ZERO_WIDTH = /^[\u0300-\u036F\u200B-\u200F\uFE00-\uFE0F\u2060-\u2064]$/u;
28125
28463
  var WIDE_RANGES = [
28126
28464
  [4352, 4447],
@@ -53556,7 +53894,7 @@ import { spawnSync as spawnSync2 } from "child_process";
53556
53894
  // package.json
53557
53895
  var package_default = {
53558
53896
  name: "@mrciphersmith/keryx",
53559
- version: "0.2.65",
53897
+ version: "0.2.66",
53560
53898
  description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
53561
53899
  private: false,
53562
53900
  publishConfig: {
@@ -53919,7 +54257,7 @@ function diffChunks(otui, text) {
53919
54257
  }
53920
54258
  return out;
53921
54259
  }
53922
- function codeChunks(otui, text) {
54260
+ function flatDimChunks(otui, text) {
53923
54261
  const out = [];
53924
54262
  for (const [index, line] of splitLines(text).entries()) {
53925
54263
  if (index > 0) {
@@ -53930,6 +54268,34 @@ function codeChunks(otui, text) {
53930
54268
  }
53931
54269
  return out;
53932
54270
  }
54271
+ function codeChunks(otui, text, lang) {
54272
+ const out = [];
54273
+ for (const [index, line] of splitLines(text).entries()) {
54274
+ if (index > 0) {
54275
+ out.push(...otui.stringToStyledText(`
54276
+ `).chunks);
54277
+ }
54278
+ for (const token of tokenizeCodeLine(line, lang)) {
54279
+ switch (token.kind) {
54280
+ case "comment":
54281
+ out.push(otui.dim(token.text));
54282
+ break;
54283
+ case "string":
54284
+ out.push(otui.green(token.text));
54285
+ break;
54286
+ case "number":
54287
+ out.push(otui.yellow(token.text));
54288
+ break;
54289
+ case "keyword":
54290
+ out.push(otui.cyan(token.text));
54291
+ break;
54292
+ default:
54293
+ out.push(...otui.stringToStyledText(token.text).chunks);
54294
+ }
54295
+ }
54296
+ }
54297
+ return out;
54298
+ }
53933
54299
  function payloadChunks(otui, text, lang = "") {
53934
54300
  const kind2 = payloadKind(lang, lineCountOf(text));
53935
54301
  if (kind2 === "diff" || looksLikeUnifiedDiff(text)) {
@@ -53938,7 +54304,7 @@ function payloadChunks(otui, text, lang = "") {
53938
54304
  if (kind2 === "markdown" || lang.length === 0) {
53939
54305
  return markdownToChunks(otui, text);
53940
54306
  }
53941
- return codeChunks(otui, text);
54307
+ return codeChunks(otui, text, lang);
53942
54308
  }
53943
54309
  function createSegmentView(otui, renderer, parent, segment) {
53944
54310
  viewSeq += 1;
@@ -53966,7 +54332,7 @@ function createSegmentView(otui, renderer, parent, segment) {
53966
54332
  }
53967
54333
  const tag = (lang, body2) => {
53968
54334
  const n = lineCountOf(body2);
53969
- return `${lang.length > 0 ? lang : "text"} \xB7 ${n} ${n === 1 ? "line" : "lines"}`;
54335
+ return `${lang.length > 0 ? lang : "text"} \xB7 ${n} ${n === 1 ? "line" : "lines"} \xB7 y copy`;
53970
54336
  };
53971
54337
  const frameWidth = (lang, body2) => Math.max(hugWidth(body2, FRAME_CHROME), hugWidth(tag(lang, body2), FRAME_CHROME));
53972
54338
  const frame = new otui.BoxRenderable(renderer, {
@@ -54012,6 +54378,7 @@ function createSegmentView(otui, renderer, parent, segment) {
54012
54378
  var messageSeq = 0;
54013
54379
  function createAssistantMessageStream(otui, renderer, parent) {
54014
54380
  let message2;
54381
+ let lastCode;
54015
54382
  const start = () => {
54016
54383
  messageSeq += 1;
54017
54384
  const container = new otui.BoxRenderable(renderer, {
@@ -54040,6 +54407,11 @@ function createAssistantMessageStream(otui, renderer, parent) {
54040
54407
  stale.destroy();
54041
54408
  }
54042
54409
  m.frozen = frozen;
54410
+ for (const segment of segments2) {
54411
+ if (segment.kind === "code") {
54412
+ lastCode = { lang: segment.lang, body: segment.body };
54413
+ }
54414
+ }
54043
54415
  };
54044
54416
  return {
54045
54417
  push: (chunk) => {
@@ -54077,7 +54449,8 @@ function createAssistantMessageStream(otui, renderer, parent) {
54077
54449
  parent.remove(message2.container);
54078
54450
  } catch {}
54079
54451
  message2 = undefined;
54080
- }
54452
+ },
54453
+ lastCodeSegment: () => lastCode
54081
54454
  };
54082
54455
  }
54083
54456
  function createBlockView(otui, renderer, parent, block, options = {}) {
@@ -54134,7 +54507,7 @@ function createBlockView(otui, renderer, parent, block, options = {}) {
54134
54507
  return;
54135
54508
  }
54136
54509
  const shown = clipBody(text, options.maxLines ?? MAX_BODY_LINES);
54137
- const content = new otui.StyledText(options.dim === true ? codeChunks(otui, shown) : payloadChunks(otui, shown));
54510
+ const content = new otui.StyledText(options.dim === true ? flatDimChunks(otui, shown) : payloadChunks(otui, shown));
54138
54511
  painted = text;
54139
54512
  if (bodyText !== undefined) {
54140
54513
  bodyText.content = content;
@@ -61740,7 +62113,8 @@ function createTuiAgentIo(otui, renderer, transcript) {
61740
62113
  onSystem: (text) => append(text.includes("[error]") ? otui.t`${otui.red(text)}` : otui.t`${otui.dim(text)}`),
61741
62114
  resetStream: () => {
61742
62115
  messages.reset();
61743
- }
62116
+ },
62117
+ lastCodeSegment: () => messages.lastCodeSegment()
61744
62118
  };
61745
62119
  }
61746
62120
  function attachBlockIo(io, addBlock, chrome = {}) {
@@ -62926,6 +63300,23 @@ async function launchTuiAgentShell(opts) {
62926
63300
  const newestBlock = (kind2) => nav.newest(kind2);
62927
63301
  const toggleNewestBlock = (kind2) => nav.toggleNewest(kind2);
62928
63302
  const copyBlock = (id) => nav.copy(id);
63303
+ const copyNewestOrLastCode = () => {
63304
+ const target = newestBlock();
63305
+ if (target !== undefined) {
63306
+ return copyBlock(target.id);
63307
+ }
63308
+ const code = io.lastCodeSegment();
63309
+ if (code === undefined) {
63310
+ return false;
63311
+ }
63312
+ try {
63313
+ r.copyToClipboardOSC52(code.body);
63314
+ chrome.showToast("Copied to clipboard");
63315
+ return true;
63316
+ } catch {
63317
+ return false;
63318
+ }
63319
+ };
62929
63320
  const addBlock = (input3, options = {}) => {
62930
63321
  const id = blockMount.add(input3, options);
62931
63322
  nav.paint(id);
@@ -63917,17 +64308,6 @@ Staying in the current session.
63917
64308
  } catch {}
63918
64309
  }, 12000);
63919
64310
  };
63920
- const summarizeSubmittedLine = (line) => {
63921
- const normalized = line.replace(/\r\n/g, `
63922
- `).replace(/\r/g, `
63923
- `);
63924
- const count = normalized.split(`
63925
- `).filter((linePart) => linePart.length > 0).length;
63926
- if (count <= 1) {
63927
- return line;
63928
- }
63929
- return `[pasted ${count} lines]`;
63930
- };
63931
64311
  const spawnSideWorker = (question, displayQuestion = question) => {
63932
64312
  sideQueue.push({ question, displayQuestion });
63933
64313
  if (sideQueue.length > 1 || sideWorkerRunning) {
@@ -64140,8 +64520,7 @@ Staying in the current session.
64140
64520
  return;
64141
64521
  }
64142
64522
  case "copy": {
64143
- const target = newestBlock();
64144
- if (target === undefined || !copyBlock(target.id)) {
64523
+ if (!copyNewestOrLastCode()) {
64145
64524
  io.onSystem?.(`Nothing to copy yet.
64146
64525
  `);
64147
64526
  }
@@ -64400,8 +64779,7 @@ Staying in the current session.
64400
64779
  return;
64401
64780
  }
64402
64781
  if (command.name === "/copy") {
64403
- const target = newestBlock();
64404
- if (target === undefined || !copyBlock(target.id)) {
64782
+ if (!copyNewestOrLastCode()) {
64405
64783
  io.onSystem?.(`Nothing to copy yet.
64406
64784
  `);
64407
64785
  }
@@ -64884,17 +65262,6 @@ async function mountChatShell(otui, renderer, opts) {
64884
65262
  chrome.setStatus(label());
64885
65263
  sbModel.content = otui.t`${otui.dim(label())}`;
64886
65264
  };
64887
- const summarizeSubmittedLine = (line) => {
64888
- const normalized = line.replace(/\r\n/g, `
64889
- `).replace(/\r/g, `
64890
- `);
64891
- const count = normalized.split(`
64892
- `).filter((linePart) => linePart.length > 0).length;
64893
- if (count <= 1) {
64894
- return line;
64895
- }
64896
- return `[pasted ${count} lines]`;
64897
- };
64898
65265
  const bridge = createChatBridge({
64899
65266
  onAccepted: (line) => {
64900
65267
  const displayLine = line.startsWith("/") ? line : summarizeSubmittedLine(line);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.2.65",
3
+ "version": "0.2.66",
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": {