open-agents-ai 0.187.238 → 0.187.240

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.
package/dist/index.js CHANGED
@@ -271693,14 +271693,19 @@ Call task_complete(summary="...") NOW with whatever you have.`
271693
271693
  }
271694
271694
  if (isThinkOnly) {
271695
271695
  if (consecutiveThinkOnly >= MAX_CONSECUTIVE_THINK_ONLY) {
271696
+ const recentSuccesses = this._littlemanToolOutcomes.slice(-3).filter((o2) => o2.succeeded);
271697
+ const hasRecentSuccess = recentSuccesses.length > 0;
271698
+ const successHint = hasRecentSuccess ? `
271699
+
271700
+ Your most recent tool calls SUCCEEDED. If the task is complete, call task_complete now with a summary of what you accomplished.` : "";
271696
271701
  this.emit({
271697
271702
  type: "status",
271698
- content: `Model produced ${consecutiveThinkOnly} consecutive think-only responses — nudging toward visible output`,
271703
+ content: `Model produced ${consecutiveThinkOnly} consecutive think-only responses — nudging toward action${hasRecentSuccess ? " (recent tools succeeded)" : ""}`,
271699
271704
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
271700
271705
  });
271701
271706
  messages2.push({
271702
271707
  role: "user",
271703
- content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response."
271708
+ content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response." + successHint
271704
271709
  });
271705
271710
  }
271706
271711
  continue;
@@ -272049,9 +272054,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
272049
272054
  }
272050
272055
  if (isThinkOnlyBF) {
272051
272056
  if (consecutiveThinkOnly >= MAX_CONSECUTIVE_THINK_ONLY) {
272057
+ const recentSucc = this._littlemanToolOutcomes.slice(-3).filter((o2) => o2.succeeded);
272058
+ const succHint = recentSucc.length > 0 ? "\n\nYour most recent tool calls SUCCEEDED. If the task is complete, call task_complete now with a summary." : "";
272052
272059
  messages2.push({
272053
272060
  role: "user",
272054
- content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response."
272061
+ content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response." + succHint
272055
272062
  });
272056
272063
  }
272057
272064
  continue;
@@ -422,10 +422,21 @@ function main() {
422
422
  }
423
423
 
424
424
  if (alreadyUp) {
425
- log("OA daemon already responding on port " + PORT + " reinstalling service definition so it picks up the new build.");
426
- // Fall through to (re)install service files; the serve command's
427
- // daemon-mode /health pre-check will no-op if the existing daemon
428
- // is still healthy.
425
+ log("OA daemon on port " + PORT + " is running the old version — killing it so the new build starts cleanly.");
426
+ // Kill the old daemon explicitly. The preinstall hook already tried
427
+ // pkill, but by this point the install has completed and the old
428
+ // binary was replaced. A stale daemon holding the port would prevent
429
+ // the new one from binding. Kill by port to be precise.
430
+ if (!IS_WIN) {
431
+ runQuiet("fuser -k " + PORT + "/tcp 2>/dev/null || true");
432
+ // Also try systemctl restart which handles service-managed daemons.
433
+ runQuiet("systemctl --user restart " + SERVICE_LABEL + ".service 2>/dev/null || true");
434
+ } else {
435
+ runQuiet("netstat -aon | findstr :" + PORT + " | for /f \"tokens=5\" %a in ('findstr LISTENING') do taskkill /PID %a /F 2>nul");
436
+ }
437
+ // Give it a moment to release the port
438
+ try { cp.execSync("sleep 1 || timeout /t 1 /nobreak >nul 2>&1", { stdio: "pipe", timeout: 3000 }); } catch (e) {}
439
+ // Fall through to (re)install service files and start the new daemon.
429
440
  }
430
441
 
431
442
  log("Installing OA API daemon service for port " + PORT + " ...");
@@ -3,6 +3,63 @@
3
3
  // Pure CJS (no ESM, no backticks) so it works on any Node version.
4
4
  // Cross-platform: Linux, macOS, Windows (cmd, PowerShell, Git Bash).
5
5
  // If Node is too old, guides the user through installing Node 22.
6
+
7
+ // ── ENOTEMPTY fix: clean stale staging dirs before npm tries to rename ──
8
+ // npm's atomic-rename strategy fails with ENOTEMPTY when a previous install
9
+ // was interrupted or the daemon held file handles open. Clean any leftover
10
+ // .open-agents-ai-* temp dirs in the global node_modules BEFORE npm starts
11
+ // the install. Also kill any running daemon so its file handles release.
12
+ (function cleanStaleStaging() {
13
+ try {
14
+ var cp = require("child_process");
15
+ var path = require("path");
16
+ var fs = require("fs");
17
+
18
+ // 1. Kill running OA daemon so it releases file handles on the old install.
19
+ // Without this, npm can't rename the directory because node has dist/index.js open.
20
+ try {
21
+ if (process.platform === "win32") {
22
+ cp.execSync('taskkill /F /IM node.exe /FI "WINDOWTITLE eq open-agents*" 2>nul', { stdio: "pipe", timeout: 5000 });
23
+ } else {
24
+ // Kill any `oa serve` or `open-agents serve` processes. SIGTERM so they shut down cleanly.
25
+ cp.execSync("pkill -f 'open-agents.*serve' 2>/dev/null || true", { stdio: "pipe", timeout: 5000 });
26
+ // Also kill by port if pkill missed it
27
+ cp.execSync("fuser -k 11435/tcp 2>/dev/null || true", { stdio: "pipe", timeout: 5000 });
28
+ }
29
+ } catch (e) { /* daemon not running or pkill unavailable — fine */ }
30
+
31
+ // 2. Find and remove stale .open-agents-ai-* staging directories.
32
+ // These are npm's temp rename targets that got left behind.
33
+ var globalDir;
34
+ try {
35
+ globalDir = cp.execSync("npm root -g", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 10000 }).trim();
36
+ } catch (e) {
37
+ globalDir = "";
38
+ }
39
+ if (globalDir && fs.existsSync(globalDir)) {
40
+ try {
41
+ var entries = fs.readdirSync(globalDir);
42
+ var cleaned = 0;
43
+ for (var i = 0; i < entries.length; i++) {
44
+ if (entries[i].indexOf(".open-agents-ai-") === 0) {
45
+ var stale = path.join(globalDir, entries[i]);
46
+ try {
47
+ fs.rmSync(stale, { recursive: true, force: true });
48
+ cleaned++;
49
+ } catch (e2) {
50
+ // rmSync not available on old Node — try rm -rf
51
+ try { cp.execSync("rm -rf " + JSON.stringify(stale), { stdio: "pipe", timeout: 10000 }); cleaned++; } catch (e3) {}
52
+ }
53
+ }
54
+ }
55
+ if (cleaned > 0) {
56
+ process.stdout.write(" [preinstall] Cleaned " + cleaned + " stale staging dir(s)\n");
57
+ }
58
+ } catch (e) { /* readdir failed — non-fatal */ }
59
+ }
60
+ } catch (e) { /* entire cleanup failed — non-fatal, let npm try anyway */ }
61
+ })();
62
+
6
63
  var nodeVersion = parseInt(process.versions.node, 10);
7
64
 
8
65
  if (nodeVersion >= 22) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.238",
3
+ "version": "0.187.240",
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",