open-agents-ai 0.187.290 → 0.187.291

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 +188 -57
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -270036,6 +270036,41 @@ ${graphSummary}`,
270036
270036
  * the entire messages array. Reset on run(). */
270037
270037
  _lastTodoWriteTurn = -1;
270038
270038
  _lastTodoReminderTurn = -1;
270039
+ /**
270040
+ * Check whether the current session's todo list (if any) has any open items.
270041
+ * Returns the list of open items (pending/in_progress/blocked). If there is
270042
+ * no todo list, returns an empty array to allow task completion.
270043
+ */
270044
+ getOpenTodoItems() {
270045
+ const todos = this.readSessionTodos();
270046
+ if (!todos || todos.length === 0)
270047
+ return [];
270048
+ return todos.filter((t2) => t2.status !== "completed");
270049
+ }
270050
+ /**
270051
+ * Build a guard prompt injected when the model attempts to call task_complete
270052
+ * while there are open todo items. This asks the model to verify each item by
270053
+ * name with objective evidence, complete remaining items in order, update the
270054
+ * checklist via todo_write, and only then call task_complete.
270055
+ */
270056
+ buildTodoCompletionGuard(openItems) {
270057
+ const list = openItems.slice(0, 20).map((t2, i2) => `${i2 + 1}. [${t2.status}] ${t2.content}`).join("\n");
270058
+ return `[TODO COMPLETION REQUIRED]
270059
+ You attempted to call task_complete, but the session checklist still has ${openItems.length} open item(s).
270060
+ Before finishing, do ALL of the following:
270061
+ 1) For each item BY NAME, state if it is completed and provide objective evidence (file diffs, test output, logs, or concrete code references).
270062
+ 2) If any item is not completed, proceed to complete them IN ORDER.
270063
+ 3) After all items are truly implemented, call todo_write to mark every item as "completed".
270064
+ 4) ONLY AFTER updating the todo list, call task_complete with a concise final summary.
270065
+
270066
+ Current checklist (open items):
270067
+ ${list}
270068
+
270069
+ Respond with a short verification section in this shape (example):
270070
+ - verify: [{ name: "<exact item text>", completed: true|false, evidence: "<objective proof>" }, ...]
270071
+ - next: "what you will do next OR the exact todo_write(...) call to update statuses"
270072
+ Do NOT call task_complete until all items are marked completed via todo_write.`;
270073
+ }
270039
270074
  /**
270040
270075
  * WO-META-TRACK — Hannover-style turn-counter reminder.
270041
270076
  *
@@ -270243,6 +270278,40 @@ ${body}`;
270243
270278
  this.registerTool(tool);
270244
270279
  }
270245
270280
  }
270281
+ /**
270282
+ * Get a static catalog of registered tools for discovery/minified prompts.
270283
+ * Only exposes name, description, and parameters schema (JSON shape).
270284
+ */
270285
+ getToolCatalog() {
270286
+ const list = [];
270287
+ for (const t2 of this.tools.values()) {
270288
+ list.push({ name: t2.name, description: t2.description, parameters: t2.parameters });
270289
+ }
270290
+ return list;
270291
+ }
270292
+ /**
270293
+ * Execute a registered tool by name with provided args.
270294
+ * Validates against inputSchema if present and returns the tool result.
270295
+ */
270296
+ async runToolByName(name11, args2) {
270297
+ const tool = this.tools.get(name11);
270298
+ if (!tool) {
270299
+ return { success: false, output: "", error: `Unknown tool: ${name11}` };
270300
+ }
270301
+ try {
270302
+ if (tool.inputSchema) {
270303
+ tool.inputSchema.parse(args2);
270304
+ }
270305
+ } catch (e2) {
270306
+ return { success: false, output: "", error: `Invalid args for ${name11}: ${e2?.message || String(e2)}` };
270307
+ }
270308
+ try {
270309
+ const result = await tool.execute(args2);
270310
+ return result;
270311
+ } catch (e2) {
270312
+ return { success: false, output: "", error: e2?.message || String(e2) };
270313
+ }
270314
+ }
270246
270315
  /** Subscribe to agent events */
270247
270316
  onEvent(handler) {
270248
270317
  this.handlers.push(handler);
@@ -271677,13 +271746,24 @@ Then use file_read on individual FILES inside it.`);
271677
271746
  ${sr.result.output}`;
271678
271747
  messages2.push(this.buildToolMessage(output, matchTc.id));
271679
271748
  if (matchTc.name === "task_complete") {
271680
- completed = true;
271681
- summary = extractTaskCompleteSummary(matchTc.arguments);
271682
- if (summary && !this._assistantTextEmitted) {
271683
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271684
- this._assistantTextEmitted = true;
271749
+ const open2 = this.getOpenTodoItems();
271750
+ if (open2.length > 0) {
271751
+ const guard = this.buildTodoCompletionGuard(open2);
271752
+ messages2.push({ role: "system", content: guard });
271753
+ this.emit({
271754
+ type: "status",
271755
+ content: `task_complete intercepted — ${open2.length} open todo(s) remain`,
271756
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
271757
+ });
271758
+ } else {
271759
+ completed = true;
271760
+ summary = extractTaskCompleteSummary(matchTc.arguments);
271761
+ if (summary && !this._assistantTextEmitted) {
271762
+ this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271763
+ this._assistantTextEmitted = true;
271764
+ }
271765
+ break;
271685
271766
  }
271686
- break;
271687
271767
  }
271688
271768
  }
271689
271769
  }
@@ -271696,13 +271776,24 @@ ${sr.result.output}`;
271696
271776
  if (r2) {
271697
271777
  messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
271698
271778
  if (r2.tc.name === "task_complete") {
271699
- completed = true;
271700
- summary = extractTaskCompleteSummary(r2.tc.arguments);
271701
- if (summary && !this._assistantTextEmitted) {
271702
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271703
- this._assistantTextEmitted = true;
271779
+ const open2 = this.getOpenTodoItems();
271780
+ if (open2.length > 0) {
271781
+ const guard = this.buildTodoCompletionGuard(open2);
271782
+ messages2.push({ role: "system", content: guard });
271783
+ this.emit({
271784
+ type: "status",
271785
+ content: `task_complete intercepted — ${open2.length} open todo(s) remain`,
271786
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
271787
+ });
271788
+ } else {
271789
+ completed = true;
271790
+ summary = extractTaskCompleteSummary(r2.tc.arguments);
271791
+ if (summary && !this._assistantTextEmitted) {
271792
+ this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271793
+ this._assistantTextEmitted = true;
271794
+ }
271795
+ break;
271704
271796
  }
271705
- break;
271706
271797
  }
271707
271798
  }
271708
271799
  }
@@ -271725,13 +271816,24 @@ ${sr.result.output}`;
271725
271816
  if (r2) {
271726
271817
  messages2.push(this.buildToolMessage(r2.output, r2.tc.id));
271727
271818
  if (r2.tc.name === "task_complete") {
271728
- completed = true;
271729
- summary = extractTaskCompleteSummary(r2.tc.arguments);
271730
- if (summary && !this._assistantTextEmitted) {
271731
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271732
- this._assistantTextEmitted = true;
271819
+ const open2 = this.getOpenTodoItems();
271820
+ if (open2.length > 0) {
271821
+ const guard = this.buildTodoCompletionGuard(open2);
271822
+ messages2.push({ role: "system", content: guard });
271823
+ this.emit({
271824
+ type: "status",
271825
+ content: `task_complete intercepted — ${open2.length} open todo(s) remain`,
271826
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
271827
+ });
271828
+ } else {
271829
+ completed = true;
271830
+ summary = extractTaskCompleteSummary(r2.tc.arguments);
271831
+ if (summary && !this._assistantTextEmitted) {
271832
+ this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
271833
+ this._assistantTextEmitted = true;
271834
+ }
271835
+ break;
271733
271836
  }
271734
- break;
271735
271837
  }
271736
271838
  }
271737
271839
  }
@@ -272149,13 +272251,24 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
272149
272251
  const toolMsg = this.buildToolMessage(output, tc.id);
272150
272252
  messages2.push(toolMsg);
272151
272253
  if (tc.name === "task_complete") {
272152
- completed = true;
272153
- summary = extractTaskCompleteSummary(tc.arguments);
272154
- if (summary && !this._assistantTextEmitted) {
272155
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
272156
- this._assistantTextEmitted = true;
272254
+ const open2 = this.getOpenTodoItems();
272255
+ if (open2.length > 0) {
272256
+ const guard = this.buildTodoCompletionGuard(open2);
272257
+ messages2.push({ role: "system", content: guard });
272258
+ this.emit({
272259
+ type: "status",
272260
+ content: `task_complete intercepted — ${open2.length} open todo(s) remain`,
272261
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
272262
+ });
272263
+ } else {
272264
+ completed = true;
272265
+ summary = extractTaskCompleteSummary(tc.arguments);
272266
+ if (summary && !this._assistantTextEmitted) {
272267
+ this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
272268
+ this._assistantTextEmitted = true;
272269
+ }
272270
+ break;
272157
272271
  }
272158
- break;
272159
272272
  }
272160
272273
  }
272161
272274
  if (completed)
@@ -272172,9 +272285,20 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
272172
272285
  }
272173
272286
  this.emit({ type: "model_response", content: content.slice(0, 200), turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
272174
272287
  if (/task.?complete|all tests pass/i.test(content)) {
272175
- completed = true;
272176
- summary = content;
272177
- break;
272288
+ const open2 = this.getOpenTodoItems();
272289
+ if (open2.length > 0) {
272290
+ const guard = this.buildTodoCompletionGuard(open2);
272291
+ messages2.push({ role: "system", content: guard });
272292
+ this.emit({
272293
+ type: "status",
272294
+ content: `task_complete text detected but intercepted — ${open2.length} open todo(s) remain`,
272295
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
272296
+ });
272297
+ } else {
272298
+ completed = true;
272299
+ summary = content;
272300
+ break;
272301
+ }
272178
272302
  }
272179
272303
  const finalVarMatch = content.match(/FINAL_VAR\s*\(\s*["']?(\w+)["']?\s*\)/);
272180
272304
  if (finalVarMatch && this.options.finalVarResolver) {
@@ -285447,7 +285571,7 @@ var init_status_bar = __esm({
285447
285571
  return `\x1B]8;;${cmdPrefix}\x07\x1B[38;5;${fg2}m${label}\x1B]8;;\x07`;
285448
285572
  };
285449
285573
  const verBase = ` OA v${this._version}`;
285450
- const verArrow = this._updateLatest ? " " : "";
285574
+ const verArrow = this._updateLatest ? " 🢁" : "";
285451
285575
  const verText = verBase + verArrow;
285452
285576
  const menuBtns = [
285453
285577
  { cmd: "help", label: " help ", w: 6 },
@@ -285477,11 +285601,11 @@ var init_status_bar = __esm({
285477
285601
  let out = "";
285478
285602
  let usedW = 0;
285479
285603
  if (isFirstPage) {
285480
- if (this._updateLatest) {
285481
- out += `\x1B]8;;oa-cmd:/update\x07\x1B[1;38;5;${TEXT_PRIMARY}m${verText}\x1B]8;;\x07\x1B[0m`;
285482
- } else {
285483
- out += `\x1B[1;38;5;${TEXT_PRIMARY}m${verText}\x1B[0m`;
285604
+ try {
285605
+ this._verClickZone = this._updateLatest ? { start: 4, end: 4 + verW - 1 } : null;
285606
+ } catch {
285484
285607
  }
285608
+ out += `\x1B[1;38;5;${TEXT_PRIMARY}m${verText}\x1B[0m`;
285485
285609
  usedW += verW;
285486
285610
  }
285487
285611
  let btnTotalW = 0;
@@ -286432,6 +286556,14 @@ var init_status_bar = __esm({
286432
286556
  return;
286433
286557
  }
286434
286558
  }
286559
+ if (type === "press" && this._updateLatest) {
286560
+ const hdrRow2 = layout().headerContent;
286561
+ const verZone = this._verClickZone;
286562
+ if (row === hdrRow2 && verZone && col >= verZone.start && col <= verZone.end) {
286563
+ if (this._headerButtonHandler) this._headerButtonHandler("/update");
286564
+ return;
286565
+ }
286566
+ }
286435
286567
  const cmd = hitTestHeaderButton(row, col, w);
286436
286568
  if (type === "press" && cmd) {
286437
286569
  if (cmd === "header-prev") {
@@ -331550,32 +331682,31 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
331550
331682
  setupTasks.push(visionDepsPromise.catch(() => {
331551
331683
  }));
331552
331684
  let updateNotified = false;
331553
- if (!isResumed) {
331554
- checkForUpdate(version4).then((updateInfo) => {
331555
- if (updateInfo) {
331556
- banner.setUpdateAvailable(updateInfo.latestVersion);
331557
- try {
331558
- statusBar.setUpdateAvailable(updateInfo.latestVersion);
331559
- } catch {
331560
- }
331561
- const vTextLen = ` OA v${version4}`.length;
331562
- const { setUpdateBadgeRegion: setUpdateBadgeRegion2 } = (init_text_selection(), __toCommonJS(text_selection_exports));
331563
- setUpdateBadgeRegion2(true, vTextLen + 1, " UPDATE ".length);
331564
- const writeMsg = () => {
331565
- if (statusBar?.isActive && statusBar.isStreaming) {
331566
- setTimeout(writeMsg, 3e3);
331567
- return;
331568
- }
331569
- updateNotified = true;
331570
- if (statusBar?.isActive) statusBar.beginContentWrite();
331571
- renderInfo2(`Update available: v${updateInfo.currentVersion} → v${c3.bold(c3.green(updateInfo.latestVersion))}. Click UPDATE in header or run /update.`);
331572
- if (statusBar?.isActive) statusBar.endContentWrite();
331573
- };
331574
- writeMsg();
331685
+ checkForUpdate(version4).then((updateInfo) => {
331686
+ if (updateInfo) {
331687
+ banner.setUpdateAvailable(updateInfo.latestVersion);
331688
+ try {
331689
+ statusBar.setUpdateAvailable(updateInfo.latestVersion);
331690
+ } catch {
331575
331691
  }
331576
- }).catch(() => {
331577
- });
331578
- }
331692
+ const vTextLen = ` OA v${version4}`.length;
331693
+ const { setUpdateBadgeRegion: setUpdateBadgeRegion2 } = (init_text_selection(), __toCommonJS(text_selection_exports));
331694
+ setUpdateBadgeRegion2(true, vTextLen + 1, " UPDATE ".length);
331695
+ const writeMsg = () => {
331696
+ if (updateNotified) return;
331697
+ if (statusBar?.isActive && statusBar.isStreaming) {
331698
+ setTimeout(writeMsg, 3e3);
331699
+ return;
331700
+ }
331701
+ updateNotified = true;
331702
+ if (statusBar?.isActive) statusBar.beginContentWrite();
331703
+ renderInfo2(`Update available: v${updateInfo.currentVersion} → v${c3.bold(c3.green(updateInfo.latestVersion))}. Click version ↑ or run /update.`);
331704
+ if (statusBar?.isActive) statusBar.endContentWrite();
331705
+ };
331706
+ if (!isResumed) writeMsg();
331707
+ }
331708
+ }).catch(() => {
331709
+ });
331579
331710
  const AUTO_UPDATE_INTERVAL_MS = 30 * 60 * 1e3;
331580
331711
  const autoUpdateTimer = setInterval(() => {
331581
331712
  if (updateNotified) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.290",
3
+ "version": "0.187.291",
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",