@oxecli/oxe 1.0.95 → 1.0.97
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/dist/api.js +1 -2
- package/dist/config.js +2 -1
- package/dist/engine.js +20 -5
- package/dist/ui.js +25 -2
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -4,8 +4,7 @@ export async function validateOxeApiKey(apiKey) {
|
|
|
4
4
|
if (!key.startsWith(OXE_KEY_PREFIX)) {
|
|
5
5
|
return {
|
|
6
6
|
valid: false,
|
|
7
|
-
error: "Invalid API key format.
|
|
8
|
-
"Generate your key at: http://localhost:5173/dashboard/api-keys",
|
|
7
|
+
error: "Invalid API key format. Generate your key at: http://localhost:5173/dashboard/api-keys",
|
|
9
8
|
};
|
|
10
9
|
}
|
|
11
10
|
try {
|
package/dist/config.js
CHANGED
|
@@ -98,7 +98,8 @@ export function detectedShell() {
|
|
|
98
98
|
export function osPrefix() {
|
|
99
99
|
return (`Running environment: ${runtimeOsSummary()}. ` +
|
|
100
100
|
`Shell commands run via ${detectedShell()} ` +
|
|
101
|
-
|
|
101
|
+
`with \`shell=True\`, from the working directory \`${process.cwd()}\`; ` +
|
|
102
|
+
"use commands, quoting, and path separators " +
|
|
102
103
|
"appropriate to this OS.\n\n");
|
|
103
104
|
}
|
|
104
105
|
export const IGNORED_DIRS_BY_CATEGORY = [
|
package/dist/engine.js
CHANGED
|
@@ -155,10 +155,12 @@ export class InferenceEngine {
|
|
|
155
155
|
let sawReasoning = false;
|
|
156
156
|
let status = null;
|
|
157
157
|
let thinkingStart = null;
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
158
|
+
// A "Worked for …" block is committed once per working phase. The flag is
|
|
159
|
+
// reset whenever a tool call runs (in the tool loop below), which is the
|
|
160
|
+
// only way a later phase can begin — the loop only continues after a tool
|
|
161
|
+
// call. So unlimited working blocks can appear, but never two in a row
|
|
162
|
+
// without a tool call in between. An answer ends the query. The total
|
|
163
|
+
// worked time also lands in the final footer.
|
|
162
164
|
const showWorkSpinner = !this.workedCommitted;
|
|
163
165
|
if (showWorkSpinner)
|
|
164
166
|
dockTransientStart();
|
|
@@ -537,7 +539,13 @@ export class InferenceEngine {
|
|
|
537
539
|
conversation.push(rp);
|
|
538
540
|
inputItems.push(rp);
|
|
539
541
|
retryPrompts.push(rp);
|
|
540
|
-
|
|
542
|
+
// Always retry with the full transcript in visible context (which
|
|
543
|
+
// includes the original user prompt), instead of relying solely on
|
|
544
|
+
// previous_response_id continuation. Server-side continuation of a
|
|
545
|
+
// cut-off response can lose the task context, leaving the model with
|
|
546
|
+
// "no context about what was being worked on."
|
|
547
|
+
prevId = null;
|
|
548
|
+
pending = conversation;
|
|
541
549
|
continue;
|
|
542
550
|
}
|
|
543
551
|
dropRetryPrompts(conversation, inputItems, retryPrompts);
|
|
@@ -545,6 +553,10 @@ export class InferenceEngine {
|
|
|
545
553
|
dockAppendContent(summary() + "\n");
|
|
546
554
|
return;
|
|
547
555
|
}
|
|
556
|
+
// A successful turn (text or tool call) after a retry must not leave the
|
|
557
|
+
// cut-off retry prompts in the transcript — they'd pollute the context of
|
|
558
|
+
// later turns. Drop them now that the retry produced real output.
|
|
559
|
+
dropRetryPrompts(conversation, inputItems, retryPrompts);
|
|
548
560
|
if (!calls.length) {
|
|
549
561
|
story.push({ type: "footer", text: footerText() });
|
|
550
562
|
attachFooter(conversation);
|
|
@@ -562,6 +574,9 @@ export class InferenceEngine {
|
|
|
562
574
|
const toolSpinner = new Spinner();
|
|
563
575
|
toolSpinner.startDots("\x1b[90m╰─\x1b[0m Working");
|
|
564
576
|
const rawResult = await this.runTool(c.name, c.arguments);
|
|
577
|
+
// A tool call was made, which interrupts any current working phase,
|
|
578
|
+
// so the next agent iteration may commit a fresh "Worked for …" block.
|
|
579
|
+
this.workedCommitted = false;
|
|
565
580
|
if (this.interrupted) {
|
|
566
581
|
toolSpinner.stop();
|
|
567
582
|
throw new Error("interrupt");
|
package/dist/ui.js
CHANGED
|
@@ -1299,6 +1299,9 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1299
1299
|
if (done)
|
|
1300
1300
|
return;
|
|
1301
1301
|
done = true;
|
|
1302
|
+
const sentValue = isErr
|
|
1303
|
+
? null
|
|
1304
|
+
: value;
|
|
1302
1305
|
process.stdout.write("\x1b[?2004l");
|
|
1303
1306
|
process.stdin.setRawMode(false);
|
|
1304
1307
|
if (pasteBurstTimer)
|
|
@@ -1308,10 +1311,30 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1308
1311
|
dockSetInactive();
|
|
1309
1312
|
}
|
|
1310
1313
|
else {
|
|
1314
|
+
// Clear the sent prompt from the box immediately, so the field shows an
|
|
1315
|
+
// empty prompt as soon as the user sends it while the query streams
|
|
1316
|
+
// above the dock. The resolved value still carries the original sent
|
|
1317
|
+
// buffer/paste spans so the query and draft-restore keep working.
|
|
1318
|
+
const { frame, totalRows } = renderBufferWithCursor("", [], prefix, label, 0, hints);
|
|
1319
|
+
const newLines = frame.split("\n");
|
|
1311
1320
|
if (lastCursorRow > 0)
|
|
1312
1321
|
process.stdout.write(`\x1b[${lastCursorRow}A`);
|
|
1313
1322
|
process.stdout.write("\r");
|
|
1314
|
-
|
|
1323
|
+
const oldLines = prevFrameLines ?? [];
|
|
1324
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
1325
|
+
for (let i = 0; i < maxLen; i++) {
|
|
1326
|
+
process.stdout.write("\r\x1b[K" + (newLines[i] ?? ""));
|
|
1327
|
+
if (i < maxLen - 1)
|
|
1328
|
+
process.stdout.write("\n");
|
|
1329
|
+
}
|
|
1330
|
+
// Reposition at the box's top row so the dock can manage it. The erase
|
|
1331
|
+
// loop above ends with the cursor at row (maxLen - 1), so move up by
|
|
1332
|
+
// that many rows — NOT newLines.length - 1, which is too few whenever
|
|
1333
|
+
// the sent (old) box was taller than the emptied box (e.g. a wrapped or
|
|
1334
|
+
// multi-line prompt). Using the wrong count leaves the cursor below the
|
|
1335
|
+
// box top, desyncing the dock and corrupting later redraws.
|
|
1336
|
+
process.stdout.write(`\x1b[${maxLen - 1}A\r`);
|
|
1337
|
+
dockSetFrame(frame, totalRows);
|
|
1315
1338
|
dockEnterDocked();
|
|
1316
1339
|
}
|
|
1317
1340
|
process.stdin.removeListener("keypress", onKeypress);
|
|
@@ -1320,7 +1343,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1320
1343
|
if (isErr)
|
|
1321
1344
|
reject(value);
|
|
1322
1345
|
else
|
|
1323
|
-
resolve(
|
|
1346
|
+
resolve(sentValue);
|
|
1324
1347
|
};
|
|
1325
1348
|
const repaint = (isFirst = false) => {
|
|
1326
1349
|
const { frame, cursorRow, cursorCol, totalRows } = renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor, hints);
|