clixad 0.0.1-beta.43 → 0.0.1-beta.44
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.
|
@@ -5486,79 +5486,92 @@ ${NO_SEARCH_INSTRUCTION}`,
|
|
|
5486
5486
|
...turn.spendable ? { spendable: turn.spendable } : {}
|
|
5487
5487
|
});
|
|
5488
5488
|
}
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
tools: opts.tools ? opts.tools() : TOOL_SCHEMA,
|
|
5497
|
-
signal: opts.signal,
|
|
5498
|
-
onDelta: (text) => emit({ type: "delta", text })
|
|
5499
|
-
});
|
|
5500
|
-
} catch (err) {
|
|
5501
|
-
if (isAbort(err) || opts.signal?.aborted) return stop("aborted");
|
|
5502
|
-
throw err;
|
|
5503
|
-
}
|
|
5504
|
-
creditsCharged += turn.creditsCharged;
|
|
5505
|
-
creditsWaived += turn.creditsWaived ?? 0;
|
|
5506
|
-
if (turn.freeCreditsLeft !== void 0) freeCreditsLeft = turn.freeCreditsLeft;
|
|
5507
|
-
balance = turn.balance;
|
|
5508
|
-
emitUsage(turn);
|
|
5509
|
-
const content = messageText(turn.message);
|
|
5510
|
-
const calls = turn.message.tool_calls ?? [];
|
|
5511
|
-
if (calls.length === 0 && !content.trim() && !retriedEmpty) {
|
|
5512
|
-
retriedEmpty = true;
|
|
5513
|
-
continue;
|
|
5514
|
-
}
|
|
5515
|
-
retriedEmpty = false;
|
|
5516
|
-
messages.push(turn.message);
|
|
5517
|
-
if (content) lastText = content;
|
|
5518
|
-
if (calls.length === 0) {
|
|
5519
|
-
emit({ type: "final", content, creditsCharged, balance });
|
|
5520
|
-
return {
|
|
5521
|
-
content,
|
|
5522
|
-
messages: withoutReasoning(messages),
|
|
5523
|
-
creditsCharged,
|
|
5524
|
-
balance,
|
|
5525
|
-
creditsWaived,
|
|
5526
|
-
freeCreditsLeft,
|
|
5527
|
-
searchCredits,
|
|
5528
|
-
steps: step + 1
|
|
5529
|
-
};
|
|
5489
|
+
const base = messages.length;
|
|
5490
|
+
try {
|
|
5491
|
+
return await loop();
|
|
5492
|
+
} catch (err) {
|
|
5493
|
+
if (typeof err === "object" && err !== null) {
|
|
5494
|
+
if (messages.length > base) interrupted.set(err, closeOpenCalls(withoutReasoning(messages)));
|
|
5495
|
+
else interrupted.delete(err);
|
|
5530
5496
|
}
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5497
|
+
throw err;
|
|
5498
|
+
}
|
|
5499
|
+
async function loop() {
|
|
5500
|
+
let retriedEmpty = false;
|
|
5501
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
5502
|
+
if (opts.signal?.aborted) return stop("aborted");
|
|
5503
|
+
let turn;
|
|
5504
|
+
try {
|
|
5505
|
+
turn = await client.chatStream(messages, opts.model, {
|
|
5506
|
+
effort: opts.effort,
|
|
5507
|
+
tools: opts.tools ? opts.tools() : TOOL_SCHEMA,
|
|
5508
|
+
signal: opts.signal,
|
|
5509
|
+
onDelta: (text) => emit({ type: "delta", text })
|
|
5510
|
+
});
|
|
5511
|
+
} catch (err) {
|
|
5512
|
+
if (isAbort(err) || opts.signal?.aborted) return stop("aborted");
|
|
5513
|
+
throw err;
|
|
5537
5514
|
}
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5515
|
+
creditsCharged += turn.creditsCharged;
|
|
5516
|
+
creditsWaived += turn.creditsWaived ?? 0;
|
|
5517
|
+
if (turn.freeCreditsLeft !== void 0) freeCreditsLeft = turn.freeCreditsLeft;
|
|
5518
|
+
balance = turn.balance;
|
|
5519
|
+
emitUsage(turn);
|
|
5520
|
+
const content = messageText(turn.message);
|
|
5521
|
+
const calls = turn.message.tool_calls ?? [];
|
|
5522
|
+
if (calls.length === 0 && !content.trim() && !retriedEmpty) {
|
|
5523
|
+
retriedEmpty = true;
|
|
5524
|
+
continue;
|
|
5525
|
+
}
|
|
5526
|
+
retriedEmpty = false;
|
|
5527
|
+
messages.push(turn.message);
|
|
5528
|
+
if (content) lastText = content;
|
|
5529
|
+
if (calls.length === 0) {
|
|
5530
|
+
emit({ type: "final", content, creditsCharged, balance });
|
|
5531
|
+
return {
|
|
5532
|
+
content,
|
|
5533
|
+
messages: withoutReasoning(messages),
|
|
5534
|
+
creditsCharged,
|
|
5535
|
+
balance,
|
|
5536
|
+
creditsWaived,
|
|
5537
|
+
freeCreditsLeft,
|
|
5538
|
+
searchCredits,
|
|
5539
|
+
steps: step + 1
|
|
5540
|
+
};
|
|
5541
|
+
}
|
|
5542
|
+
if (content) emit({ type: "message", content });
|
|
5547
5543
|
pendingImages = [];
|
|
5544
|
+
for (const [i, call] of calls.entries()) {
|
|
5545
|
+
if (opts.signal?.aborted) {
|
|
5546
|
+
for (const rest of calls.slice(i)) messages.push(toolMessage(rest, "cancelled by the user"));
|
|
5547
|
+
return stop("aborted");
|
|
5548
|
+
}
|
|
5549
|
+
const result = await executeToolCall(ctx, call, emit);
|
|
5550
|
+
messages.push(toolMessage(call, result));
|
|
5551
|
+
}
|
|
5552
|
+
if (pendingImages.length) {
|
|
5553
|
+
messages.push(imageMessage(pendingImages));
|
|
5554
|
+
emit({
|
|
5555
|
+
type: "attachment",
|
|
5556
|
+
labels: pendingImages.map((image) => image.label)
|
|
5557
|
+
});
|
|
5558
|
+
pendingImages = [];
|
|
5559
|
+
}
|
|
5560
|
+
opts.onCheckpoint?.(withoutReasoning(messages));
|
|
5548
5561
|
}
|
|
5562
|
+
emit({ type: "max_steps" });
|
|
5563
|
+
return {
|
|
5564
|
+
content: lastText || "(stopped: reached max steps)",
|
|
5565
|
+
messages: withoutReasoning(messages),
|
|
5566
|
+
creditsCharged,
|
|
5567
|
+
balance,
|
|
5568
|
+
creditsWaived,
|
|
5569
|
+
freeCreditsLeft,
|
|
5570
|
+
searchCredits,
|
|
5571
|
+
steps: maxSteps,
|
|
5572
|
+
stopped: "max_steps"
|
|
5573
|
+
};
|
|
5549
5574
|
}
|
|
5550
|
-
emit({ type: "max_steps" });
|
|
5551
|
-
return {
|
|
5552
|
-
content: lastText || "(stopped: reached max steps)",
|
|
5553
|
-
messages: withoutReasoning(messages),
|
|
5554
|
-
creditsCharged,
|
|
5555
|
-
balance,
|
|
5556
|
-
creditsWaived,
|
|
5557
|
-
freeCreditsLeft,
|
|
5558
|
-
searchCredits,
|
|
5559
|
-
steps: maxSteps,
|
|
5560
|
-
stopped: "max_steps"
|
|
5561
|
-
};
|
|
5562
5575
|
function stop(reason) {
|
|
5563
5576
|
emit({ type: reason });
|
|
5564
5577
|
return {
|
|
@@ -5574,6 +5587,21 @@ ${NO_SEARCH_INSTRUCTION}`,
|
|
|
5574
5587
|
};
|
|
5575
5588
|
}
|
|
5576
5589
|
}
|
|
5590
|
+
var interrupted = /* @__PURE__ */ new WeakMap();
|
|
5591
|
+
function interruptedConversation(err) {
|
|
5592
|
+
return typeof err === "object" && err !== null ? interrupted.get(err) : void 0;
|
|
5593
|
+
}
|
|
5594
|
+
var INTERRUPTED_CALL = "not completed: the turn stopped with an error before this call finished";
|
|
5595
|
+
function closeOpenCalls(messages) {
|
|
5596
|
+
const out = [...messages];
|
|
5597
|
+
const last = out.findLastIndex((m) => m.role === "assistant");
|
|
5598
|
+
const calls = last >= 0 ? out[last].tool_calls ?? [] : [];
|
|
5599
|
+
const answered = new Set(out.slice(last + 1).map((m) => m.tool_call_id));
|
|
5600
|
+
for (const call of calls) {
|
|
5601
|
+
if (!answered.has(call.id)) out.push(toolMessage(call, INTERRUPTED_CALL));
|
|
5602
|
+
}
|
|
5603
|
+
return out;
|
|
5604
|
+
}
|
|
5577
5605
|
function toolMessage(call, content) {
|
|
5578
5606
|
return { role: "tool", tool_call_id: call.id, name: call.function.name, content };
|
|
5579
5607
|
}
|
|
@@ -6574,6 +6602,7 @@ export {
|
|
|
6574
6602
|
pickReviewModel,
|
|
6575
6603
|
NO_SEARCH_INSTRUCTION,
|
|
6576
6604
|
runAgent,
|
|
6605
|
+
interruptedConversation,
|
|
6577
6606
|
collectContext,
|
|
6578
6607
|
INIT_PROMPT,
|
|
6579
6608
|
INIT_HINT,
|
package/dist/clixad.mjs
CHANGED
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
takeConfigNotices,
|
|
54
54
|
toolSchemaFor,
|
|
55
55
|
usd
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-JV44GYWT.mjs";
|
|
57
57
|
|
|
58
58
|
// src/tui/load.ts
|
|
59
59
|
import * as nodeModule from "node:module";
|
|
@@ -132,7 +132,7 @@ async function withProductionReact(load) {
|
|
|
132
132
|
}
|
|
133
133
|
function loadTui() {
|
|
134
134
|
boundInkCaches();
|
|
135
|
-
return withProductionReact(() => import("./tui-
|
|
135
|
+
return withProductionReact(() => import("./tui-KA2P7O7W.mjs"));
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
// src/title.ts
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
freeHelpLine,
|
|
46
46
|
freeTierNotice,
|
|
47
47
|
grantLabel,
|
|
48
|
+
interruptedConversation,
|
|
48
49
|
isNewerVersion,
|
|
49
50
|
listSessions,
|
|
50
51
|
listWorkspaceFiles,
|
|
@@ -97,7 +98,7 @@ import {
|
|
|
97
98
|
visibleLength,
|
|
98
99
|
webSearchCostLine,
|
|
99
100
|
welcomeBanner
|
|
100
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-JV44GYWT.mjs";
|
|
101
102
|
|
|
102
103
|
// src/tui/index.tsx
|
|
103
104
|
import "react";
|
|
@@ -1615,6 +1616,7 @@ var SENDING_FEEDBACK = "sending\u2026";
|
|
|
1615
1616
|
var WAITING_FOR_PAYMENT = "waiting for the payment\u2026";
|
|
1616
1617
|
var FEEDBACK_TURN_INTERVAL = 50;
|
|
1617
1618
|
var NOT_SIGNED_IN = " Not signed in, or the stored token isn't valid for this gateway.\n Run /login to sign in.";
|
|
1619
|
+
var KEPT_AFTER_ERROR = " The work done before this error is kept. Send a message to carry on from there,\n now or after a restart with clixad --continue.";
|
|
1618
1620
|
var LIVE_OUTPUT_LINES = 5;
|
|
1619
1621
|
var DELTA_FLUSH_MS = 50;
|
|
1620
1622
|
var PASTE_ENTER_MS = 30;
|
|
@@ -2481,6 +2483,18 @@ function App({
|
|
|
2481
2483
|
setLive({ text: "" });
|
|
2482
2484
|
nextSponsor(model2);
|
|
2483
2485
|
let history = messagesRef.current;
|
|
2486
|
+
const persist = (conversation) => {
|
|
2487
|
+
sessionRef.current.title ??= (task.split("\n")[0] || task).slice(0, 80);
|
|
2488
|
+
saveSession({
|
|
2489
|
+
id: sessionRef.current.id,
|
|
2490
|
+
started: sessionRef.current.started,
|
|
2491
|
+
updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2492
|
+
cwd: root,
|
|
2493
|
+
model: model2,
|
|
2494
|
+
title: sessionRef.current.title,
|
|
2495
|
+
messages: conversation
|
|
2496
|
+
});
|
|
2497
|
+
};
|
|
2484
2498
|
try {
|
|
2485
2499
|
const window = contextWindow(model2);
|
|
2486
2500
|
if (shouldCompact([{ role: "system", content: contextRef.current.systemPrompt }, ...history], window)) {
|
|
@@ -2546,20 +2560,13 @@ ${preferencesText}` : ""),
|
|
|
2546
2560
|
webSearch: searchRef.current
|
|
2547
2561
|
}),
|
|
2548
2562
|
signal: ac.signal,
|
|
2549
|
-
onEvent: handleEvent
|
|
2563
|
+
onEvent: handleEvent,
|
|
2564
|
+
// Without the system prompt, which is rebuilt per run.
|
|
2565
|
+
onCheckpoint: (conversation) => persist(conversation.slice(1))
|
|
2550
2566
|
});
|
|
2551
2567
|
const next = result.messages.slice(1);
|
|
2552
2568
|
setMessages(next);
|
|
2553
|
-
|
|
2554
|
-
saveSession({
|
|
2555
|
-
id: sessionRef.current.id,
|
|
2556
|
-
started: sessionRef.current.started,
|
|
2557
|
-
updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2558
|
-
cwd: root,
|
|
2559
|
-
model: model2,
|
|
2560
|
-
title: sessionRef.current.title,
|
|
2561
|
-
messages: next
|
|
2562
|
-
});
|
|
2569
|
+
persist(next);
|
|
2563
2570
|
if (result.stopped === "aborted") {
|
|
2564
2571
|
if (streamRef.current.streamed) finishStream();
|
|
2565
2572
|
push({ kind: "notice", tone: "warn", text: " (stopped)" });
|
|
@@ -2647,6 +2654,11 @@ ${preferencesText}` : ""),
|
|
|
2647
2654
|
}
|
|
2648
2655
|
} catch (err) {
|
|
2649
2656
|
if (streamRef.current.streamed) finishStream();
|
|
2657
|
+
const kept = interruptedConversation(err)?.slice(1);
|
|
2658
|
+
if (kept) {
|
|
2659
|
+
setMessages(kept);
|
|
2660
|
+
persist(kept);
|
|
2661
|
+
}
|
|
2650
2662
|
if ((err instanceof LimitRefusalError || err instanceof PremiumLockedError) && err.spendable) {
|
|
2651
2663
|
balanceSeqRef.current++;
|
|
2652
2664
|
takeSpendable(err.spendable.figures, err.spendable.balance);
|
|
@@ -2706,6 +2718,9 @@ ${preferencesText}` : ""),
|
|
|
2706
2718
|
} else {
|
|
2707
2719
|
push({ kind: "notice", tone: "error", text: ` error: ${errorNotice(err.message, void 0, " ")}` });
|
|
2708
2720
|
}
|
|
2721
|
+
if (kept && !(err instanceof PaywallError) && !(err instanceof PremiumLockedError)) {
|
|
2722
|
+
push({ kind: "notice", text: KEPT_AFTER_ERROR });
|
|
2723
|
+
}
|
|
2709
2724
|
} finally {
|
|
2710
2725
|
abortRef.current = null;
|
|
2711
2726
|
dropDelta();
|