open-agents-ai 0.184.68 → 0.184.70

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 +218 -50
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -41,6 +41,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
41
41
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
42
42
 
43
43
  // packages/cli/dist/config.js
44
+ var config_exports = {};
45
+ __export(config_exports, {
46
+ DEFAULT_CONFIG: () => DEFAULT_CONFIG,
47
+ loadConfig: () => loadConfig,
48
+ mergeConfig: () => mergeConfig,
49
+ setConfigValue: () => setConfigValue
50
+ });
44
51
  import { readFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
45
52
  import { homedir } from "node:os";
46
53
  import { join } from "node:path";
@@ -28392,21 +28399,35 @@ ${transcript}`
28392
28399
  thinking;
28393
28400
  /** Abort signal — set by the runner so /stop can cancel in-flight requests */
28394
28401
  _abortSignal = null;
28402
+ /** Multi-key pool — round-robin rotation per request for load distribution */
28403
+ _keyPool = [];
28404
+ _keyIndex = 0;
28395
28405
  constructor(baseUrl, model, apiKey, thinking) {
28396
28406
  this.baseUrl = normalizeBaseUrl(baseUrl);
28397
28407
  this.model = model;
28398
28408
  this.apiKey = apiKey ?? "";
28399
28409
  this.thinking = thinking ?? true;
28400
28410
  }
28411
+ /** Set multiple API keys for round-robin rotation per request */
28412
+ setKeyPool(keys) {
28413
+ this._keyPool = keys.filter((k) => k.length > 0);
28414
+ this._keyIndex = 0;
28415
+ }
28401
28416
  /** Set the abort signal from the runner (called at run start) */
28402
28417
  setAbortSignal(signal) {
28403
28418
  this._abortSignal = signal;
28404
28419
  }
28405
- /** Build auth headers — all providers use standard Bearer token auth. */
28420
+ /** Build auth headers — all providers use standard Bearer token auth.
28421
+ * When a key pool is set, round-robins through keys per request. */
28406
28422
  authHeaders() {
28407
28423
  const headers = { "Content-Type": "application/json" };
28408
- if (this.apiKey) {
28409
- headers["Authorization"] = `Bearer ${this.apiKey}`;
28424
+ let key = this.apiKey;
28425
+ if (this._keyPool.length > 0) {
28426
+ key = this._keyPool[this._keyIndex % this._keyPool.length];
28427
+ this._keyIndex++;
28428
+ }
28429
+ if (key) {
28430
+ headers["Authorization"] = `Bearer ${key}`;
28410
28431
  }
28411
28432
  return headers;
28412
28433
  }
@@ -41141,56 +41162,50 @@ async function doSetup(config, rl) {
41141
41162
  `);
41142
41163
  }
41143
41164
  const score = computeInferenceScore(specs);
41144
- const w = 24;
41145
41165
  const bw = 30;
41146
- process.stdout.write(`
41147
- ${c2.dim("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510")}
41148
- `);
41149
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.bold(" Inference Capability")} ${c2.dim("\u2502")}
41150
- `);
41151
- process.stdout.write(` ${c2.dim("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524")}
41152
- `);
41153
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.bold("Overall")} ${c2.dim("\u2502")}
41154
- `);
41155
- process.stdout.write(` ${c2.dim("\u2502")} ${renderScoreBar(score.overall, bw)} ${c2.bold(String(score.overall).padStart(3))}${c2.dim("/100")} ${c2.dim("\u2502")}
41156
- `);
41157
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.dim(score.summary.padEnd(46))} ${c2.dim("\u2502")}
41158
- `);
41159
- process.stdout.write(` ${c2.dim("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524")}
41160
- `);
41161
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.bold("Memory")} ${c2.dim(`${specs.totalRamGB.toFixed(0)} GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)} GB VRAM` : ""))}${" ".repeat(Math.max(0, 27 - (`${specs.totalRamGB.toFixed(0)} GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)} GB VRAM` : "")).length))} ${c2.dim("\u2502")}
41162
- `);
41163
- process.stdout.write(` ${c2.dim("\u2502")} ${renderScoreBar(score.memory, w)} ${String(score.memory).padStart(3)} ${c2.dim("\u2502")}
41164
- `);
41165
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.dim("\u2502")}
41166
- `);
41167
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.bold("Compute")} ${c2.dim(specs.gpuVramGB > 0 ? specs.gpuName || "NVIDIA GPU" : "CPU only")}${" ".repeat(Math.max(0, 28 - (specs.gpuVramGB > 0 ? specs.gpuName || "NVIDIA GPU" : "CPU only").length))} ${c2.dim("\u2502")}
41168
- `);
41169
- process.stdout.write(` ${c2.dim("\u2502")} ${renderScoreBar(score.compute, w)} ${String(score.compute).padStart(3)} ${c2.dim("\u2502")}
41170
- `);
41171
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.dim("\u2502")}
41172
- `);
41173
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.bold("Speed")} ${c2.dim(specs.gpuVramGB > 0 ? "GPU accelerated" : "CPU inference")}${" ".repeat(Math.max(0, 28 - (specs.gpuVramGB > 0 ? "GPU accelerated" : "CPU inference").length))} ${c2.dim("\u2502")}
41174
- `);
41175
- process.stdout.write(` ${c2.dim("\u2502")} ${renderScoreBar(score.speed, w)} ${String(score.speed).padStart(3)} ${c2.dim("\u2502")}
41176
- `);
41177
- process.stdout.write(` ${c2.dim("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524")}
41178
- `);
41179
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.bold(" Model Compatibility")} ${c2.dim("\u2502")}
41180
- `);
41166
+ const sw = 24;
41167
+ const boxW = 52;
41168
+ const boxLine = (content, visLen) => {
41169
+ const pad = Math.max(0, boxW - visLen);
41170
+ return ` ${c2.dim("\u2502")}${content}${" ".repeat(pad)}${c2.dim("\u2502")}
41171
+ `;
41172
+ };
41173
+ const hLine = (ch) => ` ${c2.dim(ch + "\u2500".repeat(boxW) + (ch === "\u250C" ? "\u2510" : ch === "\u251C" ? "\u2524" : "\u2518"))}
41174
+ `;
41175
+ process.stdout.write("\n");
41176
+ process.stdout.write(hLine("\u250C"));
41177
+ process.stdout.write(boxLine(` ${c2.bold("Inference Capability")}`, 22));
41178
+ process.stdout.write(hLine("\u251C"));
41179
+ process.stdout.write(boxLine(` ${c2.bold("Overall")}`, 9));
41180
+ const overallBar = renderScoreBar(score.overall, bw);
41181
+ const overallLabel = `${String(score.overall).padStart(3)}/100`;
41182
+ process.stdout.write(boxLine(` ${overallBar} ${c2.bold(overallLabel)}`, 2 + bw + 1 + overallLabel.length));
41183
+ process.stdout.write(boxLine(` ${c2.dim(score.summary)}`, 2 + score.summary.length));
41184
+ process.stdout.write(hLine("\u251C"));
41185
+ const memLabel = `${specs.totalRamGB.toFixed(0)} GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)} GB VRAM` : "");
41186
+ process.stdout.write(boxLine(` ${c2.bold("Memory")} ${c2.dim(memLabel)}`, 11 + memLabel.length));
41187
+ process.stdout.write(boxLine(` ${renderScoreBar(score.memory, sw)} ${String(score.memory).padStart(3)}`, 2 + sw + 1 + 3));
41188
+ process.stdout.write(boxLine("", 0));
41189
+ const gpuLabel = specs.gpuVramGB > 0 ? specs.gpuName || "NVIDIA GPU" : "CPU only";
41190
+ process.stdout.write(boxLine(` ${c2.bold("Compute")} ${c2.dim(gpuLabel)}`, 11 + gpuLabel.length));
41191
+ process.stdout.write(boxLine(` ${renderScoreBar(score.compute, sw)} ${String(score.compute).padStart(3)}`, 2 + sw + 1 + 3));
41192
+ process.stdout.write(boxLine("", 0));
41193
+ const speedLabel = specs.gpuVramGB > 0 ? "GPU accelerated" : "CPU inference";
41194
+ process.stdout.write(boxLine(` ${c2.bold("Speed")} ${c2.dim(speedLabel)}`, 11 + speedLabel.length));
41195
+ process.stdout.write(boxLine(` ${renderScoreBar(score.speed, sw)} ${String(score.speed).padStart(3)}`, 2 + sw + 1 + 3));
41196
+ process.stdout.write(hLine("\u251C"));
41197
+ process.stdout.write(boxLine(` ${c2.bold("Model Compatibility")}`, 21));
41181
41198
  for (const compat of score.modelCompat) {
41182
41199
  const icon = compat.fits ? c2.green("\u2714") : c2.red("\u2716");
41183
41200
  const tag = compat.fits ? compat.tag : c2.dim(compat.tag);
41184
41201
  const note = c2.dim(compat.note);
41185
- const visTag = compat.tag;
41186
- const visNote = compat.note;
41187
- const pad = Math.max(0, 44 - 2 - visTag.length - 1 - visNote.length);
41188
- process.stdout.write(` ${c2.dim("\u2502")} ${icon} ${tag} ${" ".repeat(pad)}${note} ${c2.dim("\u2502")}
41202
+ const visLen = 2 + 1 + 1 + compat.tag.length;
41203
+ const notePad = Math.max(1, boxW - visLen - compat.note.length);
41204
+ process.stdout.write(` ${c2.dim("\u2502")} ${icon} ${tag}${" ".repeat(notePad)}${note}${c2.dim("\u2502")}
41189
41205
  `);
41190
41206
  }
41191
- process.stdout.write(` ${c2.dim("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")}
41192
-
41193
- `);
41207
+ process.stdout.write(hLine("\u2514"));
41208
+ process.stdout.write("\n");
41194
41209
  let hasPython = hasCmd("python3") || hasCmd("python");
41195
41210
  if (!hasPython) {
41196
41211
  process.stdout.write(` ${c2.yellow("\u26A0")} Python3 not found (needed for vision, OCR, browser automation).
@@ -47776,6 +47791,19 @@ async function handleSlashCommand(input, ctx) {
47776
47791
  case "upgrade":
47777
47792
  await handleUpdate(arg, ctx);
47778
47793
  return "handled";
47794
+ case "setup":
47795
+ case "wizard": {
47796
+ const setupModel = await runSetupWizard(ctx.config);
47797
+ if (setupModel) {
47798
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
47799
+ const freshConfig = loadConfig2();
47800
+ Object.assign(ctx.config, freshConfig, { model: setupModel });
47801
+ renderInfo(`Setup complete \u2014 model set to ${setupModel}`);
47802
+ } else {
47803
+ renderInfo("Setup cancelled \u2014 no changes made.");
47804
+ }
47805
+ return "handled";
47806
+ }
47779
47807
  case "voice": {
47780
47808
  const save = (settings) => {
47781
47809
  ctx.saveSettings(settings);
@@ -49955,6 +49983,85 @@ async function handleEndpoint(arg, ctx, local = false) {
49955
49983
  await handleSponsoredEndpoint(ctx, local);
49956
49984
  return;
49957
49985
  }
49986
+ if (arg.startsWith("add ")) {
49987
+ const addArg = arg.slice(4).replace(/\u2014/g, "--").replace(/\u2013/g, "--");
49988
+ const addParts = addArg.split(/\s+/);
49989
+ const addUrl = addParts[0];
49990
+ const addAuthIdx = addParts.indexOf("--auth") !== -1 ? addParts.indexOf("--auth") : addParts.indexOf("-auth");
49991
+ const addKey = addAuthIdx !== -1 && addParts[addAuthIdx + 1] ? addParts[addAuthIdx + 1] : "";
49992
+ if (!addKey) {
49993
+ renderError("Usage: /endpoint add <url> --auth <key>");
49994
+ return;
49995
+ }
49996
+ const normalizedAddUrl = normalizeBaseUrl(addUrl);
49997
+ const suffix = addKey.slice(-4);
49998
+ const provider2 = detectProvider(addUrl);
49999
+ const settings = resolveSettings(ctx.repoRoot);
50000
+ const pool = settings.endpointKeys ?? [];
50001
+ if (pool.some((k) => k.suffix === suffix)) {
50002
+ renderWarning(`Key ending ...${suffix} is already in the pool.`);
50003
+ return;
50004
+ }
50005
+ pool.push({ key: addKey, suffix });
50006
+ const backendType2 = provider2.id === "ollama" ? "ollama" : "vllm";
50007
+ ctx.setEndpoint(normalizedAddUrl, backendType2, addKey);
50008
+ setConfigValue("backendUrl", normalizedAddUrl);
50009
+ setConfigValue("backendType", backendType2);
50010
+ setConfigValue("apiKey", addKey);
50011
+ ctx.saveSettings({ backendUrl: normalizedAddUrl, backendType: backendType2, apiKey: addKey, endpointKeys: pool });
50012
+ saveGlobalSettings({ endpointKeys: pool });
50013
+ if (ctx.setKeyPool)
50014
+ ctx.setKeyPool(pool.map((k) => k.key));
50015
+ recordUsage("endpoint", normalizedAddUrl, {
50016
+ meta: { provider: provider2.label, backendType: backendType2, authHint: addKey.slice(0, 4) + "...", authKey: addKey }
50017
+ });
50018
+ renderInfo(`Added key ...${suffix} to pool (${pool.length} key${pool.length > 1 ? "s" : ""} total)`);
50019
+ for (const k of pool) {
50020
+ process.stdout.write(` ${c2.dim("\u25CF")} ${provider2.label}-${k.suffix} ${c2.dim(k.key.slice(0, 4) + "..." + k.key.slice(-4))}
50021
+ `);
50022
+ }
50023
+ process.stdout.write("\n");
50024
+ return;
50025
+ }
50026
+ if (arg === "keys" || arg === "pool") {
50027
+ const settings = resolveSettings(ctx.repoRoot);
50028
+ const pool = settings.endpointKeys ?? [];
50029
+ if (pool.length === 0) {
50030
+ renderInfo("No key pool configured. Use /endpoint add <url> --auth <key> to add keys.");
50031
+ return;
50032
+ }
50033
+ const provider2 = detectProvider(ctx.config.backendUrl);
50034
+ renderInfo(`Key pool for ${c2.bold(ctx.config.backendUrl)} (${pool.length} key${pool.length > 1 ? "s" : ""}):`);
50035
+ for (const k of pool) {
50036
+ process.stdout.write(` ${c2.green("\u25CF")} ${provider2.label}-${k.suffix} ${c2.dim(k.key.slice(0, 4) + "..." + k.key.slice(-4))}
50037
+ `);
50038
+ }
50039
+ process.stdout.write(`
50040
+ ${c2.dim("Remove: /endpoint remove <suffix>")}
50041
+
50042
+ `);
50043
+ return;
50044
+ }
50045
+ if (arg.startsWith("remove ") || arg.startsWith("rm ")) {
50046
+ const suffix = arg.split(/\s+/)[1];
50047
+ const settings = resolveSettings(ctx.repoRoot);
50048
+ const pool = settings.endpointKeys ?? [];
50049
+ const idx = pool.findIndex((k) => k.suffix === suffix);
50050
+ if (idx === -1) {
50051
+ renderError(`No key with suffix "${suffix}" in the pool.`);
50052
+ return;
50053
+ }
50054
+ pool.splice(idx, 1);
50055
+ ctx.saveSettings({ endpointKeys: pool });
50056
+ saveGlobalSettings({ endpointKeys: pool });
50057
+ if (ctx.setKeyPool)
50058
+ ctx.setKeyPool(pool.map((k) => k.key));
50059
+ renderInfo(`Removed key ...${suffix} from pool (${pool.length} remaining).`);
50060
+ if (pool.length === 0) {
50061
+ renderInfo("Pool empty \u2014 using single API key from config.");
50062
+ }
50063
+ return;
50064
+ }
49958
50065
  const normalizedArg = arg.replace(/\u2014/g, "--").replace(/\u2013/g, "--");
49959
50066
  const parts = normalizedArg.split(/\s+/);
49960
50067
  const url = parts[0];
@@ -60955,6 +61062,17 @@ ${CONTENT_BG_SEQ}`);
60955
61062
  }
60956
61063
  }
60957
61064
  }
61065
+ /**
61066
+ * Remove the last N lines from the content scrollback buffer and repaint.
61067
+ * Used by Esc-to-recall to erase the just-rendered user prompt.
61068
+ */
61069
+ popLastContentLines(n) {
61070
+ if (n <= 0)
61071
+ return;
61072
+ this._contentLines.splice(-n, n);
61073
+ if (this.active)
61074
+ this.refreshDisplay();
61075
+ }
60958
61076
  /** Number of visible content rows */
60959
61077
  get contentHeight() {
60960
61078
  const rows = process.stdout.rows ?? 24;
@@ -64024,6 +64142,10 @@ ${lines.join("\n")}
64024
64142
  backend = new NexusAgenticBackend(sendFn, config.model, targetPeer, config.apiKey, thinkingEnabled);
64025
64143
  } else {
64026
64144
  backend = new OllamaAgenticBackend(config.backendUrl, config.model, config.apiKey, thinkingEnabled);
64145
+ const poolKeys = config._keyPool;
64146
+ if (poolKeys && poolKeys.length > 0 && backend instanceof OllamaAgenticBackend) {
64147
+ backend.setKeyPool(poolKeys);
64148
+ }
64027
64149
  }
64028
64150
  try {
64029
64151
  const endpointHistory = loadUsageHistory("endpoint", repoRoot);
@@ -64283,7 +64405,7 @@ ${entry.fullContent}`
64283
64405
  if (slashCommandHandler) {
64284
64406
  runner.registerTool({
64285
64407
  name: "slash_command",
64286
- description: "Invoke a slash command programmatically. Available when /commands auto is set by the user. Safe commands: help, config, models, skills, tools, stats, cost, score, nexus, commands, verbose, stream, brute-force, deep-context, flow, style, emojis, colors, task-type, compact, context, evaluate. Skill commands: /<skill-name> <args>. BLOCKED commands (user-only): quit, exit, destroy, model, endpoint, update, telegram, call, listen, expose, p2p, secrets, dream, bless, clear. Use this to check configuration, run evaluations, discover skills, or adjust modes during a task.",
64408
+ description: "Invoke a slash command programmatically. Available when /commands auto is set by the user. Safe commands: help, config, models, skills, tools, stats, cost, score, nexus, commands, verbose, stream, brute-force, deep-context, flow, style, emojis, colors, task-type, compact, context, evaluate. Skill commands: /<skill-name> <args>. BLOCKED commands (user-only): quit, exit, destroy, model, endpoint, update, setup, telegram, call, listen, expose, p2p, secrets, dream, bless, clear. Use this to check configuration, run evaluations, discover skills, or adjust modes during a task.",
64287
64409
  parameters: {
64288
64410
  type: "object",
64289
64411
  properties: {
@@ -64311,6 +64433,8 @@ ${entry.fullContent}`
64311
64433
  "ep",
64312
64434
  "update",
64313
64435
  "upgrade",
64436
+ "setup",
64437
+ "wizard",
64314
64438
  "parallel",
64315
64439
  "think",
64316
64440
  "telegram",
@@ -64907,6 +65031,9 @@ async function startInteractive(config, repoPath) {
64907
65031
  }
64908
65032
  if (savedSettings.apiKey)
64909
65033
  config = { ...config, apiKey: savedSettings.apiKey };
65034
+ if (savedSettings.endpointKeys && savedSettings.endpointKeys.length > 0) {
65035
+ config._keyPool = savedSettings.endpointKeys.map((k) => k.key);
65036
+ }
64910
65037
  if (savedSettings.verbose !== void 0)
64911
65038
  config = { ...config, verbose: savedSettings.verbose };
64912
65039
  if (savedSettings.maxRetries !== void 0)
@@ -65277,6 +65404,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
65277
65404
  let sessionToolCallCount = 0;
65278
65405
  let lastSteeringInput = "";
65279
65406
  let lastSteeringRetracted = false;
65407
+ let _recallText = null;
65408
+ let _recallTimer = null;
65409
+ const RECALL_WINDOW_MS = 1500;
65280
65410
  let restoredSessionContext = null;
65281
65411
  let sessionSudoPassword = null;
65282
65412
  let sudoPromptPending = false;
@@ -65952,6 +66082,14 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
65952
66082
  statusBar.stopRemoteMetricsPolling();
65953
66083
  }
65954
66084
  },
66085
+ setKeyPool(keys) {
66086
+ if (activeTask) {
66087
+ const backend = activeTask.runner._backend;
66088
+ if (backend?.setKeyPool)
66089
+ backend.setKeyPool(keys);
66090
+ }
66091
+ currentConfig._keyPool = keys;
66092
+ },
65955
66093
  clearScreen() {
65956
66094
  if (isNeovimActive()) {
65957
66095
  writeToNeovimOutput("[screen cleared]\n");
@@ -67607,6 +67745,13 @@ Summarize or analyze this transcription as appropriate.`;
67607
67745
  const inputLineCount = fullInput.split("\n").length;
67608
67746
  const displayText = isImage ? `[Image: ${cleanPath}]` : inputLineCount > 1 ? `[pasted ${inputLineCount} lines]` : fullInput;
67609
67747
  writeContent(() => renderUserMessage(displayText));
67748
+ _recallText = input;
67749
+ if (_recallTimer)
67750
+ clearTimeout(_recallTimer);
67751
+ _recallTimer = setTimeout(() => {
67752
+ _recallText = null;
67753
+ _recallTimer = null;
67754
+ }, RECALL_WINDOW_MS);
67610
67755
  lastSubmittedPrompt = fullInput;
67611
67756
  const taskPreview = fullInput.length > 100 ? fullInput.slice(0, 100) + "..." : fullInput;
67612
67757
  emotionEngine.setCurrentTask(taskPreview);
@@ -67644,6 +67789,11 @@ NEW TASK: ${fullInput}`;
67644
67789
  setTerminalTitle(summary?.slice(0, 60), version);
67645
67790
  }, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler(), thinkingEnabled, handleAskUser);
67646
67791
  activeTask = task;
67792
+ _recallText = null;
67793
+ if (_recallTimer) {
67794
+ clearTimeout(_recallTimer);
67795
+ _recallTimer = null;
67796
+ }
67647
67797
  setTerminalTitle(input.slice(0, 60), version);
67648
67798
  showPrompt();
67649
67799
  if (isNeovimActive() && !isNeovimFocused()) {
@@ -67843,6 +67993,24 @@ ${c2.dim("(Use /quit to exit)")}
67843
67993
  showPrompt();
67844
67994
  });
67845
67995
  _escapeHandler = () => {
67996
+ if (_recallText !== null) {
67997
+ const recalled = _recallText;
67998
+ _recallText = null;
67999
+ if (_recallTimer) {
68000
+ clearTimeout(_recallTimer);
68001
+ _recallTimer = null;
68002
+ }
68003
+ if (activeTask) {
68004
+ activeTask.runner.abort();
68005
+ activeTask = null;
68006
+ }
68007
+ statusBar.setProcessing(false);
68008
+ statusBar.popLastContentLines(1);
68009
+ rl.line = recalled;
68010
+ rl.cursor = recalled.length;
68011
+ showPrompt();
68012
+ return;
68013
+ }
67846
68014
  if (!activeTask)
67847
68015
  return;
67848
68016
  if (activeTask.runner.isPaused) {
@@ -68851,8 +69019,8 @@ var init_status = __esm({
68851
69019
  });
68852
69020
 
68853
69021
  // packages/cli/dist/commands/config.js
68854
- var config_exports = {};
68855
- __export(config_exports, {
69022
+ var config_exports2 = {};
69023
+ __export(config_exports2, {
68856
69024
  configCommand: () => configCommand
68857
69025
  });
68858
69026
  import { join as join73, resolve as resolve35 } from "node:path";
@@ -69638,7 +69806,7 @@ async function main() {
69638
69806
  break;
69639
69807
  }
69640
69808
  case "config": {
69641
- const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config3(), config_exports));
69809
+ const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config3(), config_exports2));
69642
69810
  await configCommand2({
69643
69811
  subCommand: parsed.configSubCommand,
69644
69812
  key: parsed.configKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.68",
3
+ "version": "0.184.70",
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",