open-agents-ai 0.25.0 → 0.27.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.
- package/dist/index.js +270 -20
- 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 {
|
|
@@ -6616,9 +6635,18 @@ var init_vision = __esm({
|
|
|
6616
6635
|
},
|
|
6617
6636
|
required: ["image"]
|
|
6618
6637
|
};
|
|
6638
|
+
/** Active Ollama model name — used as vision fallback if it has vision capability */
|
|
6639
|
+
_activeModel = "";
|
|
6640
|
+
/** Whether the active model has vision capability */
|
|
6641
|
+
_activeModelHasVision = false;
|
|
6619
6642
|
constructor(workingDir) {
|
|
6620
6643
|
this.workingDir = workingDir;
|
|
6621
6644
|
}
|
|
6645
|
+
/** Set the active Ollama model and whether it supports vision */
|
|
6646
|
+
setActiveModel(model, hasVision) {
|
|
6647
|
+
this._activeModel = model;
|
|
6648
|
+
this._activeModelHasVision = hasVision;
|
|
6649
|
+
}
|
|
6622
6650
|
async execute(args) {
|
|
6623
6651
|
const start = performance.now();
|
|
6624
6652
|
const rawPath = args["image"];
|
|
@@ -6719,7 +6747,8 @@ Coordinates are normalized (0-1). Multiply by image width/height for pixel value
|
|
|
6719
6747
|
}
|
|
6720
6748
|
async tryOllamaVision(buffer, filename, action, prompt, length, start) {
|
|
6721
6749
|
const ollamaHost = process.env["OLLAMA_HOST"] || "http://localhost:11434";
|
|
6722
|
-
const
|
|
6750
|
+
const envModel = process.env["OLLAMA_VISION_MODEL"];
|
|
6751
|
+
const model = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
|
|
6723
6752
|
const imageBase64 = buffer.toString("base64");
|
|
6724
6753
|
let ollamaPrompt;
|
|
6725
6754
|
switch (action) {
|
|
@@ -6946,7 +6975,16 @@ var init_desktop_click = __esm({
|
|
|
6946
6975
|
DesktopClickTool = class {
|
|
6947
6976
|
workingDir;
|
|
6948
6977
|
name = "desktop_click";
|
|
6949
|
-
description = "Click on a UI element identified by natural language description. Takes a screenshot, uses
|
|
6978
|
+
description = "Click on a UI element identified by natural language description. Takes a screenshot, uses vision to find the described element, then clicks at that location using xdotool (Linux) or cliclick (macOS). Example: desktop_click({ target: 'the Save button' })";
|
|
6979
|
+
/** Active Ollama model name — used as vision fallback if it has vision capability */
|
|
6980
|
+
_activeModel = "";
|
|
6981
|
+
/** Whether the active model has vision capability */
|
|
6982
|
+
_activeModelHasVision = false;
|
|
6983
|
+
/** Set the active Ollama model and whether it supports vision */
|
|
6984
|
+
setActiveModel(model, hasVision) {
|
|
6985
|
+
this._activeModel = model;
|
|
6986
|
+
this._activeModelHasVision = hasVision;
|
|
6987
|
+
}
|
|
6950
6988
|
parameters = {
|
|
6951
6989
|
type: "object",
|
|
6952
6990
|
properties: {
|
|
@@ -7031,7 +7069,8 @@ var init_desktop_click = __esm({
|
|
|
7031
7069
|
if (!visionWorked) {
|
|
7032
7070
|
try {
|
|
7033
7071
|
const ollamaHost = process.env["OLLAMA_HOST"] || "http://localhost:11434";
|
|
7034
|
-
const
|
|
7072
|
+
const envModel = process.env["OLLAMA_VISION_MODEL"];
|
|
7073
|
+
const ollamaModel = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
|
|
7035
7074
|
const imageBase64 = readFileSync11(screenshotPath).toString("base64");
|
|
7036
7075
|
const res = await fetch(`${ollamaHost}/api/generate`, {
|
|
7037
7076
|
method: "POST",
|
|
@@ -7129,7 +7168,16 @@ Screenshot: ${screenshotPath}`,
|
|
|
7129
7168
|
DesktopDescribeTool = class {
|
|
7130
7169
|
workingDir;
|
|
7131
7170
|
name = "desktop_describe";
|
|
7132
|
-
description = "Take a screenshot and describe what's on the desktop using
|
|
7171
|
+
description = "Take a screenshot and describe what's on the desktop using vision. Optionally ask a specific question about the screen contents. Use this to become aware of the desktop environment.";
|
|
7172
|
+
/** Active Ollama model name — used as vision fallback if it has vision capability */
|
|
7173
|
+
_activeModel = "";
|
|
7174
|
+
/** Whether the active model has vision capability */
|
|
7175
|
+
_activeModelHasVision = false;
|
|
7176
|
+
/** Set the active Ollama model and whether it supports vision */
|
|
7177
|
+
setActiveModel(model, hasVision) {
|
|
7178
|
+
this._activeModel = model;
|
|
7179
|
+
this._activeModelHasVision = hasVision;
|
|
7180
|
+
}
|
|
7133
7181
|
parameters = {
|
|
7134
7182
|
type: "object",
|
|
7135
7183
|
properties: {
|
|
@@ -7195,7 +7243,8 @@ ${caption}`);
|
|
|
7195
7243
|
if (!visionWorked) {
|
|
7196
7244
|
try {
|
|
7197
7245
|
const ollamaHost = process.env["OLLAMA_HOST"] || "http://localhost:11434";
|
|
7198
|
-
const
|
|
7246
|
+
const envModel = process.env["OLLAMA_VISION_MODEL"];
|
|
7247
|
+
const ollamaModel = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
|
|
7199
7248
|
const imageBase64 = imageBuffer.toString("base64");
|
|
7200
7249
|
const ollamaPrompt = question || "Describe what you see on this desktop screenshot in detail. Include visible applications, windows, text, and UI elements.";
|
|
7201
7250
|
const res = await fetch(`${ollamaHost}/api/generate`, {
|
|
@@ -10299,9 +10348,14 @@ Rules:
|
|
|
10299
10348
|
streamEnabled: options?.streamEnabled ?? false,
|
|
10300
10349
|
bruteForce: options?.bruteForce ?? true,
|
|
10301
10350
|
bruteForceMaxCycles: options?.bruteForceMaxCycles ?? 100,
|
|
10302
|
-
modelTier: options?.modelTier ?? "large"
|
|
10351
|
+
modelTier: options?.modelTier ?? "large",
|
|
10352
|
+
contextWindowSize: options?.contextWindowSize ?? 0
|
|
10303
10353
|
};
|
|
10304
10354
|
}
|
|
10355
|
+
/** Update context window size (e.g. after querying Ollama /api/show) */
|
|
10356
|
+
setContextWindowSize(size) {
|
|
10357
|
+
this.options.contextWindowSize = size;
|
|
10358
|
+
}
|
|
10305
10359
|
/** Register a tool for the agent to use */
|
|
10306
10360
|
registerTool(tool) {
|
|
10307
10361
|
this.tools.set(tool.name, tool);
|
|
@@ -10455,11 +10509,13 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
10455
10509
|
});
|
|
10456
10510
|
}
|
|
10457
10511
|
const compacted = this.compactMessages(messages);
|
|
10512
|
+
const ctxWindow = this.options.contextWindowSize;
|
|
10513
|
+
const effectiveMaxTokens = ctxWindow > 0 ? Math.min(this.options.maxTokens, Math.max(2048, Math.floor(ctxWindow * 0.25))) : this.options.maxTokens;
|
|
10458
10514
|
const chatRequest = {
|
|
10459
10515
|
messages: compacted,
|
|
10460
10516
|
tools: toolDefs,
|
|
10461
10517
|
temperature: this.options.temperature,
|
|
10462
|
-
maxTokens:
|
|
10518
|
+
maxTokens: effectiveMaxTokens,
|
|
10463
10519
|
timeoutMs: this.options.requestTimeoutMs
|
|
10464
10520
|
};
|
|
10465
10521
|
let response;
|
|
@@ -10553,10 +10609,10 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
10553
10609
|
}
|
|
10554
10610
|
}
|
|
10555
10611
|
}
|
|
10556
|
-
const
|
|
10557
|
-
const
|
|
10558
|
-
|
|
10559
|
-
${result.output}`;
|
|
10612
|
+
const ctxW = this.options.contextWindowSize;
|
|
10613
|
+
const maxLen = ctxW > 0 ? Math.max(2e3, Math.min(8e3, Math.floor(ctxW * 0.5))) : 8e3;
|
|
10614
|
+
const output = result.success ? result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : result.output : `Error: ${result.error || "unknown error"}
|
|
10615
|
+
${result.output.length > maxLen ? this.foldOutput(result.output, maxLen) : result.output}`;
|
|
10560
10616
|
this.emit({
|
|
10561
10617
|
type: "tool_result",
|
|
10562
10618
|
toolName: tc.name,
|
|
@@ -10862,6 +10918,29 @@ ${marker}` : marker);
|
|
|
10862
10918
|
return { role: "tool", content: output, tool_call_id: toolCallId };
|
|
10863
10919
|
}
|
|
10864
10920
|
// -------------------------------------------------------------------------
|
|
10921
|
+
// Output folding — keep head + tail, omit middle (preserves errors at end)
|
|
10922
|
+
// -------------------------------------------------------------------------
|
|
10923
|
+
foldOutput(output, maxChars) {
|
|
10924
|
+
const lines = output.split("\n");
|
|
10925
|
+
if (lines.length <= 40) {
|
|
10926
|
+
return output.slice(0, maxChars) + "\n...(truncated)";
|
|
10927
|
+
}
|
|
10928
|
+
const headLines = 20;
|
|
10929
|
+
const tailLines = 10;
|
|
10930
|
+
const head = lines.slice(0, headLines).join("\n");
|
|
10931
|
+
const tail = lines.slice(-tailLines).join("\n");
|
|
10932
|
+
const omitted = lines.length - headLines - tailLines;
|
|
10933
|
+
const folded = `${head}
|
|
10934
|
+
|
|
10935
|
+
[... ${omitted} lines omitted ...]
|
|
10936
|
+
|
|
10937
|
+
${tail}`;
|
|
10938
|
+
if (folded.length > maxChars) {
|
|
10939
|
+
return folded.slice(0, maxChars) + "\n...(truncated)";
|
|
10940
|
+
}
|
|
10941
|
+
return folded;
|
|
10942
|
+
}
|
|
10943
|
+
// -------------------------------------------------------------------------
|
|
10865
10944
|
// Context compaction
|
|
10866
10945
|
// -------------------------------------------------------------------------
|
|
10867
10946
|
compactMessages(messages) {
|
|
@@ -10879,7 +10958,8 @@ ${marker}` : marker);
|
|
|
10879
10958
|
if (estimatedTokens < this.options.compactionThreshold) {
|
|
10880
10959
|
return messages;
|
|
10881
10960
|
}
|
|
10882
|
-
const
|
|
10961
|
+
const ctxWin = this.options.contextWindowSize;
|
|
10962
|
+
const keepRecent = ctxWin > 0 ? Math.max(4, Math.min(12, Math.floor(ctxWin / 4e3))) : 12;
|
|
10883
10963
|
const head = messages.slice(0, 2);
|
|
10884
10964
|
if (messages.length <= 2 + keepRecent)
|
|
10885
10965
|
return messages;
|
|
@@ -12733,6 +12813,52 @@ async function queryContextSize(baseUrl, modelName, apiKey) {
|
|
|
12733
12813
|
return ollamaSize;
|
|
12734
12814
|
return queryOpenAIContextSize(baseUrl, modelName, apiKey);
|
|
12735
12815
|
}
|
|
12816
|
+
async function queryModelCapabilities(baseUrl, modelName) {
|
|
12817
|
+
const caps = { vision: false, toolUse: false, thinking: false };
|
|
12818
|
+
try {
|
|
12819
|
+
const normalized = normalizeBaseUrl(baseUrl);
|
|
12820
|
+
const res = await fetch(`${normalized}/api/show`, {
|
|
12821
|
+
method: "POST",
|
|
12822
|
+
headers: { "Content-Type": "application/json" },
|
|
12823
|
+
body: JSON.stringify({ name: modelName }),
|
|
12824
|
+
signal: AbortSignal.timeout(1e4)
|
|
12825
|
+
});
|
|
12826
|
+
if (!res.ok)
|
|
12827
|
+
return caps;
|
|
12828
|
+
const data = await res.json();
|
|
12829
|
+
if (Array.isArray(data.capabilities)) {
|
|
12830
|
+
if (data.capabilities.includes("vision"))
|
|
12831
|
+
caps.vision = true;
|
|
12832
|
+
if (data.capabilities.includes("tools"))
|
|
12833
|
+
caps.toolUse = true;
|
|
12834
|
+
if (data.capabilities.includes("thinking"))
|
|
12835
|
+
caps.thinking = true;
|
|
12836
|
+
}
|
|
12837
|
+
if (data.model_info) {
|
|
12838
|
+
for (const key of Object.keys(data.model_info)) {
|
|
12839
|
+
const k = key.toLowerCase();
|
|
12840
|
+
if (k.includes("vision.block_count") || k.includes("clip.") || k.includes("image_token_id") || k.includes("projector") || k.includes("vision.embedding_length")) {
|
|
12841
|
+
const val = data.model_info[key];
|
|
12842
|
+
if (val !== null && val !== void 0 && val !== 0 && val !== "") {
|
|
12843
|
+
caps.vision = true;
|
|
12844
|
+
}
|
|
12845
|
+
}
|
|
12846
|
+
}
|
|
12847
|
+
}
|
|
12848
|
+
const nameLower = modelName.toLowerCase();
|
|
12849
|
+
if (/qwen3|qwen2\.5|llama3\.[13]|mistral|mixtral|command-r|gemma3|devstral|deepseek/.test(nameLower)) {
|
|
12850
|
+
caps.toolUse = true;
|
|
12851
|
+
}
|
|
12852
|
+
if (data.template) {
|
|
12853
|
+
if (data.template.includes("<think>") || data.template.includes("thinking")) {
|
|
12854
|
+
caps.thinking = true;
|
|
12855
|
+
}
|
|
12856
|
+
}
|
|
12857
|
+
return caps;
|
|
12858
|
+
} catch {
|
|
12859
|
+
return caps;
|
|
12860
|
+
}
|
|
12861
|
+
}
|
|
12736
12862
|
function formatBytes(bytes) {
|
|
12737
12863
|
if (bytes < 1024)
|
|
12738
12864
|
return `${bytes} B`;
|
|
@@ -14635,6 +14761,63 @@ function isFirstRun() {
|
|
|
14635
14761
|
return true;
|
|
14636
14762
|
}
|
|
14637
14763
|
}
|
|
14764
|
+
async function ensureVisionDeps(onInfo) {
|
|
14765
|
+
const log = onInfo ?? (() => {
|
|
14766
|
+
});
|
|
14767
|
+
try {
|
|
14768
|
+
execSync13("which tesseract", { stdio: "pipe", timeout: 3e3 });
|
|
14769
|
+
} catch {
|
|
14770
|
+
log("Installing tesseract-ocr...");
|
|
14771
|
+
try {
|
|
14772
|
+
const cmds = [
|
|
14773
|
+
"sudo -n apt-get install -y tesseract-ocr 2>/dev/null",
|
|
14774
|
+
"sudo -n dnf install -y tesseract 2>/dev/null",
|
|
14775
|
+
"sudo -n pacman -S --noconfirm tesseract 2>/dev/null",
|
|
14776
|
+
"brew install tesseract 2>/dev/null"
|
|
14777
|
+
];
|
|
14778
|
+
let installed = false;
|
|
14779
|
+
for (const cmd of cmds) {
|
|
14780
|
+
try {
|
|
14781
|
+
execSync13(cmd, { stdio: "pipe", timeout: 6e4 });
|
|
14782
|
+
installed = true;
|
|
14783
|
+
break;
|
|
14784
|
+
} catch {
|
|
14785
|
+
}
|
|
14786
|
+
}
|
|
14787
|
+
if (installed)
|
|
14788
|
+
log("Tesseract installed.");
|
|
14789
|
+
else
|
|
14790
|
+
log("Could not auto-install tesseract (install manually: sudo apt install tesseract-ocr)");
|
|
14791
|
+
} catch {
|
|
14792
|
+
}
|
|
14793
|
+
}
|
|
14794
|
+
try {
|
|
14795
|
+
execSync13("which moondream-station", { stdio: "pipe", timeout: 3e3 });
|
|
14796
|
+
} catch {
|
|
14797
|
+
log("Installing moondream-station...");
|
|
14798
|
+
try {
|
|
14799
|
+
const pipCmds = [
|
|
14800
|
+
"pip3 install moondream-station 2>/dev/null",
|
|
14801
|
+
"pip install moondream-station 2>/dev/null",
|
|
14802
|
+
"python3 -m pip install moondream-station 2>/dev/null"
|
|
14803
|
+
];
|
|
14804
|
+
let installed = false;
|
|
14805
|
+
for (const cmd of pipCmds) {
|
|
14806
|
+
try {
|
|
14807
|
+
execSync13(cmd, { stdio: "pipe", timeout: 12e4 });
|
|
14808
|
+
installed = true;
|
|
14809
|
+
break;
|
|
14810
|
+
} catch {
|
|
14811
|
+
}
|
|
14812
|
+
}
|
|
14813
|
+
if (installed)
|
|
14814
|
+
log("moondream-station installed.");
|
|
14815
|
+
else
|
|
14816
|
+
log("Could not auto-install moondream-station (install manually: pip install moondream-station)");
|
|
14817
|
+
} catch {
|
|
14818
|
+
}
|
|
14819
|
+
}
|
|
14820
|
+
}
|
|
14638
14821
|
function expandedModelName(baseModel) {
|
|
14639
14822
|
return `open-agents-${baseModel.replace(":", "-").replace(/\./g, "")}`;
|
|
14640
14823
|
}
|
|
@@ -15434,6 +15617,10 @@ async function switchModel(query, ctx, local = false) {
|
|
|
15434
15617
|
ctx.setContextWindowSize(ctxSize);
|
|
15435
15618
|
}
|
|
15436
15619
|
}
|
|
15620
|
+
if (ctx.setCapabilities) {
|
|
15621
|
+
const caps = await queryModelCapabilities(ctx.config.backendUrl, finalModel);
|
|
15622
|
+
ctx.setCapabilities(caps);
|
|
15623
|
+
}
|
|
15437
15624
|
} catch (err) {
|
|
15438
15625
|
renderError(`Failed to switch model: ${err instanceof Error ? err.message : String(err)}`);
|
|
15439
15626
|
}
|
|
@@ -18616,6 +18803,18 @@ var init_status_bar = __esm({
|
|
|
18616
18803
|
setContextWindowSize(size) {
|
|
18617
18804
|
this.metrics.contextWindowSize = size;
|
|
18618
18805
|
}
|
|
18806
|
+
/** Model capabilities — shown as emoji indicators on the status bar */
|
|
18807
|
+
_caps = {
|
|
18808
|
+
vision: false,
|
|
18809
|
+
toolUse: false,
|
|
18810
|
+
thinking: false
|
|
18811
|
+
};
|
|
18812
|
+
/** Update model capability indicators */
|
|
18813
|
+
setCapabilities(caps) {
|
|
18814
|
+
this._caps = caps;
|
|
18815
|
+
if (this.active)
|
|
18816
|
+
this.renderFooterPreserveCursor();
|
|
18817
|
+
}
|
|
18619
18818
|
/** Update token metrics from a token_usage event */
|
|
18620
18819
|
updateMetrics(update) {
|
|
18621
18820
|
if (update.promptTokens !== void 0)
|
|
@@ -18772,7 +18971,15 @@ var init_status_bar = __esm({
|
|
|
18772
18971
|
const countdown = this._countdown > 0 ? c2.dim(` ${this._countdown}s`) : "";
|
|
18773
18972
|
recordingLabel = pipe + dot + pastel2(210, " REC") + countdown;
|
|
18774
18973
|
}
|
|
18775
|
-
|
|
18974
|
+
const capParts = [];
|
|
18975
|
+
if (this._caps.vision)
|
|
18976
|
+
capParts.push("\u{1F441}");
|
|
18977
|
+
if (this._caps.toolUse)
|
|
18978
|
+
capParts.push("\u{1F527}");
|
|
18979
|
+
if (this._caps.thinking)
|
|
18980
|
+
capParts.push("\u{1F9E0}");
|
|
18981
|
+
const capsLabel = capParts.length > 0 ? pipe + pastel2(183, capParts.join(" ")) : "";
|
|
18982
|
+
return ` ${tokInLabel}${pipe}${tokOutLabel}${pipe}${ctxLabel}${costLabel}${capsLabel}${recordingLabel}`;
|
|
18776
18983
|
}
|
|
18777
18984
|
// -------------------------------------------------------------------------
|
|
18778
18985
|
// Private
|
|
@@ -19107,7 +19314,7 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
19107
19314
|
}
|
|
19108
19315
|
};
|
|
19109
19316
|
}
|
|
19110
|
-
function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType) {
|
|
19317
|
+
function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps) {
|
|
19111
19318
|
const modelTier = getModelTier(config.model);
|
|
19112
19319
|
const projectCtx = buildProjectContext(repoRoot, taskStores?.contextStores);
|
|
19113
19320
|
let dynamicContext = formatContextForPrompt(projectCtx, modelTier);
|
|
@@ -19128,10 +19335,25 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
19128
19335
|
modelTier,
|
|
19129
19336
|
streamEnabled: stream?.enabled ?? false,
|
|
19130
19337
|
bruteForce: bruteForce ?? true,
|
|
19131
|
-
bruteForceMaxCycles: 100
|
|
19338
|
+
bruteForceMaxCycles: 100,
|
|
19132
19339
|
// effectively unlimited — hard timeout is the real bound
|
|
19340
|
+
contextWindowSize: contextWindowSize ?? 0
|
|
19133
19341
|
});
|
|
19134
|
-
|
|
19342
|
+
const tools = buildTools(repoRoot, config);
|
|
19343
|
+
if (contextWindowSize && contextWindowSize > 0) {
|
|
19344
|
+
for (const tool of tools) {
|
|
19345
|
+
if ("setContextWindowSize" in tool && typeof tool.setContextWindowSize === "function") {
|
|
19346
|
+
tool.setContextWindowSize(contextWindowSize);
|
|
19347
|
+
}
|
|
19348
|
+
}
|
|
19349
|
+
}
|
|
19350
|
+
const hasVision = modelCaps?.vision ?? false;
|
|
19351
|
+
for (const tool of tools) {
|
|
19352
|
+
if ("setActiveModel" in tool && typeof tool.setActiveModel === "function") {
|
|
19353
|
+
tool.setActiveModel(config.model, hasVision);
|
|
19354
|
+
}
|
|
19355
|
+
}
|
|
19356
|
+
runner.registerTools(tools);
|
|
19135
19357
|
const filesTouched = /* @__PURE__ */ new Set();
|
|
19136
19358
|
const toolSequence = [];
|
|
19137
19359
|
const editSessionId = `task-${Date.now()}`;
|
|
@@ -19422,9 +19644,22 @@ async function startInteractive(config, repoPath) {
|
|
|
19422
19644
|
end: () => statusBar.endContentWrite()
|
|
19423
19645
|
});
|
|
19424
19646
|
}
|
|
19647
|
+
let resolvedContextWindowSize = 0;
|
|
19425
19648
|
queryContextSize(config.backendUrl, config.model, config.apiKey).then((ctxSize) => {
|
|
19426
|
-
if (ctxSize)
|
|
19649
|
+
if (ctxSize) {
|
|
19650
|
+
resolvedContextWindowSize = ctxSize;
|
|
19427
19651
|
statusBar.setContextWindowSize(ctxSize);
|
|
19652
|
+
}
|
|
19653
|
+
}).catch(() => {
|
|
19654
|
+
});
|
|
19655
|
+
let resolvedCaps = {
|
|
19656
|
+
vision: false,
|
|
19657
|
+
toolUse: false,
|
|
19658
|
+
thinking: false
|
|
19659
|
+
};
|
|
19660
|
+
queryModelCapabilities(config.backendUrl, config.model).then((caps) => {
|
|
19661
|
+
resolvedCaps = caps;
|
|
19662
|
+
statusBar.setCapabilities(caps);
|
|
19428
19663
|
}).catch(() => {
|
|
19429
19664
|
});
|
|
19430
19665
|
const provider = detectProvider(config.backendUrl);
|
|
@@ -19432,6 +19667,14 @@ async function startInteractive(config, repoPath) {
|
|
|
19432
19667
|
const sessionMetrics = new SessionMetrics();
|
|
19433
19668
|
const workEvaluator = new WorkEvaluator();
|
|
19434
19669
|
ensureTranscribeCliBackground();
|
|
19670
|
+
ensureVisionDeps((msg) => {
|
|
19671
|
+
if (statusBar?.isActive) {
|
|
19672
|
+
statusBar.beginContentWrite();
|
|
19673
|
+
renderInfo(msg);
|
|
19674
|
+
statusBar.endContentWrite();
|
|
19675
|
+
}
|
|
19676
|
+
}).catch(() => {
|
|
19677
|
+
});
|
|
19435
19678
|
const voiceEngine = new VoiceEngine();
|
|
19436
19679
|
const streamRenderer = new StreamRenderer();
|
|
19437
19680
|
if (savedSettings.voice) {
|
|
@@ -19725,7 +19968,14 @@ async function startInteractive(config, repoPath) {
|
|
|
19725
19968
|
setEmojis: (enabled) => setEmojisEnabled(enabled),
|
|
19726
19969
|
getColors: () => getColorsEnabled(),
|
|
19727
19970
|
setColors: (enabled) => setColorsEnabled(enabled),
|
|
19728
|
-
setContextWindowSize: (size) =>
|
|
19971
|
+
setContextWindowSize: (size) => {
|
|
19972
|
+
resolvedContextWindowSize = size;
|
|
19973
|
+
statusBar.setContextWindowSize(size);
|
|
19974
|
+
},
|
|
19975
|
+
setCapabilities: (caps) => {
|
|
19976
|
+
resolvedCaps = caps;
|
|
19977
|
+
statusBar.setCapabilities(caps);
|
|
19978
|
+
},
|
|
19729
19979
|
hasActiveTask: () => activeTask !== null,
|
|
19730
19980
|
abortTask() {
|
|
19731
19981
|
if (!activeTask)
|
|
@@ -19881,7 +20131,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
19881
20131
|
toolPatternStore: toolPatternStore ?? void 0
|
|
19882
20132
|
}, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary) => {
|
|
19883
20133
|
lastCompletedSummary = summary;
|
|
19884
|
-
}, currentTaskType);
|
|
20134
|
+
}, currentTaskType, resolvedContextWindowSize, resolvedCaps);
|
|
19885
20135
|
activeTask = task;
|
|
19886
20136
|
showPrompt();
|
|
19887
20137
|
await task.promise;
|
|
@@ -19983,7 +20233,7 @@ Summarize or analyze this transcription as appropriate.`;
|
|
|
19983
20233
|
toolPatternStore: toolPatternStore ?? void 0
|
|
19984
20234
|
}, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary) => {
|
|
19985
20235
|
lastCompletedSummary = summary;
|
|
19986
|
-
}, currentTaskType);
|
|
20236
|
+
}, currentTaskType, resolvedContextWindowSize, resolvedCaps);
|
|
19987
20237
|
activeTask = task;
|
|
19988
20238
|
showPrompt();
|
|
19989
20239
|
await task.promise;
|
package/package.json
CHANGED