omnikey-cli 1.0.20 → 1.0.21

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.
@@ -112,7 +112,7 @@ async function runToolLoop(initialResult, session, sessionId, send, log, tools,
112
112
  session.history.push(result.assistantMessage);
113
113
  session.history.push({
114
114
  role: 'user',
115
- content: 'You have reached the maximum number of tool calls. Based on all the information gathered so far, provide a single, final, concise answer. Do not call any more tools.',
115
+ content: 'You have reached the maximum number of tool calls. Do NOT make any further tool calls or web searches. You MUST now provide a final answer directly. If you still need to gather information from the system, generate a `<shell_scripts>` block instead of making tool calls.',
116
116
  });
117
117
  result = await ai_client_1.aiClient.complete(aiModel, session.history, {
118
118
  tools: undefined,
@@ -123,9 +123,6 @@ async function runToolLoop(initialResult, session, sessionId, send, log, tools,
123
123
  log.info('Finished reasoning and tool calls: ', {
124
124
  reason: result.finish_reason,
125
125
  });
126
- if (result.assistantMessage) {
127
- session.history.push(result.assistantMessage);
128
- }
129
126
  return result;
130
127
  }
131
128
  function buildAvailableTools() {
@@ -298,6 +295,7 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
298
295
  isError: isErrorFlag,
299
296
  rawContentLength: (clientMessage.content || '').length,
300
297
  userContentLength: userContent.length,
298
+ isRecursiveCall: clientMessage.is_web_call,
301
299
  });
302
300
  const isAssistance = isTerminalOutput || isErrorFlag;
303
301
  if (!clientMessage?.is_web_call) {
@@ -371,21 +369,60 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
371
369
  subscriptionId: subscription.id,
372
370
  turn: session.turns,
373
371
  });
374
- result = await runToolLoop(result, session, sessionId, send, log, buildAvailableTools(), recordUsage);
375
- content = result.content.trim();
376
- if (!content) {
377
- log.warn('Agent returned empty content after tool loop; sending generic error.');
378
- sendFinalAnswer(send, sessionId, 'The agent returned an empty response. Please try again.', true);
379
- sessionMessages.delete(sessionId);
372
+ const toolLoopResult = await runToolLoop(result, session, sessionId, send, log, buildAvailableTools(), recordUsage);
373
+ const toolLoopContent = toolLoopResult.content.trim();
374
+ const toolLoopHasShell = toolLoopContent.includes('<shell_script>');
375
+ const toolLoopHasFinal = toolLoopContent.includes('<final_answer>');
376
+ const webToolFailed = session.history.some((msg) => msg.role === 'tool' && typeof msg.content === 'string' && msg.content.startsWith('Error'));
377
+ if (toolLoopHasShell || (toolLoopHasFinal && !webToolFailed)) {
378
+ // The tool loop already produced a shell script — use it directly.
379
+ // This avoids a redundant AI call and handles the case where the model
380
+ // emits a <shell_script> immediately after its web tool calls.
381
+ log.info('Tool loop produced shell script; processing inline', { sessionId });
382
+ content = toolLoopContent;
383
+ result = toolLoopResult;
384
+ // Fall through to the <shell_script> handling below.
385
+ }
386
+ else {
387
+ // The tool loop returned either plain text or a <final_answer>.
388
+ // We always make one more AI turn here so the model has a chance to
389
+ // correct itself — specifically when web tools failed (404 / error) the
390
+ // model tends to wrap a "please run this manually" message in
391
+ // <final_answer>. The directive below tells it to use <shell_script> as
392
+ // a fallback instead of asking the user to run commands.
393
+ if (toolLoopResult.assistantMessage) {
394
+ session.history.push(toolLoopResult.assistantMessage);
395
+ }
396
+ session.history.push({
397
+ role: 'user',
398
+ content: webToolFailed
399
+ ? [
400
+ 'IMPORTANT: The web search tool failed and is unavailable. Do NOT attempt any further web calls or ask the user to run commands manually.',
401
+ 'You MUST retrieve any needed data by generating a <shell_script> that runs terminal commands (curl, grep, cat, etc.).',
402
+ 'The shell script output will be returned to you automatically.',
403
+ '',
404
+ 'Respond with exactly one of:',
405
+ '- <shell_script>...</shell_script> — to fetch or retrieve data via terminal commands',
406
+ '- <final_answer>...</final_answer> — only if you already have enough information',
407
+ 'No plain text. No web tool calls. No other format.',
408
+ ].join('\n')
409
+ : [
410
+ 'Web research is complete. The results are in the conversation above.',
411
+ '',
412
+ 'Now respond with exactly one of:',
413
+ '- <shell_script>...</shell_script> — to run terminal commands (output will be returned to you automatically)',
414
+ '- <final_answer>...</final_answer> — only if you genuinely have enough information',
415
+ 'No plain text. No other format.',
416
+ ].join('\n'),
417
+ });
418
+ await runAgentTurn(sessionId, subscription, {
419
+ sender: 'agent',
420
+ session_id: sessionId,
421
+ content: '',
422
+ is_web_call: true,
423
+ }, send, logger_1.logger);
380
424
  return;
381
425
  }
382
- await runAgentTurn(sessionId, subscription, {
383
- sender: 'agent',
384
- session_id: sessionId,
385
- content: '',
386
- is_web_call: true,
387
- }, send, logger_1.logger);
388
- return;
389
426
  }
390
427
  // Ensure that a proper <final_answer> block is produced for the
391
428
  // desktop clients once we reach the final turn. If the model did
@@ -64,8 +64,8 @@ app.get('/macos/appcast', (req, res) => {
64
64
  const appcastUrl = `${baseUrl}/macos/appcast`;
65
65
  // These should match the values embedded into the macOS app
66
66
  // Info.plist in macOS/build_release_dmg.sh.
67
- const bundleVersion = '16';
68
- const shortVersion = '1.0.15';
67
+ const bundleVersion = '17';
68
+ const shortVersion = '1.0.16';
69
69
  const xml = `<?xml version="1.0" encoding="utf-8"?>
70
70
  <rss version="2.0"
71
71
  xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle"
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "registry": "https://registry.npmjs.org/"
6
6
  },
7
- "version": "1.0.20",
7
+ "version": "1.0.21",
8
8
  "description": "CLI for onboarding users to Omnikey AI and configuring OPENAI_API_KEY. Use Yarn for install/build.",
9
9
  "engines": {
10
10
  "node": ">=14.0.0",