open-agents-ai 0.138.58 → 0.138.59

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 +141 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -22322,17 +22322,22 @@ Integrate this guidance into your current approach. Continue working on the task
22322
22322
  const turnTier = this.options.modelTier ?? "large";
22323
22323
  const turnBudget = turnTier === "small" ? 5 : turnTier === "medium" ? 8 : 0;
22324
22324
  if (turnBudget > 0 && turn > 0 && turn % turnBudget === 0) {
22325
- const progress = this._taskState.completedSteps.slice(-3).join("; ");
22326
- const failures = this._taskState.failedApproaches.slice(-2).join("; ");
22327
- messages.push({
22328
- role: "user",
22329
- content: `[PROGRESS CHECK \u2014 Turn ${turn}]
22325
+ const repetitionRatio = this.detectRepetition(toolCallLog);
22326
+ const noProgress = this._taskState.completedSteps.length === 0 && turn >= turnBudget;
22327
+ const isLooping = repetitionRatio > 0.4;
22328
+ if (isLooping || noProgress) {
22329
+ const progress = this._taskState.completedSteps.slice(-3).join("; ");
22330
+ const failures = this._taskState.failedApproaches.slice(-2).join("; ");
22331
+ messages.push({
22332
+ role: "user",
22333
+ content: `[PROGRESS CHECK \u2014 Turn ${turn}]
22330
22334
  **Goal:** ${this._taskState.goal}
22331
22335
  ` + (progress ? `**Done so far:** ${progress}
22332
22336
  ` : "") + (failures ? `**Failed (don't repeat):** ${failures}
22333
22337
  ` : "") + `**What is the ONE next step you need to take?** State it, then do it with a tool call.
22334
22338
  If you're stuck, try a completely different approach. Do NOT repeat what failed above.`
22335
- });
22339
+ });
22340
+ }
22336
22341
  }
22337
22342
  let compacted;
22338
22343
  if (this._pendingCompaction) {
@@ -23342,18 +23347,49 @@ ${tail}`;
23342
23347
  const head = messages.slice(0, 2);
23343
23348
  if (messages.length <= 2 + keepRecent)
23344
23349
  return messages;
23350
+ const tailTokenBudget = Math.max(4e3, Math.floor((this.options.contextWindowSize || 32e3) * 0.15));
23345
23351
  let recentStart = messages.length - keepRecent;
23352
+ {
23353
+ let accumulated = 0;
23354
+ let budgetCut = messages.length;
23355
+ for (let i = messages.length - 1; i >= 2; i--) {
23356
+ const msg = messages[i];
23357
+ const msgChars = typeof msg.content === "string" ? msg.content.length : 100;
23358
+ const toolCallChars = (msg.tool_calls || []).reduce((s, tc) => s + (tc.function?.arguments?.length || 0) + (tc.function?.name?.length || 0), 0);
23359
+ const msgTokens = Math.ceil((msgChars + toolCallChars) / 4) + 10;
23360
+ if (accumulated + msgTokens > tailTokenBudget && messages.length - i >= 4) {
23361
+ budgetCut = i + 1;
23362
+ break;
23363
+ }
23364
+ accumulated += msgTokens;
23365
+ budgetCut = i;
23366
+ }
23367
+ recentStart = Math.min(recentStart, budgetCut);
23368
+ recentStart = Math.max(2, recentStart);
23369
+ }
23346
23370
  while (recentStart > 2) {
23347
23371
  const msg = messages[recentStart];
23348
23372
  if (msg && msg.role === "tool") {
23349
23373
  recentStart--;
23374
+ } else if (msg && msg.role === "assistant" && msg.tool_calls && msg.tool_calls.length > 0) {
23375
+ const callIds = new Set(msg.tool_calls.map((tc) => tc.id));
23376
+ let allResultsIncluded = true;
23377
+ for (let j = recentStart + 1; j < messages.length; j++) {
23378
+ const r = messages[j];
23379
+ if (r && r.role === "tool" && callIds.has(r.tool_call_id)) {
23380
+ callIds.delete(r.tool_call_id);
23381
+ }
23382
+ }
23383
+ if (callIds.size > 0) {
23384
+ recentStart--;
23385
+ } else {
23386
+ break;
23387
+ }
23350
23388
  } else {
23351
23389
  break;
23352
23390
  }
23353
23391
  }
23354
- if (recentStart > 2 && messages[recentStart]?.role === "tool") {
23355
- recentStart = Math.max(2, recentStart - 1);
23356
- }
23392
+ recentStart = Math.max(2, recentStart);
23357
23393
  const recent = messages.slice(recentStart);
23358
23394
  const middle = messages.slice(2, recentStart);
23359
23395
  if (middle.length === 0)
@@ -38344,7 +38380,7 @@ __export(voice_exports, {
38344
38380
  resetNarrationContext: () => resetNarrationContext
38345
38381
  });
38346
38382
  import { existsSync as existsSync35, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync24, unlinkSync as unlinkSync8, readdirSync as readdirSync9, renameSync, statSync as statSync12 } from "node:fs";
38347
- import { join as join50 } from "node:path";
38383
+ import { join as join50, dirname as dirname17 } from "node:path";
38348
38384
  import { homedir as homedir11, tmpdir as tmpdir9, platform as platform2 } from "node:os";
38349
38385
  import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
38350
38386
  import { createRequire } from "node:module";
@@ -38395,6 +38431,87 @@ function luxttsCloneRefsDir() {
38395
38431
  function luxttsInferScript() {
38396
38432
  return join50(voiceDir(), "luxtts-infer.py");
38397
38433
  }
38434
+ function writeDetectTorchScript(targetPath) {
38435
+ if (existsSync35(targetPath))
38436
+ return;
38437
+ try {
38438
+ mkdirSync13(dirname17(targetPath), { recursive: true });
38439
+ } catch {
38440
+ }
38441
+ const script = `#!/usr/bin/env python3
38442
+ """detect-torch.py \u2014 Architecture-aware PyTorch install detection."""
38443
+ import json, os, platform, subprocess, sys
38444
+ from pathlib import Path
38445
+
38446
+ def detect_cuda():
38447
+ try:
38448
+ r = subprocess.run(["nvidia-smi"], capture_output=True, text=True, timeout=5)
38449
+ if r.returncode == 0:
38450
+ import re
38451
+ m = re.search(r"CUDA Version:\\s*(\\d+\\.\\d+)", r.stdout)
38452
+ if m: return m.group(1)
38453
+ except: pass
38454
+ try:
38455
+ r = subprocess.run(["nvcc", "--version"], capture_output=True, text=True, timeout=5)
38456
+ if r.returncode == 0:
38457
+ import re
38458
+ m = re.search(r"release (\\d+\\.\\d+)", r.stdout)
38459
+ if m: return m.group(1)
38460
+ except: pass
38461
+ return None
38462
+
38463
+ def is_jetson():
38464
+ return platform.machine().lower() in ("aarch64","arm64") and Path("/etc/nv_tegra_release").exists()
38465
+
38466
+ def main():
38467
+ m = platform.machine().lower()
38468
+ s = platform.system().lower()
38469
+ spec = {"platform":s,"arch":m,"accelerator":"cpu","cuda_version":None,"is_jetson":False,"pip_args":[],"pip_args_str":"","description":""}
38470
+ if s == "darwin":
38471
+ spec["accelerator"] = "mps" if m in ("arm64","aarch64") else "cpu"
38472
+ spec["pip_args"] = ["torch","torchaudio"]
38473
+ spec["description"] = f"macOS {'Apple Silicon (MPS)' if m in ('arm64','aarch64') else 'Intel (CPU)'}"
38474
+ spec["pip_args_str"] = " ".join(spec["pip_args"])
38475
+ elif m in ("aarch64","arm64","armv7l"):
38476
+ cv = detect_cuda()
38477
+ if is_jetson():
38478
+ spec["is_jetson"] = True; spec["accelerator"] = "cuda"; spec["cuda_version"] = cv
38479
+ whl = os.environ.get("JETSON_TORCH_WHEEL","")
38480
+ spec["pip_args"] = [whl] if whl else ["torch","torchaudio"]
38481
+ spec["pip_args_str"] = whl if whl else "torch torchaudio"
38482
+ spec["description"] = f"Jetson aarch64 CUDA {cv or '?'}"
38483
+ elif cv:
38484
+ spec["accelerator"] = "cuda"; spec["cuda_version"] = cv
38485
+ spec["pip_args"] = ["torch","torchaudio"]; spec["pip_args_str"] = "torch torchaudio"
38486
+ spec["description"] = f"Linux aarch64 CUDA {cv}"
38487
+ else:
38488
+ spec["pip_args"] = ["torch","torchaudio"]; spec["pip_args_str"] = "torch torchaudio"
38489
+ spec["description"] = "Linux aarch64 CPU"
38490
+ else:
38491
+ cv = detect_cuda()
38492
+ if cv:
38493
+ spec["accelerator"] = "cuda"; spec["cuda_version"] = cv
38494
+ mj = int(cv.split(".")[0]); mn = int(cv.split(".")[1]) if "." in cv else 0
38495
+ tag = "cu124" if mj>=12 and mn>=4 else "cu121" if mj>=12 else "cu118" if mj>=11 and mn>=8 else "cu121"
38496
+ spec["pip_args"] = ["torch","torchaudio","--index-url",f"https://download.pytorch.org/whl/{tag}"]
38497
+ spec["pip_args_str"] = f"torch torchaudio --index-url https://download.pytorch.org/whl/{tag}"
38498
+ spec["description"] = f"Linux x86_64 CUDA {cv} ({tag})"
38499
+ else:
38500
+ spec["pip_args"] = ["torch","torchaudio","--index-url","https://download.pytorch.org/whl/cpu"]
38501
+ spec["pip_args_str"] = "torch torchaudio --index-url https://download.pytorch.org/whl/cpu"
38502
+ spec["description"] = "Linux x86_64 CPU"
38503
+ if "--pip-args" in sys.argv: print(spec["pip_args_str"])
38504
+ elif "--json" in sys.argv or len(sys.argv) <= 1: print(json.dumps(spec, indent=2))
38505
+ elif "--description" in sys.argv: print(spec["description"])
38506
+ elif "--accelerator" in sys.argv: print(spec["accelerator"])
38507
+
38508
+ if __name__ == "__main__": main()
38509
+ `;
38510
+ try {
38511
+ writeFileSync14(targetPath, script, { mode: 493 });
38512
+ } catch {
38513
+ }
38514
+ }
38398
38515
  function emotionToPitchBias(emotion, stark = false, autist = false) {
38399
38516
  if (autist)
38400
38517
  return 0;
@@ -40238,7 +40355,8 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
40238
40355
  if (torchCheck === "cpu") {
40239
40356
  renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
40240
40357
  try {
40241
- const detectScript = join50(__dirname, "../../../../scripts/detect-torch.py");
40358
+ const detectScript = join50(voiceDir(), "detect-torch.py");
40359
+ writeDetectTorchScript(detectScript);
40242
40360
  let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
40243
40361
  try {
40244
40362
  const args = await this.asyncShell(`python3 ${JSON.stringify(detectScript)} --pip-args`, 1e4);
@@ -40271,7 +40389,8 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
40271
40389
  }
40272
40390
  }
40273
40391
  {
40274
- const detectScript = join50(__dirname, "../../../../scripts/detect-torch.py");
40392
+ const detectScript = join50(voiceDir(), "detect-torch.py");
40393
+ writeDetectTorchScript(detectScript);
40275
40394
  let pipArgsStr = "torch torchaudio";
40276
40395
  let torchDesc = "unknown platform";
40277
40396
  try {
@@ -43214,9 +43333,9 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
43214
43333
  if (models.length > 0) {
43215
43334
  try {
43216
43335
  const { writeFileSync: writeFileSync20, mkdirSync: mkdirSync21 } = await import("node:fs");
43217
- const { join: join64, dirname: dirname20 } = await import("node:path");
43336
+ const { join: join64, dirname: dirname21 } = await import("node:path");
43218
43337
  const cachePath = join64(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
43219
- mkdirSync21(dirname20(cachePath), { recursive: true });
43338
+ mkdirSync21(dirname21(cachePath), { recursive: true });
43220
43339
  writeFileSync20(cachePath, JSON.stringify({
43221
43340
  peerId,
43222
43341
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -43416,10 +43535,10 @@ async function handleUpdate(subcommand, ctx) {
43416
43535
  try {
43417
43536
  const { createRequire: createRequire4 } = await import("node:module");
43418
43537
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
43419
- const { dirname: dirname20, join: join64 } = await import("node:path");
43538
+ const { dirname: dirname21, join: join64 } = await import("node:path");
43420
43539
  const { existsSync: existsSync45 } = await import("node:fs");
43421
43540
  const req = createRequire4(import.meta.url);
43422
- const thisDir = dirname20(fileURLToPath14(import.meta.url));
43541
+ const thisDir = dirname21(fileURLToPath14(import.meta.url));
43423
43542
  const candidates = [
43424
43543
  join64(thisDir, "..", "package.json"),
43425
43544
  join64(thisDir, "..", "..", "package.json"),
@@ -46507,7 +46626,7 @@ var init_edit_history = __esm({
46507
46626
 
46508
46627
  // packages/cli/dist/tui/promptLoader.js
46509
46628
  import { readFileSync as readFileSync27, existsSync as existsSync38 } from "node:fs";
46510
- import { join as join54, dirname as dirname17 } from "node:path";
46629
+ import { join as join54, dirname as dirname18 } from "node:path";
46511
46630
  import { fileURLToPath as fileURLToPath11 } from "node:url";
46512
46631
  function loadPrompt3(promptPath, vars) {
46513
46632
  let content = cache3.get(promptPath);
@@ -46528,7 +46647,7 @@ var init_promptLoader3 = __esm({
46528
46647
  "packages/cli/dist/tui/promptLoader.js"() {
46529
46648
  "use strict";
46530
46649
  __filename3 = fileURLToPath11(import.meta.url);
46531
- __dirname6 = dirname17(__filename3);
46650
+ __dirname6 = dirname18(__filename3);
46532
46651
  devPath2 = join54(__dirname6, "..", "..", "prompts");
46533
46652
  publishedPath2 = join54(__dirname6, "..", "prompts");
46534
46653
  PROMPTS_DIR3 = existsSync38(devPath2) ? devPath2 : publishedPath2;
@@ -53356,7 +53475,7 @@ var init_mouse_filter = __esm({
53356
53475
  import * as readline2 from "node:readline";
53357
53476
  import { Writable } from "node:stream";
53358
53477
  import { cwd } from "node:process";
53359
- import { resolve as resolve29, join as join59, dirname as dirname18, extname as extname10 } from "node:path";
53478
+ import { resolve as resolve29, join as join59, dirname as dirname19, extname as extname10 } from "node:path";
53360
53479
  import { createRequire as createRequire2 } from "node:module";
53361
53480
  import { fileURLToPath as fileURLToPath12 } from "node:url";
53362
53481
  import { readFileSync as readFileSync32, writeFileSync as writeFileSync18, appendFileSync as appendFileSync4, rmSync as rmSync2, readdirSync as readdirSync16, mkdirSync as mkdirSync19 } from "node:fs";
@@ -53378,7 +53497,7 @@ function formatTimeAgo(date) {
53378
53497
  function getVersion3() {
53379
53498
  try {
53380
53499
  const require2 = createRequire2(import.meta.url);
53381
- const thisDir = dirname18(fileURLToPath12(import.meta.url));
53500
+ const thisDir = dirname19(fileURLToPath12(import.meta.url));
53382
53501
  const candidates = [
53383
53502
  join59(thisDir, "..", "package.json"),
53384
53503
  join59(thisDir, "..", "..", "package.json"),
@@ -58395,7 +58514,7 @@ init_updater();
58395
58514
  import { parseArgs as nodeParseArgs2 } from "node:util";
58396
58515
  import { createRequire as createRequire3 } from "node:module";
58397
58516
  import { fileURLToPath as fileURLToPath13 } from "node:url";
58398
- import { dirname as dirname19, join as join63 } from "node:path";
58517
+ import { dirname as dirname20, join as join63 } from "node:path";
58399
58518
 
58400
58519
  // packages/cli/dist/cli.js
58401
58520
  import { createInterface } from "node:readline";
@@ -58502,7 +58621,7 @@ init_output();
58502
58621
  function getVersion4() {
58503
58622
  try {
58504
58623
  const require2 = createRequire3(import.meta.url);
58505
- const pkgPath = join63(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
58624
+ const pkgPath = join63(dirname20(fileURLToPath13(import.meta.url)), "..", "package.json");
58506
58625
  const pkg = require2(pkgPath);
58507
58626
  return pkg.version;
58508
58627
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.138.58",
3
+ "version": "0.138.59",
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",