@livx.cc/agentx 0.99.15 → 0.99.17
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/{Agent-CsVuR2O0.d.ts → Agent-BfQS-MfB.d.ts} +18 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +72 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +41 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -370,6 +370,24 @@ declare class Agent {
|
|
|
370
370
|
* `options.tools` — otherwise a constructor-passed tool resurrects on the next prepare()
|
|
371
371
|
* rebuild (and re-adding it via addTools() would then DUPLICATE it in the wire schema). */
|
|
372
372
|
removeTools(names: Set<string> | string[]): number;
|
|
373
|
+
/** Messages the host queued to steer the RUNNING turn (Claude-Code-style mid-turn input). The loop
|
|
374
|
+
* drains them at each step boundary — after tool results are appended, before the next model call —
|
|
375
|
+
* so they ride along with the latest tool results. A no-op between turns (nothing drains it). */
|
|
376
|
+
private pendingInjections;
|
|
377
|
+
/** Queue a user message into the in-flight turn. It lands as a `user` message at the next step
|
|
378
|
+
* boundary; if the model was about to stop, the injection re-opens the loop so it's never lost.
|
|
379
|
+
* Pushing onto `transcript` directly from outside would race the loop — this drains inside it. */
|
|
380
|
+
inject(content: MessageContent): void;
|
|
381
|
+
/** Drop any queued-but-unconsumed injections. The REPL calls this after a LOCAL command (/cmd, !bash)
|
|
382
|
+
* — which runs no send() to drain them — so a mid-command steer can't leak into the next real turn. */
|
|
383
|
+
clearInjections(): void;
|
|
384
|
+
/** Pull queued injections that are plain TEXT, removing them, for a runtime that can accept mid-turn
|
|
385
|
+
* steers over its own channel (claude-code's warm InputQueue via `providerOptions.steer`). Non-text
|
|
386
|
+
* injections (images) stay queued for the step-boundary `drainInjections()` re-open — the text-only
|
|
387
|
+
* steer channel can't carry them. Consumed DURING chat(); no overlap with drainInjections() (post-call). */
|
|
388
|
+
drainPendingSteers(): string[];
|
|
389
|
+
/** Fold any host-injected messages into the transcript as user turns. Returns true if any landed. */
|
|
390
|
+
private drainInjections;
|
|
373
391
|
constructor(options?: Partial<AgentOptions>);
|
|
374
392
|
/** Build the tool context from the resolved fs + options. Idempotent-safe: called once (ctor or ensureFs). */
|
|
375
393
|
private buildCtx;
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { H as Hooks, h as RunResult, R as ReasoningEffort, A as Agent } from './Agent-
|
|
2
|
+
import { H as Hooks, h as RunResult, R as ReasoningEffort, A as Agent } from './Agent-BfQS-MfB.js';
|
|
3
3
|
import { IFilesystem } from '@livx.cc/wcli/core';
|
|
4
4
|
import { M as Message, H as HostBridge, c as ContentPart, e as MessageContent } from './tools-DKf3hN4M.js';
|
|
5
5
|
|
package/dist/cli.js
CHANGED
|
@@ -3406,6 +3406,43 @@ var Agent = class _Agent {
|
|
|
3406
3406
|
if (this.options.tools) this.options.tools = this.options.tools.filter((t) => !s.has(t.name));
|
|
3407
3407
|
return before - this.activeTools.length;
|
|
3408
3408
|
}
|
|
3409
|
+
/** Messages the host queued to steer the RUNNING turn (Claude-Code-style mid-turn input). The loop
|
|
3410
|
+
* drains them at each step boundary — after tool results are appended, before the next model call —
|
|
3411
|
+
* so they ride along with the latest tool results. A no-op between turns (nothing drains it). */
|
|
3412
|
+
pendingInjections = [];
|
|
3413
|
+
/** Queue a user message into the in-flight turn. It lands as a `user` message at the next step
|
|
3414
|
+
* boundary; if the model was about to stop, the injection re-opens the loop so it's never lost.
|
|
3415
|
+
* Pushing onto `transcript` directly from outside would race the loop — this drains inside it. */
|
|
3416
|
+
inject(content) {
|
|
3417
|
+
this.pendingInjections.push(content);
|
|
3418
|
+
}
|
|
3419
|
+
/** Drop any queued-but-unconsumed injections. The REPL calls this after a LOCAL command (/cmd, !bash)
|
|
3420
|
+
* — which runs no send() to drain them — so a mid-command steer can't leak into the next real turn. */
|
|
3421
|
+
clearInjections() {
|
|
3422
|
+
this.pendingInjections.length = 0;
|
|
3423
|
+
}
|
|
3424
|
+
/** Pull queued injections that are plain TEXT, removing them, for a runtime that can accept mid-turn
|
|
3425
|
+
* steers over its own channel (claude-code's warm InputQueue via `providerOptions.steer`). Non-text
|
|
3426
|
+
* injections (images) stay queued for the step-boundary `drainInjections()` re-open — the text-only
|
|
3427
|
+
* steer channel can't carry them. Consumed DURING chat(); no overlap with drainInjections() (post-call). */
|
|
3428
|
+
drainPendingSteers() {
|
|
3429
|
+
if (!this.pendingInjections.length) return [];
|
|
3430
|
+
const texts = [];
|
|
3431
|
+
this.pendingInjections = this.pendingInjections.filter((c) => {
|
|
3432
|
+
if (typeof c === "string") {
|
|
3433
|
+
texts.push(c);
|
|
3434
|
+
return false;
|
|
3435
|
+
}
|
|
3436
|
+
return true;
|
|
3437
|
+
});
|
|
3438
|
+
return texts;
|
|
3439
|
+
}
|
|
3440
|
+
/** Fold any host-injected messages into the transcript as user turns. Returns true if any landed. */
|
|
3441
|
+
drainInjections() {
|
|
3442
|
+
if (!this.pendingInjections.length) return false;
|
|
3443
|
+
for (const content of this.pendingInjections.splice(0)) this.transcript.push({ role: "user", content });
|
|
3444
|
+
return true;
|
|
3445
|
+
}
|
|
3409
3446
|
constructor(options) {
|
|
3410
3447
|
this.options = { ...new AgentOptions(), ...options };
|
|
3411
3448
|
if (this.options.fs) this.buildCtx();
|
|
@@ -3604,10 +3641,11 @@ var Agent = class _Agent {
|
|
|
3604
3641
|
return typeof raw === "string" ? raw : raw.text;
|
|
3605
3642
|
}
|
|
3606
3643
|
} : void 0;
|
|
3644
|
+
const claudeSteerPo = o.model.startsWith("claude-code/") ? { steer: () => this.drainPendingSteers() } : void 0;
|
|
3607
3645
|
const reasonOpts = {
|
|
3608
3646
|
...frag,
|
|
3609
3647
|
...o.promptCache ? { promptCache: true } : {},
|
|
3610
|
-
...o.providerOptions || cursorPo ? { providerOptions: { ...frag.providerOptions, ...o.providerOptions, ...cursorPo } } : {}
|
|
3648
|
+
...o.providerOptions || cursorPo || claudeSteerPo ? { providerOptions: { ...frag.providerOptions, ...o.providerOptions, ...cursorPo, ...claudeSteerPo } } : {}
|
|
3611
3649
|
};
|
|
3612
3650
|
try {
|
|
3613
3651
|
for (let attempt = 0; ; attempt++) {
|
|
@@ -3671,6 +3709,7 @@ var Agent = class _Agent {
|
|
|
3671
3709
|
});
|
|
3672
3710
|
}
|
|
3673
3711
|
if (toolCalls.length === 0) {
|
|
3712
|
+
if (this.drainInjections()) continue;
|
|
3674
3713
|
log4.verbose(`completed in ${steps} step(s)`);
|
|
3675
3714
|
await this.ctx.jobs?.drain();
|
|
3676
3715
|
await this.activeHooks?.onStop?.(res.content ?? "");
|
|
@@ -3695,6 +3734,7 @@ var Agent = class _Agent {
|
|
|
3695
3734
|
}
|
|
3696
3735
|
this.transcript.push({ role: "tool", tool_call_id: tc.id, name: tc.function.name, content });
|
|
3697
3736
|
}
|
|
3737
|
+
this.drainInjections();
|
|
3698
3738
|
}
|
|
3699
3739
|
}
|
|
3700
3740
|
/**
|
|
@@ -11740,6 +11780,13 @@ function installUpdate() {
|
|
|
11740
11780
|
const r = spawnSync6("bun", ["add", "-g", "@livx.cc/agentx"], { stdio: "inherit" });
|
|
11741
11781
|
return (r.status ?? 1) === 0;
|
|
11742
11782
|
}
|
|
11783
|
+
var typeaheadOnLine = false;
|
|
11784
|
+
var clearTypeaheadLine = () => {
|
|
11785
|
+
if (typeaheadOnLine) {
|
|
11786
|
+
err("\r\x1B[2K");
|
|
11787
|
+
typeaheadOnLine = false;
|
|
11788
|
+
}
|
|
11789
|
+
};
|
|
11743
11790
|
var spinner = /* @__PURE__ */ (() => {
|
|
11744
11791
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
11745
11792
|
let timer;
|
|
@@ -11768,8 +11815,10 @@ var spinner = /* @__PURE__ */ (() => {
|
|
|
11768
11815
|
clearInterval(timer);
|
|
11769
11816
|
timer = void 0;
|
|
11770
11817
|
err("\r\x1B[2K");
|
|
11818
|
+
typeaheadOnLine = false;
|
|
11771
11819
|
}
|
|
11772
11820
|
}
|
|
11821
|
+
// the tail (type-ahead) went with it
|
|
11773
11822
|
};
|
|
11774
11823
|
})();
|
|
11775
11824
|
var setTermTitle = (t) => {
|
|
@@ -11947,7 +11996,7 @@ REPL slash commands: /help /version /tools /permissions /status /cost /context /
|
|
|
11947
11996
|
REPL completion: type / (commands+skills) or @ (files) for a LIVE menu \u2014 \u2191/\u2193 select, \u23CE/Tab accept, Esc dismiss.
|
|
11948
11997
|
REPL multi-line: Option/Alt+Enter inserts a newline, or end a line with \\ to continue. Esc cancels a running turn / clears the input line; double-Esc jumps back to edit a previous message.
|
|
11949
11998
|
REPL shortcuts: Shift+Tab cycles permission posture (ask \u2192 accept-edits \u2192 plan) \xB7 Alt+T toggles reasoning \xB7 Alt+P switches model \xB7 Ctrl+O toggles verbose tool output \xB7 Ctrl+X Ctrl+E edits the buffer in $EDITOR \xB7 \u2192 or Tab accepts the dim history ghost-suggestion \xB7 Alt+S/Ctrl+S stash/unstash.
|
|
11950
|
-
REPL stash: type while a turn is running \u2192 Enter
|
|
11999
|
+
REPL steer/stash: type while a turn is running \u2192 Enter STEERS it (the text reaches the model at its next step, alongside the next tool result). Alt+S (or Ctrl+S) with text stashes it for AFTER the turn instead; on an empty prompt pops the next stashed entry for editing.
|
|
11951
12000
|
REPL editing (emacs/readline): Ctrl-A/E line start/end \xB7 Ctrl-B/F char \xB7 Alt-B/F or Alt/Ctrl-\u2190/\u2192 word \xB7 Ctrl-W kill word \xB7 Ctrl-U/K kill to start/end \xB7 Ctrl-Y yank \xB7 Ctrl-_ undo \xB7 Alt-D kill word fwd \xB7 Ctrl-L clear screen. Set editorMode:'vim' (or /config) for modal vim editing.
|
|
11952
12001
|
REPL paste: large/multi-line pastes collapse to a [Pasted text +N lines] preview (expands on send); a pasted image/file path attaches as [Image]/[File]; Ctrl-V or /paste grabs a clipboard image (macOS).`;
|
|
11953
12002
|
function newestModel() {
|
|
@@ -12035,9 +12084,11 @@ function makeHost(format = "text", opts) {
|
|
|
12035
12084
|
notify(e) {
|
|
12036
12085
|
if (e.kind === "turn_start") {
|
|
12037
12086
|
activitySeen.clear();
|
|
12087
|
+
typeaheadOnLine = false;
|
|
12038
12088
|
return;
|
|
12039
12089
|
}
|
|
12040
12090
|
spinner.stop();
|
|
12091
|
+
clearTypeaheadLine();
|
|
12041
12092
|
if (e.kind === "text_delta") {
|
|
12042
12093
|
flushLookupGroup();
|
|
12043
12094
|
if (streamJson) process.stdout.write(JSON.stringify({ type: "text", text: e.message }) + "\n");
|
|
@@ -12184,7 +12235,10 @@ function displayHooks(fs, opts) {
|
|
|
12184
12235
|
if (call.name === "TodoWrite" && Array.isArray(call.args?.todos)) latestTodos = call.args.todos;
|
|
12185
12236
|
if (!on()) return;
|
|
12186
12237
|
if (bg) err("\r\x1B[0J");
|
|
12187
|
-
else
|
|
12238
|
+
else {
|
|
12239
|
+
spinner.stop();
|
|
12240
|
+
clearTypeaheadLine();
|
|
12241
|
+
}
|
|
12188
12242
|
flush();
|
|
12189
12243
|
if (!bg && !verboseOutput && LOOKUP.has(call.name)) {
|
|
12190
12244
|
pendingHeader = header(call);
|
|
@@ -12205,7 +12259,10 @@ function displayHooks(fs, opts) {
|
|
|
12205
12259
|
async postToolUse(call, result) {
|
|
12206
12260
|
if (!on()) return;
|
|
12207
12261
|
if (bg) err("\r\x1B[0J");
|
|
12208
|
-
else
|
|
12262
|
+
else {
|
|
12263
|
+
spinner.stop();
|
|
12264
|
+
clearTypeaheadLine();
|
|
12265
|
+
}
|
|
12209
12266
|
try {
|
|
12210
12267
|
if (pendingHeader) {
|
|
12211
12268
|
const t = String(result).replace(/\s+$/, "");
|
|
@@ -14662,6 +14719,7 @@ ${task}`;
|
|
|
14662
14719
|
const renderStashBuf = () => {
|
|
14663
14720
|
if (spinner.active) return;
|
|
14664
14721
|
err(`\r\x1B[K${sEd.buf ? " " + stashView() : ""}`);
|
|
14722
|
+
typeaheadOnLine = !!sEd.buf;
|
|
14665
14723
|
};
|
|
14666
14724
|
repaintStash = renderStashBuf;
|
|
14667
14725
|
keyInput.on("keypress", (_s, key) => {
|
|
@@ -14694,11 +14752,18 @@ ${task}`;
|
|
|
14694
14752
|
if (action === "submit") {
|
|
14695
14753
|
const text = sEd.expand().trim();
|
|
14696
14754
|
sEd.reset();
|
|
14755
|
+
typeaheadOnLine = false;
|
|
14697
14756
|
if (text) {
|
|
14698
|
-
inputStash.push(text);
|
|
14699
14757
|
const view = text.replace(/\n+/g, " \u23CE ");
|
|
14700
|
-
|
|
14758
|
+
if ((activeTurn || dispatchPending) && !duplex) {
|
|
14759
|
+
agent.inject(text);
|
|
14760
|
+
err(`\r\x1B[K${bold(cyan(" \u21B3 steering \u203A"))} ${cyan(`${view.slice(0, 60)}${view.length > 60 ? "\u2026" : ""}`)}
|
|
14701
14761
|
`);
|
|
14762
|
+
} else {
|
|
14763
|
+
inputStash.push(text);
|
|
14764
|
+
err(`\r\x1B[K${green(" \u2713 stashed")} ${dim(`#${inputStash.length}: ${view.slice(0, 50)}${view.length > 50 ? "\u2026" : ""}`)}
|
|
14765
|
+
`);
|
|
14766
|
+
}
|
|
14702
14767
|
}
|
|
14703
14768
|
return;
|
|
14704
14769
|
}
|
|
@@ -15079,6 +15144,7 @@ ${out}
|
|
|
15079
15144
|
}
|
|
15080
15145
|
let quit = await dispatchLine(line) === "quit";
|
|
15081
15146
|
const wasLocal = /^[!#/]/.test(line);
|
|
15147
|
+
if (wasLocal) agent.clearInjections();
|
|
15082
15148
|
while (!quit && !wasLocal && inputStash.length) {
|
|
15083
15149
|
const next = inputStash.shift();
|
|
15084
15150
|
const nview = next.replace(/\n+/g, " \u23CE ");
|