@livx.cc/agentx 0.99.73 → 0.99.75
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-CSFGRC-I.d.ts → Agent-BBlKI8uD.d.ts} +8 -1
- package/dist/cli.d.ts +7 -2
- package/dist/cli.js +168 -296
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +44 -173
- package/dist/index.js.map +1 -1
- package/dist/{mcp-8_lBApgs.d.ts → mcp-BhTxN2I7.d.ts} +1 -1
- package/dist/mcp.client.d.ts +2 -2
- package/dist/{tools-wVQBhYwm.d.ts → tools-lC3jn60o.d.ts} +2 -2
- package/dist/tools.shell.d.ts +1 -1
- package/dist/tools.shell.js +2 -7
- package/dist/tools.shell.js.map +1 -1
- package/package.json +3 -6
package/dist/cli.js
CHANGED
|
@@ -20,134 +20,14 @@ var init_logging = __esm({
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
// src/imageWire.ts
|
|
23
|
-
import { readFileSync,
|
|
24
|
-
import {
|
|
25
|
-
import { createHash } from "crypto";
|
|
26
|
-
import { tmpdir } from "os";
|
|
27
|
-
import { join as join2 } from "path";
|
|
28
|
-
import { PNG } from "pngjs";
|
|
29
|
-
import jpeg from "jpeg-js";
|
|
30
|
-
function imageSize(b) {
|
|
31
|
-
const u16 = (i) => b[i] << 8 | b[i + 1];
|
|
32
|
-
const le16 = (i) => b[i] | b[i + 1] << 8;
|
|
33
|
-
const u32 = (i) => (b[i] << 24 >>> 0) + (b[i + 1] << 16) + (b[i + 2] << 8) + b[i + 3];
|
|
34
|
-
if (b[0] === 137 && b[1] === 80 && b.length >= 24) return { w: u32(16), h: u32(20) };
|
|
35
|
-
if (b[0] === 71 && b[1] === 73 && b.length >= 10) return { w: le16(6), h: le16(8) };
|
|
36
|
-
if (b[0] === 255 && b[1] === 216) {
|
|
37
|
-
for (let i = 2; i + 9 < b.length; ) {
|
|
38
|
-
if (b[i] !== 255) return null;
|
|
39
|
-
const m = b[i + 1];
|
|
40
|
-
if (m >= 192 && m <= 207 && m !== 196 && m !== 200 && m !== 204) return { w: u16(i + 7), h: u16(i + 5) };
|
|
41
|
-
i += 2 + u16(i + 2);
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
if (b.length >= 30 && String.fromCharCode(...b.subarray(8, 12)) === "WEBP") {
|
|
46
|
-
const kind = String.fromCharCode(...b.subarray(12, 16));
|
|
47
|
-
if (kind === "VP8X") return { w: 1 + (b[24] | b[25] << 8 | b[26] << 16), h: 1 + (b[27] | b[28] << 8 | b[29] << 16) };
|
|
48
|
-
if (kind === "VP8 ") return { w: le16(26) & 16383, h: le16(28) & 16383 };
|
|
49
|
-
if (kind === "VP8L") {
|
|
50
|
-
const v = b[21] | b[22] << 8 | b[23] << 16 | b[24] << 24;
|
|
51
|
-
return { w: (v & 16383) + 1, h: (v >> 14 & 16383) + 1 };
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
function imageNote(what, bytes, dims, why) {
|
|
57
|
-
return `[image ${what}${dims ? `, ${dims.w}x${dims.h}` : ""}, ${fmtBytes(bytes)} \u2014 not sent: ${why}]`;
|
|
58
|
-
}
|
|
59
|
-
function downscaleJs(buf, maxSide) {
|
|
60
|
-
let src;
|
|
61
|
-
try {
|
|
62
|
-
if (buf[0] === 137 && buf[1] === 80) src = PNG.sync.read(buf);
|
|
63
|
-
else if (buf[0] === 255 && buf[1] === 216) src = jpeg.decode(buf, { useTArray: true, maxMemoryUsageInMB: 1024 });
|
|
64
|
-
else return null;
|
|
65
|
-
} catch (e) {
|
|
66
|
-
log2.warn("pure-JS image decode failed", e);
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
const { width: sw, height: sh, data: s } = src;
|
|
70
|
-
const k = Math.min(1, maxSide / Math.max(sw, sh));
|
|
71
|
-
const w = Math.max(1, Math.round(sw * k)), h = Math.max(1, Math.round(sh * k));
|
|
72
|
-
const d = new Uint8Array(w * h * 4);
|
|
73
|
-
for (let y = 0; y < h; y++) {
|
|
74
|
-
const y0 = Math.floor(y * sh / h), y1 = Math.max(y0 + 1, Math.floor((y + 1) * sh / h));
|
|
75
|
-
for (let x = 0; x < w; x++) {
|
|
76
|
-
const x0 = Math.floor(x * sw / w), x1 = Math.max(x0 + 1, Math.floor((x + 1) * sw / w));
|
|
77
|
-
let r = 0, g = 0, b = 0, a = 0;
|
|
78
|
-
for (let yy = y0; yy < y1; yy++) for (let xx = x0; xx < x1; xx++) {
|
|
79
|
-
const i = (yy * sw + xx) * 4, al = s[i + 3];
|
|
80
|
-
r += s[i] * al;
|
|
81
|
-
g += s[i + 1] * al;
|
|
82
|
-
b += s[i + 2] * al;
|
|
83
|
-
a += al;
|
|
84
|
-
}
|
|
85
|
-
const o = (y * w + x) * 4, n = (y1 - y0) * (x1 - x0), bg = 255 * (n - a / 255);
|
|
86
|
-
d[o] = (r / 255 + bg) / n;
|
|
87
|
-
d[o + 1] = (g / 255 + bg) / n;
|
|
88
|
-
d[o + 2] = (b / 255 + bg) / n;
|
|
89
|
-
d[o + 3] = 255;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
let out = Buffer.alloc(0);
|
|
93
|
-
for (const q2 of [80, 60, 40]) {
|
|
94
|
-
out = Buffer.from(jpeg.encode({ width: w, height: h, data: d }, q2).data);
|
|
95
|
-
if (out.length <= IMAGE_MAX_BYTES) break;
|
|
96
|
-
}
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
function downscale(path, maxSide) {
|
|
100
|
-
const dir = mkdtempSync(join2(tmpdir(), "agentx-img-"));
|
|
101
|
-
const out = join2(dir, "x.jpg");
|
|
102
|
-
try {
|
|
103
|
-
const tries = [
|
|
104
|
-
["sips", ["-Z", String(maxSide), "-s", "format", "jpeg", "-s", "formatOptions", "80", path, "--out", out]],
|
|
105
|
-
["magick", [path, "-resize", `${maxSide}x${maxSide}>`, "-quality", "80", out]],
|
|
106
|
-
["convert", [path, "-resize", `${maxSide}x${maxSide}>`, "-quality", "80", out]]
|
|
107
|
-
];
|
|
108
|
-
for (const [cmd, args] of tries) {
|
|
109
|
-
const r = spawnSync(cmd, args, { stdio: "ignore", timeout: 15e3 });
|
|
110
|
-
if (r.status !== 0) continue;
|
|
111
|
-
try {
|
|
112
|
-
const o = readFileSync(out);
|
|
113
|
-
if (o.length <= IMAGE_MAX_BYTES) return o;
|
|
114
|
-
break;
|
|
115
|
-
} catch {
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
const js = downscaleJs(readFileSync(path), maxSide);
|
|
119
|
-
if (!js) log2.warn(`could not downscale ${path} (tried sips/magick/convert/pure JS)`);
|
|
120
|
-
return js;
|
|
121
|
-
} finally {
|
|
122
|
-
rmSync(dir, { recursive: true, force: true });
|
|
123
|
-
}
|
|
124
|
-
}
|
|
23
|
+
import { readFileSync, statSync as statSync2 } from "fs";
|
|
24
|
+
import { imageWireOf, inlineImageForWire, scrubBase64Text, imageSize, imageNote, IMAGE_MAX_SIDE, IMAGE_MAX_BYTES } from "ai.libx.js";
|
|
125
25
|
function remember(id, w) {
|
|
126
26
|
cache.delete(id);
|
|
127
27
|
cache.set(id, w);
|
|
128
28
|
if (cache.size > CACHE_MAX) cache.delete(cache.keys().next().value);
|
|
129
29
|
return w;
|
|
130
30
|
}
|
|
131
|
-
function wireOf(key, buf, mime, label, file) {
|
|
132
|
-
const dims = imageSize(buf);
|
|
133
|
-
const fits = buf.length <= IMAGE_MAX_BYTES && (!dims || Math.max(dims.w, dims.h) <= IMAGE_MAX_SIDE);
|
|
134
|
-
let small = null;
|
|
135
|
-
if (!fits) {
|
|
136
|
-
if (file) small = downscale(file, IMAGE_MAX_SIDE);
|
|
137
|
-
else {
|
|
138
|
-
const dir = mkdtempSync(join2(tmpdir(), "agentx-img-in-"));
|
|
139
|
-
try {
|
|
140
|
-
const f = join2(dir, `in.${mime.split("/")[1] || "img"}`);
|
|
141
|
-
writeFileSync2(f, buf);
|
|
142
|
-
small = downscale(f, IMAGE_MAX_SIDE);
|
|
143
|
-
} finally {
|
|
144
|
-
rmSync(dir, { recursive: true, force: true });
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const url = fits ? `data:${mime};base64,${buf.toString("base64")}` : small && small.length <= IMAGE_MAX_BYTES ? `data:image/jpeg;base64,${small.toString("base64")}` : null;
|
|
149
|
-
return { key, url, note: imageNote(label, buf.length, dims, url ? "this model can't see images" : "too large and it couldn't be downscaled") };
|
|
150
|
-
}
|
|
151
31
|
function imageForWire(path, mime, vision) {
|
|
152
32
|
let st;
|
|
153
33
|
try {
|
|
@@ -158,48 +38,30 @@ function imageForWire(path, mime, vision) {
|
|
|
158
38
|
}
|
|
159
39
|
const key = `${st.mtimeMs}:${st.size}`;
|
|
160
40
|
let hit = cache.get(path);
|
|
161
|
-
if (!hit || hit.key !== key) hit = remember(path,
|
|
41
|
+
if (!hit || hit.key !== key) hit = remember(path, { key, ...imageWireOf(readFileSync(path), mime, path, path) });
|
|
162
42
|
return vision && hit.url ? { url: hit.url } : { note: hit.note };
|
|
163
43
|
}
|
|
164
|
-
function
|
|
165
|
-
|
|
166
|
-
const mime = url.slice(5, url.indexOf(";"));
|
|
167
|
-
if (vision && url.length < 3e5) {
|
|
168
|
-
const b64 = url.slice(comma + 1);
|
|
169
|
-
const dims = imageSize(Buffer.from(b64.slice(0, 4096), "base64")) ?? imageSize(Buffer.from(b64, "base64"));
|
|
170
|
-
if (!dims || Math.max(dims.w, dims.h) <= IMAGE_MAX_SIDE) return { url };
|
|
171
|
-
}
|
|
172
|
-
const id = `inline:${createHash("sha1").update(url).digest("base64")}`;
|
|
173
|
-
let hit = cache.get(id);
|
|
174
|
-
if (!hit) {
|
|
175
|
-
const buf = Buffer.from(url.slice(comma + 1), "base64");
|
|
176
|
-
hit = remember(id, wireOf(id, buf, mime, `(${mime})`));
|
|
177
|
-
}
|
|
178
|
-
return vision && hit.url ? { url: hit.url } : { note: hit.note };
|
|
44
|
+
function imageTokens(dims) {
|
|
45
|
+
return dims ? Math.min(IMAGE_TOKENS_MAX, Math.max(1, Math.ceil(dims.w * dims.h / 750))) : IMAGE_TOKENS_MAX;
|
|
179
46
|
}
|
|
180
|
-
function
|
|
181
|
-
|
|
182
|
-
|
|
47
|
+
function wiredImageWeight(r) {
|
|
48
|
+
if ("note" in r) return r.note.length;
|
|
49
|
+
const b64 = r.url.slice(r.url.indexOf(",") + 1);
|
|
50
|
+
return 4 * imageTokens(imageSize(Buffer.from(b64.slice(0, 4096), "base64")));
|
|
183
51
|
}
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (out !== s) log2.warn(`scrubbed base64 from request text (${s.length} \u2192 ${out.length} chars)`);
|
|
188
|
-
return out;
|
|
52
|
+
function imageWireWeight(path, mime, vision) {
|
|
53
|
+
const r = imageForWire(path, mime, vision);
|
|
54
|
+
return r ? wiredImageWeight(r) : 0;
|
|
189
55
|
}
|
|
190
|
-
var log2,
|
|
56
|
+
var log2, cache, CACHE_MAX, IMAGE_TOKENS_MAX;
|
|
191
57
|
var init_imageWire = __esm({
|
|
192
58
|
"src/imageWire.ts"() {
|
|
193
59
|
"use strict";
|
|
194
60
|
init_logging();
|
|
195
61
|
log2 = forComponent("imageWire");
|
|
196
|
-
IMAGE_MAX_SIDE = 1568;
|
|
197
|
-
IMAGE_MAX_BYTES = 1e6;
|
|
198
|
-
fmtBytes = (n) => n >= 1e6 ? `${(n / 1e6).toFixed(1)} MB` : n >= 1e3 ? `${Math.round(n / 1e3)} KB` : `${n} B`;
|
|
199
62
|
cache = /* @__PURE__ */ new Map();
|
|
200
63
|
CACHE_MAX = 8;
|
|
201
|
-
|
|
202
|
-
B64_RUN = /[A-Za-z0-9+/=]{2000,}/g;
|
|
64
|
+
IMAGE_TOKENS_MAX = 1600;
|
|
203
65
|
}
|
|
204
66
|
});
|
|
205
67
|
|
|
@@ -394,7 +256,7 @@ function sendBytesPer(messages, keepRecent = 1, vision = true, stub = IMAGE_ELID
|
|
|
394
256
|
}
|
|
395
257
|
function wireBytes(content, kept, vision, stub) {
|
|
396
258
|
const tool = toolImageRef(content);
|
|
397
|
-
if (tool) return kept ?
|
|
259
|
+
if (tool) return kept ? imageWireWeight(tool.path, tool.mime, vision) || stub.length : stub.length;
|
|
398
260
|
if (content == null || typeof content === "string") return contentBytes(content);
|
|
399
261
|
if (kept) {
|
|
400
262
|
let n2 = 0;
|
|
@@ -402,7 +264,7 @@ function wireBytes(content, kept, vision, stub) {
|
|
|
402
264
|
const url = p.type === "image_url" ? p.image_url?.url ?? "" : "";
|
|
403
265
|
const ref = url ? parseImageRef(url) : null;
|
|
404
266
|
const inline = url.startsWith("data:") ? inlineImageForWire(url, vision) : null;
|
|
405
|
-
n2 += ref ?
|
|
267
|
+
n2 += ref ? imageWireWeight(ref.path, ref.mime, vision) : inline ? wiredImageWeight(inline) : contentBytes([p]);
|
|
406
268
|
}
|
|
407
269
|
return n2;
|
|
408
270
|
}
|
|
@@ -2149,9 +2011,9 @@ __export(worktree_exports, {
|
|
|
2149
2011
|
validateWorktreeSlug: () => validateWorktreeSlug,
|
|
2150
2012
|
worktreeBranchName: () => worktreeBranchName
|
|
2151
2013
|
});
|
|
2152
|
-
import { spawnSync
|
|
2153
|
-
import { symlinkSync, mkdirSync, statSync as statSync4, readFileSync as readFileSync3, rmSync
|
|
2154
|
-
import { join as
|
|
2014
|
+
import { spawnSync } from "child_process";
|
|
2015
|
+
import { symlinkSync, mkdirSync, statSync as statSync4, readFileSync as readFileSync3, rmSync } from "fs";
|
|
2016
|
+
import { join as join2 } from "path";
|
|
2155
2017
|
function validateWorktreeSlug(slug2) {
|
|
2156
2018
|
if (!slug2) throw new Error("worktree slug must not be empty");
|
|
2157
2019
|
if (slug2.length > MAX_SLUG_LENGTH) throw new Error(`worktree slug must be \u2264${MAX_SLUG_LENGTH} chars (got ${slug2.length})`);
|
|
@@ -2167,13 +2029,13 @@ function worktreeBranchName(slug2) {
|
|
|
2167
2029
|
return `worktree-${flattenSlug(slug2)}`;
|
|
2168
2030
|
}
|
|
2169
2031
|
function worktreesDir(repoRoot) {
|
|
2170
|
-
return
|
|
2032
|
+
return join2(repoRoot, ".claude", "worktrees");
|
|
2171
2033
|
}
|
|
2172
2034
|
function worktreePathFor(repoRoot, slug2) {
|
|
2173
|
-
return
|
|
2035
|
+
return join2(worktreesDir(repoRoot), flattenSlug(slug2));
|
|
2174
2036
|
}
|
|
2175
2037
|
function git(args, cwd) {
|
|
2176
|
-
const r =
|
|
2038
|
+
const r = spawnSync("git", args, {
|
|
2177
2039
|
cwd,
|
|
2178
2040
|
stdio: ["ignore", "pipe", "pipe"],
|
|
2179
2041
|
env: { ...process.env, ...GIT_NO_PROMPT_ENV }
|
|
@@ -2186,14 +2048,14 @@ function findGitRoot(from) {
|
|
|
2186
2048
|
}
|
|
2187
2049
|
function readWorktreeHead(worktreePath) {
|
|
2188
2050
|
try {
|
|
2189
|
-
const gitFile = readFileSync3(
|
|
2051
|
+
const gitFile = readFileSync3(join2(worktreePath, ".git"), "utf-8").trim();
|
|
2190
2052
|
const m = gitFile.match(/^gitdir:\s*(.+)$/);
|
|
2191
2053
|
if (!m) return null;
|
|
2192
|
-
const headPath =
|
|
2054
|
+
const headPath = join2(m[1], "HEAD");
|
|
2193
2055
|
const head = readFileSync3(headPath, "utf-8").trim();
|
|
2194
2056
|
const refMatch = head.match(/^ref:\s*(.+)$/);
|
|
2195
2057
|
if (!refMatch) return head.length === 40 ? head : null;
|
|
2196
|
-
const refPath =
|
|
2058
|
+
const refPath = join2(m[1], "..", refMatch[1]);
|
|
2197
2059
|
try {
|
|
2198
2060
|
return readFileSync3(refPath, "utf-8").trim();
|
|
2199
2061
|
} catch {
|
|
@@ -2228,8 +2090,8 @@ function getOrCreateWorktree(repoRoot, slug2) {
|
|
|
2228
2090
|
}
|
|
2229
2091
|
function symlinkDirs(repoRoot, worktreePath, dirs) {
|
|
2230
2092
|
for (const dir of dirs) {
|
|
2231
|
-
const src =
|
|
2232
|
-
const dst =
|
|
2093
|
+
const src = join2(repoRoot, dir);
|
|
2094
|
+
const dst = join2(worktreePath, dir);
|
|
2233
2095
|
try {
|
|
2234
2096
|
statSync4(src);
|
|
2235
2097
|
} catch {
|
|
@@ -2257,7 +2119,7 @@ function cleanupWorktree(repoRoot, slug2, opts) {
|
|
|
2257
2119
|
}
|
|
2258
2120
|
for (const dir of ["node_modules", ".bun"]) {
|
|
2259
2121
|
try {
|
|
2260
|
-
|
|
2122
|
+
rmSync(join2(worktreePath, dir));
|
|
2261
2123
|
} catch {
|
|
2262
2124
|
}
|
|
2263
2125
|
}
|
|
@@ -3172,9 +3034,9 @@ var init_tools_shell = __esm({
|
|
|
3172
3034
|
|
|
3173
3035
|
// cli/cli.ts
|
|
3174
3036
|
import { createInterface } from "readline/promises";
|
|
3175
|
-
import { existsSync as existsSync9, readFileSync as readFileSync10, appendFileSync, mkdirSync as mkdirSync12, writeFileSync as
|
|
3037
|
+
import { existsSync as existsSync9, readFileSync as readFileSync10, appendFileSync, mkdirSync as mkdirSync12, writeFileSync as writeFileSync9, readdirSync as readdirSync4, statSync as statSync7, unlinkSync as unlinkSync5 } from "fs";
|
|
3176
3038
|
import { homedir as homedir10 } from "os";
|
|
3177
|
-
import { spawnSync as
|
|
3039
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
3178
3040
|
|
|
3179
3041
|
// cli/clipboard.ts
|
|
3180
3042
|
import { execFileSync } from "child_process";
|
|
@@ -3241,7 +3103,7 @@ function copyTextToClipboard(text, platform2 = process.platform) {
|
|
|
3241
3103
|
}
|
|
3242
3104
|
|
|
3243
3105
|
// cli/cli.ts
|
|
3244
|
-
import { join as
|
|
3106
|
+
import { join as join14, resolve as resolve4, basename as basename2, extname, dirname as dirname5 } from "path";
|
|
3245
3107
|
import { AIClient, DecideClient, listModels, listProviders, getProviderFromModel, getModelInfo, resolveModel, isModelSupported, disposeCursorSessions, disposeClaudeCodeSessions } from "ai.libx.js";
|
|
3246
3108
|
|
|
3247
3109
|
// src/ccBridge.ts
|
|
@@ -3822,8 +3684,8 @@ ${sections.join("\n\n---\n\n")}`;
|
|
|
3822
3684
|
|
|
3823
3685
|
// src/subagent.ts
|
|
3824
3686
|
init_tools();
|
|
3825
|
-
import { mkdirSync as mkdirSync2, writeFileSync as
|
|
3826
|
-
import { join as
|
|
3687
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
3688
|
+
import { join as join4 } from "path";
|
|
3827
3689
|
|
|
3828
3690
|
// src/models.ts
|
|
3829
3691
|
var MODEL_ALIASES = {
|
|
@@ -4072,7 +3934,7 @@ function traceFileFor(dir, label, depth) {
|
|
|
4072
3934
|
try {
|
|
4073
3935
|
mkdirSync2(dir, { recursive: true });
|
|
4074
3936
|
const id = `${Date.now().toString(36)}-${(traceSeq++).toString(36)}`;
|
|
4075
|
-
return
|
|
3937
|
+
return join4(dir, `${id}-d${depth}-${sanitizeSlug(label) || "sub"}.json`);
|
|
4076
3938
|
} catch (e) {
|
|
4077
3939
|
log7.warn(`subagent trace dir unavailable (${dir}) \u2014 running without a trace: ${e instanceof Error ? e.message : String(e)}`);
|
|
4078
3940
|
return void 0;
|
|
@@ -4080,7 +3942,7 @@ function traceFileFor(dir, label, depth) {
|
|
|
4080
3942
|
}
|
|
4081
3943
|
function flushTrace(file, meta, messages, status) {
|
|
4082
3944
|
try {
|
|
4083
|
-
|
|
3945
|
+
writeFileSync2(file, JSON.stringify({ ...meta, status, updated: Date.now(), messages }, null, 2));
|
|
4084
3946
|
} catch (e) {
|
|
4085
3947
|
log7.warn(`subagent trace flush failed (${file}): ${e instanceof Error ? e.message : String(e)}`);
|
|
4086
3948
|
}
|
|
@@ -5014,6 +4876,7 @@ var Agent = class _Agent {
|
|
|
5014
4876
|
let steps = 0;
|
|
5015
4877
|
const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
5016
4878
|
let usageEstimated = false;
|
|
4879
|
+
let spent = 0, prevPrompt = -1, stepPrompt = 0;
|
|
5017
4880
|
const start = Date.now();
|
|
5018
4881
|
this.parkedMs = 0;
|
|
5019
4882
|
this.ctx.needsInput = void 0;
|
|
@@ -5024,12 +4887,12 @@ var Agent = class _Agent {
|
|
|
5024
4887
|
let closureNudged = false;
|
|
5025
4888
|
let lastProgressAt = start;
|
|
5026
4889
|
const kill = (finishReason) => {
|
|
5027
|
-
log8.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, budgetTokens=${Math.round(
|
|
4890
|
+
log8.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, budgetTokens=${Math.round(spent)}, ms=${Date.now() - start - this.parkedMs}${finishReason === "timeout" ? `, idle=${Date.now() - lastProgressAt - this.parkedMs}ms` : ""}${this.parkedMs ? ` +${this.parkedMs} parked` : ""})`);
|
|
5028
4891
|
this.jobs.killAll(`run ended: ${finishReason}`, true);
|
|
5029
4892
|
const claims = this.survivingClaims();
|
|
5030
|
-
return { text: lastAssistantText(this.transcript), steps, finishReason, messages: this.transcript, usage, usageEstimated, ...claims.length ? { fabricatedToolClaims: claims } : {} };
|
|
4893
|
+
return { text: lastAssistantText(this.transcript), steps, finishReason, messages: this.transcript, usage, usageEstimated, ...finishReason === "budget" ? { budget: { spent: Math.round(spent), limit: o.maxTokens, stepPrompt } } : {}, ...claims.length ? { fabricatedToolClaims: claims } : {} };
|
|
5031
4894
|
};
|
|
5032
|
-
const overBudget = () => !!o.maxTokens &&
|
|
4895
|
+
const overBudget = () => !!o.maxTokens && spent >= o.maxTokens;
|
|
5033
4896
|
const canNudge = () => steps < o.maxSteps && !overBudget();
|
|
5034
4897
|
while (true) {
|
|
5035
4898
|
if (o.signal?.aborted) return kill("aborted");
|
|
@@ -5183,6 +5046,14 @@ var Agent = class _Agent {
|
|
|
5183
5046
|
usage.totalTokens += res.usage.totalTokens ?? 0;
|
|
5184
5047
|
usage.cacheCreationTokens += res.usage.cacheCreationTokens ?? 0;
|
|
5185
5048
|
usage.cacheReadTokens += res.usage.cacheReadTokens ?? 0;
|
|
5049
|
+
const prompt = res.usage.promptTokens ?? 0, cacheRead = res.usage.cacheReadTokens ?? 0;
|
|
5050
|
+
if (prevPrompt < 0) {
|
|
5051
|
+
const u = sent.map((m) => m.role).lastIndexOf("user");
|
|
5052
|
+
prevPrompt = u > 0 ? estimateTokens(sent.slice(0, u)) : 0;
|
|
5053
|
+
}
|
|
5054
|
+
const reused = Math.min(prompt, Math.max(cacheRead, prevPrompt));
|
|
5055
|
+
spent += (res.usage.totalTokens ?? 0) - 0.9 * reused;
|
|
5056
|
+
prevPrompt = stepPrompt = prompt;
|
|
5186
5057
|
}
|
|
5187
5058
|
const delegatedTools = res.delegatedTools ?? [];
|
|
5188
5059
|
if (delegatedTools.length) {
|
|
@@ -11459,7 +11330,7 @@ import { MemFilesystem as MemFilesystem3, IndexedDbFilesystem, CommandExecutor a
|
|
|
11459
11330
|
// src/mcp.client.ts
|
|
11460
11331
|
init_logging();
|
|
11461
11332
|
import { spawn } from "child_process";
|
|
11462
|
-
import { createHash
|
|
11333
|
+
import { createHash } from "crypto";
|
|
11463
11334
|
var log23 = forComponent("mcp");
|
|
11464
11335
|
var PROTOCOL_VERSION = "2025-06-18";
|
|
11465
11336
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -11865,8 +11736,8 @@ var defaultPool = new McpPool();
|
|
|
11865
11736
|
|
|
11866
11737
|
// cli/mcpOAuth.ts
|
|
11867
11738
|
import { createServer } from "http";
|
|
11868
|
-
import { randomBytes as randomBytes2, createHash as
|
|
11869
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
11739
|
+
import { randomBytes as randomBytes2, createHash as createHash2 } from "crypto";
|
|
11740
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync } from "fs";
|
|
11870
11741
|
import { dirname as dirname2 } from "path";
|
|
11871
11742
|
var McpOAuthOptions = class {
|
|
11872
11743
|
/** Where to persist tokens. Mode 0600. */
|
|
@@ -11901,7 +11772,7 @@ var McpOAuth = class {
|
|
|
11901
11772
|
}
|
|
11902
11773
|
save(store) {
|
|
11903
11774
|
mkdirSync3(dirname2(this.options.storePath), { recursive: true });
|
|
11904
|
-
|
|
11775
|
+
writeFileSync3(this.options.storePath, JSON.stringify(store, null, 2), { mode: 384 });
|
|
11905
11776
|
}
|
|
11906
11777
|
// -- ATTENDED: one-time authorization ----------------------------------------
|
|
11907
11778
|
/** Run the authorization-code + PKCE flow and persist the resulting tokens for `serverUrl`. */
|
|
@@ -11909,7 +11780,7 @@ var McpOAuth = class {
|
|
|
11909
11780
|
const meta = await this.discover(serverUrl);
|
|
11910
11781
|
const clientId = this.options.clientId ?? await this.registerClient(meta, serverUrl);
|
|
11911
11782
|
const verifier = b64url(randomBytes2(32));
|
|
11912
|
-
const challenge = b64url(
|
|
11783
|
+
const challenge = b64url(createHash2("sha256").update(verifier).digest());
|
|
11913
11784
|
const state = b64url(randomBytes2(16));
|
|
11914
11785
|
const { code, redirectUri } = await this.captureCode(meta.authorization_endpoint, clientId, challenge, state);
|
|
11915
11786
|
const tok = await this.exchange(meta.token_endpoint, {
|
|
@@ -12059,9 +11930,9 @@ function defaultOpenBrowser(url) {
|
|
|
12059
11930
|
// cli/core.ts
|
|
12060
11931
|
import { randomUUID } from "crypto";
|
|
12061
11932
|
import { execFile as execFile2 } from "child_process";
|
|
12062
|
-
import { resolve as resolve2, basename, join as
|
|
11933
|
+
import { resolve as resolve2, basename, join as join5 } from "path";
|
|
12063
11934
|
import { existsSync as existsSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
12064
|
-
import { platform, arch, release, userInfo, homedir as homedir2, tmpdir
|
|
11935
|
+
import { platform, arch, release, userInfo, homedir as homedir2, tmpdir } from "os";
|
|
12065
11936
|
init_tools_shell();
|
|
12066
11937
|
|
|
12067
11938
|
// src/tools.notify.ts
|
|
@@ -12249,7 +12120,7 @@ async function buildAgent(o) {
|
|
|
12249
12120
|
} else if (o.boddb) {
|
|
12250
12121
|
const root = resolve2(o.boddb);
|
|
12251
12122
|
mkdirSync4(root, { recursive: true });
|
|
12252
|
-
const db = new BodDB2({ path:
|
|
12123
|
+
const db = new BodDB2({ path: join5(root, "meta.db"), sweepInterval: 0, vfs: { storageRoot: join5(root, "files") } });
|
|
12253
12124
|
const bod = new BodDbFilesystem(db);
|
|
12254
12125
|
const firstRun = (await bod.readDir("/").catch(() => [])).length === 0;
|
|
12255
12126
|
await mkdirp(bod, cwd);
|
|
@@ -12316,7 +12187,7 @@ Reference files in them by their mount path (the left side).`;
|
|
|
12316
12187
|
});
|
|
12317
12188
|
realShell = [makeRealShellTool({ cwd, registry: jobs, osSandbox: o.osSandbox, jobsSurviveRun: o.singleRun !== true }), ...makeShellJobTools(jobs)];
|
|
12318
12189
|
}
|
|
12319
|
-
const scratchDir = o.scratch ? o.scratchDir ?? (virtual ? `${cwd}/.agent/scratch` : `${
|
|
12190
|
+
const scratchDir = o.scratch ? o.scratchDir ?? (virtual ? `${cwd}/.agent/scratch` : `${tmpdir()}/agentx-scratch-${process.pid}`) : void 0;
|
|
12320
12191
|
const scratch = scratchDir ? new Scratch(fs, { dir: scratchDir }) : void 0;
|
|
12321
12192
|
return agentRef.agent = new Agent({
|
|
12322
12193
|
ai: o.ai,
|
|
@@ -12429,10 +12300,10 @@ var trunc = (s, n) => (s == null ? "" : String(s).length > n ? String(s).slice(0
|
|
|
12429
12300
|
|
|
12430
12301
|
// cli/voice.ts
|
|
12431
12302
|
init_logging();
|
|
12432
|
-
import { spawn as spawn2, spawnSync as
|
|
12303
|
+
import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
12433
12304
|
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
12434
12305
|
import { homedir as homedir3 } from "os";
|
|
12435
|
-
import { dirname as dirname3, join as
|
|
12306
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
12436
12307
|
import { fileURLToPath } from "url";
|
|
12437
12308
|
var log27 = forComponent("VoiceIO");
|
|
12438
12309
|
var now3 = () => performance.now();
|
|
@@ -12475,10 +12346,10 @@ var Player = class {
|
|
|
12475
12346
|
this.proc = null;
|
|
12476
12347
|
}
|
|
12477
12348
|
};
|
|
12478
|
-
var nativeDir = () =>
|
|
12349
|
+
var nativeDir = () => join6(dirname3(fileURLToPath(import.meta.url)), "native");
|
|
12479
12350
|
function detectFfmpegMic() {
|
|
12480
12351
|
if (process.env.MIC_DEVICE) return process.env.MIC_DEVICE;
|
|
12481
|
-
const r =
|
|
12352
|
+
const r = spawnSync2("ffmpeg", ["-f", "avfoundation", "-list_devices", "true", "-i", ""], { encoding: "utf8" });
|
|
12482
12353
|
if (r.error?.code === "ENOENT") throw new Error("ffmpeg not installed \u2014 run `brew install ffmpeg` to enable voice");
|
|
12483
12354
|
if (r.error) throw new Error(`ffmpeg failed to run (${r.error.message}) \u2014 likely a wrong-arch binary; run \`brew reinstall ffmpeg\``);
|
|
12484
12355
|
const out = r.stderr ?? "";
|
|
@@ -12492,10 +12363,10 @@ function detectFfmpegMic() {
|
|
|
12492
12363
|
function detectedInputDevice() {
|
|
12493
12364
|
if (process.platform !== "darwin") return null;
|
|
12494
12365
|
let name = "";
|
|
12495
|
-
if (
|
|
12496
|
-
name = (
|
|
12366
|
+
if (spawnSync2("which", ["SwitchAudioSource"]).status === 0) {
|
|
12367
|
+
name = (spawnSync2("SwitchAudioSource", ["-c", "-t", "input"], { encoding: "utf8" }).stdout || "").trim();
|
|
12497
12368
|
} else {
|
|
12498
|
-
const out =
|
|
12369
|
+
const out = spawnSync2("system_profiler", ["SPAudioDataType"], { encoding: "utf8" }).stdout || "";
|
|
12499
12370
|
let last = "";
|
|
12500
12371
|
for (const ln of out.split("\n")) {
|
|
12501
12372
|
const hdr = ln.match(/^\s{6,}(\S.*?):\s*$/);
|
|
@@ -12514,21 +12385,21 @@ function detectedInputDevice() {
|
|
|
12514
12385
|
}
|
|
12515
12386
|
function resolveAecBinary() {
|
|
12516
12387
|
if (process.env.MIC_AEC === "0" || process.platform !== "darwin") return null;
|
|
12517
|
-
const src =
|
|
12518
|
-
const plist =
|
|
12388
|
+
const src = join6(nativeDir(), "mic-aec.swift");
|
|
12389
|
+
const plist = join6(nativeDir(), "Info.plist");
|
|
12519
12390
|
if (!existsSync4(src)) return null;
|
|
12520
|
-
const cacheDir =
|
|
12521
|
-
const bin =
|
|
12391
|
+
const cacheDir = join6(homedir3(), ".agent", "cache");
|
|
12392
|
+
const bin = join6(cacheDir, "mic-aec");
|
|
12522
12393
|
if (existsSync4(bin) && statSync5(bin).mtimeMs >= statSync5(src).mtimeMs) return bin;
|
|
12523
|
-
if (
|
|
12394
|
+
if (spawnSync2("which", ["swiftc"]).status !== 0) return null;
|
|
12524
12395
|
mkdirSync5(cacheDir, { recursive: true });
|
|
12525
12396
|
log27.info("compiling AEC mic helper (first run)\u2026");
|
|
12526
|
-
const build =
|
|
12397
|
+
const build = spawnSync2("swiftc", ["-O", "-o", bin, src, "-Xlinker", "-sectcreate", "-Xlinker", "__TEXT", "-Xlinker", "__info_plist", "-Xlinker", plist], { encoding: "utf8" });
|
|
12527
12398
|
if (build.status !== 0) {
|
|
12528
12399
|
log27.warn(`AEC build failed: ${build.stderr?.slice(0, 400)}`);
|
|
12529
12400
|
return null;
|
|
12530
12401
|
}
|
|
12531
|
-
const sign =
|
|
12402
|
+
const sign = spawnSync2("codesign", ["-fs", "-", bin], { encoding: "utf8" });
|
|
12532
12403
|
if (sign.status !== 0) {
|
|
12533
12404
|
log27.warn(`codesign failed: ${sign.stderr?.slice(0, 200)}`);
|
|
12534
12405
|
return null;
|
|
@@ -12538,14 +12409,14 @@ function resolveAecBinary() {
|
|
|
12538
12409
|
function openMicSettings() {
|
|
12539
12410
|
if (process.platform !== "darwin") return;
|
|
12540
12411
|
try {
|
|
12541
|
-
|
|
12412
|
+
spawnSync2("open", ["x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone"]);
|
|
12542
12413
|
} catch {
|
|
12543
12414
|
}
|
|
12544
12415
|
}
|
|
12545
12416
|
function micPermissionStatus() {
|
|
12546
12417
|
const bin = resolveAecBinary();
|
|
12547
12418
|
if (!bin) return null;
|
|
12548
|
-
const r =
|
|
12419
|
+
const r = spawnSync2(bin, ["--check-mic"], { encoding: "utf8" });
|
|
12549
12420
|
const out = (r.stdout ?? "").trim();
|
|
12550
12421
|
if (out === "authorized") return "authorized";
|
|
12551
12422
|
if (out === "denied" || out === "restricted") return "denied";
|
|
@@ -12555,7 +12426,7 @@ function micPermissionStatus() {
|
|
|
12555
12426
|
function aecUnavailableHint() {
|
|
12556
12427
|
if (process.env.MIC_AEC === "0" || process.platform !== "darwin") return null;
|
|
12557
12428
|
if (resolveAecBinary()) return null;
|
|
12558
|
-
if (
|
|
12429
|
+
if (spawnSync2("which", ["swiftc"]).status !== 0) return "install Xcode CLI tools (`xcode-select --install`) for echo cancellation";
|
|
12559
12430
|
return null;
|
|
12560
12431
|
}
|
|
12561
12432
|
var NodeMicSource = class {
|
|
@@ -12571,7 +12442,7 @@ var NodeMicSource = class {
|
|
|
12571
12442
|
if (this.bin) {
|
|
12572
12443
|
this.proc = spawn2(this.bin, [], { stdio: ["ignore", "pipe", "ignore"] });
|
|
12573
12444
|
} else {
|
|
12574
|
-
if (
|
|
12445
|
+
if (spawnSync2("which", ["ffmpeg"]).status !== 0) throw new Error("voice I/O unavailable: no AEC helper and no ffmpeg on PATH");
|
|
12575
12446
|
log27.info("mic: raw capture (no AEC) \u2014 echo handled heuristically; headphones recommended");
|
|
12576
12447
|
this.proc = spawn2(
|
|
12577
12448
|
"ffmpeg",
|
|
@@ -13020,12 +12891,12 @@ var JsonlDiagSink = class {
|
|
|
13020
12891
|
// cli/config.ts
|
|
13021
12892
|
import { homedir as homedir4 } from "os";
|
|
13022
12893
|
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
13023
|
-
import { join as
|
|
12894
|
+
import { join as join7 } from "path";
|
|
13024
12895
|
import { pathToFileURL } from "url";
|
|
13025
12896
|
var FILES = ["config.ts", "config.js", "config.mjs", "config.json"];
|
|
13026
12897
|
async function loadFrom(dir) {
|
|
13027
12898
|
for (const f of FILES) {
|
|
13028
|
-
const p =
|
|
12899
|
+
const p = join7(dir, ".agent", f);
|
|
13029
12900
|
if (!existsSync5(p)) continue;
|
|
13030
12901
|
try {
|
|
13031
12902
|
const mod = await import(pathToFileURL(p).href, f.endsWith(".json") ? { with: { type: "json" } } : void 0);
|
|
@@ -13038,7 +12909,7 @@ async function loadFrom(dir) {
|
|
|
13038
12909
|
return {};
|
|
13039
12910
|
}
|
|
13040
12911
|
function loadSettings(dir) {
|
|
13041
|
-
const p =
|
|
12912
|
+
const p = join7(dir, ".agent", "settings.json");
|
|
13042
12913
|
if (!existsSync5(p)) return {};
|
|
13043
12914
|
try {
|
|
13044
12915
|
const raw = JSON.parse(readFileSync7(p, "utf8"));
|
|
@@ -13074,7 +12945,7 @@ async function loadConfig(cwd) {
|
|
|
13074
12945
|
}
|
|
13075
12946
|
|
|
13076
12947
|
// cli/hooks-config.ts
|
|
13077
|
-
import { spawnSync as
|
|
12948
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
13078
12949
|
var log29 = forComponent("hooks");
|
|
13079
12950
|
var escapeRegex = (s) => s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13080
12951
|
function ruleMatches(rule, toolName) {
|
|
@@ -13084,7 +12955,7 @@ function ruleMatches(rule, toolName) {
|
|
|
13084
12955
|
}
|
|
13085
12956
|
function runCmd(rule, env) {
|
|
13086
12957
|
try {
|
|
13087
|
-
const r =
|
|
12958
|
+
const r = spawnSync3(rule.command, {
|
|
13088
12959
|
shell: true,
|
|
13089
12960
|
encoding: "utf8",
|
|
13090
12961
|
timeout: rule.timeoutMs ?? 1e4,
|
|
@@ -13196,15 +13067,15 @@ function formatDiff(ops, opts = {}) {
|
|
|
13196
13067
|
}
|
|
13197
13068
|
|
|
13198
13069
|
// cli/session.ts
|
|
13199
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as
|
|
13070
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync4, readdirSync, renameSync, symlinkSync as symlinkSync2, unlinkSync, readlinkSync, statSync as statSync6 } from "fs";
|
|
13200
13071
|
import { homedir as homedir5 } from "os";
|
|
13201
|
-
import { join as
|
|
13072
|
+
import { join as join8 } from "path";
|
|
13202
13073
|
var log30 = forComponent("session");
|
|
13203
|
-
var globalDir = () =>
|
|
13074
|
+
var globalDir = () => join8(homedir5(), ".agent", "sessions");
|
|
13204
13075
|
var SessionStore = class {
|
|
13205
13076
|
dir;
|
|
13206
13077
|
constructor(cwd) {
|
|
13207
|
-
this.dir =
|
|
13078
|
+
this.dir = join8(cwd, ".agent", "sessions");
|
|
13208
13079
|
}
|
|
13209
13080
|
/** Sortable, human-readable id: `YYYYMMDD-HHMMSS-<folder>`. */
|
|
13210
13081
|
newId(now4 = Date.now(), cwd) {
|
|
@@ -13212,10 +13083,10 @@ var SessionStore = class {
|
|
|
13212
13083
|
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
13213
13084
|
const slug2 = (cwd ?? process.cwd()).split("/").pop()?.replace(/[^A-Za-z0-9_-]/g, "") || "session";
|
|
13214
13085
|
let id = `${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}-${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}-${slug2}`;
|
|
13215
|
-
if (existsSync6(this.dir) && existsSync6(
|
|
13086
|
+
if (existsSync6(this.dir) && existsSync6(join8(this.dir, `${id}.json`))) {
|
|
13216
13087
|
for (let i = 2; i <= 99; i++) {
|
|
13217
13088
|
const c = `${id}-${i}`;
|
|
13218
|
-
if (!existsSync6(
|
|
13089
|
+
if (!existsSync6(join8(this.dir, `${c}.json`))) {
|
|
13219
13090
|
id = c;
|
|
13220
13091
|
break;
|
|
13221
13092
|
}
|
|
@@ -13230,14 +13101,14 @@ var SessionStore = class {
|
|
|
13230
13101
|
save(data) {
|
|
13231
13102
|
if (!this.safeId(data.meta.id)) throw new Error(`unsafe session id: ${data.meta.id}`);
|
|
13232
13103
|
if (!existsSync6(this.dir)) mkdirSync7(this.dir, { recursive: true });
|
|
13233
|
-
const path =
|
|
13104
|
+
const path = join8(this.dir, `${data.meta.id}.json`);
|
|
13234
13105
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
13235
|
-
|
|
13106
|
+
writeFileSync4(tmp, JSON.stringify(data));
|
|
13236
13107
|
renameSync(tmp, path);
|
|
13237
13108
|
try {
|
|
13238
13109
|
const gd = globalDir();
|
|
13239
13110
|
if (!existsSync6(gd)) mkdirSync7(gd, { recursive: true });
|
|
13240
|
-
const link2 =
|
|
13111
|
+
const link2 = join8(gd, `${data.meta.id}.json`);
|
|
13241
13112
|
if (!existsSync6(link2)) symlinkSync2(path, link2);
|
|
13242
13113
|
} catch {
|
|
13243
13114
|
}
|
|
@@ -13247,7 +13118,7 @@ var SessionStore = class {
|
|
|
13247
13118
|
log30.debug(`rejecting unsafe session id: ${id}`);
|
|
13248
13119
|
return void 0;
|
|
13249
13120
|
}
|
|
13250
|
-
const path =
|
|
13121
|
+
const path = join8(this.dir, `${id}.json`);
|
|
13251
13122
|
if (!existsSync6(path)) return void 0;
|
|
13252
13123
|
try {
|
|
13253
13124
|
return JSON.parse(readFileSync8(path, "utf8"));
|
|
@@ -13263,7 +13134,7 @@ var SessionStore = class {
|
|
|
13263
13134
|
for (const f of readdirSync(this.dir)) {
|
|
13264
13135
|
if (!f.endsWith(".json")) continue;
|
|
13265
13136
|
try {
|
|
13266
|
-
metas.push(JSON.parse(readFileSync8(
|
|
13137
|
+
metas.push(JSON.parse(readFileSync8(join8(this.dir, f), "utf8")).meta);
|
|
13267
13138
|
} catch (e) {
|
|
13268
13139
|
log30.debug(`skipping unreadable session file ${f}`, e);
|
|
13269
13140
|
}
|
|
@@ -13278,7 +13149,7 @@ var SessionStore = class {
|
|
|
13278
13149
|
for (const f of readdirSync(this.dir)) {
|
|
13279
13150
|
if (!f.endsWith(".json")) continue;
|
|
13280
13151
|
try {
|
|
13281
|
-
const st = statSync6(
|
|
13152
|
+
const st = statSync6(join8(this.dir, f));
|
|
13282
13153
|
out.push({ id: f.slice(0, -5), mtime: st.mtimeMs, size: st.size });
|
|
13283
13154
|
} catch {
|
|
13284
13155
|
}
|
|
@@ -13297,7 +13168,7 @@ var SessionStore = class {
|
|
|
13297
13168
|
function globalSessionLoad(idOrPrefix) {
|
|
13298
13169
|
const gd = globalDir();
|
|
13299
13170
|
if (!existsSync6(gd)) return void 0;
|
|
13300
|
-
const exact =
|
|
13171
|
+
const exact = join8(gd, `${idOrPrefix}.json`);
|
|
13301
13172
|
if (existsSync6(exact)) {
|
|
13302
13173
|
try {
|
|
13303
13174
|
const target = readlinkSync(exact);
|
|
@@ -13311,7 +13182,7 @@ function globalSessionLoad(idOrPrefix) {
|
|
|
13311
13182
|
if (!f.endsWith(".json")) continue;
|
|
13312
13183
|
const base = f.slice(0, -5);
|
|
13313
13184
|
if (base.includes(idOrPrefix) || base.endsWith(idOrPrefix)) {
|
|
13314
|
-
const target = readlinkSync(
|
|
13185
|
+
const target = readlinkSync(join8(gd, f));
|
|
13315
13186
|
return JSON.parse(readFileSync8(target, "utf8"));
|
|
13316
13187
|
}
|
|
13317
13188
|
}
|
|
@@ -13326,10 +13197,10 @@ function globalSessionList() {
|
|
|
13326
13197
|
for (const f of readdirSync(gd)) {
|
|
13327
13198
|
if (!f.endsWith(".json")) continue;
|
|
13328
13199
|
try {
|
|
13329
|
-
const target = readlinkSync(
|
|
13200
|
+
const target = readlinkSync(join8(gd, f));
|
|
13330
13201
|
if (!existsSync6(target)) {
|
|
13331
13202
|
try {
|
|
13332
|
-
unlinkSync(
|
|
13203
|
+
unlinkSync(join8(gd, f));
|
|
13333
13204
|
} catch {
|
|
13334
13205
|
}
|
|
13335
13206
|
continue;
|
|
@@ -13501,9 +13372,9 @@ ${formatDiff(ops)}`);
|
|
|
13501
13372
|
// cli/gitCheckpoints.ts
|
|
13502
13373
|
import { execFile as execFile3 } from "child_process";
|
|
13503
13374
|
import { promisify } from "util";
|
|
13504
|
-
import { writeFileSync as
|
|
13375
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync8 } from "fs";
|
|
13505
13376
|
import { homedir as homedir6 } from "os";
|
|
13506
|
-
import { join as
|
|
13377
|
+
import { join as join9, resolve as resolve3, sep as sep3, parse as parsePath } from "path";
|
|
13507
13378
|
var log31 = forComponent("checkpoints");
|
|
13508
13379
|
var exec = promisify(execFile3);
|
|
13509
13380
|
var DEFAULT_EXCLUDE = [".agent/", ".git/", "node_modules/", "dist/", "build/", ".next/", "target/", ".venv/", "__pycache__/", "*.log"];
|
|
@@ -13546,8 +13417,8 @@ var ShadowRepo = class {
|
|
|
13546
13417
|
mkdirSync8(this.gitDir, { recursive: true });
|
|
13547
13418
|
const valid = await this.run("rev-parse", "--git-dir").then(() => true, () => false);
|
|
13548
13419
|
if (!valid) await this.run("init", "-q");
|
|
13549
|
-
mkdirSync8(
|
|
13550
|
-
|
|
13420
|
+
mkdirSync8(join9(this.gitDir, "info"), { recursive: true });
|
|
13421
|
+
writeFileSync5(join9(this.gitDir, "info", "exclude"), this.exclude.join("\n") + "\n");
|
|
13551
13422
|
this.ready = true;
|
|
13552
13423
|
} catch (e) {
|
|
13553
13424
|
log31.debug(`git checkpoints unavailable for ${this.workTree}`, e);
|
|
@@ -13662,7 +13533,7 @@ var GitCheckpoints = class {
|
|
|
13662
13533
|
const abs = resolve3(d);
|
|
13663
13534
|
if (abs === cwd || abs.startsWith(cwd + sep3)) continue;
|
|
13664
13535
|
if (cwd.startsWith(abs + sep3)) continue;
|
|
13665
|
-
out.push({ workTree: abs, gitDir:
|
|
13536
|
+
out.push({ workTree: abs, gitDir: join9(abs, ".agent", "checkpoints.git") });
|
|
13666
13537
|
}
|
|
13667
13538
|
return out;
|
|
13668
13539
|
}
|
|
@@ -13805,7 +13676,7 @@ var GitCheckpointsOptions = class {
|
|
|
13805
13676
|
/** Real working tree to snapshot (the launch cwd). */
|
|
13806
13677
|
workTree = process.cwd();
|
|
13807
13678
|
/** Isolated git dir for the cwd shadow repo (kept out of the user's real .git). */
|
|
13808
|
-
gitDir =
|
|
13679
|
+
gitDir = join9(process.cwd(), ".agent", "checkpoints.git");
|
|
13809
13680
|
/** Extra mounted dirs (`--add-dir`); those outside cwd each get their own shadow repo. */
|
|
13810
13681
|
addDirs = [];
|
|
13811
13682
|
/** Conversation id → per-session restore-point ref. */
|
|
@@ -13821,9 +13692,9 @@ var GitCheckpointsOptions = class {
|
|
|
13821
13692
|
};
|
|
13822
13693
|
|
|
13823
13694
|
// cli/permissions.ts
|
|
13824
|
-
import { writeFileSync as
|
|
13695
|
+
import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync9 } from "fs";
|
|
13825
13696
|
import { homedir as homedir7 } from "os";
|
|
13826
|
-
import { join as
|
|
13697
|
+
import { join as join10 } from "path";
|
|
13827
13698
|
var RULE_RE = /^(\w[\w*-]*)(?:\((.+)\))?$/;
|
|
13828
13699
|
function parseOne(raw, decision) {
|
|
13829
13700
|
const m = RULE_RE.exec(raw.trim());
|
|
@@ -13845,13 +13716,13 @@ function parsePermRules(perms, explicit = false) {
|
|
|
13845
13716
|
function describeRule(r) {
|
|
13846
13717
|
return `${r.decision.padEnd(5)} ${r.tool ?? "*"}${r.pathGlob ? `(${r.pathGlob})` : ""}`;
|
|
13847
13718
|
}
|
|
13848
|
-
var PERM_FILE = (cwd) =>
|
|
13719
|
+
var PERM_FILE = (cwd) => join10(cwd, ".agent", "permissions.json");
|
|
13849
13720
|
function loadPersistedRules(cwd) {
|
|
13850
13721
|
const j = readJsonFile(PERM_FILE(cwd), null);
|
|
13851
13722
|
return j ? { allow: j.allow ?? [], ask: j.ask ?? [], deny: j.deny ?? [] } : {};
|
|
13852
13723
|
}
|
|
13853
13724
|
function loadClaudeSettings(cwd, home = homedir7()) {
|
|
13854
|
-
const files = [
|
|
13725
|
+
const files = [join10(home, ".claude", "settings.json"), join10(cwd, ".claude", "settings.json"), join10(cwd, ".claude", "settings.local.json")];
|
|
13855
13726
|
let out = {};
|
|
13856
13727
|
for (const p of files) {
|
|
13857
13728
|
const perms = readJsonFile(p, null)?.permissions;
|
|
@@ -13864,8 +13735,8 @@ function persistRule(cwd, decision, ruleStr) {
|
|
|
13864
13735
|
const list = cur[decision] ??= [];
|
|
13865
13736
|
if (!list.includes(ruleStr)) list.push(ruleStr);
|
|
13866
13737
|
try {
|
|
13867
|
-
mkdirSync9(
|
|
13868
|
-
|
|
13738
|
+
mkdirSync9(join10(cwd, ".agent"), { recursive: true });
|
|
13739
|
+
writeFileSync6(PERM_FILE(cwd), JSON.stringify(cur, null, 2) + "\n");
|
|
13869
13740
|
} catch {
|
|
13870
13741
|
}
|
|
13871
13742
|
}
|
|
@@ -13878,7 +13749,7 @@ function mergePerms(a, b) {
|
|
|
13878
13749
|
}
|
|
13879
13750
|
return Object.keys(out).length ? out : void 0;
|
|
13880
13751
|
}
|
|
13881
|
-
var TRUST_FILE =
|
|
13752
|
+
var TRUST_FILE = join10(homedir7(), ".agent", "trusted.json");
|
|
13882
13753
|
function isTrusted(cwd, file = TRUST_FILE) {
|
|
13883
13754
|
const list = readJsonFile(file, []);
|
|
13884
13755
|
return Array.isArray(list) && list.includes(cwd);
|
|
@@ -13888,8 +13759,8 @@ function trustDir(cwd, file = TRUST_FILE) {
|
|
|
13888
13759
|
if (!Array.isArray(list)) list = [];
|
|
13889
13760
|
if (!list.includes(cwd)) list.push(cwd);
|
|
13890
13761
|
try {
|
|
13891
|
-
mkdirSync9(
|
|
13892
|
-
|
|
13762
|
+
mkdirSync9(join10(file, ".."), { recursive: true });
|
|
13763
|
+
writeFileSync6(file, JSON.stringify(list, null, 2) + "\n");
|
|
13893
13764
|
} catch {
|
|
13894
13765
|
}
|
|
13895
13766
|
}
|
|
@@ -13952,10 +13823,10 @@ function completePath(listDir, ref) {
|
|
|
13952
13823
|
|
|
13953
13824
|
// cli/lineEditor.ts
|
|
13954
13825
|
import { emitKeypressEvents } from "readline";
|
|
13955
|
-
import { spawnSync as
|
|
13956
|
-
import { writeFileSync as
|
|
13957
|
-
import { tmpdir as
|
|
13958
|
-
import { join as
|
|
13826
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
13827
|
+
import { writeFileSync as writeFileSync7, readFileSync as readFileSync9, unlinkSync as unlinkSync2 } from "fs";
|
|
13828
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
13829
|
+
import { join as join11 } from "path";
|
|
13959
13830
|
|
|
13960
13831
|
// cli/bidi.ts
|
|
13961
13832
|
var RTL_RE = /[\u0590-\u05ff\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb1d-\ufdff\ufe70-\ufeff]/;
|
|
@@ -15142,12 +15013,12 @@ function createLineEditor(out, input = keyInput) {
|
|
|
15142
15013
|
function externalEdit(s) {
|
|
15143
15014
|
const spec = process.env.VISUAL || process.env.EDITOR || "vi";
|
|
15144
15015
|
const [cmd, ...cargs] = spec.split(" ").filter(Boolean);
|
|
15145
|
-
const file =
|
|
15016
|
+
const file = join11(tmpdir2(), `agentx-edit-${process.pid}-${Date.now()}.md`);
|
|
15146
15017
|
try {
|
|
15147
|
-
|
|
15018
|
+
writeFileSync7(file, s.buf);
|
|
15148
15019
|
process.stdin.setRawMode(false);
|
|
15149
15020
|
out.write("\x1B[?2004l");
|
|
15150
|
-
const r =
|
|
15021
|
+
const r = spawnSync4(cmd, [...cargs, file], { stdio: "inherit" });
|
|
15151
15022
|
if (r.status === 0) {
|
|
15152
15023
|
const text = readFileSync9(file, "utf8").replace(/\n$/, "");
|
|
15153
15024
|
s.reset();
|
|
@@ -15602,10 +15473,10 @@ function readPlainLine() {
|
|
|
15602
15473
|
}
|
|
15603
15474
|
|
|
15604
15475
|
// cli/osScheduler.ts
|
|
15605
|
-
import { spawnSync as
|
|
15606
|
-
import { writeFileSync as
|
|
15476
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
15477
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync10, readdirSync as readdirSync2, unlinkSync as unlinkSync3, chmodSync, existsSync as existsSync7 } from "fs";
|
|
15607
15478
|
import { homedir as homedir8 } from "os";
|
|
15608
|
-
import { join as
|
|
15479
|
+
import { join as join12 } from "path";
|
|
15609
15480
|
var log32 = forComponent("os-sched");
|
|
15610
15481
|
var OsScheduler = class {
|
|
15611
15482
|
options;
|
|
@@ -15613,13 +15484,13 @@ var OsScheduler = class {
|
|
|
15613
15484
|
this.options = { ...new OsSchedulerOptions(), ...options };
|
|
15614
15485
|
}
|
|
15615
15486
|
get dir() {
|
|
15616
|
-
return
|
|
15487
|
+
return join12(this.options.home, ".agent", "sched");
|
|
15617
15488
|
}
|
|
15618
15489
|
label(id) {
|
|
15619
15490
|
return `cc.livx.agentx.sched-${id}`;
|
|
15620
15491
|
}
|
|
15621
15492
|
plistPath(id) {
|
|
15622
|
-
return
|
|
15493
|
+
return join12(this.options.home, "Library", "LaunchAgents", `${this.label(id)}.plist`);
|
|
15623
15494
|
}
|
|
15624
15495
|
run(cmd, args, input) {
|
|
15625
15496
|
return this.options.exec(cmd, args, input);
|
|
@@ -15635,11 +15506,11 @@ var OsScheduler = class {
|
|
|
15635
15506
|
const script = this.writeScript(spec, oneOff);
|
|
15636
15507
|
const mechanism = this.options.platform === "darwin" ? this.scheduleDarwin(spec, script) : this.scheduleLinux(spec, script, oneOff);
|
|
15637
15508
|
const meta = { ...spec, created: Date.now(), mechanism };
|
|
15638
|
-
|
|
15509
|
+
writeFileSync8(join12(this.dir, `${spec.id}.json`), JSON.stringify(meta, null, 2));
|
|
15639
15510
|
return mechanism;
|
|
15640
15511
|
}
|
|
15641
15512
|
cancel(id) {
|
|
15642
|
-
const meta = readJsonFile(
|
|
15513
|
+
const meta = readJsonFile(join12(this.dir, `${id}.json`), null);
|
|
15643
15514
|
if (!meta) return false;
|
|
15644
15515
|
try {
|
|
15645
15516
|
if (this.options.platform === "darwin") {
|
|
@@ -15672,7 +15543,7 @@ var OsScheduler = class {
|
|
|
15672
15543
|
}
|
|
15673
15544
|
for (const f of [`${id}.json`, `${id}.sh`]) {
|
|
15674
15545
|
try {
|
|
15675
|
-
unlinkSync3(
|
|
15546
|
+
unlinkSync3(join12(this.dir, f));
|
|
15676
15547
|
} catch {
|
|
15677
15548
|
}
|
|
15678
15549
|
}
|
|
@@ -15680,19 +15551,19 @@ var OsScheduler = class {
|
|
|
15680
15551
|
}
|
|
15681
15552
|
list() {
|
|
15682
15553
|
if (!existsSync7(this.dir)) return [];
|
|
15683
|
-
return readdirSync2(this.dir).filter((f) => f.endsWith(".json")).map((f) => readJsonFile(
|
|
15554
|
+
return readdirSync2(this.dir).filter((f) => f.endsWith(".json")).map((f) => readJsonFile(join12(this.dir, f), null)).filter(Boolean);
|
|
15684
15555
|
}
|
|
15685
15556
|
/** The per-job runner script: cd to the project, headless-resume the session, log, notify. */
|
|
15686
15557
|
writeScript(spec, oneOff) {
|
|
15687
|
-
const p =
|
|
15558
|
+
const p = join12(this.dir, `${spec.id}.sh`);
|
|
15688
15559
|
const q2 = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
15689
|
-
const cleanup = oneOff ? this.options.platform === "darwin" ? `launchctl remove ${this.label(spec.id)} 2>/dev/null; rm -f ${q2(this.plistPath(spec.id))} ${q2(
|
|
15690
|
-
` : `rm -f ${q2(
|
|
15560
|
+
const cleanup = oneOff ? this.options.platform === "darwin" ? `launchctl remove ${this.label(spec.id)} 2>/dev/null; rm -f ${q2(this.plistPath(spec.id))} ${q2(join12(this.dir, `${spec.id}.json`))} ${q2(p)}
|
|
15561
|
+
` : `rm -f ${q2(join12(this.dir, `${spec.id}.json`))} ${q2(p)}
|
|
15691
15562
|
` : "";
|
|
15692
|
-
|
|
15563
|
+
writeFileSync8(p, `#!/bin/sh
|
|
15693
15564
|
# agentx scheduled job ${spec.id}${spec.label ? ` \u2014 ${spec.label}` : ""}
|
|
15694
15565
|
cd ${q2(spec.cwd)} || exit 1
|
|
15695
|
-
${this.options.agentx} -p ${q2(spec.prompt)} --resume ${q2(spec.sessionId)} --yes >> ${q2(
|
|
15566
|
+
${this.options.agentx} -p ${q2(spec.prompt)} --resume ${q2(spec.sessionId)} --yes >> ${q2(join12(this.dir, `${spec.id}.log`))} 2>&1
|
|
15696
15567
|
${cleanup}`);
|
|
15697
15568
|
chmodSync(p, 493);
|
|
15698
15569
|
return p;
|
|
@@ -15729,8 +15600,8 @@ ${trigger}
|
|
|
15729
15600
|
<key>RunAtLoad</key><false/>
|
|
15730
15601
|
</dict></plist>
|
|
15731
15602
|
`;
|
|
15732
|
-
mkdirSync10(
|
|
15733
|
-
|
|
15603
|
+
mkdirSync10(join12(this.options.home, "Library", "LaunchAgents"), { recursive: true });
|
|
15604
|
+
writeFileSync8(this.plistPath(spec.id), plist);
|
|
15734
15605
|
this.run("launchctl", ["load", this.plistPath(spec.id)]);
|
|
15735
15606
|
return `launchd:${this.label(spec.id)}`;
|
|
15736
15607
|
}
|
|
@@ -15767,7 +15638,7 @@ var OsSchedulerOptions = class {
|
|
|
15767
15638
|
/** Injectable executor for tests. Returns stdout+stderr merged — `at` reports "job N" on STDERR,
|
|
15768
15639
|
* and the job id is what atrm needs for cancel. Throws on non-zero exit. */
|
|
15769
15640
|
exec = (cmd, args, input) => {
|
|
15770
|
-
const r =
|
|
15641
|
+
const r = spawnSync5(cmd, args, { input, encoding: "utf8" });
|
|
15771
15642
|
if (r.error) throw r.error;
|
|
15772
15643
|
if (r.status !== 0) throw new Error(`${cmd} exited ${r.status}: ${r.stderr || r.stdout}`);
|
|
15773
15644
|
return `${r.stdout ?? ""}${r.stderr ?? ""}`;
|
|
@@ -15784,10 +15655,10 @@ import { createServer as createServer2, createConnection } from "net";
|
|
|
15784
15655
|
import { spawn as spawn3 } from "child_process";
|
|
15785
15656
|
import { existsSync as existsSync8, mkdirSync as mkdirSync11, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
|
|
15786
15657
|
import { homedir as homedir9 } from "os";
|
|
15787
|
-
import { join as
|
|
15658
|
+
import { join as join13 } from "path";
|
|
15788
15659
|
var log33 = forComponent("remote-trigger");
|
|
15789
|
-
var TRIGGER_DIR = () =>
|
|
15790
|
-
var sockPath = (sessionId, dir = TRIGGER_DIR()) =>
|
|
15660
|
+
var TRIGGER_DIR = () => join13(homedir9(), ".agent", "triggers");
|
|
15661
|
+
var sockPath = (sessionId, dir = TRIGGER_DIR()) => join13(dir, `${sessionId}.sock`);
|
|
15791
15662
|
var TriggerServer = class {
|
|
15792
15663
|
constructor(onTrigger) {
|
|
15793
15664
|
this.onTrigger = onTrigger;
|
|
@@ -15973,7 +15844,7 @@ async function checkForUpdate(current) {
|
|
|
15973
15844
|
return `Update available: ${current} \u2192 ${latest}. Run \`bun add -g @livx.cc/agentx\` to update.`;
|
|
15974
15845
|
}
|
|
15975
15846
|
function installUpdate() {
|
|
15976
|
-
const r =
|
|
15847
|
+
const r = spawnSync6("bun", ["add", "-g", "@livx.cc/agentx"], { stdio: "inherit" });
|
|
15977
15848
|
return (r.status ?? 1) === 0;
|
|
15978
15849
|
}
|
|
15979
15850
|
var typeaheadOnLine = false;
|
|
@@ -16272,10 +16143,10 @@ function loadEnvFile(file) {
|
|
|
16272
16143
|
}
|
|
16273
16144
|
function loadInstallEnv() {
|
|
16274
16145
|
let dir = dirname5(import.meta.path);
|
|
16275
|
-
for (let i = 0; i < 5 && !existsSync9(
|
|
16146
|
+
for (let i = 0; i < 5 && !existsSync9(join14(dir, "package.json")); i++) dir = dirname5(dir);
|
|
16276
16147
|
for (const name of [".env", ".env.local"]) {
|
|
16277
|
-
loadEnvFile(
|
|
16278
|
-
loadEnvFile(
|
|
16148
|
+
loadEnvFile(join14(dir, name));
|
|
16149
|
+
loadEnvFile(join14(homedir10(), ".agent", name));
|
|
16279
16150
|
}
|
|
16280
16151
|
}
|
|
16281
16152
|
async function loadBodifySecrets() {
|
|
@@ -16999,7 +16870,7 @@ var IMG_EXT = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg"
|
|
|
16999
16870
|
function mentionRefs(line) {
|
|
17000
16871
|
return [...line.matchAll(/(?:^|\s)@(?:"([^"]+)"|(\S+))/g)].map((m) => m[1] ?? m[2].replace(/[?!.,;:)\]}'">]+$/, "")).filter(Boolean);
|
|
17001
16872
|
}
|
|
17002
|
-
var untilde = (p) => p.startsWith("~/") ?
|
|
16873
|
+
var untilde = (p) => p.startsWith("~/") ? join14(homedir10(), p.slice(2)) : p;
|
|
17003
16874
|
function readImageParts(cwd, line) {
|
|
17004
16875
|
const refs = mentionRefs(line);
|
|
17005
16876
|
const parts = [];
|
|
@@ -17080,6 +16951,7 @@ function jsonResult(res, session) {
|
|
|
17080
16951
|
steps: res.steps,
|
|
17081
16952
|
tools: res.messages.slice(lastUser).filter((m) => m.role === "tool").length,
|
|
17082
16953
|
usage: res.usage,
|
|
16954
|
+
...res.budget ? { budget: res.budget } : {},
|
|
17083
16955
|
...res.routing ? { costUsd: res.costUsd, routing: res.routing } : {},
|
|
17084
16956
|
// cast: tsup dts hoists a modelRouter import above the shebang
|
|
17085
16957
|
sessionId: session.meta.id,
|
|
@@ -17203,7 +17075,7 @@ async function runTurn(agent, store, session, task, cp, cwd = process.cwd(), sen
|
|
|
17203
17075
|
}
|
|
17204
17076
|
return { ok, res };
|
|
17205
17077
|
}
|
|
17206
|
-
var remintSessionImages = (data, store, cwd) => remintImageRefs(data.messages, [
|
|
17078
|
+
var remintSessionImages = (data, store, cwd) => remintImageRefs(data.messages, [join14(store.dir, `${data.meta.id}.images`), cwd]);
|
|
17207
17079
|
function startSession(args, store, agent, cwd) {
|
|
17208
17080
|
if (args.resume || args.cont) {
|
|
17209
17081
|
const data = args.resume ? store.load(args.resume) ?? globalSessionLoad(args.resume) : store.latestData();
|
|
@@ -17250,25 +17122,25 @@ var AGENTS_MD_TEMPLATE = `# ${"${name}"}
|
|
|
17250
17122
|
`;
|
|
17251
17123
|
function initInstructions(cwd) {
|
|
17252
17124
|
for (const f of ["AGENTS.md", "CLAUDE.md"]) {
|
|
17253
|
-
if (existsSync9(
|
|
17125
|
+
if (existsSync9(join14(cwd, f))) {
|
|
17254
17126
|
err(yellow(` ${f} already exists \u2014 leaving it as-is
|
|
17255
17127
|
`));
|
|
17256
17128
|
return;
|
|
17257
17129
|
}
|
|
17258
17130
|
}
|
|
17259
|
-
const path =
|
|
17260
|
-
|
|
17131
|
+
const path = join14(cwd, "AGENTS.md");
|
|
17132
|
+
writeFileSync9(path, AGENTS_MD_TEMPLATE.replace("${name}", basename2(cwd)));
|
|
17261
17133
|
err(green(` created ${path}
|
|
17262
17134
|
`) + dim(" edit it, then it auto-loads into every run.\n"));
|
|
17263
17135
|
}
|
|
17264
17136
|
function persistSetting(cwd, key, value) {
|
|
17265
|
-
const path =
|
|
17137
|
+
const path = join14(cwd, ".agent", "settings.json");
|
|
17266
17138
|
try {
|
|
17267
17139
|
const obj = existsSync9(path) ? JSON.parse(readFileSync10(path, "utf8")) : {};
|
|
17268
17140
|
if (obj[key] === value) return;
|
|
17269
17141
|
obj[key] = value;
|
|
17270
17142
|
mkdirSync12(dirname5(path), { recursive: true });
|
|
17271
|
-
|
|
17143
|
+
writeFileSync9(path, JSON.stringify(obj, null, 2) + "\n");
|
|
17272
17144
|
} catch (e) {
|
|
17273
17145
|
err(yellow(` \u26A0 couldn't persist ${key} to ${path} \u2014 ${e?.message ?? e}
|
|
17274
17146
|
`));
|
|
@@ -17300,7 +17172,7 @@ function installCancelGuards(mounted) {
|
|
|
17300
17172
|
});
|
|
17301
17173
|
}
|
|
17302
17174
|
async function repl(args, ai, cfg, cwd) {
|
|
17303
|
-
const oauth = new McpOAuth({ storePath:
|
|
17175
|
+
const oauth = new McpOAuth({ storePath: join14(cwd, ".agent", "mcp-auth.json") });
|
|
17304
17176
|
const mounted = await mountMcp(cfg, oauth);
|
|
17305
17177
|
let mcpToolNames = [];
|
|
17306
17178
|
const initialMcpTools = mcpAgentTools(mounted);
|
|
@@ -17576,7 +17448,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
17576
17448
|
quickLook: {
|
|
17577
17449
|
branch: () => {
|
|
17578
17450
|
try {
|
|
17579
|
-
const head = readFileSync10(
|
|
17451
|
+
const head = readFileSync10(join14(cwd, ".git", "HEAD"), "utf8").trim();
|
|
17580
17452
|
return head.startsWith("ref: refs/heads/") ? `branch: ${head.slice("ref: refs/heads/".length)}` : `detached HEAD at ${head.slice(0, 12)}`;
|
|
17581
17453
|
} catch {
|
|
17582
17454
|
return "not a git repository";
|
|
@@ -17710,7 +17582,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
17710
17582
|
const pendingImages = [];
|
|
17711
17583
|
const bangContext = [];
|
|
17712
17584
|
const grabClipboardAttachment = () => {
|
|
17713
|
-
const dir =
|
|
17585
|
+
const dir = join14(store.dir, `${session.meta.id}.images`);
|
|
17714
17586
|
try {
|
|
17715
17587
|
mkdirSync12(dir, { recursive: true });
|
|
17716
17588
|
} catch (e) {
|
|
@@ -17768,7 +17640,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
17768
17640
|
err(dim(` \u23F0 ${scheduler.size} scheduled job(s) re-armed
|
|
17769
17641
|
`));
|
|
17770
17642
|
}
|
|
17771
|
-
const checkpoints = args.vfs || args.boddb ? new CheckpointStack(agent.options.fs) : new GitCheckpoints({ workTree: cwd, gitDir:
|
|
17643
|
+
const checkpoints = args.vfs || args.boddb ? new CheckpointStack(agent.options.fs) : new GitCheckpoints({ workTree: cwd, gitDir: join14(cwd, ".agent", "checkpoints.git"), addDirs: args.addDirs, sessionId: session.meta.id });
|
|
17772
17644
|
const cpHooks = checkpoints.hooks?.();
|
|
17773
17645
|
if (cpHooks) {
|
|
17774
17646
|
agent.options.hooks = composeHooks(agent.options.hooks, cpHooks);
|
|
@@ -17820,11 +17692,11 @@ ${lines.join("\n")}
|
|
|
17820
17692
|
Added entries are loadable now via the Skill/SlashCommand tools; removed ones are gone even if still listed in the system prompt.
|
|
17821
17693
|
</system-reminder>`;
|
|
17822
17694
|
};
|
|
17823
|
-
const histPath =
|
|
17695
|
+
const histPath = join14(cwd, ".agent", "history");
|
|
17824
17696
|
const history = existsSync9(histPath) ? readFileSync10(histPath, "utf8").split("\n").filter(Boolean).reverse().slice(0, 500) : [];
|
|
17825
17697
|
const remember2 = (line) => {
|
|
17826
17698
|
try {
|
|
17827
|
-
mkdirSync12(
|
|
17699
|
+
mkdirSync12(join14(cwd, ".agent"), { recursive: true });
|
|
17828
17700
|
appendFileSync(histPath, line + "\n");
|
|
17829
17701
|
} catch (e) {
|
|
17830
17702
|
log34.debug("history write failed", e);
|
|
@@ -18127,8 +17999,8 @@ ${task}`;
|
|
|
18127
17999
|
const wasRaw = process.stdin.isTTY && process.stdin.isRaw;
|
|
18128
18000
|
if (wasRaw) process.stdin.setRawMode(false);
|
|
18129
18001
|
try {
|
|
18130
|
-
const { spawnSync:
|
|
18131
|
-
const r =
|
|
18002
|
+
const { spawnSync: spawnSync7 } = await import("child_process");
|
|
18003
|
+
const r = spawnSync7("less", ["-R"], { input: text, stdio: ["pipe", "inherit", "inherit"] });
|
|
18132
18004
|
if (r.error) err(text);
|
|
18133
18005
|
} finally {
|
|
18134
18006
|
if (wasRaw) process.stdin.setRawMode(true);
|
|
@@ -18148,8 +18020,8 @@ ${task}`;
|
|
|
18148
18020
|
keys.length ? ok(`provider keys: ${keys.join(", ")}`) : bad("no provider keys set (ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY)");
|
|
18149
18021
|
process.env.BODIFY_API_KEY && process.env.BODIFY_APP_ID ? ok(`bodify secrets: ${process.env.BODIFY_APP_ID}`) : warn("bodify secrets: not configured (set BODIFY_API_KEY + BODIFY_APP_ID)");
|
|
18150
18022
|
{
|
|
18151
|
-
const { spawnSync:
|
|
18152
|
-
const has = (cmd) =>
|
|
18023
|
+
const { spawnSync: spawnSync7 } = await import("child_process");
|
|
18024
|
+
const has = (cmd) => spawnSync7("which", [cmd]).status === 0;
|
|
18153
18025
|
if (!VoiceIO.available()) warn("voice: keys missing (SONIOX_API_KEY / CARTESIA_API_KEY / CARTESIA_VOICE_ID) \u2014 voice disabled");
|
|
18154
18026
|
else {
|
|
18155
18027
|
ok("voice: keys present");
|
|
@@ -18170,7 +18042,7 @@ ${task}`;
|
|
|
18170
18042
|
try {
|
|
18171
18043
|
const probe = `${cwd}/.agent/sessions/.doctor-probe`;
|
|
18172
18044
|
mkdirSync12(`${cwd}/.agent/sessions`, { recursive: true });
|
|
18173
|
-
|
|
18045
|
+
writeFileSync9(probe, "ok");
|
|
18174
18046
|
unlinkSync5(probe);
|
|
18175
18047
|
ok(`session store writable (${cwd}/.agent/sessions)`);
|
|
18176
18048
|
} catch (e) {
|
|
@@ -18580,8 +18452,8 @@ ${task}`;
|
|
|
18580
18452
|
const wasRaw = process.stdin.isTTY && process.stdin.isRaw;
|
|
18581
18453
|
if (wasRaw) process.stdin.setRawMode(false);
|
|
18582
18454
|
try {
|
|
18583
|
-
const { spawnSync:
|
|
18584
|
-
|
|
18455
|
+
const { spawnSync: spawnSync7 } = await import("child_process");
|
|
18456
|
+
spawnSync7(ed, [idx], { stdio: "inherit" });
|
|
18585
18457
|
} finally {
|
|
18586
18458
|
if (wasRaw) process.stdin.setRawMode(true);
|
|
18587
18459
|
}
|
|
@@ -18931,11 +18803,11 @@ ${task}`;
|
|
|
18931
18803
|
return;
|
|
18932
18804
|
}
|
|
18933
18805
|
const md = exportMarkdown(session.meta, shown);
|
|
18934
|
-
const name = a[0] ? extname(a[0]) ? a[0] : a[0] + ".md" :
|
|
18806
|
+
const name = a[0] ? extname(a[0]) ? a[0] : a[0] + ".md" : join14(".agent", "exports", `${session.meta.id}.md`);
|
|
18935
18807
|
const path = resolve4(cwd, name);
|
|
18936
18808
|
try {
|
|
18937
18809
|
mkdirSync12(dirname5(path), { recursive: true });
|
|
18938
|
-
|
|
18810
|
+
writeFileSync9(path, md);
|
|
18939
18811
|
err(green(` \u2713 exported \u2192 ${path}
|
|
18940
18812
|
`) + dim(` ${shown.length} message(s) \xB7 ${md.length} chars
|
|
18941
18813
|
`));
|
|
@@ -19017,7 +18889,7 @@ ${task}`;
|
|
|
19017
18889
|
});
|
|
19018
18890
|
const listDir = (absDir) => {
|
|
19019
18891
|
try {
|
|
19020
|
-
return readdirSync4(
|
|
18892
|
+
return readdirSync4(join14(cwd, absDir.replace(/^\/+/, "")), { withFileTypes: true }).map((d) => ({ name: d.name, dir: d.isDirectory() }));
|
|
19021
18893
|
} catch (e) {
|
|
19022
18894
|
log34.debug("completion readdir failed", absDir, e);
|
|
19023
18895
|
return null;
|
|
@@ -19202,7 +19074,7 @@ ${out}
|
|
|
19202
19074
|
return false;
|
|
19203
19075
|
}
|
|
19204
19076
|
const fakeVoice = process.env.AGENTX_VOICE_FAKE ? fakeVoiceParts(process.env.AGENTX_VOICE_FAKE) : null;
|
|
19205
|
-
voiceDiag = new JsonlDiagSink(
|
|
19077
|
+
voiceDiag = new JsonlDiagSink(join14(store.dir, `${session.meta.id}.voice.jsonl`));
|
|
19206
19078
|
voiceIO = new VoiceIO({
|
|
19207
19079
|
...fakeVoice ?? {},
|
|
19208
19080
|
onDiag: (ev) => voiceDiag?.push(ev),
|
|
@@ -19605,7 +19477,7 @@ ${out}
|
|
|
19605
19477
|
}
|
|
19606
19478
|
async function duplexServe(args, ai, cfg, cwd) {
|
|
19607
19479
|
const out = (o) => process.stdout.write(JSON.stringify(o) + "\n");
|
|
19608
|
-
const mounted = await mountMcp(cfg, new McpOAuth({ storePath:
|
|
19480
|
+
const mounted = await mountMcp(cfg, new McpOAuth({ storePath: join14(cwd, ".agent", "mcp-auth.json") }));
|
|
19609
19481
|
installCancelGuards(mounted);
|
|
19610
19482
|
const agent = await makeAgent(args, ai, cfg, mcpAgentTools(mounted, { quiet: true }), mounted.map((m) => m.name));
|
|
19611
19483
|
const { host: _h, stream: _s, signal: _g, providerOptions: _po, ...wo } = agent.options;
|
|
@@ -19787,7 +19659,7 @@ async function main() {
|
|
|
19787
19659
|
}
|
|
19788
19660
|
});
|
|
19789
19661
|
if (args.task) {
|
|
19790
|
-
const mounted = await mountMcp(cfg, new McpOAuth({ storePath:
|
|
19662
|
+
const mounted = await mountMcp(cfg, new McpOAuth({ storePath: join14(cwd, ".agent", "mcp-auth.json") }));
|
|
19791
19663
|
const agent = await makeAgent(args, ai, cfg, mcpAgentTools(mounted), mounted.map((m) => m.name));
|
|
19792
19664
|
const store = new SessionStore(cwd);
|
|
19793
19665
|
const session = startSession(args, store, agent, cwd);
|