agent.libx.js 0.94.17 → 0.94.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/dist/{Agent-COa80xYy.d.ts → Agent-DmsB5hzp.d.ts} +7 -2
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +36 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +24 -6
- package/dist/index.js.map +1 -1
- package/dist/{mcp-C5GuDinb.d.ts → mcp-D00OuccC.d.ts} +1 -1
- package/dist/mcp.client.d.ts +2 -2
- package/dist/{tools-GPWp7oXq.d.ts → tools-9AUK6SG2.d.ts} +4 -0
- package/dist/tools.shell.d.ts +1 -1
- package/dist/tools.shell.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IFilesystem } from '@livx.cc/wcli/core';
|
|
2
|
-
import { M as Message, H as HostBridge, A as AgentTool, C as ChatLike, e as MessageContent } from './tools-
|
|
2
|
+
import { M as Message, H as HostBridge, A as AgentTool, C as ChatLike, e as MessageContent } from './tools-9AUK6SG2.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Hooks — deterministic interception points around tool execution, run by the
|
|
@@ -209,7 +209,8 @@ declare class AgentOptions {
|
|
|
209
209
|
systemPrompt: string;
|
|
210
210
|
tools: AgentTool[];
|
|
211
211
|
maxSteps: number;
|
|
212
|
-
/** Hard ceiling on accumulated tokens (prompt+completion) across the run
|
|
212
|
+
/** Hard ceiling on accumulated tokens (prompt+completion) across the run; cache READS count at 0.1×
|
|
213
|
+
* (their real price) so a fat cached context doesn't trip the guard on healthy turns. 0 = unbounded. */
|
|
213
214
|
maxTokens: number;
|
|
214
215
|
/** Wall-clock ceiling in ms for the whole run. 0 = unbounded. */
|
|
215
216
|
timeoutMs: number;
|
|
@@ -317,6 +318,10 @@ declare class Agent {
|
|
|
317
318
|
private prepared;
|
|
318
319
|
private systemPromptCache;
|
|
319
320
|
private started;
|
|
321
|
+
private parkedMs;
|
|
322
|
+
/** Time a human-blocking await (a permission/plan prompt) and bank it in `parkedMs` so idle prompt
|
|
323
|
+
* time never trips the wall-clock kill-switch. The agent did no work while parked on the user. */
|
|
324
|
+
private park;
|
|
320
325
|
/** Force the next `send()`/`run()` to rebuild the system prompt, tools, plan-mode and permission hooks
|
|
321
326
|
* from `options` — apply mid-conversation changes to `planMode`/`permissions`/`model` etc. (prepare()
|
|
322
327
|
* is otherwise memoized per conversation). */
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { h as RunResult, R as ReasoningEffort } from './Agent-
|
|
2
|
+
import { h as RunResult, R as ReasoningEffort } from './Agent-DmsB5hzp.js';
|
|
3
3
|
import { IFilesystem } from '@livx.cc/wcli/core';
|
|
4
|
-
import { M as Message, c as ContentPart } from './tools-
|
|
4
|
+
import { M as Message, c as ContentPart } from './tools-9AUK6SG2.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* On-disk session store for the CLI: each conversation is one JSON file at
|
package/dist/cli.js
CHANGED
|
@@ -2590,9 +2590,10 @@ function planMode(opts) {
|
|
|
2590
2590
|
parameters: { type: "object", required: ["plan"], properties: { plan: { type: "string", description: "the concrete steps you will take" } } },
|
|
2591
2591
|
async run({ plan }, _ctx) {
|
|
2592
2592
|
if (opts?.host?.confirm) {
|
|
2593
|
-
const
|
|
2593
|
+
const confirm = opts.host.confirm(`Approve this plan?
|
|
2594
2594
|
|
|
2595
2595
|
${String(plan ?? "")}`);
|
|
2596
|
+
const ok = await (_ctx?.parkHuman ? _ctx.parkHuman(confirm) : confirm);
|
|
2596
2597
|
if (!ok) return "Plan not approved. Revise it and call ExitPlanMode again.";
|
|
2597
2598
|
}
|
|
2598
2599
|
approved = true;
|
|
@@ -2748,7 +2749,8 @@ var AgentOptions = class {
|
|
|
2748
2749
|
tools = defaultTools();
|
|
2749
2750
|
maxSteps = 25;
|
|
2750
2751
|
// --- automatic kill-switches (always on; protect the API budget against runaway loops/abuse) ---
|
|
2751
|
-
/** Hard ceiling on accumulated tokens (prompt+completion) across the run
|
|
2752
|
+
/** Hard ceiling on accumulated tokens (prompt+completion) across the run; cache READS count at 0.1×
|
|
2753
|
+
* (their real price) so a fat cached context doesn't trip the guard on healthy turns. 0 = unbounded. */
|
|
2752
2754
|
maxTokens = 2e5;
|
|
2753
2755
|
/** Wall-clock ceiling in ms for the whole run. 0 = unbounded. */
|
|
2754
2756
|
timeoutMs = 12e4;
|
|
@@ -2850,6 +2852,18 @@ var Agent = class _Agent {
|
|
|
2850
2852
|
// the assembled system prompt from the last prepare()
|
|
2851
2853
|
started = false;
|
|
2852
2854
|
// session-start lifecycle hook fires once per conversation
|
|
2855
|
+
parkedMs = 0;
|
|
2856
|
+
// cumulative time blocked on the HUMAN (permission/plan prompts) — excluded from the timeout
|
|
2857
|
+
/** Time a human-blocking await (a permission/plan prompt) and bank it in `parkedMs` so idle prompt
|
|
2858
|
+
* time never trips the wall-clock kill-switch. The agent did no work while parked on the user. */
|
|
2859
|
+
async park(p) {
|
|
2860
|
+
const t = Date.now();
|
|
2861
|
+
try {
|
|
2862
|
+
return await p;
|
|
2863
|
+
} finally {
|
|
2864
|
+
this.parkedMs += Date.now() - t;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2853
2867
|
/** Force the next `send()`/`run()` to rebuild the system prompt, tools, plan-mode and permission hooks
|
|
2854
2868
|
* from `options` — apply mid-conversation changes to `planMode`/`permissions`/`model` etc. (prepare()
|
|
2855
2869
|
* is otherwise memoized per conversation). */
|
|
@@ -2878,6 +2892,7 @@ var Agent = class _Agent {
|
|
|
2878
2892
|
if (this.options.lintOnWrite) this.ctx.lint = checkSyntax;
|
|
2879
2893
|
this.ctx.ai = this.options.ai;
|
|
2880
2894
|
this.ctx.model = this.options.model;
|
|
2895
|
+
this.ctx.parkHuman = (p) => this.park(p);
|
|
2881
2896
|
if (this.options.backgroundJobs) this.ctx.jobs = new SandboxJobRegistry();
|
|
2882
2897
|
}
|
|
2883
2898
|
/**
|
|
@@ -3023,19 +3038,21 @@ var Agent = class _Agent {
|
|
|
3023
3038
|
const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
3024
3039
|
let usageEstimated = false;
|
|
3025
3040
|
const start = Date.now();
|
|
3041
|
+
this.parkedMs = 0;
|
|
3026
3042
|
let toolCallsTotal = 0;
|
|
3027
3043
|
let lastFp = "";
|
|
3028
3044
|
let repeats = 0;
|
|
3029
3045
|
const kill = (finishReason) => {
|
|
3030
|
-
log3.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, ms=${Date.now() - start})`);
|
|
3046
|
+
log3.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, budgetTokens=${Math.round(usage.totalTokens - 0.9 * usage.cacheReadTokens)}, ms=${Date.now() - start - this.parkedMs}${this.parkedMs ? ` +${this.parkedMs} parked` : ""})`);
|
|
3031
3047
|
this.ctx.jobs?.killAll();
|
|
3032
3048
|
return { text: lastAssistantText(this.transcript), steps, finishReason, messages: this.transcript, usage, usageEstimated };
|
|
3033
3049
|
};
|
|
3034
3050
|
while (true) {
|
|
3035
3051
|
if (o.signal?.aborted) return kill("aborted");
|
|
3036
3052
|
if (steps >= o.maxSteps) return kill("max_steps");
|
|
3037
|
-
if (o.timeoutMs && Date.now() - start >= o.timeoutMs) return kill("timeout");
|
|
3038
|
-
|
|
3053
|
+
if (o.timeoutMs && Date.now() - start - this.parkedMs >= o.timeoutMs) return kill("timeout");
|
|
3054
|
+
const budgetTokens = usage.totalTokens - 0.9 * usage.cacheReadTokens;
|
|
3055
|
+
if (o.maxTokens && budgetTokens >= o.maxTokens) return kill("budget");
|
|
3039
3056
|
steps++;
|
|
3040
3057
|
this.options.host?.notify?.({ kind: "turn_start", message: `step ${steps}` });
|
|
3041
3058
|
let res;
|
|
@@ -3170,7 +3187,7 @@ var Agent = class _Agent {
|
|
|
3170
3187
|
const hooks = this.activeHooks;
|
|
3171
3188
|
const call = { name: tc.function.name, args };
|
|
3172
3189
|
const meta = { id: tc.id };
|
|
3173
|
-
const decision = await hooks?.preToolUse?.(call, meta);
|
|
3190
|
+
const decision = await this.park(Promise.resolve(hooks?.preToolUse?.(call, meta)));
|
|
3174
3191
|
if (decision?.block) {
|
|
3175
3192
|
const blocked = `Blocked by hook: ${decision.reason ?? "no reason given"}`;
|
|
3176
3193
|
log3.debug(`${tc.function.name} -> ${blocked}`);
|
|
@@ -3212,6 +3229,7 @@ var Agent = class _Agent {
|
|
|
3212
3229
|
this.ctx.emit = void 0;
|
|
3213
3230
|
}
|
|
3214
3231
|
if (!threw) result = await this.maybeAutoTest(tc.function.name, result);
|
|
3232
|
+
if (images?.length && !result) result = `[${images.length} image${images.length > 1 ? "s" : ""} attached]`;
|
|
3215
3233
|
const cap = this.options.maxToolResultBytes ?? 0;
|
|
3216
3234
|
if (!threw && cap > 0 && result.length > cap) {
|
|
3217
3235
|
const info = { tool: tc.function.name, args };
|
|
@@ -7457,6 +7475,12 @@ var EditorState = class _EditorState {
|
|
|
7457
7475
|
pasteChar(c) {
|
|
7458
7476
|
this.pasteBuf += c;
|
|
7459
7477
|
}
|
|
7478
|
+
/** Actively grab a clipboard image and attach it (Ctrl-V; same hook as the empty-paste path). */
|
|
7479
|
+
grabClipboard() {
|
|
7480
|
+
const att = this.onEmptyPaste?.();
|
|
7481
|
+
if (att) this.attach(att.display, att.ref);
|
|
7482
|
+
return !!att;
|
|
7483
|
+
}
|
|
7460
7484
|
endPaste() {
|
|
7461
7485
|
this.pasting = false;
|
|
7462
7486
|
const text = this.pasteBuf;
|
|
@@ -7887,6 +7911,10 @@ function applyKey(s, key, str) {
|
|
|
7887
7911
|
if (key?.ctrl && k === "u") return s.killToStart(), "none";
|
|
7888
7912
|
if (key?.ctrl && k === "k") return s.killToEnd(), "none";
|
|
7889
7913
|
if (key?.ctrl && k === "y") return s.yank(), "none";
|
|
7914
|
+
if (key?.ctrl && k === "v") {
|
|
7915
|
+
s.grabClipboard();
|
|
7916
|
+
return "none";
|
|
7917
|
+
}
|
|
7890
7918
|
if (str === "") return s.undo(), "none";
|
|
7891
7919
|
if (key?.meta && k === "b") return s.wordLeft(), "none";
|
|
7892
7920
|
if (key?.meta && k === "f") return s.wordRight(), "none";
|
|
@@ -8774,7 +8802,7 @@ REPL multi-line: Option/Alt+Enter inserts a newline, or end a line with \\ to co
|
|
|
8774
8802
|
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 \u2192 or Tab accepts the dim history ghost-suggestion \xB7 Alt+S/Ctrl+S stash/unstash.
|
|
8775
8803
|
REPL stash: type while a turn is running \u2192 Enter queues it (auto-submits when the turn finishes). Alt+S (or Ctrl+S) with text stashes it; on an empty prompt pops the next entry for editing.
|
|
8776
8804
|
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.
|
|
8777
|
-
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]; /paste grabs a clipboard image (macOS).`;
|
|
8805
|
+
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).`;
|
|
8778
8806
|
function newestModel() {
|
|
8779
8807
|
return listModels().slice().sort((a, b) => (getModelInfo(b)?.releaseDate ?? "").localeCompare(getModelInfo(a)?.releaseDate ?? ""))[0] ?? "";
|
|
8780
8808
|
}
|
|
@@ -10949,7 +10977,7 @@ ${extra}` : body);
|
|
|
10949
10977
|
},
|
|
10950
10978
|
init: { desc: "scaffold ./AGENTS.md project instructions", run: () => initInstructions(cwd) },
|
|
10951
10979
|
paste: {
|
|
10952
|
-
desc: "attach an image from the clipboard (macOS) \u2014 /paste [message] sends now, /paste alone attaches to your next message",
|
|
10980
|
+
desc: "attach an image from the clipboard (macOS, = Ctrl-V) \u2014 /paste [message] sends now, /paste alone attaches to your next message",
|
|
10953
10981
|
run: async (a) => {
|
|
10954
10982
|
const att = grabClipboardAttachment();
|
|
10955
10983
|
if (!att) {
|