omnikey-cli 1.0.20 → 1.0.22
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.
|
@@ -110,9 +110,20 @@ async function runToolLoop(initialResult, session, sessionId, send, log, tools,
|
|
|
110
110
|
if (result.finish_reason === 'tool_calls') {
|
|
111
111
|
log.warn('Tool loop hit MAX_TOOL_ITERATIONS; forcing final conclusion', { sessionId });
|
|
112
112
|
session.history.push(result.assistantMessage);
|
|
113
|
+
// The API requires a tool_result for every tool_use in the preceding
|
|
114
|
+
// assistant message. Add synthetic results for any unexecuted calls so
|
|
115
|
+
// the history remains valid before we send the follow-up user message.
|
|
116
|
+
for (const tc of result.tool_calls ?? []) {
|
|
117
|
+
session.history.push({
|
|
118
|
+
role: 'tool',
|
|
119
|
+
tool_call_id: tc.id,
|
|
120
|
+
tool_name: tc.name,
|
|
121
|
+
content: 'Tool call limit reached. Result unavailable.',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
113
124
|
session.history.push({
|
|
114
125
|
role: 'user',
|
|
115
|
-
content: 'You have reached the maximum number of tool calls.
|
|
126
|
+
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
127
|
});
|
|
117
128
|
result = await ai_client_1.aiClient.complete(aiModel, session.history, {
|
|
118
129
|
tools: undefined,
|
|
@@ -123,9 +134,6 @@ async function runToolLoop(initialResult, session, sessionId, send, log, tools,
|
|
|
123
134
|
log.info('Finished reasoning and tool calls: ', {
|
|
124
135
|
reason: result.finish_reason,
|
|
125
136
|
});
|
|
126
|
-
if (result.assistantMessage) {
|
|
127
|
-
session.history.push(result.assistantMessage);
|
|
128
|
-
}
|
|
129
137
|
return result;
|
|
130
138
|
}
|
|
131
139
|
function buildAvailableTools() {
|
|
@@ -298,6 +306,7 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
|
298
306
|
isError: isErrorFlag,
|
|
299
307
|
rawContentLength: (clientMessage.content || '').length,
|
|
300
308
|
userContentLength: userContent.length,
|
|
309
|
+
isRecursiveCall: clientMessage.is_web_call,
|
|
301
310
|
});
|
|
302
311
|
const isAssistance = isTerminalOutput || isErrorFlag;
|
|
303
312
|
if (!clientMessage?.is_web_call) {
|
|
@@ -371,21 +380,60 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
|
371
380
|
subscriptionId: subscription.id,
|
|
372
381
|
turn: session.turns,
|
|
373
382
|
});
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
383
|
+
const toolLoopResult = await runToolLoop(result, session, sessionId, send, log, buildAvailableTools(), recordUsage);
|
|
384
|
+
const toolLoopContent = toolLoopResult.content.trim();
|
|
385
|
+
const toolLoopHasShell = toolLoopContent.includes('<shell_script>');
|
|
386
|
+
const toolLoopHasFinal = toolLoopContent.includes('<final_answer>');
|
|
387
|
+
const webToolFailed = session.history.some((msg) => msg.role === 'tool' && typeof msg.content === 'string' && msg.content.startsWith('Error'));
|
|
388
|
+
if (toolLoopHasShell || (toolLoopHasFinal && !webToolFailed)) {
|
|
389
|
+
// The tool loop already produced a shell script — use it directly.
|
|
390
|
+
// This avoids a redundant AI call and handles the case where the model
|
|
391
|
+
// emits a <shell_script> immediately after its web tool calls.
|
|
392
|
+
log.info('Tool loop produced shell script; processing inline', { sessionId });
|
|
393
|
+
content = toolLoopContent;
|
|
394
|
+
result = toolLoopResult;
|
|
395
|
+
// Fall through to the <shell_script> handling below.
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
// The tool loop returned either plain text or a <final_answer>.
|
|
399
|
+
// We always make one more AI turn here so the model has a chance to
|
|
400
|
+
// correct itself — specifically when web tools failed (404 / error) the
|
|
401
|
+
// model tends to wrap a "please run this manually" message in
|
|
402
|
+
// <final_answer>. The directive below tells it to use <shell_script> as
|
|
403
|
+
// a fallback instead of asking the user to run commands.
|
|
404
|
+
if (toolLoopResult.assistantMessage) {
|
|
405
|
+
session.history.push(toolLoopResult.assistantMessage);
|
|
406
|
+
}
|
|
407
|
+
session.history.push({
|
|
408
|
+
role: 'user',
|
|
409
|
+
content: webToolFailed
|
|
410
|
+
? [
|
|
411
|
+
'IMPORTANT: The web search tool failed and is unavailable. Do NOT attempt any further web calls or ask the user to run commands manually.',
|
|
412
|
+
'You MUST retrieve any needed data by generating a <shell_script> that runs terminal commands (curl, grep, cat, etc.).',
|
|
413
|
+
'The shell script output will be returned to you automatically.',
|
|
414
|
+
'',
|
|
415
|
+
'Respond with exactly one of:',
|
|
416
|
+
'- <shell_script>...</shell_script> — to fetch or retrieve data via terminal commands',
|
|
417
|
+
'- <final_answer>...</final_answer> — only if you already have enough information',
|
|
418
|
+
'No plain text. No web tool calls. No other format.',
|
|
419
|
+
].join('\n')
|
|
420
|
+
: [
|
|
421
|
+
'Web research is complete. The results are in the conversation above.',
|
|
422
|
+
'',
|
|
423
|
+
'Now respond with exactly one of:',
|
|
424
|
+
'- <shell_script>...</shell_script> — to run terminal commands (output will be returned to you automatically)',
|
|
425
|
+
'- <final_answer>...</final_answer> — only if you genuinely have enough information',
|
|
426
|
+
'No plain text. No other format.',
|
|
427
|
+
].join('\n'),
|
|
428
|
+
});
|
|
429
|
+
await runAgentTurn(sessionId, subscription, {
|
|
430
|
+
sender: 'agent',
|
|
431
|
+
session_id: sessionId,
|
|
432
|
+
content: '',
|
|
433
|
+
is_web_call: true,
|
|
434
|
+
}, send, logger_1.logger);
|
|
380
435
|
return;
|
|
381
436
|
}
|
|
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
437
|
}
|
|
390
438
|
// Ensure that a proper <final_answer> block is produced for the
|
|
391
439
|
// desktop clients once we reach the final turn. If the model did
|
package/backend-dist/index.js
CHANGED
|
@@ -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 = '
|
|
68
|
-
const shortVersion = '1.0.
|
|
67
|
+
const bundleVersion = '18';
|
|
68
|
+
const shortVersion = '1.0.17';
|
|
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"
|
|
@@ -93,7 +93,7 @@ app.get('/macos/appcast', (req, res) => {
|
|
|
93
93
|
// ── Windows distribution endpoints ───────────────────────────────────────────
|
|
94
94
|
// These should match the values in windows/OmniKey.Windows.csproj
|
|
95
95
|
// <Version> and windows/build_release_zip.ps1 $APP_VERSION.
|
|
96
|
-
const WIN_VERSION = '1.
|
|
96
|
+
const WIN_VERSION = '1.4';
|
|
97
97
|
const WIN_ZIP_FILENAME = 'OmniKeyAI-windows-win-x64.zip';
|
|
98
98
|
const WIN_ZIP_PATH = path_1.default.join(process.cwd(), 'windows', WIN_ZIP_FILENAME);
|
|
99
99
|
// Serves the pre-built ZIP produced by windows/build_release_zip.ps1.
|
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.
|
|
7
|
+
"version": "1.0.22",
|
|
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",
|