agent.libx.js 0.93.18 → 0.93.19
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/cli/cli.ts +19 -2
- package/dist/cli.js +12 -1
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/cli/cli.ts
CHANGED
|
@@ -1035,6 +1035,9 @@ async function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: st
|
|
|
1035
1035
|
let dx: DuplexAgent | undefined;
|
|
1036
1036
|
let voiceIO: VoiceIO | undefined; // real voice I/O (--voice + keys): mic→STT in, text_delta→TTS out
|
|
1037
1037
|
let editorRef: LineEditor | undefined; // bound once the line editor exists — async chrome repaints the prompt via it
|
|
1038
|
+
// During a turn the user's type-ahead lives on a "stash ›" line (no active editor to own it). Async
|
|
1039
|
+
// chrome (streamed deltas, task events) lands on top of it — repaint the stash below, so it survives.
|
|
1040
|
+
let repaintStash: () => void = () => {};
|
|
1038
1041
|
let workerOptions: AgentOptions | undefined;
|
|
1039
1042
|
// Worker UI verbosity: 'full' = ⚙ tool chrome per worker step; 'minimal' = task events only
|
|
1040
1043
|
// (started/progress/⦿ done). Voice defaults minimal (chrome is noise next to speech); /workers toggles live.
|
|
@@ -1110,6 +1113,13 @@ async function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: st
|
|
|
1110
1113
|
if (e.kind === 'text_delta' && voiceIO) {
|
|
1111
1114
|
voiceIO.speakDelta(e.message);
|
|
1112
1115
|
editorRef?.suspend(); // no-op when already suspended
|
|
1116
|
+
} else if (e.kind === 'text_delta' && stashBuf) {
|
|
1117
|
+
// TEXT mode with type-ahead pending: lift the sacred stash line, let the markdown stream
|
|
1118
|
+
// land, then repaint the stash below it (else the streamed ack overwrites what's being typed).
|
|
1119
|
+
process.stdout.write('\r\x1b[K');
|
|
1120
|
+
base.notify!(e);
|
|
1121
|
+
repaintStash();
|
|
1122
|
+
return;
|
|
1113
1123
|
}
|
|
1114
1124
|
if (e.kind === 'hold_filler' && voiceIO) {
|
|
1115
1125
|
voiceIO.speakFiller(e.message);
|
|
@@ -1135,6 +1145,7 @@ async function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: st
|
|
|
1135
1145
|
if (lines.length > shown.length) err(dim(` … (+${lines.length - shown.length} more lines)\n`));
|
|
1136
1146
|
duplexAccount(e.data); // worker tokens/cost are real spend — fold into /cost
|
|
1137
1147
|
editorRef?.redrawNow();
|
|
1148
|
+
repaintStash(); // type-ahead survives the async ⦿ landing
|
|
1138
1149
|
return;
|
|
1139
1150
|
}
|
|
1140
1151
|
// Remaining task_* events (started/progress/cancelled/error) land ASYNC at a live prompt —
|
|
@@ -1145,6 +1156,7 @@ async function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: st
|
|
|
1145
1156
|
// asks are decisions, not chatter — make them stand out (the voice also speaks them)
|
|
1146
1157
|
err('\r\x1b[0J' + (e.kind === 'task_ask' ? yellow(` ? ${e.message} — answer by voice or type yes/no\n`) : dim(` · ${e.message}\n`)));
|
|
1147
1158
|
editorRef?.redrawNow();
|
|
1159
|
+
repaintStash(); // type-ahead survives the async task event landing
|
|
1148
1160
|
return;
|
|
1149
1161
|
}
|
|
1150
1162
|
base.notify!(e); // makeHost always provides notify (the HostBridge type just marks it optional)
|
|
@@ -1921,6 +1933,8 @@ async function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: st
|
|
|
1921
1933
|
const q = inputStash.length ? dim(` [${inputStash.length} queued]`) : '';
|
|
1922
1934
|
err(`\r\x1b[K${dim(' stash › ')}${stashBuf}${q}`);
|
|
1923
1935
|
};
|
|
1936
|
+
repaintStash = renderStashBuf; // async chrome repaints the type-ahead line through this
|
|
1937
|
+
|
|
1924
1938
|
process.stdin.on('keypress', (_s, key) => {
|
|
1925
1939
|
if (!activeTurn) return;
|
|
1926
1940
|
if (key?.ctrl && key?.name === 'o') { toggleVerbose(); return; }
|
|
@@ -2064,9 +2078,12 @@ async function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: st
|
|
|
2064
2078
|
while (true) {
|
|
2065
2079
|
// Double-Esc fired during the just-finished turn → open the jump-back picker now (turn has unwound).
|
|
2066
2080
|
if (pendingRewind) { pendingRewind = false; const t = await rewindToMessage(); if (t !== undefined) prefill = t; }
|
|
2067
|
-
aborting = false;
|
|
2081
|
+
aborting = false;
|
|
2082
|
+
const carry = stashBuf; stashBuf = ''; // type-ahead typed (not Enter'd) during the turn → carry it forward
|
|
2068
2083
|
err('\n'); // blank line before the prompt (the editor renders on one line)
|
|
2069
|
-
|
|
2084
|
+
// Consume the pending jump-back text (once); else fall back to un-submitted type-ahead so a line
|
|
2085
|
+
// typed while the turn ran isn't lost — it lands editable in the fresh prompt (CC parity).
|
|
2086
|
+
const initial = prefill ?? (carry || undefined); prefill = undefined;
|
|
2070
2087
|
// Dim status footer under the prompt (context% · cost). Constant while typing one line (transcript is
|
|
2071
2088
|
// fixed until submit), so compute once per iteration. Hidden on a fresh REPL (no usage yet) to stay clean.
|
|
2072
2089
|
const ctxTok = estimateTranscriptTokens(face.transcript); // expensive: compute once per iteration (not per keystroke)
|
package/dist/cli.js
CHANGED
|
@@ -8600,6 +8600,8 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
8600
8600
|
let dx;
|
|
8601
8601
|
let voiceIO;
|
|
8602
8602
|
let editorRef;
|
|
8603
|
+
let repaintStash = () => {
|
|
8604
|
+
};
|
|
8603
8605
|
let workerOptions;
|
|
8604
8606
|
let workerChrome = "full";
|
|
8605
8607
|
let duplexPersist = () => {
|
|
@@ -8655,6 +8657,11 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
8655
8657
|
if (e.kind === "text_delta" && voiceIO) {
|
|
8656
8658
|
voiceIO.speakDelta(e.message);
|
|
8657
8659
|
editorRef?.suspend();
|
|
8660
|
+
} else if (e.kind === "text_delta" && stashBuf) {
|
|
8661
|
+
process.stdout.write("\r\x1B[K");
|
|
8662
|
+
base.notify(e);
|
|
8663
|
+
repaintStash();
|
|
8664
|
+
return;
|
|
8658
8665
|
}
|
|
8659
8666
|
if (e.kind === "hold_filler" && voiceIO) {
|
|
8660
8667
|
voiceIO.speakFiller(e.message);
|
|
@@ -8679,6 +8686,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
8679
8686
|
`));
|
|
8680
8687
|
duplexAccount(e.data);
|
|
8681
8688
|
editorRef?.redrawNow();
|
|
8689
|
+
repaintStash();
|
|
8682
8690
|
return;
|
|
8683
8691
|
}
|
|
8684
8692
|
if (typeof e.kind === "string" && e.kind.startsWith("task_")) {
|
|
@@ -8687,6 +8695,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
8687
8695
|
`) : dim(` \xB7 ${e.message}
|
|
8688
8696
|
`)));
|
|
8689
8697
|
editorRef?.redrawNow();
|
|
8698
|
+
repaintStash();
|
|
8690
8699
|
return;
|
|
8691
8700
|
}
|
|
8692
8701
|
base.notify(e);
|
|
@@ -9681,6 +9690,7 @@ ${extra}` : body);
|
|
|
9681
9690
|
const q2 = inputStash.length ? dim(` [${inputStash.length} queued]`) : "";
|
|
9682
9691
|
err(`\r\x1B[K${dim(" stash \u203A ")}${stashBuf}${q2}`);
|
|
9683
9692
|
};
|
|
9693
|
+
repaintStash = renderStashBuf;
|
|
9684
9694
|
process.stdin.on("keypress", (_s, key) => {
|
|
9685
9695
|
if (!activeTurn) return;
|
|
9686
9696
|
if (key?.ctrl && key?.name === "o") {
|
|
@@ -9870,9 +9880,10 @@ ${extra}` : body);
|
|
|
9870
9880
|
if (t !== void 0) prefill = t;
|
|
9871
9881
|
}
|
|
9872
9882
|
aborting = false;
|
|
9883
|
+
const carry = stashBuf;
|
|
9873
9884
|
stashBuf = "";
|
|
9874
9885
|
err("\n");
|
|
9875
|
-
const initial = prefill;
|
|
9886
|
+
const initial = prefill ?? (carry || void 0);
|
|
9876
9887
|
prefill = void 0;
|
|
9877
9888
|
const ctxTok = estimateTranscriptTokens(face.transcript);
|
|
9878
9889
|
const ctxCap = face.options.maxTokens || 2e5;
|