@holoscript/holoscript-agent 2.1.1 → 2.1.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 +75 -2
- package/dist/index.js.map +1 -1
- package/dist/runner.js +75 -2
- package/dist/runner.js.map +1 -1
- package/dist/supervisor.js +75 -2
- package/dist/supervisor.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -941,6 +941,8 @@ function isProductiveToolUse(use) {
|
|
|
941
941
|
return true;
|
|
942
942
|
case "str_replace":
|
|
943
943
|
return true;
|
|
944
|
+
case "vision_analyze":
|
|
945
|
+
return true;
|
|
944
946
|
default:
|
|
945
947
|
return false;
|
|
946
948
|
}
|
|
@@ -1077,6 +1079,28 @@ var MESH_TOOLS = [
|
|
|
1077
1079
|
},
|
|
1078
1080
|
required: ["title"]
|
|
1079
1081
|
}
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
name: "vision_analyze",
|
|
1085
|
+
description: "Analyze an image using the local Fara-7B vision model (Ollama on loopback). Reads the image file at `image_path`, sends it to fara:7b via the local Ollama API, and returns the model's text analysis. Counts as a productive tool call \u2014 use for GUI-grounding, visual QA, image captioning, or any task that requires perceiving image content. Only available on surfaces with a local Ollama instance running fara:7b.",
|
|
1086
|
+
input_schema: {
|
|
1087
|
+
type: "object",
|
|
1088
|
+
properties: {
|
|
1089
|
+
image_path: {
|
|
1090
|
+
type: "string",
|
|
1091
|
+
description: "Absolute path to the image file (png, jpg, webp, gif)"
|
|
1092
|
+
},
|
|
1093
|
+
prompt: {
|
|
1094
|
+
type: "string",
|
|
1095
|
+
description: 'Instruction for the vision model (default: "Describe this image in detail.")'
|
|
1096
|
+
},
|
|
1097
|
+
model: {
|
|
1098
|
+
type: "string",
|
|
1099
|
+
description: 'Ollama model tag to use (default: "fara:7b")'
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
required: ["image_path"]
|
|
1103
|
+
}
|
|
1080
1104
|
}
|
|
1081
1105
|
];
|
|
1082
1106
|
function resolveActiveTools(brain, opts = {}) {
|
|
@@ -1320,6 +1344,49 @@ ${truncated}`);
|
|
|
1320
1344
|
const result = await opts.addTask([{ title, description, priority: priority2, source, tags }]);
|
|
1321
1345
|
return okResult(use.id, `delegate_task: posted "${title}" to board \u2014 ${result.added} task(s) added`);
|
|
1322
1346
|
}
|
|
1347
|
+
if (use.name === "vision_analyze") {
|
|
1348
|
+
const imagePath = String(use.input.image_path ?? "").trim();
|
|
1349
|
+
if (!imagePath) return errResult(use.id, "vision_analyze: image_path is required");
|
|
1350
|
+
const denied = checkReadAllowed(imagePath);
|
|
1351
|
+
if (denied) return errResult(use.id, `vision_analyze: ${denied}`);
|
|
1352
|
+
const prompt = String(use.input.prompt ?? "Describe this image in detail.");
|
|
1353
|
+
const model = String(use.input.model ?? "fara:7b");
|
|
1354
|
+
const ollamaBase = process.env.HOLOSCRIPT_AGENT_LOCAL_LLM_BASE_URL;
|
|
1355
|
+
if (!ollamaBase) {
|
|
1356
|
+
return errResult(
|
|
1357
|
+
use.id,
|
|
1358
|
+
"vision_analyze: HOLOSCRIPT_AGENT_LOCAL_LLM_BASE_URL is not set \u2014 configure it to point to your local Ollama instance (e.g. http://holojetson.local:11434)"
|
|
1359
|
+
);
|
|
1360
|
+
}
|
|
1361
|
+
const TIMEOUT_MS = 12e4;
|
|
1362
|
+
const controller = new AbortController();
|
|
1363
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
1364
|
+
try {
|
|
1365
|
+
const imageBytes = await readFile3(imagePath);
|
|
1366
|
+
const imageB64 = imageBytes.toString("base64");
|
|
1367
|
+
const res = await fetch(`${ollamaBase}/api/generate`, {
|
|
1368
|
+
method: "POST",
|
|
1369
|
+
headers: { "content-type": "application/json" },
|
|
1370
|
+
body: JSON.stringify({ model, prompt, images: [imageB64], stream: false }),
|
|
1371
|
+
signal: controller.signal
|
|
1372
|
+
});
|
|
1373
|
+
clearTimeout(timer);
|
|
1374
|
+
if (!res.ok) {
|
|
1375
|
+
const text = await res.text();
|
|
1376
|
+
return errResult(use.id, `vision_analyze: Ollama HTTP ${res.status}: ${text.slice(0, 500)}`);
|
|
1377
|
+
}
|
|
1378
|
+
const json = await res.json();
|
|
1379
|
+
if (json.error) return errResult(use.id, `vision_analyze: model error \u2014 ${json.error}`);
|
|
1380
|
+
return okResult(use.id, json.response ?? "");
|
|
1381
|
+
} catch (err) {
|
|
1382
|
+
clearTimeout(timer);
|
|
1383
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1384
|
+
return errResult(
|
|
1385
|
+
use.id,
|
|
1386
|
+
msg.includes("abort") ? `vision_analyze: timed out after ${TIMEOUT_MS}ms` : `vision_analyze: ${msg}`
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1323
1390
|
return errResult(use.id, `unknown tool: ${use.name}`);
|
|
1324
1391
|
} catch (err) {
|
|
1325
1392
|
return errResult(use.id, err instanceof Error ? err.message : String(err));
|
|
@@ -1735,12 +1802,18 @@ var AgentRunner = class {
|
|
|
1735
1802
|
}
|
|
1736
1803
|
if (productiveCallCount === 0 && toolsCalled.size > 0 && iters < MAX_TOOL_ITERS) {
|
|
1737
1804
|
iters++;
|
|
1805
|
+
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
|
1806
|
+
messages.pop();
|
|
1807
|
+
}
|
|
1738
1808
|
messages.push({
|
|
1739
1809
|
role: "user",
|
|
1740
|
-
content:
|
|
1810
|
+
content: `You read data but did NOT call write_file. This is a TASK FAILURE unless you act now.
|
|
1811
|
+
Task: ${target.title}
|
|
1812
|
+
Required output path (from task description): ${target.description.match(/path[:\s]+([^\s\n,]+\.json)/i)?.[1] ?? "see task description"}
|
|
1813
|
+
Call write_file NOW. Embed ALL data from the tool result above into the content. Do NOT output any text \u2014 your ONLY valid response is a write_file tool call.`
|
|
1741
1814
|
});
|
|
1742
1815
|
const reResp = await provider.complete(
|
|
1743
|
-
{ messages, maxTokens: 8192, temperature: 0
|
|
1816
|
+
{ messages, maxTokens: 8192, temperature: 0, tools: activeTools },
|
|
1744
1817
|
identity.llmModel
|
|
1745
1818
|
);
|
|
1746
1819
|
aggUsage = {
|