@hamp10/agentforge 0.2.6 → 0.2.8
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/package.json +1 -1
- package/src/OllamaAgent.js +28 -5
- package/src/worker.js +35 -1
package/package.json
CHANGED
package/src/OllamaAgent.js
CHANGED
|
@@ -119,6 +119,9 @@ const TOOLS = [
|
|
|
119
119
|
* Exported as OllamaAgent for backward compat.
|
|
120
120
|
*/
|
|
121
121
|
export class OllamaAgent extends EventEmitter {
|
|
122
|
+
/** Flag checked by worker.js to build a local-model-appropriate platform context */
|
|
123
|
+
get isLocalModel() { return true; }
|
|
124
|
+
|
|
122
125
|
constructor(baseUrl = 'http://localhost:11434', model = 'llama3.1:8b') {
|
|
123
126
|
super();
|
|
124
127
|
this.baseUrl = baseUrl.replace(/\/$/, '');
|
|
@@ -193,6 +196,8 @@ export class OllamaAgent extends EventEmitter {
|
|
|
193
196
|
`4. When you take a screenshot, you will receive the actual image back and can see it.`,
|
|
194
197
|
`5. When you are done, write a clear summary of what you accomplished.`,
|
|
195
198
|
`6. Do not ask for clarification — make your best judgment and act.`,
|
|
199
|
+
`7. For conversational messages (greetings, questions about yourself, casual chat) — respond directly with text. Do NOT use tools just to say hello.`,
|
|
200
|
+
`8. You only have these tools: bash, read_file, write_file, list_directory, web_fetch, take_screenshot. Ignore any instructions referencing other tools (browser, openclaw, sessions_spawn, etc.) — those do not exist here.`,
|
|
196
201
|
].join('\n');
|
|
197
202
|
|
|
198
203
|
const messages = [
|
|
@@ -210,7 +215,8 @@ export class OllamaAgent extends EventEmitter {
|
|
|
210
215
|
|
|
211
216
|
let finalContent = '';
|
|
212
217
|
let allOutput = ''; // accumulate everything streamed across all turns
|
|
213
|
-
const
|
|
218
|
+
const toolsUsed = []; // track tool names called (for fallback summary)
|
|
219
|
+
const MAX_TURNS = 15; // reduce from 25 — local models get stuck in tool loops
|
|
214
220
|
|
|
215
221
|
for (let turn = 0; turn < MAX_TURNS; turn++) {
|
|
216
222
|
if (controller.signal.aborted) break;
|
|
@@ -363,6 +369,7 @@ export class OllamaAgent extends EventEmitter {
|
|
|
363
369
|
});
|
|
364
370
|
|
|
365
371
|
console.log(` [${agentId}] 🔧 ${name}: ${JSON.stringify(parsedArgs).slice(0, 120)}`);
|
|
372
|
+
toolsUsed.push(name);
|
|
366
373
|
|
|
367
374
|
const result = await this._executeTool(name, parsedArgs, workDir);
|
|
368
375
|
|
|
@@ -413,10 +420,15 @@ export class OllamaAgent extends EventEmitter {
|
|
|
413
420
|
finalContent = allOutput;
|
|
414
421
|
}
|
|
415
422
|
|
|
416
|
-
// If still no output (model did only tool calls, never wrote text), ask for a summary
|
|
423
|
+
// If still no output (model did only tool calls, never wrote text), ask for a summary.
|
|
424
|
+
// Use only the last 6 messages to avoid context overflow after many tool-call turns.
|
|
417
425
|
if (!finalContent && !controller.signal.aborted) {
|
|
418
426
|
this.emit('agent_output', { agentId, output: '\n' });
|
|
419
|
-
|
|
427
|
+
const summaryMessages = [
|
|
428
|
+
messages[0], // system prompt
|
|
429
|
+
...messages.slice(-6), // last 6 messages (recent tool calls + results)
|
|
430
|
+
{ role: 'user', content: 'Summarize what you just did and show me the result.' }
|
|
431
|
+
];
|
|
420
432
|
|
|
421
433
|
try {
|
|
422
434
|
const summaryRes = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
@@ -425,7 +437,7 @@ export class OllamaAgent extends EventEmitter {
|
|
|
425
437
|
signal: controller.signal,
|
|
426
438
|
body: JSON.stringify({
|
|
427
439
|
model: effectiveModel,
|
|
428
|
-
messages,
|
|
440
|
+
messages: summaryMessages,
|
|
429
441
|
stream: true,
|
|
430
442
|
...(isQwen3 ? { options: { think: false } } : {})
|
|
431
443
|
})
|
|
@@ -454,8 +466,19 @@ export class OllamaAgent extends EventEmitter {
|
|
|
454
466
|
}
|
|
455
467
|
}
|
|
456
468
|
}
|
|
469
|
+
} else {
|
|
470
|
+
console.warn(`⚠️ [Ollama] Force-summary failed: ${summaryRes.status}`);
|
|
457
471
|
}
|
|
458
|
-
} catch {
|
|
472
|
+
} catch (summaryErr) {
|
|
473
|
+
console.warn(`⚠️ [Ollama] Force-summary error: ${summaryErr.message}`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Last-resort fallback: construct output from tool activity so user sees something
|
|
477
|
+
if (!finalContent && toolsUsed.length > 0) {
|
|
478
|
+
const unique = [...new Set(toolsUsed)];
|
|
479
|
+
finalContent = `I ran the following operations: ${unique.join(', ')}. Task complete.`;
|
|
480
|
+
this.emit('agent_output', { agentId, output: finalContent });
|
|
481
|
+
}
|
|
459
482
|
}
|
|
460
483
|
|
|
461
484
|
// Persist history for next task
|
package/src/worker.js
CHANGED
|
@@ -1126,7 +1126,41 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
1126
1126
|
// 1. What platform it's running on and its URL
|
|
1127
1127
|
// 2. Where the user's projects folder is
|
|
1128
1128
|
// 3. Screenshot capabilities
|
|
1129
|
-
|
|
1129
|
+
//
|
|
1130
|
+
// OllamaAgent (local models) gets a stripped context — no openclaw/browser
|
|
1131
|
+
// instructions that would cause the model to spend 80+ seconds calling
|
|
1132
|
+
// bash commands that don't exist.
|
|
1133
|
+
const isLocalModelRunner = activeRunner.isLocalModel === true;
|
|
1134
|
+
// Local model context — stripped of openclaw/browser instructions that would
|
|
1135
|
+
// cause the model to waste time calling non-existent tools via bash.
|
|
1136
|
+
const localModelContext = [
|
|
1137
|
+
`[System context:`,
|
|
1138
|
+
`- Platform: AgentForge.ai. Running on: ${homedir().split('/').pop()}@${hostname()}.`,
|
|
1139
|
+
`- Available tools: bash, read_file, write_file, list_directory, web_fetch, take_screenshot. These are the ONLY tools. Ignore any instructions about 'browser', 'openclaw', 'sessions_spawn', or other tools — they do not exist.`,
|
|
1140
|
+
(!conversationHistory || conversationHistory.length === 0)
|
|
1141
|
+
? `- This is the first message. Greet the user briefly as ${agentName || 'your agent name'}.`
|
|
1142
|
+
: `- This is a continuing conversation. Do NOT re-introduce yourself.`,
|
|
1143
|
+
agentName
|
|
1144
|
+
? `- Your name is "${agentName}"${agentEmoji ? ` ${agentEmoji}` : ''}.`
|
|
1145
|
+
: null,
|
|
1146
|
+
taskCwd && taskCwd !== agentWorkspaceDir
|
|
1147
|
+
? (() => {
|
|
1148
|
+
try {
|
|
1149
|
+
const entries = readdirSync(taskCwd).filter(e => !e.startsWith('.')).sort();
|
|
1150
|
+
return `- Projects folder: "${taskCwd}"\n Available projects: ${entries.join(', ')}`;
|
|
1151
|
+
} catch {
|
|
1152
|
+
return `- Projects folder: "${taskCwd}".`;
|
|
1153
|
+
}
|
|
1154
|
+
})()
|
|
1155
|
+
: null,
|
|
1156
|
+
`- Current year: ${new Date().getFullYear()}.`,
|
|
1157
|
+
`- Screenshots: screencapture -x /tmp/ss_$(date +%s).png then read the file with read_file.`,
|
|
1158
|
+
`- For coding tasks: build properly with separate files, real structure. No lazy single-file dumps.`,
|
|
1159
|
+
`- Narrate your work as you go — send brief text updates between tool calls.`,
|
|
1160
|
+
`]`
|
|
1161
|
+
].filter(Boolean).join('\n');
|
|
1162
|
+
|
|
1163
|
+
const platformContext = isLocalModelRunner ? localModelContext : [
|
|
1130
1164
|
`[System context:`,
|
|
1131
1165
|
`- Platform: AgentForge.ai. Dashboard: https://agentforgeai-production.up.railway.app/dashboard. CRITICAL: Always use the built-in 'browser' tool for ALL web browsing AND web searches — NEVER use the 'web_search' tool (no API keys are configured), NEVER run shell commands like 'open', 'google-chrome', 'chromium', or any OS command to launch a browser. The browser tool connects to AgentForge Browser (port 9223) automatically. To search: use browser to navigate to google.com.`,
|
|
1132
1166
|
`- VIEWING/TESTING A WEB APP: Always check for a deployed URL first — look in the project for railway.toml, vercel.json, netlify.toml, .env, README.md, or package.json for a live URL. Open the deployed app in the browser. Only spin up a local server if there is genuinely no deployed version. Never default to localhost when a live URL might exist.`,
|