open-agents-ai 0.103.5 → 0.103.7

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/index.js +386 -55
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28448,7 +28448,77 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
28448
28448
  }
28449
28449
  return result;
28450
28450
  }
28451
- var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SKIP_DIRS;
28451
+ function loadUsageFile(filePath) {
28452
+ try {
28453
+ if (existsSync28(filePath)) {
28454
+ return JSON.parse(readFileSync20(filePath, "utf-8"));
28455
+ }
28456
+ } catch {
28457
+ }
28458
+ return { records: [] };
28459
+ }
28460
+ function saveUsageFile(filePath, data) {
28461
+ const dir = join38(filePath, "..");
28462
+ mkdirSync9(dir, { recursive: true });
28463
+ writeFileSync9(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
28464
+ }
28465
+ function recordUsage(kind, value, opts) {
28466
+ const now = (/* @__PURE__ */ new Date()).toISOString();
28467
+ const update = (filePath) => {
28468
+ const data = loadUsageFile(filePath);
28469
+ const existing = data.records.find((r) => r.kind === kind && r.value === value);
28470
+ if (existing) {
28471
+ existing.useCount++;
28472
+ existing.lastUsed = now;
28473
+ if (opts?.meta)
28474
+ existing.meta = { ...existing.meta, ...opts.meta };
28475
+ } else {
28476
+ data.records.push({
28477
+ value,
28478
+ kind,
28479
+ useCount: 1,
28480
+ firstUsed: now,
28481
+ lastUsed: now,
28482
+ meta: opts?.meta
28483
+ });
28484
+ }
28485
+ if (data.records.length > MAX_HISTORY_RECORDS) {
28486
+ data.records.sort((a, b) => new Date(b.lastUsed).getTime() - new Date(a.lastUsed).getTime());
28487
+ data.records = data.records.slice(0, MAX_HISTORY_RECORDS);
28488
+ }
28489
+ saveUsageFile(filePath, data);
28490
+ };
28491
+ update(join38(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
28492
+ if (opts?.repoRoot) {
28493
+ update(join38(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
28494
+ }
28495
+ }
28496
+ function loadUsageHistory(kind, repoRoot) {
28497
+ const globalPath = join38(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
28498
+ const globalData = loadUsageFile(globalPath);
28499
+ const localData = repoRoot ? loadUsageFile(join38(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
28500
+ const map = /* @__PURE__ */ new Map();
28501
+ for (const r of globalData.records) {
28502
+ if (r.kind !== kind)
28503
+ continue;
28504
+ map.set(r.value, { ...r, localUses: 0 });
28505
+ }
28506
+ for (const r of localData.records) {
28507
+ if (r.kind !== kind)
28508
+ continue;
28509
+ const existing = map.get(r.value);
28510
+ if (existing) {
28511
+ existing.localUses = r.useCount;
28512
+ if (new Date(r.lastUsed) > new Date(existing.lastUsed)) {
28513
+ existing.lastUsed = r.lastUsed;
28514
+ }
28515
+ } else {
28516
+ map.set(r.value, { ...r, localUses: r.useCount });
28517
+ }
28518
+ }
28519
+ return Array.from(map.values()).sort((a, b) => new Date(b.lastUsed).getTime() - new Date(a.lastUsed).getTime());
28520
+ }
28521
+ var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
28452
28522
  var init_oa_directory = __esm({
28453
28523
  "packages/cli/dist/tui/oa-directory.js"() {
28454
28524
  "use strict";
@@ -28486,6 +28556,8 @@ var init_oa_directory = __esm({
28486
28556
  ".idea",
28487
28557
  ".vscode"
28488
28558
  ]);
28559
+ USAGE_HISTORY_FILE = "usage-history.json";
28560
+ MAX_HISTORY_RECORDS = 50;
28489
28561
  }
28490
28562
  });
28491
28563
 
@@ -30007,6 +30079,185 @@ var init_setup = __esm({
30007
30079
  }
30008
30080
  });
30009
30081
 
30082
+ // packages/cli/dist/tui/tui-select.js
30083
+ function ansi3(code, text) {
30084
+ return isTTY3 ? `\x1B[${code}m${text}\x1B[0m` : text;
30085
+ }
30086
+ function fg2562(code, text) {
30087
+ return isTTY3 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
30088
+ }
30089
+ function defaultRenderRow(item, focused, isActive) {
30090
+ const marker = isActive ? selectColors.green("\u25CF") : focused ? selectColors.orange("\u25CF") : selectColors.dim("\u25CB");
30091
+ const label = focused ? selectColors.orange(selectColors.bold(item.label)) : isActive ? selectColors.green(item.label) : item.label;
30092
+ const detail = item.detail ? ` ${selectColors.dim(item.detail)}` : "";
30093
+ return ` ${marker} ${label}${detail}`;
30094
+ }
30095
+ function tuiSelect(opts) {
30096
+ const { items, title, rl } = opts;
30097
+ const renderRow = opts.renderRow ?? defaultRenderRow;
30098
+ const activeKey = opts.activeKey ?? null;
30099
+ const skipSet = new Set(opts.skipKeys ?? []);
30100
+ if (items.length === 0) {
30101
+ return Promise.resolve({ confirmed: false, key: null, index: -1 });
30102
+ }
30103
+ const isSkippable = (idx) => skipSet.has(items[idx].key);
30104
+ const findSelectable = (from, dir) => {
30105
+ let idx = from;
30106
+ while (idx >= 0 && idx < items.length && isSkippable(idx)) {
30107
+ idx += dir;
30108
+ }
30109
+ return idx >= 0 && idx < items.length ? idx : from;
30110
+ };
30111
+ let cursor = activeKey ? items.findIndex((i) => i.key === activeKey) : 0;
30112
+ if (cursor < 0)
30113
+ cursor = 0;
30114
+ cursor = findSelectable(cursor, 1);
30115
+ const termRows = process.stdout.rows ?? 24;
30116
+ const maxVisible = opts.maxVisible ?? Math.max(5, termRows - 6);
30117
+ let scrollOffset = Math.max(0, cursor - Math.floor(maxVisible / 2));
30118
+ let lastRenderedLines = 0;
30119
+ return new Promise((resolve31) => {
30120
+ const stdin = process.stdin;
30121
+ const hadRawMode = stdin.isRaw;
30122
+ const savedRlListeners = [];
30123
+ if (rl) {
30124
+ rl.pause();
30125
+ for (const event of ["keypress", "data"]) {
30126
+ const listeners = stdin.listeners(event);
30127
+ for (const fn of listeners) {
30128
+ savedRlListeners.push({ event, fn });
30129
+ stdin.removeListener(event, fn);
30130
+ }
30131
+ }
30132
+ }
30133
+ if (typeof stdin.setRawMode === "function") {
30134
+ stdin.setRawMode(true);
30135
+ }
30136
+ stdin.resume();
30137
+ process.stdout.write("\x1B[?25l");
30138
+ function clampScroll() {
30139
+ if (cursor < scrollOffset) {
30140
+ scrollOffset = cursor;
30141
+ } else if (cursor >= scrollOffset + maxVisible) {
30142
+ scrollOffset = cursor - maxVisible + 1;
30143
+ }
30144
+ scrollOffset = Math.max(0, Math.min(items.length - maxVisible, scrollOffset));
30145
+ if (scrollOffset < 0)
30146
+ scrollOffset = 0;
30147
+ }
30148
+ function render() {
30149
+ if (lastRenderedLines > 0) {
30150
+ process.stdout.write(`\x1B[${lastRenderedLines}A`);
30151
+ for (let i = 0; i < lastRenderedLines; i++) {
30152
+ process.stdout.write("\x1B[2K\n");
30153
+ }
30154
+ process.stdout.write(`\x1B[${lastRenderedLines}A`);
30155
+ }
30156
+ clampScroll();
30157
+ const lines = [];
30158
+ if (title) {
30159
+ lines.push(`
30160
+ ${selectColors.bold(title)}`);
30161
+ lines.push("");
30162
+ }
30163
+ if (scrollOffset > 0) {
30164
+ lines.push(` ${selectColors.dim(` \u25B2 ${scrollOffset} more`)}`);
30165
+ }
30166
+ const visibleEnd = Math.min(items.length, scrollOffset + maxVisible);
30167
+ for (let i = scrollOffset; i < visibleEnd; i++) {
30168
+ const item = items[i];
30169
+ if (isSkippable(i)) {
30170
+ lines.push(` ${item.label}`);
30171
+ continue;
30172
+ }
30173
+ const focused = i === cursor;
30174
+ const isActive = item.key === activeKey;
30175
+ lines.push(renderRow(item, focused, isActive));
30176
+ }
30177
+ const remaining = items.length - visibleEnd;
30178
+ if (remaining > 0) {
30179
+ lines.push(` ${selectColors.dim(` \u25BC ${remaining} more`)}`);
30180
+ }
30181
+ lines.push("");
30182
+ lines.push(` ${selectColors.dim("\u2191/\u2193 navigate Enter select Esc cancel")}`);
30183
+ lines.push("");
30184
+ const output = lines.join("\n");
30185
+ process.stdout.write(output);
30186
+ lastRenderedLines = lines.length;
30187
+ }
30188
+ function cleanup() {
30189
+ stdin.removeListener("data", onData);
30190
+ process.stdout.write("\x1B[?25h");
30191
+ if (lastRenderedLines > 0) {
30192
+ process.stdout.write(`\x1B[${lastRenderedLines}A`);
30193
+ for (let i = 0; i < lastRenderedLines; i++) {
30194
+ process.stdout.write("\x1B[2K\n");
30195
+ }
30196
+ process.stdout.write(`\x1B[${lastRenderedLines}A`);
30197
+ }
30198
+ if (typeof stdin.setRawMode === "function") {
30199
+ stdin.setRawMode(hadRawMode ?? false);
30200
+ }
30201
+ for (const { event, fn } of savedRlListeners) {
30202
+ stdin.on(event, fn);
30203
+ }
30204
+ if (rl) {
30205
+ rl.resume();
30206
+ rl.prompt(false);
30207
+ }
30208
+ }
30209
+ function onData(chunk) {
30210
+ const seq = chunk.toString("utf8");
30211
+ if (seq === "\x1B[A" || seq === "k") {
30212
+ const next = cursor - 1;
30213
+ if (next >= 0) {
30214
+ cursor = findSelectable(next, -1);
30215
+ render();
30216
+ }
30217
+ } else if (seq === "\x1B[B" || seq === "j") {
30218
+ const next = cursor + 1;
30219
+ if (next < items.length) {
30220
+ cursor = findSelectable(next, 1);
30221
+ render();
30222
+ }
30223
+ } else if (seq === "\x1B[H" || seq === "g") {
30224
+ cursor = findSelectable(0, 1);
30225
+ render();
30226
+ } else if (seq === "\x1B[F" || seq === "G") {
30227
+ cursor = findSelectable(items.length - 1, -1);
30228
+ render();
30229
+ } else if (seq === "\r" || seq === "\n") {
30230
+ if (!isSkippable(cursor)) {
30231
+ cleanup();
30232
+ resolve31({ confirmed: true, key: items[cursor].key, index: cursor });
30233
+ }
30234
+ } else if (seq === "\x1B" || seq === "\x1B\x1B" || seq === "q") {
30235
+ cleanup();
30236
+ resolve31({ confirmed: false, key: null, index: cursor });
30237
+ } else if (seq === "") {
30238
+ cleanup();
30239
+ resolve31({ confirmed: false, key: null, index: cursor });
30240
+ }
30241
+ }
30242
+ stdin.on("data", onData);
30243
+ render();
30244
+ });
30245
+ }
30246
+ var isTTY3, selectColors;
30247
+ var init_tui_select = __esm({
30248
+ "packages/cli/dist/tui/tui-select.js"() {
30249
+ "use strict";
30250
+ isTTY3 = process.stdout.isTTY ?? false;
30251
+ selectColors = {
30252
+ orange: (t) => fg2562(208, t),
30253
+ green: (t) => ansi3("32", t),
30254
+ dim: (t) => ansi3("2", t),
30255
+ bold: (t) => ansi3("1", t),
30256
+ cyan: (t) => ansi3("36", t)
30257
+ };
30258
+ }
30259
+ });
30260
+
30010
30261
  // packages/cli/dist/tui/commands.js
30011
30262
  async function handleSlashCommand(input, ctx) {
30012
30263
  const trimmed = input.trim();
@@ -30385,7 +30636,7 @@ async function handleSlashCommand(input, ctx) {
30385
30636
  if (arg) {
30386
30637
  await switchModel(arg, ctx, hasLocal);
30387
30638
  } else {
30388
- await showModelPicker(ctx);
30639
+ await showModelPicker(ctx, hasLocal);
30389
30640
  }
30390
30641
  return "handled";
30391
30642
  case "models":
@@ -31121,20 +31372,82 @@ async function listModels(ctx) {
31121
31372
  renderError(`Failed to fetch models: ${err instanceof Error ? err.message : String(err)}`);
31122
31373
  }
31123
31374
  }
31124
- async function showModelPicker(ctx) {
31375
+ async function showModelPicker(ctx, local = false) {
31125
31376
  try {
31126
31377
  const models = await fetchModels(ctx.config.backendUrl, ctx.config.apiKey);
31127
31378
  if (models.length === 0) {
31128
31379
  renderWarning("No models found.");
31129
31380
  return;
31130
31381
  }
31131
- renderModelList(models.map((m) => ({ name: m.name, size: m.size, modified: m.modified })), ctx.config.model);
31382
+ const items = [];
31383
+ const history = loadUsageHistory("model", ctx.repoRoot);
31384
+ const liveModelNames = new Set(models.map((m) => m.name));
31385
+ if (history.length > 0) {
31386
+ items.push({ key: "__header_recent__", label: c2.dim("\u2500\u2500 Recent \u2500\u2500"), detail: "" });
31387
+ for (const h of history.slice(0, 8)) {
31388
+ const uses = h.localUses > 0 ? `${h.useCount} uses (${h.localUses} local)` : `${h.useCount} uses`;
31389
+ const available = liveModelNames.has(h.value) ? "" : c2.yellow(" [offline]");
31390
+ items.push({
31391
+ key: h.value,
31392
+ label: h.value,
31393
+ detail: `${uses}${available}`
31394
+ });
31395
+ }
31396
+ items.push({ key: "__header_available__", label: c2.dim("\u2500\u2500 Available \u2500\u2500"), detail: "" });
31397
+ }
31398
+ const historyKeys = new Set(history.map((h) => h.value));
31399
+ for (const m of models) {
31400
+ if (history.length > 0 && historyKeys.has(m.name))
31401
+ continue;
31402
+ items.push({
31403
+ key: m.name,
31404
+ label: m.name,
31405
+ detail: [m.parameterSize, m.size, m.modified].filter(Boolean).join(" ")
31406
+ });
31407
+ }
31408
+ const result = await tuiSelect({
31409
+ items,
31410
+ activeKey: ctx.config.model,
31411
+ title: "Select Model",
31412
+ rl: ctx.rl,
31413
+ // Skip header rows
31414
+ skipKeys: ["__header_recent__", "__header_available__"]
31415
+ });
31416
+ if (!result.confirmed || !result.key) {
31417
+ renderInfo("Model selection cancelled.");
31418
+ return;
31419
+ }
31420
+ await switchModel(result.key, ctx, local);
31132
31421
  } catch (err) {
31133
31422
  renderError(`Failed to fetch models: ${err instanceof Error ? err.message : String(err)}`);
31134
31423
  }
31135
31424
  }
31136
31425
  async function handleEndpoint(arg, ctx, local = false) {
31137
31426
  if (!arg) {
31427
+ const history = loadUsageHistory("endpoint", ctx.repoRoot);
31428
+ if (history.length > 0) {
31429
+ const items = history.map((h) => {
31430
+ const provider2 = h.meta?.provider ?? detectProvider(h.value).label;
31431
+ const uses = h.localUses > 0 ? `${h.useCount} uses (${h.localUses} local)` : `${h.useCount} uses`;
31432
+ return {
31433
+ key: h.value,
31434
+ label: h.value,
31435
+ detail: `${provider2} ${uses}`
31436
+ };
31437
+ });
31438
+ const result = await tuiSelect({
31439
+ items,
31440
+ activeKey: ctx.config.backendUrl,
31441
+ title: "Select Endpoint",
31442
+ rl: ctx.rl
31443
+ });
31444
+ if (result.confirmed && result.key) {
31445
+ await handleEndpoint(result.key, ctx, local);
31446
+ return;
31447
+ }
31448
+ renderInfo("Endpoint selection cancelled.");
31449
+ return;
31450
+ }
31138
31451
  const currentProvider = detectProvider(ctx.config.backendUrl);
31139
31452
  process.stdout.write(`
31140
31453
  ${c2.bold("Current endpoint:")}
@@ -31238,6 +31551,15 @@ async function handleEndpoint(arg, ctx, local = false) {
31238
31551
  }
31239
31552
  ctx.saveSettings(endpointSettings);
31240
31553
  }
31554
+ recordUsage("endpoint", normalizedUrl, {
31555
+ repoRoot: local ? ctx.repoRoot : void 0,
31556
+ local,
31557
+ meta: {
31558
+ provider: provider.label,
31559
+ backendType,
31560
+ ...apiKey ? { authHint: apiKey.slice(0, 4) + "..." } : {}
31561
+ }
31562
+ });
31241
31563
  process.stdout.write(`
31242
31564
  ${c2.green("\u2714")} Endpoint updated and saved${local ? " (project-local)" : ""}:
31243
31565
  `);
@@ -31554,6 +31876,14 @@ async function switchModel(query, ctx, local = false) {
31554
31876
  if (local) {
31555
31877
  renderInfo("Saved as project-local override.");
31556
31878
  }
31879
+ recordUsage("model", finalModel, {
31880
+ repoRoot: local ? ctx.repoRoot : void 0,
31881
+ local,
31882
+ meta: {
31883
+ endpoint: ctx.config.backendUrl,
31884
+ parameterSize: match.parameterSize ?? ""
31885
+ }
31886
+ });
31557
31887
  if (ctx.setContextWindowSize) {
31558
31888
  const ctxSize = await queryContextSize(ctx.config.backendUrl, finalModel, ctx.config.apiKey);
31559
31889
  if (ctxSize) {
@@ -31583,6 +31913,7 @@ var init_commands = __esm({
31583
31913
  init_setup();
31584
31914
  init_listen();
31585
31915
  init_dist();
31916
+ init_tui_select();
31586
31917
  }
31587
31918
  });
31588
31919
 
@@ -32432,7 +32763,7 @@ var init_dist7 = __esm({
32432
32763
 
32433
32764
  // packages/cli/dist/tui/carousel.js
32434
32765
  function fg(code, text) {
32435
- return isTTY3 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
32766
+ return isTTY4 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
32436
32767
  }
32437
32768
  function displayWidth(str) {
32438
32769
  let w = 0;
@@ -32470,11 +32801,11 @@ function createRow(phraseIndices, speed, direction, bank) {
32470
32801
  const phrases = phraseIndices.map((i) => bank[i % bank.length]);
32471
32802
  return { phrases, offset: 0, speed, direction, renderedPlain: "" };
32472
32803
  }
32473
- var isTTY3, PHRASES, Carousel;
32804
+ var isTTY4, PHRASES, Carousel;
32474
32805
  var init_carousel = __esm({
32475
32806
  "packages/cli/dist/tui/carousel.js"() {
32476
32807
  "use strict";
32477
- isTTY3 = process.stdout.isTTY ?? false;
32808
+ isTTY4 = process.stdout.isTTY ?? false;
32478
32809
  PHRASES = [
32479
32810
  // English
32480
32811
  { text: "freedom of information", color: 39 },
@@ -32583,7 +32914,7 @@ var init_carousel = __esm({
32583
32914
  * Sets scroll region to row 5+ for all content/readline.
32584
32915
  */
32585
32916
  start() {
32586
- if (!isTTY3)
32917
+ if (!isTTY4)
32587
32918
  return 0;
32588
32919
  this.started = true;
32589
32920
  const termRows = process.stdout.rows ?? 24;
@@ -32619,7 +32950,7 @@ var init_carousel = __esm({
32619
32950
  * Row 4 is left blank as a separator.
32620
32951
  */
32621
32952
  renderFrame() {
32622
- if (!isTTY3)
32953
+ if (!isTTY4)
32623
32954
  return;
32624
32955
  let buf = "\x1B7";
32625
32956
  buf += "\x1B[?7l";
@@ -32699,7 +33030,7 @@ var init_carousel = __esm({
32699
33030
  process.stdout.removeListener("resize", this.resizeHandler);
32700
33031
  this.resizeHandler = null;
32701
33032
  }
32702
- if (!isTTY3 || !this.started)
33033
+ if (!isTTY4 || !this.started)
32703
33034
  return;
32704
33035
  let buf = "\x1B7";
32705
33036
  for (let i = 0; i < this.reservedRows; i++) {
@@ -34859,26 +35190,26 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
34859
35190
  });
34860
35191
 
34861
35192
  // packages/cli/dist/tui/stream-renderer.js
34862
- function fg2562(code, text) {
34863
- return isTTY4 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
35193
+ function fg2563(code, text) {
35194
+ return isTTY5 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
34864
35195
  }
34865
35196
  function dimText(text) {
34866
- return isTTY4 ? `\x1B[2m${text}\x1B[0m` : text;
35197
+ return isTTY5 ? `\x1B[2m${text}\x1B[0m` : text;
34867
35198
  }
34868
35199
  function italicText(text) {
34869
- return isTTY4 ? `\x1B[3m${text}\x1B[0m` : text;
35200
+ return isTTY5 ? `\x1B[3m${text}\x1B[0m` : text;
34870
35201
  }
34871
35202
  function dimItalic(text) {
34872
- return isTTY4 ? `\x1B[2;3m${text}\x1B[0m` : text;
35203
+ return isTTY5 ? `\x1B[2;3m${text}\x1B[0m` : text;
34873
35204
  }
34874
35205
  function boldText(text) {
34875
- return isTTY4 ? `\x1B[1m${text}\x1B[0m` : text;
35206
+ return isTTY5 ? `\x1B[1m${text}\x1B[0m` : text;
34876
35207
  }
34877
- var isTTY4, PASTEL, StreamRenderer;
35208
+ var isTTY5, PASTEL, StreamRenderer;
34878
35209
  var init_stream_renderer = __esm({
34879
35210
  "packages/cli/dist/tui/stream-renderer.js"() {
34880
35211
  "use strict";
34881
- isTTY4 = process.stdout.isTTY ?? false;
35212
+ isTTY5 = process.stdout.isTTY ?? false;
34882
35213
  PASTEL = {
34883
35214
  key: 222,
34884
35215
  // light gold — JSON keys
@@ -35192,12 +35523,12 @@ var init_stream_renderer = __esm({
35192
35523
  const colorKey = dim ? PASTEL.toolArg : PASTEL.key;
35193
35524
  const colorStr = dim ? PASTEL.toolArg : PASTEL.string;
35194
35525
  let result = line;
35195
- result = result.replace(/"([^"]*)"(\s*:)/g, (_m, key, colon) => fg2562(colorKey, `"${key}"`) + fg2562(PASTEL.colon, colon));
35196
- result = result.replace(/(:\s*)"([^"]*)"/g, (_m, prefix, val) => fg2562(PASTEL.colon, prefix) + fg2562(colorStr, `"${val}"`));
35197
- result = result.replace(/(:\s*)(\d+\.?\d*)/g, (_m, prefix, num) => fg2562(PASTEL.colon, prefix) + fg2562(PASTEL.number, num));
35198
- result = result.replace(/(:\s*)(true|false)/g, (_m, prefix, bool) => fg2562(PASTEL.colon, prefix) + fg2562(PASTEL.boolean, bool));
35199
- result = result.replace(/(:\s*)(null)/g, (_m, prefix, n) => fg2562(PASTEL.colon, prefix) + fg2562(PASTEL.null, n));
35200
- result = result.replace(/([{}[\]])/g, (_m, b) => fg2562(PASTEL.bracket, b));
35526
+ result = result.replace(/"([^"]*)"(\s*:)/g, (_m, key, colon) => fg2563(colorKey, `"${key}"`) + fg2563(PASTEL.colon, colon));
35527
+ result = result.replace(/(:\s*)"([^"]*)"/g, (_m, prefix, val) => fg2563(PASTEL.colon, prefix) + fg2563(colorStr, `"${val}"`));
35528
+ result = result.replace(/(:\s*)(\d+\.?\d*)/g, (_m, prefix, num) => fg2563(PASTEL.colon, prefix) + fg2563(PASTEL.number, num));
35529
+ result = result.replace(/(:\s*)(true|false)/g, (_m, prefix, bool) => fg2563(PASTEL.colon, prefix) + fg2563(PASTEL.boolean, bool));
35530
+ result = result.replace(/(:\s*)(null)/g, (_m, prefix, n) => fg2563(PASTEL.colon, prefix) + fg2563(PASTEL.null, n));
35531
+ result = result.replace(/([{}[\]])/g, (_m, b) => fg2563(PASTEL.bracket, b));
35201
35532
  return dim ? dimText(result) : result;
35202
35533
  }
35203
35534
  /**
@@ -35205,13 +35536,13 @@ var init_stream_renderer = __esm({
35205
35536
  */
35206
35537
  highlightCode(line) {
35207
35538
  let result = line;
35208
- result = result.replace(/"([^"]*)"/g, (_m, s) => fg2562(PASTEL.string, `"${s}"`));
35209
- result = result.replace(/'([^']*)'/g, (_m, s) => fg2562(PASTEL.string, `'${s}'`));
35210
- result = result.replace(/\b(\d+\.?\d*)\b/g, (_m, n) => fg2562(PASTEL.number, n));
35211
- result = result.replace(/\b(true|false|null|undefined|None|True|False)\b/g, (_m, kw) => fg2562(PASTEL.boolean, kw));
35212
- result = result.replace(/\b(function|const|let|var|return|if|else|for|while|import|export|from|class|async|await|def|self|try|catch|finally|throw|new|typeof|instanceof|type|interface|enum|struct|impl|fn|pub|mod|use|match|trait|where|mut|ref|move|yield|switch|case|default|break|continue|do|in|of|extends|implements|super|this|static|abstract|override|readonly|declare|namespace|package|func|go|chan|select|defer|range|map)\b/g, (_m, kw) => fg2562(PASTEL.keyword, kw));
35213
- result = result.replace(/:\s*([A-Z]\w*)/g, (_m, t) => ": " + fg2562(147, t));
35214
- result = result.replace(/(\/\/.*$|#.*$)/gm, (_m, cm) => fg2562(PASTEL.comment, cm));
35539
+ result = result.replace(/"([^"]*)"/g, (_m, s) => fg2563(PASTEL.string, `"${s}"`));
35540
+ result = result.replace(/'([^']*)'/g, (_m, s) => fg2563(PASTEL.string, `'${s}'`));
35541
+ result = result.replace(/\b(\d+\.?\d*)\b/g, (_m, n) => fg2563(PASTEL.number, n));
35542
+ result = result.replace(/\b(true|false|null|undefined|None|True|False)\b/g, (_m, kw) => fg2563(PASTEL.boolean, kw));
35543
+ result = result.replace(/\b(function|const|let|var|return|if|else|for|while|import|export|from|class|async|await|def|self|try|catch|finally|throw|new|typeof|instanceof|type|interface|enum|struct|impl|fn|pub|mod|use|match|trait|where|mut|ref|move|yield|switch|case|default|break|continue|do|in|of|extends|implements|super|this|static|abstract|override|readonly|declare|namespace|package|func|go|chan|select|defer|range|map)\b/g, (_m, kw) => fg2563(PASTEL.keyword, kw));
35544
+ result = result.replace(/:\s*([A-Z]\w*)/g, (_m, t) => ": " + fg2563(147, t));
35545
+ result = result.replace(/(\/\/.*$|#.*$)/gm, (_m, cm) => fg2563(PASTEL.comment, cm));
35215
35546
  return result;
35216
35547
  }
35217
35548
  // -------------------------------------------------------------------------
@@ -35223,30 +35554,30 @@ var init_stream_renderer = __esm({
35223
35554
  */
35224
35555
  highlightDiff(line) {
35225
35556
  if (/^[-]{3}\s/.test(line) || /^[+]{3}\s/.test(line)) {
35226
- return boldText(fg2562(PASTEL.diffMeta, line));
35557
+ return boldText(fg2563(PASTEL.diffMeta, line));
35227
35558
  }
35228
35559
  if (line.startsWith("@@")) {
35229
- return fg2562(PASTEL.diffHunk, line);
35560
+ return fg2563(PASTEL.diffHunk, line);
35230
35561
  }
35231
35562
  if (line.startsWith("diff ") || line.startsWith("index ")) {
35232
- return fg2562(PASTEL.diffMeta, line);
35563
+ return fg2563(PASTEL.diffMeta, line);
35233
35564
  }
35234
35565
  if (line.startsWith("+")) {
35235
- return fg2562(PASTEL.diffAdded, line);
35566
+ return fg2563(PASTEL.diffAdded, line);
35236
35567
  }
35237
35568
  if (line.startsWith("-")) {
35238
- return fg2562(PASTEL.diffRemoved, line);
35569
+ return fg2563(PASTEL.diffRemoved, line);
35239
35570
  }
35240
35571
  if (/^\s*\d+\s*[+-]\s/.test(line)) {
35241
35572
  const match = line.match(/^(\s*\d+\s*)([+-])(\s.*)$/);
35242
35573
  if (match) {
35243
- const num = fg2562(PASTEL.diffContext, match[1]);
35244
- const sign = match[2] === "+" ? fg2562(PASTEL.diffAdded, "+") : fg2562(PASTEL.diffRemoved, "-");
35245
- const rest = match[2] === "+" ? fg2562(PASTEL.diffAdded, match[3]) : fg2562(PASTEL.diffRemoved, match[3]);
35574
+ const num = fg2563(PASTEL.diffContext, match[1]);
35575
+ const sign = match[2] === "+" ? fg2563(PASTEL.diffAdded, "+") : fg2563(PASTEL.diffRemoved, "-");
35576
+ const rest = match[2] === "+" ? fg2563(PASTEL.diffAdded, match[3]) : fg2563(PASTEL.diffRemoved, match[3]);
35246
35577
  return num + sign + rest;
35247
35578
  }
35248
35579
  }
35249
- return fg2562(PASTEL.diffContext, line);
35580
+ return fg2563(PASTEL.diffContext, line);
35250
35581
  }
35251
35582
  // -------------------------------------------------------------------------
35252
35583
  // Shell / bash highlighting
@@ -35256,16 +35587,16 @@ var init_stream_renderer = __esm({
35256
35587
  */
35257
35588
  highlightShell(line) {
35258
35589
  if (/^\s*#/.test(line)) {
35259
- return fg2562(PASTEL.comment, line);
35590
+ return fg2563(PASTEL.comment, line);
35260
35591
  }
35261
35592
  let result = line;
35262
- result = result.replace(/"([^"]*)"/g, (_m, s) => fg2562(PASTEL.string, `"${s}"`));
35263
- result = result.replace(/'([^']*)'/g, (_m, s) => fg2562(PASTEL.string, `'${s}'`));
35264
- result = result.replace(/(\$\{[^}]+\}|\$[A-Za-z_]\w*|\$[0-9?@#*!$-])/g, (_m, v) => fg2562(PASTEL.shellVar, v));
35265
- result = result.replace(/((?:^|\s))(--?[a-zA-Z][\w-]*)/g, (_m, ws, flag) => ws + fg2562(PASTEL.shellFlag, flag));
35266
- result = result.replace(/(\|{1,2}|>{1,2}|<{1,2}|&{1,2}|;)/g, (_m, op) => fg2562(PASTEL.shellOp, op));
35267
- result = result.replace(/^(\s*)(npm|npx|node|pnpm|yarn|git|docker|kubectl|curl|wget|cat|grep|find|ls|cd|cp|mv|rm|mkdir|chmod|chown|echo|printf|sed|awk|sort|uniq|head|tail|wc|tar|gzip|make|cargo|go|pip|python|python3|ruby|gem|brew|apt|yum|dnf|pacman|sudo|ssh|scp|rsync|man)\b/, (_m, ws, cmd) => ws + boldText(fg2562(PASTEL.keyword, cmd)));
35268
- result = result.replace(/(#[^{].*$)/gm, (_m, cm) => fg2562(PASTEL.comment, cm));
35593
+ result = result.replace(/"([^"]*)"/g, (_m, s) => fg2563(PASTEL.string, `"${s}"`));
35594
+ result = result.replace(/'([^']*)'/g, (_m, s) => fg2563(PASTEL.string, `'${s}'`));
35595
+ result = result.replace(/(\$\{[^}]+\}|\$[A-Za-z_]\w*|\$[0-9?@#*!$-])/g, (_m, v) => fg2563(PASTEL.shellVar, v));
35596
+ result = result.replace(/((?:^|\s))(--?[a-zA-Z][\w-]*)/g, (_m, ws, flag) => ws + fg2563(PASTEL.shellFlag, flag));
35597
+ result = result.replace(/(\|{1,2}|>{1,2}|<{1,2}|&{1,2}|;)/g, (_m, op) => fg2563(PASTEL.shellOp, op));
35598
+ result = result.replace(/^(\s*)(npm|npx|node|pnpm|yarn|git|docker|kubectl|curl|wget|cat|grep|find|ls|cd|cp|mv|rm|mkdir|chmod|chown|echo|printf|sed|awk|sort|uniq|head|tail|wc|tar|gzip|make|cargo|go|pip|python|python3|ruby|gem|brew|apt|yum|dnf|pacman|sudo|ssh|scp|rsync|man)\b/, (_m, ws, cmd) => ws + boldText(fg2563(PASTEL.keyword, cmd)));
35599
+ result = result.replace(/(#[^{].*$)/gm, (_m, cm) => fg2563(PASTEL.comment, cm));
35269
35600
  return result;
35270
35601
  }
35271
35602
  // -------------------------------------------------------------------------
@@ -35280,23 +35611,23 @@ var init_stream_renderer = __esm({
35280
35611
  const level = headingMatch[1].length;
35281
35612
  const text = headingMatch[2];
35282
35613
  const colors = [PASTEL.heading1, PASTEL.heading2, PASTEL.heading3, PASTEL.heading3, 183, 183];
35283
- return boldText(fg2562(colors[level - 1] ?? 147, text));
35614
+ return boldText(fg2563(colors[level - 1] ?? 147, text));
35284
35615
  }
35285
35616
  if (/^[-*_]{3,}\s*$/.test(line)) {
35286
35617
  const w = (process.stdout.columns ?? 80) - 10;
35287
- return fg2562(PASTEL.hr, "\u2500".repeat(Math.min(w, 60)));
35618
+ return fg2563(PASTEL.hr, "\u2500".repeat(Math.min(w, 60)));
35288
35619
  }
35289
35620
  if (/^>\s?/.test(line)) {
35290
35621
  const content = line.replace(/^>\s?/, "");
35291
- return fg2562(PASTEL.blockquote, "\u2502 ") + italicText(fg2562(PASTEL.blockquote, this.highlightInline(content)));
35622
+ return fg2563(PASTEL.blockquote, "\u2502 ") + italicText(fg2563(PASTEL.blockquote, this.highlightInline(content)));
35292
35623
  }
35293
35624
  const ulMatch = line.match(/^(\s*)([-*+])\s+(.*)/);
35294
35625
  if (ulMatch) {
35295
- return ulMatch[1] + fg2562(PASTEL.blockquote, "\u2022") + " " + this.highlightInline(ulMatch[3]);
35626
+ return ulMatch[1] + fg2563(PASTEL.blockquote, "\u2022") + " " + this.highlightInline(ulMatch[3]);
35296
35627
  }
35297
35628
  const olMatch = line.match(/^(\s*)(\d+[.)])\s+(.*)/);
35298
35629
  if (olMatch) {
35299
- return olMatch[1] + fg2562(PASTEL.blockquote, olMatch[2]) + " " + this.highlightInline(olMatch[3]);
35630
+ return olMatch[1] + fg2563(PASTEL.blockquote, olMatch[2]) + " " + this.highlightInline(olMatch[3]);
35300
35631
  }
35301
35632
  return this.highlightInline(line);
35302
35633
  }
@@ -35305,11 +35636,11 @@ var init_stream_renderer = __esm({
35305
35636
  */
35306
35637
  highlightInline(text) {
35307
35638
  let result = text;
35308
- result = result.replace(/`([^`]+)`/g, (_m, code) => fg2562(PASTEL.inlineCode, code));
35639
+ result = result.replace(/`([^`]+)`/g, (_m, code) => fg2563(PASTEL.inlineCode, code));
35309
35640
  result = result.replace(/\*{3}([^*]+)\*{3}/g, (_m, t) => boldText(italicText(t)));
35310
35641
  result = result.replace(/\*{2}([^*]+)\*{2}/g, (_m, t) => boldText(t));
35311
35642
  result = result.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_m, t) => italicText(t));
35312
- result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, label, url) => boldText(fg2562(PASTEL.link, label)) + " " + dimText(fg2562(PASTEL.link, `(${url})`)));
35643
+ result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, label, url) => boldText(fg2563(PASTEL.link, label)) + " " + dimText(fg2563(PASTEL.link, `(${url})`)));
35313
35644
  result = result.replace(/__([^_]+)__/g, (_m, t) => boldText(t));
35314
35645
  result = result.replace(/(?<!_)_([^_]+)_(?!_)/g, (_m, t) => italicText(t));
35315
35646
  result = result.replace(/~~([^~]+)~~/g, (_m, t) => dimText(t));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.5",
3
+ "version": "0.103.7",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",