agent.libx.js 0.89.4 → 0.89.6
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/cli.d.ts +20 -0
- package/dist/cli.js +67 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -23,6 +23,25 @@ interface SessionMeta {
|
|
|
23
23
|
costUsd?: number;
|
|
24
24
|
/** Sticky: true if any turn's usage was estimated (streamed without provider usage) → cost is approximate. */
|
|
25
25
|
costEstimated?: boolean;
|
|
26
|
+
/** Per-turn forensic log: timing, outcome, usage, and provider error per turn — for investigating a reported issue. */
|
|
27
|
+
events?: TurnEvent[];
|
|
28
|
+
}
|
|
29
|
+
/** One turn's diagnostics, captured for offline forensics (mirrors what the footer prints, but persisted). */
|
|
30
|
+
interface TurnEvent {
|
|
31
|
+
ts: number;
|
|
32
|
+
durationMs: number;
|
|
33
|
+
model: string;
|
|
34
|
+
finishReason: string;
|
|
35
|
+
steps: number;
|
|
36
|
+
tools: number;
|
|
37
|
+
tokens?: number;
|
|
38
|
+
costUsd?: number;
|
|
39
|
+
estimated?: boolean;
|
|
40
|
+
error?: {
|
|
41
|
+
message: string;
|
|
42
|
+
statusCode?: number;
|
|
43
|
+
code?: string;
|
|
44
|
+
};
|
|
26
45
|
}
|
|
27
46
|
interface SessionData {
|
|
28
47
|
meta: SessionMeta;
|
|
@@ -145,6 +164,7 @@ declare function expandMentions(fs: IFilesystem, line: string): Promise<{
|
|
|
145
164
|
}>;
|
|
146
165
|
/** The headless `--output-format json` result object for a turn. */
|
|
147
166
|
declare function jsonResult(res: RunResult, session: SessionData): {
|
|
167
|
+
error?: any;
|
|
148
168
|
ok: boolean;
|
|
149
169
|
finishReason: "error" | "budget" | "stop" | "max_steps" | "timeout" | "loop" | "max_tool_calls" | "aborted";
|
|
150
170
|
text: string;
|
package/dist/cli.js
CHANGED
|
@@ -2805,7 +2805,7 @@ var Agent = class _Agent {
|
|
|
2805
2805
|
} catch (err2) {
|
|
2806
2806
|
if (err2?.code === "budget") return kill("budget");
|
|
2807
2807
|
if (o.signal?.aborted) return kill("aborted");
|
|
2808
|
-
log3.error(
|
|
2808
|
+
log3.error(`chat() failed: ${err2?.message ?? err2}`, err2);
|
|
2809
2809
|
return { text: "", steps, finishReason: "error", messages: this.transcript, usage, usageEstimated, error: err2 };
|
|
2810
2810
|
}
|
|
2811
2811
|
if (o.signal?.aborted) return kill("aborted");
|
|
@@ -2869,12 +2869,14 @@ var Agent = class _Agent {
|
|
|
2869
2869
|
}
|
|
2870
2870
|
async dispatch(tc) {
|
|
2871
2871
|
const tool = this.activeTools.find((t) => t.name === tc.function.name);
|
|
2872
|
-
if (!tool) return `Error: unknown tool '${tc.function.name}'`;
|
|
2873
2872
|
let args = {};
|
|
2873
|
+
let earlyError;
|
|
2874
|
+
if (!tool) earlyError = `Error: unknown tool '${tc.function.name}'`;
|
|
2874
2875
|
try {
|
|
2875
2876
|
args = tc.function.arguments ? JSON.parse(tc.function.arguments) : {};
|
|
2876
2877
|
} catch (e) {
|
|
2877
|
-
|
|
2878
|
+
args = tc.function.arguments;
|
|
2879
|
+
earlyError ??= `Error: invalid JSON arguments for ${tc.function.name}: ${String(e)}`;
|
|
2878
2880
|
}
|
|
2879
2881
|
const hooks = this.activeHooks;
|
|
2880
2882
|
const call = { name: tc.function.name, args };
|
|
@@ -2887,6 +2889,12 @@ var Agent = class _Agent {
|
|
|
2887
2889
|
return blocked;
|
|
2888
2890
|
}
|
|
2889
2891
|
this.options.host?.notify?.({ kind: "tool_use", id: tc.id ?? "", name: tc.function.name, input: args });
|
|
2892
|
+
if (earlyError) {
|
|
2893
|
+
log3.debug(`${tc.function.name} -> ${earlyError}`);
|
|
2894
|
+
await hooks?.postToolUse?.(call, earlyError, meta);
|
|
2895
|
+
this.options.host?.notify?.({ kind: "tool_result", id: tc.id ?? "", output: earlyError, isError: true });
|
|
2896
|
+
return earlyError;
|
|
2897
|
+
}
|
|
2890
2898
|
let result;
|
|
2891
2899
|
let threw = false;
|
|
2892
2900
|
try {
|
|
@@ -3830,6 +3838,11 @@ async function buildAgent(o) {
|
|
|
3830
3838
|
const jailedDisk = new JailedFilesystem(disk);
|
|
3831
3839
|
jailedDisk.setCwd(cwd);
|
|
3832
3840
|
const virtual = o.sandbox || !!o.boddb;
|
|
3841
|
+
const isCursor = (o.model ?? "").startsWith("cursor/");
|
|
3842
|
+
if (virtual && isCursor)
|
|
3843
|
+
throw new Error(
|
|
3844
|
+
"cursor/* models cannot run in --sandbox/--boddb: the Cursor agent runs its own real-disk tools and bypasses the VFS jail. Use disk mode (default)."
|
|
3845
|
+
);
|
|
3833
3846
|
let fs = jailedDisk;
|
|
3834
3847
|
if (o.sandbox) {
|
|
3835
3848
|
const mem = new MemFilesystem2();
|
|
@@ -3891,6 +3904,10 @@ Reference files in them by their mount path (the left side).`;
|
|
|
3891
3904
|
ai: o.ai,
|
|
3892
3905
|
fs,
|
|
3893
3906
|
model: o.model ?? "anthropic/claude-sonnet-4-6",
|
|
3907
|
+
// Anchor cursor to the launch dir (its adapter defaults to TMPDIR otherwise). Gated to cursor:
|
|
3908
|
+
// openai/google adapters Object.assign providerOptions into the request body, so a blanket cwd
|
|
3909
|
+
// would corrupt those calls.
|
|
3910
|
+
...isCursor ? { providerOptions: { cwd } } : {},
|
|
3894
3911
|
...(() => {
|
|
3895
3912
|
const now = /* @__PURE__ */ new Date();
|
|
3896
3913
|
const platformNames = { darwin: "macOS", linux: "Linux", win32: "Windows" };
|
|
@@ -4641,7 +4658,7 @@ function completePath(listDir, ref) {
|
|
|
4641
4658
|
import { emitKeypressEvents } from "readline";
|
|
4642
4659
|
|
|
4643
4660
|
// cli/bidi.ts
|
|
4644
|
-
var RTL_RE = /[
|
|
4661
|
+
var RTL_RE = /[\u0590-\u05ff\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb1d-\ufdff\ufe70-\ufeff]/;
|
|
4645
4662
|
var needsBidi = (s) => RTL_RE.test(s);
|
|
4646
4663
|
function classify(c) {
|
|
4647
4664
|
if (c >= 1425 && c <= 1469) return "NSM";
|
|
@@ -5927,6 +5944,22 @@ function resolveModelOrNewest(model) {
|
|
|
5927
5944
|
return fallback;
|
|
5928
5945
|
}
|
|
5929
5946
|
var ENV_KEY_ALIASES = { google: ["GEMINI_API_KEY"] };
|
|
5947
|
+
function loadInstallEnv() {
|
|
5948
|
+
let dir = dirname3(import.meta.path);
|
|
5949
|
+
for (let i = 0; i < 5 && !existsSync7(join8(dir, "package.json")); i++) dir = dirname3(dir);
|
|
5950
|
+
for (const name of [".env", ".env.local"]) {
|
|
5951
|
+
const file = join8(dir, name);
|
|
5952
|
+
if (!existsSync7(file)) continue;
|
|
5953
|
+
for (const line of readFileSync5(file, "utf8").split("\n")) {
|
|
5954
|
+
const m = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
5955
|
+
if (!m || m[1] in process.env) continue;
|
|
5956
|
+
let val = m[2].trim();
|
|
5957
|
+
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) val = val.slice(1, -1);
|
|
5958
|
+
else val = val.replace(/\s+#.*$/, "").trim();
|
|
5959
|
+
process.env[m[1]] = val;
|
|
5960
|
+
}
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5930
5963
|
function apiKeysFromEnv() {
|
|
5931
5964
|
const e = process.env, keys = {};
|
|
5932
5965
|
for (const provider of listProviders()) {
|
|
@@ -5956,7 +5989,10 @@ function makeHost(format = "text", opts) {
|
|
|
5956
5989
|
}
|
|
5957
5990
|
if (e.kind === "thinking_delta") {
|
|
5958
5991
|
if (streamJson) process.stdout.write(JSON.stringify({ type: "thinking", text: e.message }) + "\n");
|
|
5959
|
-
else if (!cleanStdout)
|
|
5992
|
+
else if (!cleanStdout) {
|
|
5993
|
+
if (md && md.pending()) process.stdout.write(md.flush() + "\n");
|
|
5994
|
+
process.stderr.write(dim(e.message));
|
|
5995
|
+
}
|
|
5960
5996
|
return;
|
|
5961
5997
|
}
|
|
5962
5998
|
if (md && md.pending()) process.stdout.write(md.flush() + "\n");
|
|
@@ -6118,6 +6154,9 @@ function costOf(pricing, promptTokens = 0, completionTokens = 0) {
|
|
|
6118
6154
|
function turnCost(model, usage) {
|
|
6119
6155
|
return costOf(getModelInfo(model)?.pricing, usage?.promptTokens ?? 0, usage?.completionTokens ?? 0);
|
|
6120
6156
|
}
|
|
6157
|
+
function errInfo(e) {
|
|
6158
|
+
return { message: String(e?.message ?? e), statusCode: e?.statusCode, code: e?.code };
|
|
6159
|
+
}
|
|
6121
6160
|
function fmtUsd(n) {
|
|
6122
6161
|
return n >= 1 ? `$${n.toFixed(2)}` : `$${n.toFixed(4)}`;
|
|
6123
6162
|
}
|
|
@@ -6342,7 +6381,8 @@ function jsonResult(res, session) {
|
|
|
6342
6381
|
steps: res.steps,
|
|
6343
6382
|
tools: res.messages.slice(lastUser).filter((m) => m.role === "tool").length,
|
|
6344
6383
|
usage: res.usage,
|
|
6345
|
-
sessionId: session.meta.id
|
|
6384
|
+
sessionId: session.meta.id,
|
|
6385
|
+
...res.finishReason === "error" && res.error ? { error: res.error?.message ?? String(res.error) } : {}
|
|
6346
6386
|
};
|
|
6347
6387
|
}
|
|
6348
6388
|
async function readMultiline(readLine) {
|
|
@@ -6385,6 +6425,12 @@ async function runTurn(agent, store, session, task, cp, cwd = process.cwd()) {
|
|
|
6385
6425
|
spinner.stop();
|
|
6386
6426
|
err(red(` error: ${e?.message ?? e}
|
|
6387
6427
|
`));
|
|
6428
|
+
(session.meta.events ??= []).push({ ts: t0, durationMs: Date.now() - t0, model: agent.options.model, finishReason: "error", steps: 0, tools: 0, error: errInfo(e) });
|
|
6429
|
+
session.meta.updated = Date.now();
|
|
6430
|
+
try {
|
|
6431
|
+
store.save(session);
|
|
6432
|
+
} catch {
|
|
6433
|
+
}
|
|
6388
6434
|
return { ok: false };
|
|
6389
6435
|
} finally {
|
|
6390
6436
|
spinner.stop();
|
|
@@ -6399,8 +6445,13 @@ async function runTurn(agent, store, session, task, cp, cwd = process.cwd()) {
|
|
|
6399
6445
|
const lastUser = res.messages.map((m2) => m2.role).lastIndexOf("user");
|
|
6400
6446
|
const tools = res.messages.slice(lastUser).filter((m2) => m2.role === "tool").length;
|
|
6401
6447
|
const ok = res.finishReason === "stop";
|
|
6402
|
-
|
|
6448
|
+
const shortId = session.meta.id.slice(-10);
|
|
6449
|
+
err("\n" + (ok ? green(" \u2713 done") : red(` \u2717 ${res.finishReason}`)) + dim(` \xB7 ${res.steps} steps \xB7 ${tools} tools \xB7 ${tok}${secs}s \xB7 ${shortId}
|
|
6403
6450
|
`));
|
|
6451
|
+
if (res.finishReason === "error" && res.error) {
|
|
6452
|
+
const e = res.error;
|
|
6453
|
+
err(red(` ${e?.message ?? e}`) + (e?.statusCode ? dim(` (${e.statusCode}${e.code ? " " + e.code : ""})`) : "") + "\n");
|
|
6454
|
+
}
|
|
6404
6455
|
session.messages = agent.transcript;
|
|
6405
6456
|
session.meta.turns += 1;
|
|
6406
6457
|
session.meta.tokens = (session.meta.tokens ?? 0) + (res.usage?.totalTokens ?? 0);
|
|
@@ -6408,6 +6459,9 @@ async function runTurn(agent, store, session, task, cp, cwd = process.cwd()) {
|
|
|
6408
6459
|
if (res.usageEstimated) session.meta.costEstimated = true;
|
|
6409
6460
|
session.meta.updated = Date.now();
|
|
6410
6461
|
session.meta.model = agent.options.model;
|
|
6462
|
+
const ev = { ts: t0, durationMs: Date.now() - t0, model: agent.options.model, finishReason: res.finishReason, steps: res.steps, tools, tokens: res.usage?.totalTokens, costUsd: cost, estimated: res.usageEstimated };
|
|
6463
|
+
if (res.finishReason === "error" && res.error) ev.error = errInfo(res.error);
|
|
6464
|
+
(session.meta.events ??= []).push(ev);
|
|
6411
6465
|
if (!session.meta.title) session.meta.title = titleOf(agent.transcript);
|
|
6412
6466
|
try {
|
|
6413
6467
|
store.save(session);
|
|
@@ -6439,7 +6493,10 @@ function startSession(args, store, agent, cwd) {
|
|
|
6439
6493
|
`));
|
|
6440
6494
|
}
|
|
6441
6495
|
const now = Date.now();
|
|
6442
|
-
|
|
6496
|
+
const id = args.sessionId ?? store.newId(now);
|
|
6497
|
+
if (!args.task) err(dim(` session ${id}
|
|
6498
|
+
`));
|
|
6499
|
+
return { meta: { id, created: now, updated: now, cwd, model: agent.options.model, turns: 0, title: "" }, messages: [] };
|
|
6443
6500
|
}
|
|
6444
6501
|
var AGENTS_MD_TEMPLATE = `# ${"${name}"}
|
|
6445
6502
|
|
|
@@ -7214,7 +7271,7 @@ ${extra}` : body, checkpoints, cwd);
|
|
|
7214
7271
|
}
|
|
7215
7272
|
});
|
|
7216
7273
|
}
|
|
7217
|
-
const promptStr = bold(cyan("
|
|
7274
|
+
const promptStr = bold(cyan("agentx \u203A "));
|
|
7218
7275
|
const contPrompt = dim(" \u2026 \u203A ");
|
|
7219
7276
|
const classifyPaste = pastePathClassifier(cwd);
|
|
7220
7277
|
const releaseStdin = () => {
|
|
@@ -7376,6 +7433,7 @@ async function main() {
|
|
|
7376
7433
|
if (!id) process.exit(0);
|
|
7377
7434
|
args.resume = id;
|
|
7378
7435
|
}
|
|
7436
|
+
loadInstallEnv();
|
|
7379
7437
|
const apiKeys = { ...cfg.apiKeys, ...apiKeysFromEnv() };
|
|
7380
7438
|
if (!Object.keys(apiKeys).length) {
|
|
7381
7439
|
console.error(red("No provider key found. Set ANTHROPIC_API_KEY (or OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY), e.g. in .env."));
|