open-agents-ai 0.25.0 → 0.26.0

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 +79 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1425,9 +1425,14 @@ var init_file_read = __esm({
1425
1425
  required: ["path"]
1426
1426
  };
1427
1427
  workingDir;
1428
+ _contextWindowSize = 0;
1428
1429
  constructor(workingDir) {
1429
1430
  this.workingDir = workingDir;
1430
1431
  }
1432
+ /** Set actual context window size to enable auto-windowing for small contexts */
1433
+ setContextWindowSize(size) {
1434
+ this._contextWindowSize = size;
1435
+ }
1431
1436
  async execute(args) {
1432
1437
  const filePath = args["path"];
1433
1438
  const offset = args["offset"];
@@ -1437,9 +1442,23 @@ var init_file_read = __esm({
1437
1442
  const fullPath = resolve(this.workingDir, filePath);
1438
1443
  const content = await readFile(fullPath, "utf-8");
1439
1444
  let lines = content.split("\n");
1445
+ const totalLines = lines.length;
1440
1446
  if (offset !== void 0) {
1441
1447
  const startIdx = Math.max(0, offset - 1);
1442
1448
  lines = lines.slice(startIdx, limit ? startIdx + limit : void 0);
1449
+ } else if (this._contextWindowSize > 0 && this._contextWindowSize <= 32768 && !limit) {
1450
+ const maxLines = this._contextWindowSize <= 16384 ? 80 : 120;
1451
+ if (totalLines > maxLines) {
1452
+ lines = lines.slice(0, maxLines);
1453
+ const numbered2 = lines.map((line, i) => `${String(i + 1).padStart(6)} | ${line}`).join("\n");
1454
+ return {
1455
+ success: true,
1456
+ output: `${numbered2}
1457
+
1458
+ [File has ${totalLines} lines \u2014 showing first ${maxLines}. Use offset/limit to see more.]`,
1459
+ durationMs: performance.now() - start
1460
+ };
1461
+ }
1443
1462
  }
1444
1463
  const numbered = lines.map((line, i) => `${String(i + (offset ?? 1)).padStart(6)} | ${line}`).join("\n");
1445
1464
  return {
@@ -10299,9 +10318,14 @@ Rules:
10299
10318
  streamEnabled: options?.streamEnabled ?? false,
10300
10319
  bruteForce: options?.bruteForce ?? true,
10301
10320
  bruteForceMaxCycles: options?.bruteForceMaxCycles ?? 100,
10302
- modelTier: options?.modelTier ?? "large"
10321
+ modelTier: options?.modelTier ?? "large",
10322
+ contextWindowSize: options?.contextWindowSize ?? 0
10303
10323
  };
10304
10324
  }
10325
+ /** Update context window size (e.g. after querying Ollama /api/show) */
10326
+ setContextWindowSize(size) {
10327
+ this.options.contextWindowSize = size;
10328
+ }
10305
10329
  /** Register a tool for the agent to use */
10306
10330
  registerTool(tool) {
10307
10331
  this.tools.set(tool.name, tool);
@@ -10455,11 +10479,13 @@ Integrate this guidance into your current approach. Continue working on the task
10455
10479
  });
10456
10480
  }
10457
10481
  const compacted = this.compactMessages(messages);
10482
+ const ctxWindow = this.options.contextWindowSize;
10483
+ const effectiveMaxTokens = ctxWindow > 0 ? Math.min(this.options.maxTokens, Math.max(2048, Math.floor(ctxWindow * 0.25))) : this.options.maxTokens;
10458
10484
  const chatRequest = {
10459
10485
  messages: compacted,
10460
10486
  tools: toolDefs,
10461
10487
  temperature: this.options.temperature,
10462
- maxTokens: this.options.maxTokens,
10488
+ maxTokens: effectiveMaxTokens,
10463
10489
  timeoutMs: this.options.requestTimeoutMs
10464
10490
  };
10465
10491
  let response;
@@ -10553,10 +10579,10 @@ Integrate this guidance into your current approach. Continue working on the task
10553
10579
  }
10554
10580
  }
10555
10581
  }
10556
- const maxLen = 8e3;
10557
- const output = result.success ? result.output.length > maxLen ? result.output.slice(0, maxLen) + `
10558
- ...(truncated)` : result.output : `Error: ${result.error || "unknown error"}
10559
- ${result.output}`;
10582
+ const ctxW = this.options.contextWindowSize;
10583
+ const maxLen = ctxW > 0 ? Math.max(2e3, Math.min(8e3, Math.floor(ctxW * 0.5))) : 8e3;
10584
+ const output = result.success ? result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : result.output : `Error: ${result.error || "unknown error"}
10585
+ ${result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : result.output}`;
10560
10586
  this.emit({
10561
10587
  type: "tool_result",
10562
10588
  toolName: tc.name,
@@ -10862,6 +10888,29 @@ ${marker}` : marker);
10862
10888
  return { role: "tool", content: output, tool_call_id: toolCallId };
10863
10889
  }
10864
10890
  // -------------------------------------------------------------------------
10891
+ // Output folding — keep head + tail, omit middle (preserves errors at end)
10892
+ // -------------------------------------------------------------------------
10893
+ foldOutput(output, maxChars) {
10894
+ const lines = output.split("\n");
10895
+ if (lines.length <= 40) {
10896
+ return output.slice(0, maxChars) + "\n...(truncated)";
10897
+ }
10898
+ const headLines = 20;
10899
+ const tailLines = 10;
10900
+ const head = lines.slice(0, headLines).join("\n");
10901
+ const tail = lines.slice(-tailLines).join("\n");
10902
+ const omitted = lines.length - headLines - tailLines;
10903
+ const folded = `${head}
10904
+
10905
+ [... ${omitted} lines omitted ...]
10906
+
10907
+ ${tail}`;
10908
+ if (folded.length > maxChars) {
10909
+ return folded.slice(0, maxChars) + "\n...(truncated)";
10910
+ }
10911
+ return folded;
10912
+ }
10913
+ // -------------------------------------------------------------------------
10865
10914
  // Context compaction
10866
10915
  // -------------------------------------------------------------------------
10867
10916
  compactMessages(messages) {
@@ -10879,7 +10928,8 @@ ${marker}` : marker);
10879
10928
  if (estimatedTokens < this.options.compactionThreshold) {
10880
10929
  return messages;
10881
10930
  }
10882
- const keepRecent = 12;
10931
+ const ctxWin = this.options.contextWindowSize;
10932
+ const keepRecent = ctxWin > 0 ? Math.max(4, Math.min(12, Math.floor(ctxWin / 4e3))) : 12;
10883
10933
  const head = messages.slice(0, 2);
10884
10934
  if (messages.length <= 2 + keepRecent)
10885
10935
  return messages;
@@ -19107,7 +19157,7 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
19107
19157
  }
19108
19158
  };
19109
19159
  }
19110
- function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType) {
19160
+ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize) {
19111
19161
  const modelTier = getModelTier(config.model);
19112
19162
  const projectCtx = buildProjectContext(repoRoot, taskStores?.contextStores);
19113
19163
  let dynamicContext = formatContextForPrompt(projectCtx, modelTier);
@@ -19128,10 +19178,19 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
19128
19178
  modelTier,
19129
19179
  streamEnabled: stream?.enabled ?? false,
19130
19180
  bruteForce: bruteForce ?? true,
19131
- bruteForceMaxCycles: 100
19181
+ bruteForceMaxCycles: 100,
19132
19182
  // effectively unlimited — hard timeout is the real bound
19183
+ contextWindowSize: contextWindowSize ?? 0
19133
19184
  });
19134
- runner.registerTools(buildTools(repoRoot, config));
19185
+ const tools = buildTools(repoRoot, config);
19186
+ if (contextWindowSize && contextWindowSize > 0) {
19187
+ for (const tool of tools) {
19188
+ if ("setContextWindowSize" in tool && typeof tool.setContextWindowSize === "function") {
19189
+ tool.setContextWindowSize(contextWindowSize);
19190
+ }
19191
+ }
19192
+ }
19193
+ runner.registerTools(tools);
19135
19194
  const filesTouched = /* @__PURE__ */ new Set();
19136
19195
  const toolSequence = [];
19137
19196
  const editSessionId = `task-${Date.now()}`;
@@ -19422,9 +19481,12 @@ async function startInteractive(config, repoPath) {
19422
19481
  end: () => statusBar.endContentWrite()
19423
19482
  });
19424
19483
  }
19484
+ let resolvedContextWindowSize = 0;
19425
19485
  queryContextSize(config.backendUrl, config.model, config.apiKey).then((ctxSize) => {
19426
- if (ctxSize)
19486
+ if (ctxSize) {
19487
+ resolvedContextWindowSize = ctxSize;
19427
19488
  statusBar.setContextWindowSize(ctxSize);
19489
+ }
19428
19490
  }).catch(() => {
19429
19491
  });
19430
19492
  const provider = detectProvider(config.backendUrl);
@@ -19725,7 +19787,10 @@ async function startInteractive(config, repoPath) {
19725
19787
  setEmojis: (enabled) => setEmojisEnabled(enabled),
19726
19788
  getColors: () => getColorsEnabled(),
19727
19789
  setColors: (enabled) => setColorsEnabled(enabled),
19728
- setContextWindowSize: (size) => statusBar.setContextWindowSize(size),
19790
+ setContextWindowSize: (size) => {
19791
+ resolvedContextWindowSize = size;
19792
+ statusBar.setContextWindowSize(size);
19793
+ },
19729
19794
  hasActiveTask: () => activeTask !== null,
19730
19795
  abortTask() {
19731
19796
  if (!activeTask)
@@ -19881,7 +19946,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
19881
19946
  toolPatternStore: toolPatternStore ?? void 0
19882
19947
  }, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary) => {
19883
19948
  lastCompletedSummary = summary;
19884
- }, currentTaskType);
19949
+ }, currentTaskType, resolvedContextWindowSize);
19885
19950
  activeTask = task;
19886
19951
  showPrompt();
19887
19952
  await task.promise;
@@ -19983,7 +20048,7 @@ Summarize or analyze this transcription as appropriate.`;
19983
20048
  toolPatternStore: toolPatternStore ?? void 0
19984
20049
  }, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary) => {
19985
20050
  lastCompletedSummary = summary;
19986
- }, currentTaskType);
20051
+ }, currentTaskType, resolvedContextWindowSize);
19987
20052
  activeTask = task;
19988
20053
  showPrompt();
19989
20054
  await task.promise;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
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",