@livx.cc/agentx 0.99.73 → 0.99.74
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-Bs2ufrIU.d.ts} +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +155 -293
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +32 -170
- 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
|
}
|
|
@@ -11459,7 +11321,7 @@ import { MemFilesystem as MemFilesystem3, IndexedDbFilesystem, CommandExecutor a
|
|
|
11459
11321
|
// src/mcp.client.ts
|
|
11460
11322
|
init_logging();
|
|
11461
11323
|
import { spawn } from "child_process";
|
|
11462
|
-
import { createHash
|
|
11324
|
+
import { createHash } from "crypto";
|
|
11463
11325
|
var log23 = forComponent("mcp");
|
|
11464
11326
|
var PROTOCOL_VERSION = "2025-06-18";
|
|
11465
11327
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -11865,8 +11727,8 @@ var defaultPool = new McpPool();
|
|
|
11865
11727
|
|
|
11866
11728
|
// cli/mcpOAuth.ts
|
|
11867
11729
|
import { createServer } from "http";
|
|
11868
|
-
import { randomBytes as randomBytes2, createHash as
|
|
11869
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
11730
|
+
import { randomBytes as randomBytes2, createHash as createHash2 } from "crypto";
|
|
11731
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync } from "fs";
|
|
11870
11732
|
import { dirname as dirname2 } from "path";
|
|
11871
11733
|
var McpOAuthOptions = class {
|
|
11872
11734
|
/** Where to persist tokens. Mode 0600. */
|
|
@@ -11901,7 +11763,7 @@ var McpOAuth = class {
|
|
|
11901
11763
|
}
|
|
11902
11764
|
save(store) {
|
|
11903
11765
|
mkdirSync3(dirname2(this.options.storePath), { recursive: true });
|
|
11904
|
-
|
|
11766
|
+
writeFileSync3(this.options.storePath, JSON.stringify(store, null, 2), { mode: 384 });
|
|
11905
11767
|
}
|
|
11906
11768
|
// -- ATTENDED: one-time authorization ----------------------------------------
|
|
11907
11769
|
/** Run the authorization-code + PKCE flow and persist the resulting tokens for `serverUrl`. */
|
|
@@ -11909,7 +11771,7 @@ var McpOAuth = class {
|
|
|
11909
11771
|
const meta = await this.discover(serverUrl);
|
|
11910
11772
|
const clientId = this.options.clientId ?? await this.registerClient(meta, serverUrl);
|
|
11911
11773
|
const verifier = b64url(randomBytes2(32));
|
|
11912
|
-
const challenge = b64url(
|
|
11774
|
+
const challenge = b64url(createHash2("sha256").update(verifier).digest());
|
|
11913
11775
|
const state = b64url(randomBytes2(16));
|
|
11914
11776
|
const { code, redirectUri } = await this.captureCode(meta.authorization_endpoint, clientId, challenge, state);
|
|
11915
11777
|
const tok = await this.exchange(meta.token_endpoint, {
|
|
@@ -12059,9 +11921,9 @@ function defaultOpenBrowser(url) {
|
|
|
12059
11921
|
// cli/core.ts
|
|
12060
11922
|
import { randomUUID } from "crypto";
|
|
12061
11923
|
import { execFile as execFile2 } from "child_process";
|
|
12062
|
-
import { resolve as resolve2, basename, join as
|
|
11924
|
+
import { resolve as resolve2, basename, join as join5 } from "path";
|
|
12063
11925
|
import { existsSync as existsSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
12064
|
-
import { platform, arch, release, userInfo, homedir as homedir2, tmpdir
|
|
11926
|
+
import { platform, arch, release, userInfo, homedir as homedir2, tmpdir } from "os";
|
|
12065
11927
|
init_tools_shell();
|
|
12066
11928
|
|
|
12067
11929
|
// src/tools.notify.ts
|
|
@@ -12249,7 +12111,7 @@ async function buildAgent(o) {
|
|
|
12249
12111
|
} else if (o.boddb) {
|
|
12250
12112
|
const root = resolve2(o.boddb);
|
|
12251
12113
|
mkdirSync4(root, { recursive: true });
|
|
12252
|
-
const db = new BodDB2({ path:
|
|
12114
|
+
const db = new BodDB2({ path: join5(root, "meta.db"), sweepInterval: 0, vfs: { storageRoot: join5(root, "files") } });
|
|
12253
12115
|
const bod = new BodDbFilesystem(db);
|
|
12254
12116
|
const firstRun = (await bod.readDir("/").catch(() => [])).length === 0;
|
|
12255
12117
|
await mkdirp(bod, cwd);
|
|
@@ -12316,7 +12178,7 @@ Reference files in them by their mount path (the left side).`;
|
|
|
12316
12178
|
});
|
|
12317
12179
|
realShell = [makeRealShellTool({ cwd, registry: jobs, osSandbox: o.osSandbox, jobsSurviveRun: o.singleRun !== true }), ...makeShellJobTools(jobs)];
|
|
12318
12180
|
}
|
|
12319
|
-
const scratchDir = o.scratch ? o.scratchDir ?? (virtual ? `${cwd}/.agent/scratch` : `${
|
|
12181
|
+
const scratchDir = o.scratch ? o.scratchDir ?? (virtual ? `${cwd}/.agent/scratch` : `${tmpdir()}/agentx-scratch-${process.pid}`) : void 0;
|
|
12320
12182
|
const scratch = scratchDir ? new Scratch(fs, { dir: scratchDir }) : void 0;
|
|
12321
12183
|
return agentRef.agent = new Agent({
|
|
12322
12184
|
ai: o.ai,
|
|
@@ -12429,10 +12291,10 @@ var trunc = (s, n) => (s == null ? "" : String(s).length > n ? String(s).slice(0
|
|
|
12429
12291
|
|
|
12430
12292
|
// cli/voice.ts
|
|
12431
12293
|
init_logging();
|
|
12432
|
-
import { spawn as spawn2, spawnSync as
|
|
12294
|
+
import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
12433
12295
|
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
12434
12296
|
import { homedir as homedir3 } from "os";
|
|
12435
|
-
import { dirname as dirname3, join as
|
|
12297
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
12436
12298
|
import { fileURLToPath } from "url";
|
|
12437
12299
|
var log27 = forComponent("VoiceIO");
|
|
12438
12300
|
var now3 = () => performance.now();
|
|
@@ -12475,10 +12337,10 @@ var Player = class {
|
|
|
12475
12337
|
this.proc = null;
|
|
12476
12338
|
}
|
|
12477
12339
|
};
|
|
12478
|
-
var nativeDir = () =>
|
|
12340
|
+
var nativeDir = () => join6(dirname3(fileURLToPath(import.meta.url)), "native");
|
|
12479
12341
|
function detectFfmpegMic() {
|
|
12480
12342
|
if (process.env.MIC_DEVICE) return process.env.MIC_DEVICE;
|
|
12481
|
-
const r =
|
|
12343
|
+
const r = spawnSync2("ffmpeg", ["-f", "avfoundation", "-list_devices", "true", "-i", ""], { encoding: "utf8" });
|
|
12482
12344
|
if (r.error?.code === "ENOENT") throw new Error("ffmpeg not installed \u2014 run `brew install ffmpeg` to enable voice");
|
|
12483
12345
|
if (r.error) throw new Error(`ffmpeg failed to run (${r.error.message}) \u2014 likely a wrong-arch binary; run \`brew reinstall ffmpeg\``);
|
|
12484
12346
|
const out = r.stderr ?? "";
|
|
@@ -12492,10 +12354,10 @@ function detectFfmpegMic() {
|
|
|
12492
12354
|
function detectedInputDevice() {
|
|
12493
12355
|
if (process.platform !== "darwin") return null;
|
|
12494
12356
|
let name = "";
|
|
12495
|
-
if (
|
|
12496
|
-
name = (
|
|
12357
|
+
if (spawnSync2("which", ["SwitchAudioSource"]).status === 0) {
|
|
12358
|
+
name = (spawnSync2("SwitchAudioSource", ["-c", "-t", "input"], { encoding: "utf8" }).stdout || "").trim();
|
|
12497
12359
|
} else {
|
|
12498
|
-
const out =
|
|
12360
|
+
const out = spawnSync2("system_profiler", ["SPAudioDataType"], { encoding: "utf8" }).stdout || "";
|
|
12499
12361
|
let last = "";
|
|
12500
12362
|
for (const ln of out.split("\n")) {
|
|
12501
12363
|
const hdr = ln.match(/^\s{6,}(\S.*?):\s*$/);
|
|
@@ -12514,21 +12376,21 @@ function detectedInputDevice() {
|
|
|
12514
12376
|
}
|
|
12515
12377
|
function resolveAecBinary() {
|
|
12516
12378
|
if (process.env.MIC_AEC === "0" || process.platform !== "darwin") return null;
|
|
12517
|
-
const src =
|
|
12518
|
-
const plist =
|
|
12379
|
+
const src = join6(nativeDir(), "mic-aec.swift");
|
|
12380
|
+
const plist = join6(nativeDir(), "Info.plist");
|
|
12519
12381
|
if (!existsSync4(src)) return null;
|
|
12520
|
-
const cacheDir =
|
|
12521
|
-
const bin =
|
|
12382
|
+
const cacheDir = join6(homedir3(), ".agent", "cache");
|
|
12383
|
+
const bin = join6(cacheDir, "mic-aec");
|
|
12522
12384
|
if (existsSync4(bin) && statSync5(bin).mtimeMs >= statSync5(src).mtimeMs) return bin;
|
|
12523
|
-
if (
|
|
12385
|
+
if (spawnSync2("which", ["swiftc"]).status !== 0) return null;
|
|
12524
12386
|
mkdirSync5(cacheDir, { recursive: true });
|
|
12525
12387
|
log27.info("compiling AEC mic helper (first run)\u2026");
|
|
12526
|
-
const build =
|
|
12388
|
+
const build = spawnSync2("swiftc", ["-O", "-o", bin, src, "-Xlinker", "-sectcreate", "-Xlinker", "__TEXT", "-Xlinker", "__info_plist", "-Xlinker", plist], { encoding: "utf8" });
|
|
12527
12389
|
if (build.status !== 0) {
|
|
12528
12390
|
log27.warn(`AEC build failed: ${build.stderr?.slice(0, 400)}`);
|
|
12529
12391
|
return null;
|
|
12530
12392
|
}
|
|
12531
|
-
const sign =
|
|
12393
|
+
const sign = spawnSync2("codesign", ["-fs", "-", bin], { encoding: "utf8" });
|
|
12532
12394
|
if (sign.status !== 0) {
|
|
12533
12395
|
log27.warn(`codesign failed: ${sign.stderr?.slice(0, 200)}`);
|
|
12534
12396
|
return null;
|
|
@@ -12538,14 +12400,14 @@ function resolveAecBinary() {
|
|
|
12538
12400
|
function openMicSettings() {
|
|
12539
12401
|
if (process.platform !== "darwin") return;
|
|
12540
12402
|
try {
|
|
12541
|
-
|
|
12403
|
+
spawnSync2("open", ["x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone"]);
|
|
12542
12404
|
} catch {
|
|
12543
12405
|
}
|
|
12544
12406
|
}
|
|
12545
12407
|
function micPermissionStatus() {
|
|
12546
12408
|
const bin = resolveAecBinary();
|
|
12547
12409
|
if (!bin) return null;
|
|
12548
|
-
const r =
|
|
12410
|
+
const r = spawnSync2(bin, ["--check-mic"], { encoding: "utf8" });
|
|
12549
12411
|
const out = (r.stdout ?? "").trim();
|
|
12550
12412
|
if (out === "authorized") return "authorized";
|
|
12551
12413
|
if (out === "denied" || out === "restricted") return "denied";
|
|
@@ -12555,7 +12417,7 @@ function micPermissionStatus() {
|
|
|
12555
12417
|
function aecUnavailableHint() {
|
|
12556
12418
|
if (process.env.MIC_AEC === "0" || process.platform !== "darwin") return null;
|
|
12557
12419
|
if (resolveAecBinary()) return null;
|
|
12558
|
-
if (
|
|
12420
|
+
if (spawnSync2("which", ["swiftc"]).status !== 0) return "install Xcode CLI tools (`xcode-select --install`) for echo cancellation";
|
|
12559
12421
|
return null;
|
|
12560
12422
|
}
|
|
12561
12423
|
var NodeMicSource = class {
|
|
@@ -12571,7 +12433,7 @@ var NodeMicSource = class {
|
|
|
12571
12433
|
if (this.bin) {
|
|
12572
12434
|
this.proc = spawn2(this.bin, [], { stdio: ["ignore", "pipe", "ignore"] });
|
|
12573
12435
|
} else {
|
|
12574
|
-
if (
|
|
12436
|
+
if (spawnSync2("which", ["ffmpeg"]).status !== 0) throw new Error("voice I/O unavailable: no AEC helper and no ffmpeg on PATH");
|
|
12575
12437
|
log27.info("mic: raw capture (no AEC) \u2014 echo handled heuristically; headphones recommended");
|
|
12576
12438
|
this.proc = spawn2(
|
|
12577
12439
|
"ffmpeg",
|
|
@@ -13020,12 +12882,12 @@ var JsonlDiagSink = class {
|
|
|
13020
12882
|
// cli/config.ts
|
|
13021
12883
|
import { homedir as homedir4 } from "os";
|
|
13022
12884
|
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
13023
|
-
import { join as
|
|
12885
|
+
import { join as join7 } from "path";
|
|
13024
12886
|
import { pathToFileURL } from "url";
|
|
13025
12887
|
var FILES = ["config.ts", "config.js", "config.mjs", "config.json"];
|
|
13026
12888
|
async function loadFrom(dir) {
|
|
13027
12889
|
for (const f of FILES) {
|
|
13028
|
-
const p =
|
|
12890
|
+
const p = join7(dir, ".agent", f);
|
|
13029
12891
|
if (!existsSync5(p)) continue;
|
|
13030
12892
|
try {
|
|
13031
12893
|
const mod = await import(pathToFileURL(p).href, f.endsWith(".json") ? { with: { type: "json" } } : void 0);
|
|
@@ -13038,7 +12900,7 @@ async function loadFrom(dir) {
|
|
|
13038
12900
|
return {};
|
|
13039
12901
|
}
|
|
13040
12902
|
function loadSettings(dir) {
|
|
13041
|
-
const p =
|
|
12903
|
+
const p = join7(dir, ".agent", "settings.json");
|
|
13042
12904
|
if (!existsSync5(p)) return {};
|
|
13043
12905
|
try {
|
|
13044
12906
|
const raw = JSON.parse(readFileSync7(p, "utf8"));
|
|
@@ -13074,7 +12936,7 @@ async function loadConfig(cwd) {
|
|
|
13074
12936
|
}
|
|
13075
12937
|
|
|
13076
12938
|
// cli/hooks-config.ts
|
|
13077
|
-
import { spawnSync as
|
|
12939
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
13078
12940
|
var log29 = forComponent("hooks");
|
|
13079
12941
|
var escapeRegex = (s) => s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13080
12942
|
function ruleMatches(rule, toolName) {
|
|
@@ -13084,7 +12946,7 @@ function ruleMatches(rule, toolName) {
|
|
|
13084
12946
|
}
|
|
13085
12947
|
function runCmd(rule, env) {
|
|
13086
12948
|
try {
|
|
13087
|
-
const r =
|
|
12949
|
+
const r = spawnSync3(rule.command, {
|
|
13088
12950
|
shell: true,
|
|
13089
12951
|
encoding: "utf8",
|
|
13090
12952
|
timeout: rule.timeoutMs ?? 1e4,
|
|
@@ -13196,15 +13058,15 @@ function formatDiff(ops, opts = {}) {
|
|
|
13196
13058
|
}
|
|
13197
13059
|
|
|
13198
13060
|
// cli/session.ts
|
|
13199
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as
|
|
13061
|
+
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
13062
|
import { homedir as homedir5 } from "os";
|
|
13201
|
-
import { join as
|
|
13063
|
+
import { join as join8 } from "path";
|
|
13202
13064
|
var log30 = forComponent("session");
|
|
13203
|
-
var globalDir = () =>
|
|
13065
|
+
var globalDir = () => join8(homedir5(), ".agent", "sessions");
|
|
13204
13066
|
var SessionStore = class {
|
|
13205
13067
|
dir;
|
|
13206
13068
|
constructor(cwd) {
|
|
13207
|
-
this.dir =
|
|
13069
|
+
this.dir = join8(cwd, ".agent", "sessions");
|
|
13208
13070
|
}
|
|
13209
13071
|
/** Sortable, human-readable id: `YYYYMMDD-HHMMSS-<folder>`. */
|
|
13210
13072
|
newId(now4 = Date.now(), cwd) {
|
|
@@ -13212,10 +13074,10 @@ var SessionStore = class {
|
|
|
13212
13074
|
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
13213
13075
|
const slug2 = (cwd ?? process.cwd()).split("/").pop()?.replace(/[^A-Za-z0-9_-]/g, "") || "session";
|
|
13214
13076
|
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(
|
|
13077
|
+
if (existsSync6(this.dir) && existsSync6(join8(this.dir, `${id}.json`))) {
|
|
13216
13078
|
for (let i = 2; i <= 99; i++) {
|
|
13217
13079
|
const c = `${id}-${i}`;
|
|
13218
|
-
if (!existsSync6(
|
|
13080
|
+
if (!existsSync6(join8(this.dir, `${c}.json`))) {
|
|
13219
13081
|
id = c;
|
|
13220
13082
|
break;
|
|
13221
13083
|
}
|
|
@@ -13230,14 +13092,14 @@ var SessionStore = class {
|
|
|
13230
13092
|
save(data) {
|
|
13231
13093
|
if (!this.safeId(data.meta.id)) throw new Error(`unsafe session id: ${data.meta.id}`);
|
|
13232
13094
|
if (!existsSync6(this.dir)) mkdirSync7(this.dir, { recursive: true });
|
|
13233
|
-
const path =
|
|
13095
|
+
const path = join8(this.dir, `${data.meta.id}.json`);
|
|
13234
13096
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
13235
|
-
|
|
13097
|
+
writeFileSync4(tmp, JSON.stringify(data));
|
|
13236
13098
|
renameSync(tmp, path);
|
|
13237
13099
|
try {
|
|
13238
13100
|
const gd = globalDir();
|
|
13239
13101
|
if (!existsSync6(gd)) mkdirSync7(gd, { recursive: true });
|
|
13240
|
-
const link2 =
|
|
13102
|
+
const link2 = join8(gd, `${data.meta.id}.json`);
|
|
13241
13103
|
if (!existsSync6(link2)) symlinkSync2(path, link2);
|
|
13242
13104
|
} catch {
|
|
13243
13105
|
}
|
|
@@ -13247,7 +13109,7 @@ var SessionStore = class {
|
|
|
13247
13109
|
log30.debug(`rejecting unsafe session id: ${id}`);
|
|
13248
13110
|
return void 0;
|
|
13249
13111
|
}
|
|
13250
|
-
const path =
|
|
13112
|
+
const path = join8(this.dir, `${id}.json`);
|
|
13251
13113
|
if (!existsSync6(path)) return void 0;
|
|
13252
13114
|
try {
|
|
13253
13115
|
return JSON.parse(readFileSync8(path, "utf8"));
|
|
@@ -13263,7 +13125,7 @@ var SessionStore = class {
|
|
|
13263
13125
|
for (const f of readdirSync(this.dir)) {
|
|
13264
13126
|
if (!f.endsWith(".json")) continue;
|
|
13265
13127
|
try {
|
|
13266
|
-
metas.push(JSON.parse(readFileSync8(
|
|
13128
|
+
metas.push(JSON.parse(readFileSync8(join8(this.dir, f), "utf8")).meta);
|
|
13267
13129
|
} catch (e) {
|
|
13268
13130
|
log30.debug(`skipping unreadable session file ${f}`, e);
|
|
13269
13131
|
}
|
|
@@ -13278,7 +13140,7 @@ var SessionStore = class {
|
|
|
13278
13140
|
for (const f of readdirSync(this.dir)) {
|
|
13279
13141
|
if (!f.endsWith(".json")) continue;
|
|
13280
13142
|
try {
|
|
13281
|
-
const st = statSync6(
|
|
13143
|
+
const st = statSync6(join8(this.dir, f));
|
|
13282
13144
|
out.push({ id: f.slice(0, -5), mtime: st.mtimeMs, size: st.size });
|
|
13283
13145
|
} catch {
|
|
13284
13146
|
}
|
|
@@ -13297,7 +13159,7 @@ var SessionStore = class {
|
|
|
13297
13159
|
function globalSessionLoad(idOrPrefix) {
|
|
13298
13160
|
const gd = globalDir();
|
|
13299
13161
|
if (!existsSync6(gd)) return void 0;
|
|
13300
|
-
const exact =
|
|
13162
|
+
const exact = join8(gd, `${idOrPrefix}.json`);
|
|
13301
13163
|
if (existsSync6(exact)) {
|
|
13302
13164
|
try {
|
|
13303
13165
|
const target = readlinkSync(exact);
|
|
@@ -13311,7 +13173,7 @@ function globalSessionLoad(idOrPrefix) {
|
|
|
13311
13173
|
if (!f.endsWith(".json")) continue;
|
|
13312
13174
|
const base = f.slice(0, -5);
|
|
13313
13175
|
if (base.includes(idOrPrefix) || base.endsWith(idOrPrefix)) {
|
|
13314
|
-
const target = readlinkSync(
|
|
13176
|
+
const target = readlinkSync(join8(gd, f));
|
|
13315
13177
|
return JSON.parse(readFileSync8(target, "utf8"));
|
|
13316
13178
|
}
|
|
13317
13179
|
}
|
|
@@ -13326,10 +13188,10 @@ function globalSessionList() {
|
|
|
13326
13188
|
for (const f of readdirSync(gd)) {
|
|
13327
13189
|
if (!f.endsWith(".json")) continue;
|
|
13328
13190
|
try {
|
|
13329
|
-
const target = readlinkSync(
|
|
13191
|
+
const target = readlinkSync(join8(gd, f));
|
|
13330
13192
|
if (!existsSync6(target)) {
|
|
13331
13193
|
try {
|
|
13332
|
-
unlinkSync(
|
|
13194
|
+
unlinkSync(join8(gd, f));
|
|
13333
13195
|
} catch {
|
|
13334
13196
|
}
|
|
13335
13197
|
continue;
|
|
@@ -13501,9 +13363,9 @@ ${formatDiff(ops)}`);
|
|
|
13501
13363
|
// cli/gitCheckpoints.ts
|
|
13502
13364
|
import { execFile as execFile3 } from "child_process";
|
|
13503
13365
|
import { promisify } from "util";
|
|
13504
|
-
import { writeFileSync as
|
|
13366
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync8 } from "fs";
|
|
13505
13367
|
import { homedir as homedir6 } from "os";
|
|
13506
|
-
import { join as
|
|
13368
|
+
import { join as join9, resolve as resolve3, sep as sep3, parse as parsePath } from "path";
|
|
13507
13369
|
var log31 = forComponent("checkpoints");
|
|
13508
13370
|
var exec = promisify(execFile3);
|
|
13509
13371
|
var DEFAULT_EXCLUDE = [".agent/", ".git/", "node_modules/", "dist/", "build/", ".next/", "target/", ".venv/", "__pycache__/", "*.log"];
|
|
@@ -13546,8 +13408,8 @@ var ShadowRepo = class {
|
|
|
13546
13408
|
mkdirSync8(this.gitDir, { recursive: true });
|
|
13547
13409
|
const valid = await this.run("rev-parse", "--git-dir").then(() => true, () => false);
|
|
13548
13410
|
if (!valid) await this.run("init", "-q");
|
|
13549
|
-
mkdirSync8(
|
|
13550
|
-
|
|
13411
|
+
mkdirSync8(join9(this.gitDir, "info"), { recursive: true });
|
|
13412
|
+
writeFileSync5(join9(this.gitDir, "info", "exclude"), this.exclude.join("\n") + "\n");
|
|
13551
13413
|
this.ready = true;
|
|
13552
13414
|
} catch (e) {
|
|
13553
13415
|
log31.debug(`git checkpoints unavailable for ${this.workTree}`, e);
|
|
@@ -13662,7 +13524,7 @@ var GitCheckpoints = class {
|
|
|
13662
13524
|
const abs = resolve3(d);
|
|
13663
13525
|
if (abs === cwd || abs.startsWith(cwd + sep3)) continue;
|
|
13664
13526
|
if (cwd.startsWith(abs + sep3)) continue;
|
|
13665
|
-
out.push({ workTree: abs, gitDir:
|
|
13527
|
+
out.push({ workTree: abs, gitDir: join9(abs, ".agent", "checkpoints.git") });
|
|
13666
13528
|
}
|
|
13667
13529
|
return out;
|
|
13668
13530
|
}
|
|
@@ -13805,7 +13667,7 @@ var GitCheckpointsOptions = class {
|
|
|
13805
13667
|
/** Real working tree to snapshot (the launch cwd). */
|
|
13806
13668
|
workTree = process.cwd();
|
|
13807
13669
|
/** Isolated git dir for the cwd shadow repo (kept out of the user's real .git). */
|
|
13808
|
-
gitDir =
|
|
13670
|
+
gitDir = join9(process.cwd(), ".agent", "checkpoints.git");
|
|
13809
13671
|
/** Extra mounted dirs (`--add-dir`); those outside cwd each get their own shadow repo. */
|
|
13810
13672
|
addDirs = [];
|
|
13811
13673
|
/** Conversation id → per-session restore-point ref. */
|
|
@@ -13821,9 +13683,9 @@ var GitCheckpointsOptions = class {
|
|
|
13821
13683
|
};
|
|
13822
13684
|
|
|
13823
13685
|
// cli/permissions.ts
|
|
13824
|
-
import { writeFileSync as
|
|
13686
|
+
import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync9 } from "fs";
|
|
13825
13687
|
import { homedir as homedir7 } from "os";
|
|
13826
|
-
import { join as
|
|
13688
|
+
import { join as join10 } from "path";
|
|
13827
13689
|
var RULE_RE = /^(\w[\w*-]*)(?:\((.+)\))?$/;
|
|
13828
13690
|
function parseOne(raw, decision) {
|
|
13829
13691
|
const m = RULE_RE.exec(raw.trim());
|
|
@@ -13845,13 +13707,13 @@ function parsePermRules(perms, explicit = false) {
|
|
|
13845
13707
|
function describeRule(r) {
|
|
13846
13708
|
return `${r.decision.padEnd(5)} ${r.tool ?? "*"}${r.pathGlob ? `(${r.pathGlob})` : ""}`;
|
|
13847
13709
|
}
|
|
13848
|
-
var PERM_FILE = (cwd) =>
|
|
13710
|
+
var PERM_FILE = (cwd) => join10(cwd, ".agent", "permissions.json");
|
|
13849
13711
|
function loadPersistedRules(cwd) {
|
|
13850
13712
|
const j = readJsonFile(PERM_FILE(cwd), null);
|
|
13851
13713
|
return j ? { allow: j.allow ?? [], ask: j.ask ?? [], deny: j.deny ?? [] } : {};
|
|
13852
13714
|
}
|
|
13853
13715
|
function loadClaudeSettings(cwd, home = homedir7()) {
|
|
13854
|
-
const files = [
|
|
13716
|
+
const files = [join10(home, ".claude", "settings.json"), join10(cwd, ".claude", "settings.json"), join10(cwd, ".claude", "settings.local.json")];
|
|
13855
13717
|
let out = {};
|
|
13856
13718
|
for (const p of files) {
|
|
13857
13719
|
const perms = readJsonFile(p, null)?.permissions;
|
|
@@ -13864,8 +13726,8 @@ function persistRule(cwd, decision, ruleStr) {
|
|
|
13864
13726
|
const list = cur[decision] ??= [];
|
|
13865
13727
|
if (!list.includes(ruleStr)) list.push(ruleStr);
|
|
13866
13728
|
try {
|
|
13867
|
-
mkdirSync9(
|
|
13868
|
-
|
|
13729
|
+
mkdirSync9(join10(cwd, ".agent"), { recursive: true });
|
|
13730
|
+
writeFileSync6(PERM_FILE(cwd), JSON.stringify(cur, null, 2) + "\n");
|
|
13869
13731
|
} catch {
|
|
13870
13732
|
}
|
|
13871
13733
|
}
|
|
@@ -13878,7 +13740,7 @@ function mergePerms(a, b) {
|
|
|
13878
13740
|
}
|
|
13879
13741
|
return Object.keys(out).length ? out : void 0;
|
|
13880
13742
|
}
|
|
13881
|
-
var TRUST_FILE =
|
|
13743
|
+
var TRUST_FILE = join10(homedir7(), ".agent", "trusted.json");
|
|
13882
13744
|
function isTrusted(cwd, file = TRUST_FILE) {
|
|
13883
13745
|
const list = readJsonFile(file, []);
|
|
13884
13746
|
return Array.isArray(list) && list.includes(cwd);
|
|
@@ -13888,8 +13750,8 @@ function trustDir(cwd, file = TRUST_FILE) {
|
|
|
13888
13750
|
if (!Array.isArray(list)) list = [];
|
|
13889
13751
|
if (!list.includes(cwd)) list.push(cwd);
|
|
13890
13752
|
try {
|
|
13891
|
-
mkdirSync9(
|
|
13892
|
-
|
|
13753
|
+
mkdirSync9(join10(file, ".."), { recursive: true });
|
|
13754
|
+
writeFileSync6(file, JSON.stringify(list, null, 2) + "\n");
|
|
13893
13755
|
} catch {
|
|
13894
13756
|
}
|
|
13895
13757
|
}
|
|
@@ -13952,10 +13814,10 @@ function completePath(listDir, ref) {
|
|
|
13952
13814
|
|
|
13953
13815
|
// cli/lineEditor.ts
|
|
13954
13816
|
import { emitKeypressEvents } from "readline";
|
|
13955
|
-
import { spawnSync as
|
|
13956
|
-
import { writeFileSync as
|
|
13957
|
-
import { tmpdir as
|
|
13958
|
-
import { join as
|
|
13817
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
13818
|
+
import { writeFileSync as writeFileSync7, readFileSync as readFileSync9, unlinkSync as unlinkSync2 } from "fs";
|
|
13819
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
13820
|
+
import { join as join11 } from "path";
|
|
13959
13821
|
|
|
13960
13822
|
// cli/bidi.ts
|
|
13961
13823
|
var RTL_RE = /[\u0590-\u05ff\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb1d-\ufdff\ufe70-\ufeff]/;
|
|
@@ -15142,12 +15004,12 @@ function createLineEditor(out, input = keyInput) {
|
|
|
15142
15004
|
function externalEdit(s) {
|
|
15143
15005
|
const spec = process.env.VISUAL || process.env.EDITOR || "vi";
|
|
15144
15006
|
const [cmd, ...cargs] = spec.split(" ").filter(Boolean);
|
|
15145
|
-
const file =
|
|
15007
|
+
const file = join11(tmpdir2(), `agentx-edit-${process.pid}-${Date.now()}.md`);
|
|
15146
15008
|
try {
|
|
15147
|
-
|
|
15009
|
+
writeFileSync7(file, s.buf);
|
|
15148
15010
|
process.stdin.setRawMode(false);
|
|
15149
15011
|
out.write("\x1B[?2004l");
|
|
15150
|
-
const r =
|
|
15012
|
+
const r = spawnSync4(cmd, [...cargs, file], { stdio: "inherit" });
|
|
15151
15013
|
if (r.status === 0) {
|
|
15152
15014
|
const text = readFileSync9(file, "utf8").replace(/\n$/, "");
|
|
15153
15015
|
s.reset();
|
|
@@ -15602,10 +15464,10 @@ function readPlainLine() {
|
|
|
15602
15464
|
}
|
|
15603
15465
|
|
|
15604
15466
|
// cli/osScheduler.ts
|
|
15605
|
-
import { spawnSync as
|
|
15606
|
-
import { writeFileSync as
|
|
15467
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
15468
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync10, readdirSync as readdirSync2, unlinkSync as unlinkSync3, chmodSync, existsSync as existsSync7 } from "fs";
|
|
15607
15469
|
import { homedir as homedir8 } from "os";
|
|
15608
|
-
import { join as
|
|
15470
|
+
import { join as join12 } from "path";
|
|
15609
15471
|
var log32 = forComponent("os-sched");
|
|
15610
15472
|
var OsScheduler = class {
|
|
15611
15473
|
options;
|
|
@@ -15613,13 +15475,13 @@ var OsScheduler = class {
|
|
|
15613
15475
|
this.options = { ...new OsSchedulerOptions(), ...options };
|
|
15614
15476
|
}
|
|
15615
15477
|
get dir() {
|
|
15616
|
-
return
|
|
15478
|
+
return join12(this.options.home, ".agent", "sched");
|
|
15617
15479
|
}
|
|
15618
15480
|
label(id) {
|
|
15619
15481
|
return `cc.livx.agentx.sched-${id}`;
|
|
15620
15482
|
}
|
|
15621
15483
|
plistPath(id) {
|
|
15622
|
-
return
|
|
15484
|
+
return join12(this.options.home, "Library", "LaunchAgents", `${this.label(id)}.plist`);
|
|
15623
15485
|
}
|
|
15624
15486
|
run(cmd, args, input) {
|
|
15625
15487
|
return this.options.exec(cmd, args, input);
|
|
@@ -15635,11 +15497,11 @@ var OsScheduler = class {
|
|
|
15635
15497
|
const script = this.writeScript(spec, oneOff);
|
|
15636
15498
|
const mechanism = this.options.platform === "darwin" ? this.scheduleDarwin(spec, script) : this.scheduleLinux(spec, script, oneOff);
|
|
15637
15499
|
const meta = { ...spec, created: Date.now(), mechanism };
|
|
15638
|
-
|
|
15500
|
+
writeFileSync8(join12(this.dir, `${spec.id}.json`), JSON.stringify(meta, null, 2));
|
|
15639
15501
|
return mechanism;
|
|
15640
15502
|
}
|
|
15641
15503
|
cancel(id) {
|
|
15642
|
-
const meta = readJsonFile(
|
|
15504
|
+
const meta = readJsonFile(join12(this.dir, `${id}.json`), null);
|
|
15643
15505
|
if (!meta) return false;
|
|
15644
15506
|
try {
|
|
15645
15507
|
if (this.options.platform === "darwin") {
|
|
@@ -15672,7 +15534,7 @@ var OsScheduler = class {
|
|
|
15672
15534
|
}
|
|
15673
15535
|
for (const f of [`${id}.json`, `${id}.sh`]) {
|
|
15674
15536
|
try {
|
|
15675
|
-
unlinkSync3(
|
|
15537
|
+
unlinkSync3(join12(this.dir, f));
|
|
15676
15538
|
} catch {
|
|
15677
15539
|
}
|
|
15678
15540
|
}
|
|
@@ -15680,19 +15542,19 @@ var OsScheduler = class {
|
|
|
15680
15542
|
}
|
|
15681
15543
|
list() {
|
|
15682
15544
|
if (!existsSync7(this.dir)) return [];
|
|
15683
|
-
return readdirSync2(this.dir).filter((f) => f.endsWith(".json")).map((f) => readJsonFile(
|
|
15545
|
+
return readdirSync2(this.dir).filter((f) => f.endsWith(".json")).map((f) => readJsonFile(join12(this.dir, f), null)).filter(Boolean);
|
|
15684
15546
|
}
|
|
15685
15547
|
/** The per-job runner script: cd to the project, headless-resume the session, log, notify. */
|
|
15686
15548
|
writeScript(spec, oneOff) {
|
|
15687
|
-
const p =
|
|
15549
|
+
const p = join12(this.dir, `${spec.id}.sh`);
|
|
15688
15550
|
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(
|
|
15551
|
+
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)}
|
|
15552
|
+
` : `rm -f ${q2(join12(this.dir, `${spec.id}.json`))} ${q2(p)}
|
|
15691
15553
|
` : "";
|
|
15692
|
-
|
|
15554
|
+
writeFileSync8(p, `#!/bin/sh
|
|
15693
15555
|
# agentx scheduled job ${spec.id}${spec.label ? ` \u2014 ${spec.label}` : ""}
|
|
15694
15556
|
cd ${q2(spec.cwd)} || exit 1
|
|
15695
|
-
${this.options.agentx} -p ${q2(spec.prompt)} --resume ${q2(spec.sessionId)} --yes >> ${q2(
|
|
15557
|
+
${this.options.agentx} -p ${q2(spec.prompt)} --resume ${q2(spec.sessionId)} --yes >> ${q2(join12(this.dir, `${spec.id}.log`))} 2>&1
|
|
15696
15558
|
${cleanup}`);
|
|
15697
15559
|
chmodSync(p, 493);
|
|
15698
15560
|
return p;
|
|
@@ -15729,8 +15591,8 @@ ${trigger}
|
|
|
15729
15591
|
<key>RunAtLoad</key><false/>
|
|
15730
15592
|
</dict></plist>
|
|
15731
15593
|
`;
|
|
15732
|
-
mkdirSync10(
|
|
15733
|
-
|
|
15594
|
+
mkdirSync10(join12(this.options.home, "Library", "LaunchAgents"), { recursive: true });
|
|
15595
|
+
writeFileSync8(this.plistPath(spec.id), plist);
|
|
15734
15596
|
this.run("launchctl", ["load", this.plistPath(spec.id)]);
|
|
15735
15597
|
return `launchd:${this.label(spec.id)}`;
|
|
15736
15598
|
}
|
|
@@ -15767,7 +15629,7 @@ var OsSchedulerOptions = class {
|
|
|
15767
15629
|
/** Injectable executor for tests. Returns stdout+stderr merged — `at` reports "job N" on STDERR,
|
|
15768
15630
|
* and the job id is what atrm needs for cancel. Throws on non-zero exit. */
|
|
15769
15631
|
exec = (cmd, args, input) => {
|
|
15770
|
-
const r =
|
|
15632
|
+
const r = spawnSync5(cmd, args, { input, encoding: "utf8" });
|
|
15771
15633
|
if (r.error) throw r.error;
|
|
15772
15634
|
if (r.status !== 0) throw new Error(`${cmd} exited ${r.status}: ${r.stderr || r.stdout}`);
|
|
15773
15635
|
return `${r.stdout ?? ""}${r.stderr ?? ""}`;
|
|
@@ -15784,10 +15646,10 @@ import { createServer as createServer2, createConnection } from "net";
|
|
|
15784
15646
|
import { spawn as spawn3 } from "child_process";
|
|
15785
15647
|
import { existsSync as existsSync8, mkdirSync as mkdirSync11, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
|
|
15786
15648
|
import { homedir as homedir9 } from "os";
|
|
15787
|
-
import { join as
|
|
15649
|
+
import { join as join13 } from "path";
|
|
15788
15650
|
var log33 = forComponent("remote-trigger");
|
|
15789
|
-
var TRIGGER_DIR = () =>
|
|
15790
|
-
var sockPath = (sessionId, dir = TRIGGER_DIR()) =>
|
|
15651
|
+
var TRIGGER_DIR = () => join13(homedir9(), ".agent", "triggers");
|
|
15652
|
+
var sockPath = (sessionId, dir = TRIGGER_DIR()) => join13(dir, `${sessionId}.sock`);
|
|
15791
15653
|
var TriggerServer = class {
|
|
15792
15654
|
constructor(onTrigger) {
|
|
15793
15655
|
this.onTrigger = onTrigger;
|
|
@@ -15973,7 +15835,7 @@ async function checkForUpdate(current) {
|
|
|
15973
15835
|
return `Update available: ${current} \u2192 ${latest}. Run \`bun add -g @livx.cc/agentx\` to update.`;
|
|
15974
15836
|
}
|
|
15975
15837
|
function installUpdate() {
|
|
15976
|
-
const r =
|
|
15838
|
+
const r = spawnSync6("bun", ["add", "-g", "@livx.cc/agentx"], { stdio: "inherit" });
|
|
15977
15839
|
return (r.status ?? 1) === 0;
|
|
15978
15840
|
}
|
|
15979
15841
|
var typeaheadOnLine = false;
|
|
@@ -16272,10 +16134,10 @@ function loadEnvFile(file) {
|
|
|
16272
16134
|
}
|
|
16273
16135
|
function loadInstallEnv() {
|
|
16274
16136
|
let dir = dirname5(import.meta.path);
|
|
16275
|
-
for (let i = 0; i < 5 && !existsSync9(
|
|
16137
|
+
for (let i = 0; i < 5 && !existsSync9(join14(dir, "package.json")); i++) dir = dirname5(dir);
|
|
16276
16138
|
for (const name of [".env", ".env.local"]) {
|
|
16277
|
-
loadEnvFile(
|
|
16278
|
-
loadEnvFile(
|
|
16139
|
+
loadEnvFile(join14(dir, name));
|
|
16140
|
+
loadEnvFile(join14(homedir10(), ".agent", name));
|
|
16279
16141
|
}
|
|
16280
16142
|
}
|
|
16281
16143
|
async function loadBodifySecrets() {
|
|
@@ -16999,7 +16861,7 @@ var IMG_EXT = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg"
|
|
|
16999
16861
|
function mentionRefs(line) {
|
|
17000
16862
|
return [...line.matchAll(/(?:^|\s)@(?:"([^"]+)"|(\S+))/g)].map((m) => m[1] ?? m[2].replace(/[?!.,;:)\]}'">]+$/, "")).filter(Boolean);
|
|
17001
16863
|
}
|
|
17002
|
-
var untilde = (p) => p.startsWith("~/") ?
|
|
16864
|
+
var untilde = (p) => p.startsWith("~/") ? join14(homedir10(), p.slice(2)) : p;
|
|
17003
16865
|
function readImageParts(cwd, line) {
|
|
17004
16866
|
const refs = mentionRefs(line);
|
|
17005
16867
|
const parts = [];
|
|
@@ -17203,7 +17065,7 @@ async function runTurn(agent, store, session, task, cp, cwd = process.cwd(), sen
|
|
|
17203
17065
|
}
|
|
17204
17066
|
return { ok, res };
|
|
17205
17067
|
}
|
|
17206
|
-
var remintSessionImages = (data, store, cwd) => remintImageRefs(data.messages, [
|
|
17068
|
+
var remintSessionImages = (data, store, cwd) => remintImageRefs(data.messages, [join14(store.dir, `${data.meta.id}.images`), cwd]);
|
|
17207
17069
|
function startSession(args, store, agent, cwd) {
|
|
17208
17070
|
if (args.resume || args.cont) {
|
|
17209
17071
|
const data = args.resume ? store.load(args.resume) ?? globalSessionLoad(args.resume) : store.latestData();
|
|
@@ -17250,25 +17112,25 @@ var AGENTS_MD_TEMPLATE = `# ${"${name}"}
|
|
|
17250
17112
|
`;
|
|
17251
17113
|
function initInstructions(cwd) {
|
|
17252
17114
|
for (const f of ["AGENTS.md", "CLAUDE.md"]) {
|
|
17253
|
-
if (existsSync9(
|
|
17115
|
+
if (existsSync9(join14(cwd, f))) {
|
|
17254
17116
|
err(yellow(` ${f} already exists \u2014 leaving it as-is
|
|
17255
17117
|
`));
|
|
17256
17118
|
return;
|
|
17257
17119
|
}
|
|
17258
17120
|
}
|
|
17259
|
-
const path =
|
|
17260
|
-
|
|
17121
|
+
const path = join14(cwd, "AGENTS.md");
|
|
17122
|
+
writeFileSync9(path, AGENTS_MD_TEMPLATE.replace("${name}", basename2(cwd)));
|
|
17261
17123
|
err(green(` created ${path}
|
|
17262
17124
|
`) + dim(" edit it, then it auto-loads into every run.\n"));
|
|
17263
17125
|
}
|
|
17264
17126
|
function persistSetting(cwd, key, value) {
|
|
17265
|
-
const path =
|
|
17127
|
+
const path = join14(cwd, ".agent", "settings.json");
|
|
17266
17128
|
try {
|
|
17267
17129
|
const obj = existsSync9(path) ? JSON.parse(readFileSync10(path, "utf8")) : {};
|
|
17268
17130
|
if (obj[key] === value) return;
|
|
17269
17131
|
obj[key] = value;
|
|
17270
17132
|
mkdirSync12(dirname5(path), { recursive: true });
|
|
17271
|
-
|
|
17133
|
+
writeFileSync9(path, JSON.stringify(obj, null, 2) + "\n");
|
|
17272
17134
|
} catch (e) {
|
|
17273
17135
|
err(yellow(` \u26A0 couldn't persist ${key} to ${path} \u2014 ${e?.message ?? e}
|
|
17274
17136
|
`));
|
|
@@ -17300,7 +17162,7 @@ function installCancelGuards(mounted) {
|
|
|
17300
17162
|
});
|
|
17301
17163
|
}
|
|
17302
17164
|
async function repl(args, ai, cfg, cwd) {
|
|
17303
|
-
const oauth = new McpOAuth({ storePath:
|
|
17165
|
+
const oauth = new McpOAuth({ storePath: join14(cwd, ".agent", "mcp-auth.json") });
|
|
17304
17166
|
const mounted = await mountMcp(cfg, oauth);
|
|
17305
17167
|
let mcpToolNames = [];
|
|
17306
17168
|
const initialMcpTools = mcpAgentTools(mounted);
|
|
@@ -17576,7 +17438,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
17576
17438
|
quickLook: {
|
|
17577
17439
|
branch: () => {
|
|
17578
17440
|
try {
|
|
17579
|
-
const head = readFileSync10(
|
|
17441
|
+
const head = readFileSync10(join14(cwd, ".git", "HEAD"), "utf8").trim();
|
|
17580
17442
|
return head.startsWith("ref: refs/heads/") ? `branch: ${head.slice("ref: refs/heads/".length)}` : `detached HEAD at ${head.slice(0, 12)}`;
|
|
17581
17443
|
} catch {
|
|
17582
17444
|
return "not a git repository";
|
|
@@ -17710,7 +17572,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
17710
17572
|
const pendingImages = [];
|
|
17711
17573
|
const bangContext = [];
|
|
17712
17574
|
const grabClipboardAttachment = () => {
|
|
17713
|
-
const dir =
|
|
17575
|
+
const dir = join14(store.dir, `${session.meta.id}.images`);
|
|
17714
17576
|
try {
|
|
17715
17577
|
mkdirSync12(dir, { recursive: true });
|
|
17716
17578
|
} catch (e) {
|
|
@@ -17768,7 +17630,7 @@ async function repl(args, ai, cfg, cwd) {
|
|
|
17768
17630
|
err(dim(` \u23F0 ${scheduler.size} scheduled job(s) re-armed
|
|
17769
17631
|
`));
|
|
17770
17632
|
}
|
|
17771
|
-
const checkpoints = args.vfs || args.boddb ? new CheckpointStack(agent.options.fs) : new GitCheckpoints({ workTree: cwd, gitDir:
|
|
17633
|
+
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
17634
|
const cpHooks = checkpoints.hooks?.();
|
|
17773
17635
|
if (cpHooks) {
|
|
17774
17636
|
agent.options.hooks = composeHooks(agent.options.hooks, cpHooks);
|
|
@@ -17820,11 +17682,11 @@ ${lines.join("\n")}
|
|
|
17820
17682
|
Added entries are loadable now via the Skill/SlashCommand tools; removed ones are gone even if still listed in the system prompt.
|
|
17821
17683
|
</system-reminder>`;
|
|
17822
17684
|
};
|
|
17823
|
-
const histPath =
|
|
17685
|
+
const histPath = join14(cwd, ".agent", "history");
|
|
17824
17686
|
const history = existsSync9(histPath) ? readFileSync10(histPath, "utf8").split("\n").filter(Boolean).reverse().slice(0, 500) : [];
|
|
17825
17687
|
const remember2 = (line) => {
|
|
17826
17688
|
try {
|
|
17827
|
-
mkdirSync12(
|
|
17689
|
+
mkdirSync12(join14(cwd, ".agent"), { recursive: true });
|
|
17828
17690
|
appendFileSync(histPath, line + "\n");
|
|
17829
17691
|
} catch (e) {
|
|
17830
17692
|
log34.debug("history write failed", e);
|
|
@@ -18127,8 +17989,8 @@ ${task}`;
|
|
|
18127
17989
|
const wasRaw = process.stdin.isTTY && process.stdin.isRaw;
|
|
18128
17990
|
if (wasRaw) process.stdin.setRawMode(false);
|
|
18129
17991
|
try {
|
|
18130
|
-
const { spawnSync:
|
|
18131
|
-
const r =
|
|
17992
|
+
const { spawnSync: spawnSync7 } = await import("child_process");
|
|
17993
|
+
const r = spawnSync7("less", ["-R"], { input: text, stdio: ["pipe", "inherit", "inherit"] });
|
|
18132
17994
|
if (r.error) err(text);
|
|
18133
17995
|
} finally {
|
|
18134
17996
|
if (wasRaw) process.stdin.setRawMode(true);
|
|
@@ -18148,8 +18010,8 @@ ${task}`;
|
|
|
18148
18010
|
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
18011
|
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
18012
|
{
|
|
18151
|
-
const { spawnSync:
|
|
18152
|
-
const has = (cmd) =>
|
|
18013
|
+
const { spawnSync: spawnSync7 } = await import("child_process");
|
|
18014
|
+
const has = (cmd) => spawnSync7("which", [cmd]).status === 0;
|
|
18153
18015
|
if (!VoiceIO.available()) warn("voice: keys missing (SONIOX_API_KEY / CARTESIA_API_KEY / CARTESIA_VOICE_ID) \u2014 voice disabled");
|
|
18154
18016
|
else {
|
|
18155
18017
|
ok("voice: keys present");
|
|
@@ -18170,7 +18032,7 @@ ${task}`;
|
|
|
18170
18032
|
try {
|
|
18171
18033
|
const probe = `${cwd}/.agent/sessions/.doctor-probe`;
|
|
18172
18034
|
mkdirSync12(`${cwd}/.agent/sessions`, { recursive: true });
|
|
18173
|
-
|
|
18035
|
+
writeFileSync9(probe, "ok");
|
|
18174
18036
|
unlinkSync5(probe);
|
|
18175
18037
|
ok(`session store writable (${cwd}/.agent/sessions)`);
|
|
18176
18038
|
} catch (e) {
|
|
@@ -18580,8 +18442,8 @@ ${task}`;
|
|
|
18580
18442
|
const wasRaw = process.stdin.isTTY && process.stdin.isRaw;
|
|
18581
18443
|
if (wasRaw) process.stdin.setRawMode(false);
|
|
18582
18444
|
try {
|
|
18583
|
-
const { spawnSync:
|
|
18584
|
-
|
|
18445
|
+
const { spawnSync: spawnSync7 } = await import("child_process");
|
|
18446
|
+
spawnSync7(ed, [idx], { stdio: "inherit" });
|
|
18585
18447
|
} finally {
|
|
18586
18448
|
if (wasRaw) process.stdin.setRawMode(true);
|
|
18587
18449
|
}
|
|
@@ -18931,11 +18793,11 @@ ${task}`;
|
|
|
18931
18793
|
return;
|
|
18932
18794
|
}
|
|
18933
18795
|
const md = exportMarkdown(session.meta, shown);
|
|
18934
|
-
const name = a[0] ? extname(a[0]) ? a[0] : a[0] + ".md" :
|
|
18796
|
+
const name = a[0] ? extname(a[0]) ? a[0] : a[0] + ".md" : join14(".agent", "exports", `${session.meta.id}.md`);
|
|
18935
18797
|
const path = resolve4(cwd, name);
|
|
18936
18798
|
try {
|
|
18937
18799
|
mkdirSync12(dirname5(path), { recursive: true });
|
|
18938
|
-
|
|
18800
|
+
writeFileSync9(path, md);
|
|
18939
18801
|
err(green(` \u2713 exported \u2192 ${path}
|
|
18940
18802
|
`) + dim(` ${shown.length} message(s) \xB7 ${md.length} chars
|
|
18941
18803
|
`));
|
|
@@ -19017,7 +18879,7 @@ ${task}`;
|
|
|
19017
18879
|
});
|
|
19018
18880
|
const listDir = (absDir) => {
|
|
19019
18881
|
try {
|
|
19020
|
-
return readdirSync4(
|
|
18882
|
+
return readdirSync4(join14(cwd, absDir.replace(/^\/+/, "")), { withFileTypes: true }).map((d) => ({ name: d.name, dir: d.isDirectory() }));
|
|
19021
18883
|
} catch (e) {
|
|
19022
18884
|
log34.debug("completion readdir failed", absDir, e);
|
|
19023
18885
|
return null;
|
|
@@ -19202,7 +19064,7 @@ ${out}
|
|
|
19202
19064
|
return false;
|
|
19203
19065
|
}
|
|
19204
19066
|
const fakeVoice = process.env.AGENTX_VOICE_FAKE ? fakeVoiceParts(process.env.AGENTX_VOICE_FAKE) : null;
|
|
19205
|
-
voiceDiag = new JsonlDiagSink(
|
|
19067
|
+
voiceDiag = new JsonlDiagSink(join14(store.dir, `${session.meta.id}.voice.jsonl`));
|
|
19206
19068
|
voiceIO = new VoiceIO({
|
|
19207
19069
|
...fakeVoice ?? {},
|
|
19208
19070
|
onDiag: (ev) => voiceDiag?.push(ev),
|
|
@@ -19605,7 +19467,7 @@ ${out}
|
|
|
19605
19467
|
}
|
|
19606
19468
|
async function duplexServe(args, ai, cfg, cwd) {
|
|
19607
19469
|
const out = (o) => process.stdout.write(JSON.stringify(o) + "\n");
|
|
19608
|
-
const mounted = await mountMcp(cfg, new McpOAuth({ storePath:
|
|
19470
|
+
const mounted = await mountMcp(cfg, new McpOAuth({ storePath: join14(cwd, ".agent", "mcp-auth.json") }));
|
|
19609
19471
|
installCancelGuards(mounted);
|
|
19610
19472
|
const agent = await makeAgent(args, ai, cfg, mcpAgentTools(mounted, { quiet: true }), mounted.map((m) => m.name));
|
|
19611
19473
|
const { host: _h, stream: _s, signal: _g, providerOptions: _po, ...wo } = agent.options;
|
|
@@ -19787,7 +19649,7 @@ async function main() {
|
|
|
19787
19649
|
}
|
|
19788
19650
|
});
|
|
19789
19651
|
if (args.task) {
|
|
19790
|
-
const mounted = await mountMcp(cfg, new McpOAuth({ storePath:
|
|
19652
|
+
const mounted = await mountMcp(cfg, new McpOAuth({ storePath: join14(cwd, ".agent", "mcp-auth.json") }));
|
|
19791
19653
|
const agent = await makeAgent(args, ai, cfg, mcpAgentTools(mounted), mounted.map((m) => m.name));
|
|
19792
19654
|
const store = new SessionStore(cwd);
|
|
19793
19655
|
const session = startSession(args, store, agent, cwd);
|