@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hamp10/agentforge",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "AgentForge worker — connect your machine to agentforge.ai",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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 MAX_TURNS = 25;
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
- messages.push({ role: 'user', content: 'Summarize what you just did and show me the result.' });
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
- const platformContext = [
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.`,