obol-ai 0.2.9 → 0.2.10

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/claude.js +18 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "obol-ai",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Self-evolving AI assistant that learns, remembers, and acts on its own. Persistent vector memory, self-rewriting personality, proactive heartbeats.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/claude.js CHANGED
@@ -8,7 +8,7 @@ const { execAsync, isAllowedUrl } = require('./sanitize');
8
8
  const { ChatHistory } = require('./history');
9
9
 
10
10
  const MAX_EXEC_TIMEOUT = 120;
11
- let MAX_TOOL_ITERATIONS = 100;
11
+ let MAX_TOOL_ITERATIONS = 10;
12
12
 
13
13
  const BLOCKED_EXEC_PATTERNS = [
14
14
  /\brm\s+(-[a-zA-Z]*f|-[a-zA-Z]*r|--force|--recursive)\b/,
@@ -298,7 +298,22 @@ Model: Default to "sonnet". Use "haiku" for: greetings, brief acknowledgments (t
298
298
  return { text, usage: totalUsage, model };
299
299
  }
300
300
 
301
- const text = finalMessage.content.filter(b => b.type === 'text').map(b => b.text).join('\n');
301
+ let text = finalMessage.content.filter(b => b.type === 'text').map(b => b.text).join('\n');
302
+
303
+ if (!text.trim() && newMessages.length > 1) {
304
+ vlog('[claude] No text in final response after tool use — forcing summary');
305
+ histories.pushUser(chatId, 'Provide a concise response to the user based on the tool results above.');
306
+ const summaryResponse = await client.messages.create({
307
+ model, max_tokens: 4096, system: systemPrompt, messages: [...histories.get(chatId)],
308
+ }, { signal: abortController.signal });
309
+ histories.pushAssistant(chatId, summaryResponse.content);
310
+ if (summaryResponse.usage) {
311
+ totalUsage.input_tokens += summaryResponse.usage.input_tokens || 0;
312
+ totalUsage.output_tokens += summaryResponse.usage.output_tokens || 0;
313
+ }
314
+ text = summaryResponse.content.filter(b => b.type === 'text').map(b => b.text).join('\n');
315
+ }
316
+
302
317
  return { text, usage: totalUsage, model };
303
318
 
304
319
  } catch (e) {
@@ -579,6 +594,7 @@ You communicate via Telegram. Format responses for mobile readability.
579
594
  - Search memory before claiming you don't know something
580
595
  - Use \`store_secret\`/\`read_secret\` for all credential operations
581
596
  - If a user sends what appears to be an API key, token, or credential in conversation, immediately warn them that it's visible in chat history, tell them to revoke/rotate it, and direct them to use \`/secret set <key> <value>\` instead
597
+ - After executing tools (exec, web_fetch, read_secret, etc.), ALWAYS provide a text response summarizing what you found or did. Never end your turn with only tool calls and no text reply — the user cannot see tool results directly, they only see your text responses
582
598
  `);
583
599
 
584
600
  return parts.join('\n');