open-agents-ai 0.31.2 → 0.31.3
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 +64 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11012,6 +11012,39 @@ Rules:
|
|
|
11012
11012
|
setContextWindowSize(size) {
|
|
11013
11013
|
this.options.contextWindowSize = size;
|
|
11014
11014
|
}
|
|
11015
|
+
// -------------------------------------------------------------------------
|
|
11016
|
+
// Context-aware limits — all dynamic values derived from contextWindowSize
|
|
11017
|
+
// and modelTier. Call this instead of using hardcoded magic numbers.
|
|
11018
|
+
// -------------------------------------------------------------------------
|
|
11019
|
+
/**
|
|
11020
|
+
* Compute all context-dependent limits from the current contextWindowSize
|
|
11021
|
+
* and modelTier. Returns sensible defaults when contextWindowSize is 0.
|
|
11022
|
+
*/
|
|
11023
|
+
contextLimits() {
|
|
11024
|
+
const ctx = this.options.contextWindowSize;
|
|
11025
|
+
const tier = this.options.modelTier ?? "large";
|
|
11026
|
+
const compactionThreshold = ctx > 0 ? Math.min(this.options.compactionThreshold, Math.floor(ctx * 0.75)) : this.options.compactionThreshold;
|
|
11027
|
+
const keepRecentDivisor = tier === "small" ? 2e3 : tier === "medium" ? 3e3 : 4e3;
|
|
11028
|
+
const keepRecent = ctx > 0 ? Math.max(4, Math.min(12, Math.floor(ctx / keepRecentDivisor))) : 12;
|
|
11029
|
+
const maxOutputTokens = ctx > 0 ? Math.min(this.options.maxTokens, Math.max(2048, Math.floor(ctx * 0.25))) : this.options.maxTokens;
|
|
11030
|
+
const toolOutputMaxChars = ctx > 0 ? Math.max(2e3, Math.min(8e3, Math.floor(ctx * 0.5))) : 8e3;
|
|
11031
|
+
const foldLineThreshold = tier === "small" ? 30 : tier === "medium" ? 35 : 40;
|
|
11032
|
+
const foldHeadLines = tier === "small" ? 12 : tier === "medium" ? 16 : 20;
|
|
11033
|
+
const foldTailLines = tier === "small" ? 5 : tier === "medium" ? 8 : 10;
|
|
11034
|
+
const maxSummaryChars = ctx > 0 ? Math.max(2e3, Math.min(8e3, Math.floor(ctx * 0.2))) : 4e3;
|
|
11035
|
+
const repetitionWindow = tier === "small" ? 6 : tier === "medium" ? 8 : 10;
|
|
11036
|
+
return {
|
|
11037
|
+
compactionThreshold,
|
|
11038
|
+
keepRecent,
|
|
11039
|
+
maxOutputTokens,
|
|
11040
|
+
toolOutputMaxChars,
|
|
11041
|
+
foldLineThreshold,
|
|
11042
|
+
foldHeadLines,
|
|
11043
|
+
foldTailLines,
|
|
11044
|
+
maxSummaryChars,
|
|
11045
|
+
repetitionWindow
|
|
11046
|
+
};
|
|
11047
|
+
}
|
|
11015
11048
|
/** Register a tool for the agent to use */
|
|
11016
11049
|
registerTool(tool) {
|
|
11017
11050
|
this.tools.set(tool.name, tool);
|
|
@@ -11093,7 +11126,8 @@ Rules:
|
|
|
11093
11126
|
detectRepetition(recentToolCalls) {
|
|
11094
11127
|
if (recentToolCalls.length < 4)
|
|
11095
11128
|
return 0;
|
|
11096
|
-
const
|
|
11129
|
+
const { repetitionWindow } = this.contextLimits();
|
|
11130
|
+
const window = recentToolCalls.slice(-repetitionWindow);
|
|
11097
11131
|
const uniqueKeys = new Set(window.map((tc) => `${tc.name}:${tc.argsKey}`));
|
|
11098
11132
|
const ratio = 1 - uniqueKeys.size / window.length;
|
|
11099
11133
|
return ratio;
|
|
@@ -11213,8 +11247,7 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
11213
11247
|
});
|
|
11214
11248
|
}
|
|
11215
11249
|
const compacted = this.compactMessages(messages);
|
|
11216
|
-
const
|
|
11217
|
-
const effectiveMaxTokens = ctxWindow > 0 ? Math.min(this.options.maxTokens, Math.max(2048, Math.floor(ctxWindow * 0.25))) : this.options.maxTokens;
|
|
11250
|
+
const { maxOutputTokens: effectiveMaxTokens } = this.contextLimits();
|
|
11218
11251
|
const chatRequest = {
|
|
11219
11252
|
messages: compacted,
|
|
11220
11253
|
tools: toolDefs,
|
|
@@ -11313,8 +11346,7 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
11313
11346
|
}
|
|
11314
11347
|
}
|
|
11315
11348
|
}
|
|
11316
|
-
const
|
|
11317
|
-
const maxLen = ctxW > 0 ? Math.max(2e3, Math.min(8e3, Math.floor(ctxW * 0.5))) : 8e3;
|
|
11349
|
+
const { toolOutputMaxChars: maxLen } = this.contextLimits();
|
|
11318
11350
|
const output = result.success ? result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : result.output : `Error: ${result.error || "unknown error"}
|
|
11319
11351
|
${result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : result.output}`;
|
|
11320
11352
|
this.emit({
|
|
@@ -11527,8 +11559,8 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
11527
11559
|
}
|
|
11528
11560
|
}
|
|
11529
11561
|
}
|
|
11530
|
-
const
|
|
11531
|
-
const output = result.success ? result.output.length >
|
|
11562
|
+
const { toolOutputMaxChars: maxLen2 } = this.contextLimits();
|
|
11563
|
+
const output = result.success ? result.output.length > maxLen2 ? result.output.slice(0, maxLen2) + `
|
|
11532
11564
|
...(truncated)` : result.output : `Error: ${result.error || "unknown error"}
|
|
11533
11565
|
${result.output}`;
|
|
11534
11566
|
this.emit({ type: "tool_result", toolName: tc.name, content: output.slice(0, 200), success: result.success, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
@@ -11629,11 +11661,12 @@ ${marker}` : marker);
|
|
|
11629
11661
|
// -------------------------------------------------------------------------
|
|
11630
11662
|
foldOutput(output, maxChars) {
|
|
11631
11663
|
const lines = output.split("\n");
|
|
11632
|
-
|
|
11664
|
+
const { foldLineThreshold, foldHeadLines, foldTailLines } = this.contextLimits();
|
|
11665
|
+
if (lines.length <= foldLineThreshold) {
|
|
11633
11666
|
return output.slice(0, maxChars) + "\n...(truncated)";
|
|
11634
11667
|
}
|
|
11635
|
-
const headLines =
|
|
11636
|
-
const tailLines =
|
|
11668
|
+
const headLines = foldHeadLines;
|
|
11669
|
+
const tailLines = foldTailLines;
|
|
11637
11670
|
const head = lines.slice(0, headLines).join("\n");
|
|
11638
11671
|
const tail = lines.slice(-tailLines).join("\n");
|
|
11639
11672
|
const omitted = lines.length - headLines - tailLines;
|
|
@@ -11662,13 +11695,11 @@ ${tail}`;
|
|
|
11662
11695
|
return sum;
|
|
11663
11696
|
}, 0);
|
|
11664
11697
|
const estimatedTokens = totalChars / 4;
|
|
11665
|
-
const
|
|
11666
|
-
|
|
11667
|
-
if (estimatedTokens < effectiveThreshold) {
|
|
11698
|
+
const limits = this.contextLimits();
|
|
11699
|
+
if (estimatedTokens < limits.compactionThreshold) {
|
|
11668
11700
|
return messages;
|
|
11669
11701
|
}
|
|
11670
|
-
const
|
|
11671
|
-
const keepRecent = ctxWin > 0 ? Math.max(4, Math.min(12, Math.floor(ctxWin / 4e3))) : 12;
|
|
11702
|
+
const keepRecent = limits.keepRecent;
|
|
11672
11703
|
const head = messages.slice(0, 2);
|
|
11673
11704
|
if (messages.length <= 2 + keepRecent)
|
|
11674
11705
|
return messages;
|
|
@@ -11722,13 +11753,13 @@ ${combinedSummary}
|
|
|
11722
11753
|
* When the combined text exceeds the budget, condense the older summary.
|
|
11723
11754
|
*/
|
|
11724
11755
|
progressiveSummarize(olderSummary, newerSummary) {
|
|
11725
|
-
const
|
|
11756
|
+
const { maxSummaryChars } = this.contextLimits();
|
|
11726
11757
|
const combined = `${olderSummary}
|
|
11727
11758
|
|
|
11728
11759
|
---
|
|
11729
11760
|
|
|
11730
11761
|
${newerSummary}`;
|
|
11731
|
-
if (combined.length <=
|
|
11762
|
+
if (combined.length <= maxSummaryChars) {
|
|
11732
11763
|
return combined;
|
|
11733
11764
|
}
|
|
11734
11765
|
const condensed = this.condenseSummary(olderSummary);
|
|
@@ -11737,8 +11768,8 @@ ${newerSummary}`;
|
|
|
11737
11768
|
---
|
|
11738
11769
|
|
|
11739
11770
|
${newerSummary}`;
|
|
11740
|
-
if (result.length >
|
|
11741
|
-
const budget =
|
|
11771
|
+
if (result.length > maxSummaryChars) {
|
|
11772
|
+
const budget = maxSummaryChars - newerSummary.length - 60;
|
|
11742
11773
|
return budget > 200 ? `[Earlier work, condensed]
|
|
11743
11774
|
${olderSummary.slice(0, budget)}...
|
|
11744
11775
|
|
|
@@ -15599,11 +15630,12 @@ async function doSetup(config, rl) {
|
|
|
15599
15630
|
const createModelfile = await ask(rl, ` Create optimized model "${c2.bold(customName)}" with ${ctx.label} context? (Y/n) `);
|
|
15600
15631
|
if (createModelfile.toLowerCase() !== "n") {
|
|
15601
15632
|
try {
|
|
15633
|
+
const numPredict = Math.min(16384, Math.max(2048, Math.floor(ctx.numCtx * 0.25)));
|
|
15602
15634
|
const modelfileContent = [
|
|
15603
15635
|
`FROM ${selectedVariant.tag}`,
|
|
15604
15636
|
`PARAMETER num_ctx ${ctx.numCtx}`,
|
|
15605
15637
|
`PARAMETER temperature 0`,
|
|
15606
|
-
`PARAMETER num_predict
|
|
15638
|
+
`PARAMETER num_predict ${numPredict}`,
|
|
15607
15639
|
`PARAMETER stop "<|endoftext|>"`
|
|
15608
15640
|
].join("\n");
|
|
15609
15641
|
const modelDir2 = join24(homedir9(), ".open-agents", "models");
|
|
@@ -16005,11 +16037,12 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
16005
16037
|
const customName = expandedModelName(baseModel);
|
|
16006
16038
|
const ctx = calculateContextWindow(specs, sizeGB);
|
|
16007
16039
|
try {
|
|
16040
|
+
const numPredict = Math.min(16384, Math.max(2048, Math.floor(ctx.numCtx * 0.25)));
|
|
16008
16041
|
const modelfileContent = [
|
|
16009
16042
|
`FROM ${baseModel}`,
|
|
16010
16043
|
`PARAMETER num_ctx ${ctx.numCtx}`,
|
|
16011
16044
|
`PARAMETER temperature 0`,
|
|
16012
|
-
`PARAMETER num_predict
|
|
16045
|
+
`PARAMETER num_predict ${numPredict}`,
|
|
16013
16046
|
`PARAMETER stop "<|endoftext|>"`
|
|
16014
16047
|
].join("\n");
|
|
16015
16048
|
const modelDir2 = join24(homedir9(), ".open-agents", "models");
|
|
@@ -20983,7 +21016,7 @@ function createTaskCompleteTool() {
|
|
|
20983
21016
|
}
|
|
20984
21017
|
};
|
|
20985
21018
|
}
|
|
20986
|
-
function buildTools(repoRoot, config) {
|
|
21019
|
+
function buildTools(repoRoot, config, contextWindowSize) {
|
|
20987
21020
|
const executionTools = [
|
|
20988
21021
|
new FileReadTool(repoRoot),
|
|
20989
21022
|
new FileWriteTool(repoRoot),
|
|
@@ -21044,11 +21077,11 @@ function buildTools(repoRoot, config) {
|
|
|
21044
21077
|
];
|
|
21045
21078
|
return [
|
|
21046
21079
|
...executionTools.map(adaptTool2),
|
|
21047
|
-
createSubAgentTool(config, repoRoot),
|
|
21080
|
+
createSubAgentTool(config, repoRoot, contextWindowSize),
|
|
21048
21081
|
createTaskCompleteTool()
|
|
21049
21082
|
];
|
|
21050
21083
|
}
|
|
21051
|
-
function createSubAgentTool(config, repoRoot) {
|
|
21084
|
+
function createSubAgentTool(config, repoRoot, ctxWindowSize) {
|
|
21052
21085
|
return {
|
|
21053
21086
|
name: "sub_agent",
|
|
21054
21087
|
description: "Delegate a sub-task to an independent agent with its own context window. Each sub-agent creates an independent backend connection, enabling TRUE PARALLEL inference when the backend supports concurrent requests (Ollama with OLLAMA_NUM_PARALLEL > 1). BEST PRACTICE: Launch multiple sub_agent calls with background=true in ONE response to maximize parallelism. Check results via task_status/task_output.",
|
|
@@ -21069,13 +21102,18 @@ function createSubAgentTool(config, repoRoot) {
|
|
|
21069
21102
|
return { success: false, output: "", error: "task is required" };
|
|
21070
21103
|
}
|
|
21071
21104
|
const backend = new OllamaAgenticBackend(config.backendUrl, config.model, config.apiKey);
|
|
21105
|
+
const subCtxWindow = ctxWindowSize ?? 0;
|
|
21106
|
+
const subTier = getModelTier(config.model);
|
|
21107
|
+
const subCompaction = subTier === "small" ? 12e3 : subTier === "medium" ? 24e3 : 4e4;
|
|
21072
21108
|
const subRunner = new AgenticRunner(backend, {
|
|
21073
21109
|
maxTurns,
|
|
21074
21110
|
maxTokens: 16384,
|
|
21075
21111
|
temperature: 0,
|
|
21076
21112
|
requestTimeoutMs: config.timeoutMs,
|
|
21077
21113
|
taskTimeoutMs: config.timeoutMs * 2,
|
|
21078
|
-
compactionThreshold:
|
|
21114
|
+
compactionThreshold: subCompaction,
|
|
21115
|
+
contextWindowSize: subCtxWindow,
|
|
21116
|
+
modelTier: subTier
|
|
21079
21117
|
});
|
|
21080
21118
|
const subTools = [
|
|
21081
21119
|
new FileReadTool(repoRoot),
|
|
@@ -21145,7 +21183,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
21145
21183
|
// effectively unlimited — no hard timeout, agent runs until complete or aborted
|
|
21146
21184
|
contextWindowSize: contextWindowSize ?? 0
|
|
21147
21185
|
});
|
|
21148
|
-
const tools = buildTools(repoRoot, config);
|
|
21186
|
+
const tools = buildTools(repoRoot, config, contextWindowSize);
|
|
21149
21187
|
if (contextWindowSize && contextWindowSize > 0) {
|
|
21150
21188
|
for (const tool of tools) {
|
|
21151
21189
|
if ("setContextWindowSize" in tool && typeof tool.setContextWindowSize === "function") {
|
package/package.json
CHANGED