omnikey-cli 1.0.19 → 1.0.20
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.
|
@@ -26,14 +26,16 @@ ${hasTaskInstructions
|
|
|
26
26
|
- If a request needs BOTH machine data AND web search: emit a \`<shell_script>\` first → wait for \`TERMINAL OUTPUT:\` → then call the web tool with concrete values. Never use placeholders like "my IP" in a web query.
|
|
27
27
|
|
|
28
28
|
**Incoming message tags:**
|
|
29
|
-
- \`TERMINAL OUTPUT:\` — stdout/stderr from a prior script.
|
|
29
|
+
- \`TERMINAL OUTPUT:\` — stdout/stderr from a prior script. Analyze it immediately and respond with EITHER a follow-up \`<shell_script>\` (if more data is needed) OR a \`<final_answer>\` (if you have enough to conclude). You MUST pick one — never respond with plain text.
|
|
30
30
|
- \`COMMAND ERROR:\` — script failed. Diagnose and emit a corrected \`<shell_script>\` or explain in \`<final_answer>\`.
|
|
31
31
|
- No prefix — direct user message; treat as the primary request.
|
|
32
32
|
|
|
33
33
|
**Response format — every response must be exactly one of:**
|
|
34
|
-
1. \`<shell_script>...</shell_script>\` — to run commands.
|
|
34
|
+
1. \`<shell_script>...</shell_script>\` — to run commands and gather more data.
|
|
35
35
|
2. A \`web_search\` or \`web_fetch\` tool call — to fetch web context (use native tool calling, not XML tags).
|
|
36
|
-
3. \`<final_answer>...</final_answer>\` —
|
|
36
|
+
3. \`<final_answer>...</final_answer>\` — your conclusion once you have enough information.
|
|
37
|
+
|
|
38
|
+
**Critical rule:** After receiving \`TERMINAL OUTPUT:\` you MUST immediately produce either \`<shell_script>\` or \`<final_answer>\`. Never output raw text, markdown, or any other format. If the terminal output contains enough information to answer the user's request, output \`<final_answer>\` right away.
|
|
37
39
|
|
|
38
40
|
No plain text, reasoning, or other tags outside these blocks. Never wrap in additional XML/JSON.
|
|
39
41
|
|
|
@@ -123,6 +123,9 @@ 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
|
+
}
|
|
126
129
|
return result;
|
|
127
130
|
}
|
|
128
131
|
function buildAvailableTools() {
|
|
@@ -254,7 +257,12 @@ async function authenticateFromAuthHeader(authHeader, log) {
|
|
|
254
257
|
}
|
|
255
258
|
}
|
|
256
259
|
function createUserContent(content, hasStoredPrompt) {
|
|
257
|
-
return hasStoredPrompt
|
|
260
|
+
return hasStoredPrompt
|
|
261
|
+
? content
|
|
262
|
+
.toLowerCase()
|
|
263
|
+
.replace(/@omniagent/g, '')
|
|
264
|
+
.trim()
|
|
265
|
+
: content;
|
|
258
266
|
}
|
|
259
267
|
async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
260
268
|
const { sessionState: session, hasStoredPrompt } = await getOrCreateSession(sessionId, subscription, clientMessage.platform, log);
|
|
@@ -293,6 +301,10 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
|
293
301
|
});
|
|
294
302
|
const isAssistance = isTerminalOutput || isErrorFlag;
|
|
295
303
|
if (!clientMessage?.is_web_call) {
|
|
304
|
+
// Terminal output and command errors are always user-role messages — they
|
|
305
|
+
// represent environment feedback that the agent must reason about next.
|
|
306
|
+
// Pushing them as 'assistant' would create two consecutive assistant turns
|
|
307
|
+
// which breaks most LLM APIs and prevents the model from processing the output.
|
|
296
308
|
session.history.push({
|
|
297
309
|
role: 'user',
|
|
298
310
|
content: isAssistance
|
|
@@ -306,7 +318,7 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
|
306
318
|
const tools = isFinalTurn ? undefined : buildAvailableTools();
|
|
307
319
|
const recordUsage = async (result) => {
|
|
308
320
|
const usage = result.usage;
|
|
309
|
-
if (!usage || !subscription.id)
|
|
321
|
+
if (!usage || !subscription.id || config_1.config.isSelfHosted)
|
|
310
322
|
return;
|
|
311
323
|
try {
|
|
312
324
|
await subscriptionUsage_1.SubscriptionUsage.create({
|
|
@@ -367,6 +379,13 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
|
367
379
|
sessionMessages.delete(sessionId);
|
|
368
380
|
return;
|
|
369
381
|
}
|
|
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;
|
|
370
389
|
}
|
|
371
390
|
// Ensure that a proper <final_answer> block is produced for the
|
|
372
391
|
// desktop clients once we reach the final turn. If the model did
|
|
@@ -410,6 +429,31 @@ async function runAgentTurn(sessionId, subscription, clientMessage, send, log) {
|
|
|
410
429
|
});
|
|
411
430
|
sessionMessages.delete(sessionId);
|
|
412
431
|
}
|
|
432
|
+
else if (content) {
|
|
433
|
+
// Fallback: the LLM returned content without any recognized tag and it
|
|
434
|
+
// is not the final turn (e.g. plain-text conclusion after terminal
|
|
435
|
+
// output). Treat it as a final answer so the client is never left
|
|
436
|
+
// hanging.
|
|
437
|
+
log.info('Agent returned untagged content on a non-final turn; treating as final answer', {
|
|
438
|
+
sessionId,
|
|
439
|
+
subscriptionId: subscription.id,
|
|
440
|
+
turn: session.turns,
|
|
441
|
+
});
|
|
442
|
+
session.history.push({ role: 'assistant', content });
|
|
443
|
+
send({
|
|
444
|
+
session_id: sessionId,
|
|
445
|
+
sender: 'agent',
|
|
446
|
+
content: `<final_answer>\n${content}\n</final_answer>`,
|
|
447
|
+
});
|
|
448
|
+
sessionMessages.delete(sessionId);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
log.warn('Agent returned empty content with no recognized tags; sending error', {
|
|
452
|
+
sessionId,
|
|
453
|
+
});
|
|
454
|
+
sendFinalAnswer(send, sessionId, 'The agent returned an empty response. Please try again.', true);
|
|
455
|
+
sessionMessages.delete(sessionId);
|
|
456
|
+
}
|
|
413
457
|
}
|
|
414
458
|
catch (err) {
|
|
415
459
|
log.error('Agent LLM call failed', { error: err });
|
|
@@ -118,7 +118,7 @@ async function enhanceText(logger, text, cmd, subscription) {
|
|
|
118
118
|
const { rawResponse, usage, model } = result;
|
|
119
119
|
// Record token usage for this subscription and model, if usage
|
|
120
120
|
// data is available and we know which subscription made the call.
|
|
121
|
-
if (usage && subscription.id) {
|
|
121
|
+
if (usage && subscription.id && !config_1.config.isSelfHosted) {
|
|
122
122
|
try {
|
|
123
123
|
await subscriptionUsage_1.SubscriptionUsage.create({
|
|
124
124
|
subscriptionId: subscription.id,
|
|
@@ -197,7 +197,7 @@ async function streamEnhanceResponse(res, text, cmd) {
|
|
|
197
197
|
return;
|
|
198
198
|
}
|
|
199
199
|
const { usage, model } = result;
|
|
200
|
-
if (usage && subscription.id) {
|
|
200
|
+
if (usage && subscription.id && !config_1.config.isSelfHosted) {
|
|
201
201
|
try {
|
|
202
202
|
await subscriptionUsage_1.SubscriptionUsage.create({
|
|
203
203
|
subscriptionId: subscription.id,
|
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.20",
|
|
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",
|