@wirecat/mail-cli 0.0.0-stage → 0.1.1

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.
Files changed (198) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/LICENSE +204 -0
  3. package/README.md +166 -2
  4. package/dist/bin/mail.d.ts +3 -0
  5. package/dist/bin/mail.d.ts.map +1 -0
  6. package/dist/bin/mail.js +36 -0
  7. package/dist/bin/mail.js.map +1 -0
  8. package/dist/bundle/all-profiles-TKMBELRZ.js +286 -0
  9. package/dist/bundle/anthropic-7LMUAEIZ.js +72 -0
  10. package/dist/bundle/app-server-JGMIJDD4.js +229 -0
  11. package/dist/bundle/bun-XRO6XJHQ.js +169 -0
  12. package/dist/bundle/bun-sqlite-Z54LEHVM.js +71 -0
  13. package/dist/bundle/chunk-2LLNPNMB.js +24 -0
  14. package/dist/bundle/chunk-3E3WA2L6.js +1932 -0
  15. package/dist/bundle/chunk-3KEVLSNN.js +138 -0
  16. package/dist/bundle/chunk-3KOA73LS.js +3416 -0
  17. package/dist/bundle/chunk-4E7BN3TC.js +122 -0
  18. package/dist/bundle/chunk-4FEMINO2.js +409 -0
  19. package/dist/bundle/chunk-52F5DWS5.js +27 -0
  20. package/dist/bundle/chunk-5BVIWP3S.js +71 -0
  21. package/dist/bundle/chunk-5D4AEUVA.js +24783 -0
  22. package/dist/bundle/chunk-5NYMNSSO.js +264 -0
  23. package/dist/bundle/chunk-6MAZWSC3.js +132 -0
  24. package/dist/bundle/chunk-75CWWETH.js +379 -0
  25. package/dist/bundle/chunk-7SXGLT6T.js +444 -0
  26. package/dist/bundle/chunk-BTQX2ZSZ.js +288 -0
  27. package/dist/bundle/chunk-CEW6KIFA.js +1193 -0
  28. package/dist/bundle/chunk-CH6RXYAX.js +82 -0
  29. package/dist/bundle/chunk-D72URWJE.js +532 -0
  30. package/dist/bundle/chunk-DFDN6AUB.js +21 -0
  31. package/dist/bundle/chunk-EOEDICIE.js +6848 -0
  32. package/dist/bundle/chunk-F6D6PJ34.js +100 -0
  33. package/dist/bundle/chunk-FDCGTODC.js +78 -0
  34. package/dist/bundle/chunk-FZ5FXIG6.js +18 -0
  35. package/dist/bundle/chunk-GAH7N7HO.js +8181 -0
  36. package/dist/bundle/chunk-GK4M2SUP.js +195 -0
  37. package/dist/bundle/chunk-GN62YOT5.js +161 -0
  38. package/dist/bundle/chunk-GQQJOH7A.js +7050 -0
  39. package/dist/bundle/chunk-GWDCKUBI.js +781 -0
  40. package/dist/bundle/chunk-HTQTIKWP.js +928 -0
  41. package/dist/bundle/chunk-IK5TH3O7.js +217 -0
  42. package/dist/bundle/chunk-J3QXTBD2.js +2742 -0
  43. package/dist/bundle/chunk-J6MSJLIW.js +45 -0
  44. package/dist/bundle/chunk-JBBZCTTF.js +76 -0
  45. package/dist/bundle/chunk-JVMVLITS.js +260 -0
  46. package/dist/bundle/chunk-K4FVKPDQ.js +525 -0
  47. package/dist/bundle/chunk-KHTO2Q6E.js +886 -0
  48. package/dist/bundle/chunk-KM7Q67Z3.js +63 -0
  49. package/dist/bundle/chunk-LQ37ALDJ.js +2416 -0
  50. package/dist/bundle/chunk-MNOIRJEO.js +2315 -0
  51. package/dist/bundle/chunk-MS53RALV.js +168 -0
  52. package/dist/bundle/chunk-NK7EB63L.js +36225 -0
  53. package/dist/bundle/chunk-NPGVOZVK.js +2 -0
  54. package/dist/bundle/chunk-OTUOZ33L.js +82 -0
  55. package/dist/bundle/chunk-P7P5MNAU.js +46 -0
  56. package/dist/bundle/chunk-QLEUNU6G.js +537 -0
  57. package/dist/bundle/chunk-QQB7WT7R.js +216 -0
  58. package/dist/bundle/chunk-QX7RCLRS.js +23 -0
  59. package/dist/bundle/chunk-T6464KYA.js +35130 -0
  60. package/dist/bundle/chunk-TE5U5OAM.js +73 -0
  61. package/dist/bundle/chunk-TI6VBZKJ.js +166 -0
  62. package/dist/bundle/chunk-TQFCPUIM.js +53 -0
  63. package/dist/bundle/chunk-TVREDYX4.js +3574 -0
  64. package/dist/bundle/chunk-TWPDVUBR.js +106 -0
  65. package/dist/bundle/chunk-TWTATDM7.js +461 -0
  66. package/dist/bundle/chunk-UH4DDRHA.js +2989 -0
  67. package/dist/bundle/chunk-VEIZZRQ5.js +630 -0
  68. package/dist/bundle/chunk-WLFLBWNH.js +54 -0
  69. package/dist/bundle/chunk-WXAXYJJ7.js +486 -0
  70. package/dist/bundle/chunk-XQUUANA2.js +24600 -0
  71. package/dist/bundle/chunk-Y5E2WNWB.js +35 -0
  72. package/dist/bundle/chunk-YO4CUH5E.js +33 -0
  73. package/dist/bundle/chunk-YPQQ5J4X.js +849 -0
  74. package/dist/bundle/chunk-Z34ICZA3.js +1028 -0
  75. package/dist/bundle/chunk-ZANYM66S.js +58 -0
  76. package/dist/bundle/chunk-ZD3WUGR2.js +142 -0
  77. package/dist/bundle/chunk-ZVVMGPBJ.js +50 -0
  78. package/dist/bundle/command-contract-WU434ZUL.js +34 -0
  79. package/dist/bundle/decode-YB3ZDTES.js +162 -0
  80. package/dist/bundle/dispatch-EUKKT3PD.js +411 -0
  81. package/dist/bundle/dist-A6GKSKFC.js +2072 -0
  82. package/dist/bundle/dist-HFUVURJG.js +7577 -0
  83. package/dist/bundle/echarts-YNGCOYHW.js +42501 -0
  84. package/dist/bundle/embed-LWNHIRBQ.js +37 -0
  85. package/dist/bundle/embedder-2LYD3U37.js +110 -0
  86. package/dist/bundle/failure-OAIC5VAP.js +24 -0
  87. package/dist/bundle/first-run-N3HJKGU7.js +27 -0
  88. package/dist/bundle/first-screen-4U2DMV3G.js +32 -0
  89. package/dist/bundle/instructions-GJHHFV64.js +11 -0
  90. package/dist/bundle/mail.js +166 -0
  91. package/dist/bundle/mcp-L7SRVDRN.js +167 -0
  92. package/dist/bundle/node-GFOH6FKP.js +176 -0
  93. package/dist/bundle/node-KM3CUABH.js +2340 -0
  94. package/dist/bundle/node-TLZSIHIJ.js +21 -0
  95. package/dist/bundle/node-sqlite-NBXQXBIU.js +63 -0
  96. package/dist/bundle/oauth-56EFO5AQ.js +19 -0
  97. package/dist/bundle/open-2V7QZQJP.js +21 -0
  98. package/dist/bundle/openai-V3SVACVL.js +251 -0
  99. package/dist/bundle/process-XVDX4SPD.js +91 -0
  100. package/dist/bundle/program-JTJB26P3.js +35542 -0
  101. package/dist/bundle/prompt-YKWAI222.js +14 -0
  102. package/dist/bundle/recognize-PAR66KVM.js +25 -0
  103. package/dist/bundle/remote-CE43TKXC.js +28 -0
  104. package/dist/bundle/rerank-M7S7P2TW.js +51 -0
  105. package/dist/bundle/serve-ENPMIV6J.js +197 -0
  106. package/dist/bundle/server-JRTHUCVY.js +63 -0
  107. package/dist/bundle/server-MBEZLVKZ.js +189 -0
  108. package/dist/bundle/sqlite-runtime-HVGDHBJJ.js +18 -0
  109. package/dist/bundle/state-QZSOSKBD.js +35 -0
  110. package/dist/bundle/store-2BUX6LVX.js +124 -0
  111. package/dist/bundle/store-UJ7SNKXI.js +141 -0
  112. package/dist/bundle/store-maintenance-command-I7V5C44K.js +52 -0
  113. package/dist/commands/account.d.ts +3 -0
  114. package/dist/commands/account.d.ts.map +1 -0
  115. package/dist/commands/account.js +47 -0
  116. package/dist/commands/account.js.map +1 -0
  117. package/dist/commands/context.d.ts +41 -0
  118. package/dist/commands/context.d.ts.map +1 -0
  119. package/dist/commands/context.js +52 -0
  120. package/dist/commands/context.js.map +1 -0
  121. package/dist/commands/folders.d.ts +3 -0
  122. package/dist/commands/folders.d.ts.map +1 -0
  123. package/dist/commands/folders.js +36 -0
  124. package/dist/commands/folders.js.map +1 -0
  125. package/dist/commands/login.d.ts +5 -0
  126. package/dist/commands/login.d.ts.map +1 -0
  127. package/dist/commands/login.js +21 -0
  128. package/dist/commands/login.js.map +1 -0
  129. package/dist/commands/mailbox.d.ts +16 -0
  130. package/dist/commands/mailbox.d.ts.map +1 -0
  131. package/dist/commands/mailbox.js +54 -0
  132. package/dist/commands/mailbox.js.map +1 -0
  133. package/dist/commands/session.d.ts +3 -0
  134. package/dist/commands/session.d.ts.map +1 -0
  135. package/dist/commands/session.js +211 -0
  136. package/dist/commands/session.js.map +1 -0
  137. package/dist/commands/status.d.ts +3 -0
  138. package/dist/commands/status.d.ts.map +1 -0
  139. package/dist/commands/status.js +89 -0
  140. package/dist/commands/status.js.map +1 -0
  141. package/dist/commands/sync.d.ts +3 -0
  142. package/dist/commands/sync.d.ts.map +1 -0
  143. package/dist/commands/sync.js +190 -0
  144. package/dist/commands/sync.js.map +1 -0
  145. package/dist/config.d.ts +190 -0
  146. package/dist/config.d.ts.map +1 -0
  147. package/dist/config.js +46 -0
  148. package/dist/config.js.map +1 -0
  149. package/dist/discovery.d.ts +42 -0
  150. package/dist/discovery.d.ts.map +1 -0
  151. package/dist/discovery.js +179 -0
  152. package/dist/discovery.js.map +1 -0
  153. package/dist/identity.d.ts +5 -0
  154. package/dist/identity.d.ts.map +1 -0
  155. package/dist/identity.js +16 -0
  156. package/dist/identity.js.map +1 -0
  157. package/dist/index.d.ts +3 -0
  158. package/dist/index.d.ts.map +1 -0
  159. package/dist/index.js +3 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/mail/imap-errors.d.ts +4 -0
  162. package/dist/mail/imap-errors.d.ts.map +1 -0
  163. package/dist/mail/imap-errors.js +41 -0
  164. package/dist/mail/imap-errors.js.map +1 -0
  165. package/dist/mail/imap-messages.d.ts +18 -0
  166. package/dist/mail/imap-messages.d.ts.map +1 -0
  167. package/dist/mail/imap-messages.js +66 -0
  168. package/dist/mail/imap-messages.js.map +1 -0
  169. package/dist/mail/imap.d.ts +67 -0
  170. package/dist/mail/imap.d.ts.map +1 -0
  171. package/dist/mail/imap.js +348 -0
  172. package/dist/mail/imap.js.map +1 -0
  173. package/dist/profile.d.ts +16 -0
  174. package/dist/profile.d.ts.map +1 -0
  175. package/dist/profile.js +31 -0
  176. package/dist/profile.js.map +1 -0
  177. package/dist/program.d.ts +6 -0
  178. package/dist/program.d.ts.map +1 -0
  179. package/dist/program.js +52 -0
  180. package/dist/program.js.map +1 -0
  181. package/dist/providers.d.ts +53 -0
  182. package/dist/providers.d.ts.map +1 -0
  183. package/dist/providers.js +106 -0
  184. package/dist/providers.js.map +1 -0
  185. package/dist/secret.d.ts +30 -0
  186. package/dist/secret.d.ts.map +1 -0
  187. package/dist/secret.js +68 -0
  188. package/dist/secret.js.map +1 -0
  189. package/dist/store.d.ts +12 -0
  190. package/dist/store.d.ts.map +1 -0
  191. package/dist/store.js +25 -0
  192. package/dist/store.js.map +1 -0
  193. package/dist/version.d.ts +2 -0
  194. package/dist/version.d.ts.map +1 -0
  195. package/dist/version.js +2 -0
  196. package/dist/version.js.map +1 -0
  197. package/package.json +83 -4
  198. package/skills/mail-cli/SKILL.md +27 -0
@@ -0,0 +1,2340 @@
1
+ import { createRequire as __bundleRequire } from "node:module";
2
+ const require = __bundleRequire(import.meta.url);
3
+ import {
4
+ AnthropicError,
5
+ DEFAULT_MEMORY_SYNC_INTERVAL_MS,
6
+ MIN_MEMORY_SYNC_INTERVAL_MS,
7
+ ToolError,
8
+ __classPrivateFieldGet,
9
+ __classPrivateFieldSet,
10
+ checkMemorySyncInterval,
11
+ decodeUTF8,
12
+ encodeUTF8,
13
+ isStatus,
14
+ loggerFor,
15
+ promiseWithResolvers
16
+ } from "./chunk-XQUUANA2.js";
17
+ import {
18
+ child_process,
19
+ crypto,
20
+ fs,
21
+ path,
22
+ stream,
23
+ util
24
+ } from "./chunk-DFDN6AUB.js";
25
+ import {
26
+ __name
27
+ } from "./chunk-ZVVMGPBJ.js";
28
+
29
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/tools/agent-toolset/node.mjs
30
+ import * as fs4 from "node:fs/promises";
31
+ import * as fssync from "node:fs";
32
+ import * as path2 from "node:path";
33
+ import * as cp from "node:child_process";
34
+ import * as crypto2 from "node:crypto";
35
+ import * as readline from "node:readline";
36
+
37
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/helpers/beta/json-schema.mjs
38
+ function betaTool(options) {
39
+ const { name, inputSchema, description, run, ...extraProps } = options;
40
+ if (inputSchema.type !== "object") {
41
+ throw new Error(`JSON schema for tool "${name}" must be an object, but got ${inputSchema.type}`);
42
+ }
43
+ return {
44
+ ...extraProps,
45
+ type: "custom",
46
+ name,
47
+ input_schema: inputSchema,
48
+ description,
49
+ run,
50
+ parse: /* @__PURE__ */ __name((content) => content, "parse")
51
+ };
52
+ }
53
+ __name(betaTool, "betaTool");
54
+
55
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/tools/agent-toolset/fs-util.mjs
56
+ var fs2 = fs.promises;
57
+ var DIR_CREATE_MODE = 448;
58
+ var FILE_CREATE_MODE = 384;
59
+ function isWithin(root, p) {
60
+ const rel = path.relative(root, p);
61
+ return rel === "" || !rel.startsWith(".." + path.sep) && rel !== ".." && !path.isAbsolute(rel);
62
+ }
63
+ __name(isWithin, "isWithin");
64
+ async function containingRoot(roots, target) {
65
+ for (const root of roots) {
66
+ if (isWithin(await canonicalize(path.resolve(root)), target))
67
+ return root;
68
+ }
69
+ return void 0;
70
+ }
71
+ __name(containingRoot, "containingRoot");
72
+ var MAX_SYMLINK_HOPS = 40;
73
+ function errnoCode(err) {
74
+ const code = err?.code;
75
+ return typeof code === "string" ? code : void 0;
76
+ }
77
+ __name(errnoCode, "errnoCode");
78
+ async function canonicalize(abs) {
79
+ const tail = [];
80
+ let prefix = abs;
81
+ let hops = 0;
82
+ for (; ; ) {
83
+ let real;
84
+ try {
85
+ real = await fs2.realpath(prefix);
86
+ } catch (realpathErr) {
87
+ let isLink;
88
+ try {
89
+ isLink = (await fs2.lstat(prefix)).isSymbolicLink();
90
+ } catch (lstatErr) {
91
+ const code = errnoCode(lstatErr);
92
+ if (code !== "ENOENT" && code !== "ENOTDIR")
93
+ throw lstatErr;
94
+ const parent = path.dirname(prefix);
95
+ if (parent === prefix)
96
+ throw lstatErr;
97
+ tail.push(path.basename(prefix));
98
+ prefix = parent;
99
+ continue;
100
+ }
101
+ if (!isLink)
102
+ throw realpathErr;
103
+ if (++hops > MAX_SYMLINK_HOPS) {
104
+ throw Object.assign(new Error("too many levels of symbolic links"), { code: "ELOOP" });
105
+ }
106
+ prefix = path.resolve(path.dirname(prefix), await fs2.readlink(prefix));
107
+ continue;
108
+ }
109
+ return tail.length ? path.join(real, ...tail.reverse()) : real;
110
+ }
111
+ }
112
+ __name(canonicalize, "canonicalize");
113
+ async function confineToRoot(root, p, opts) {
114
+ const allowedRoots = opts?.allowedRoots ?? [];
115
+ const realRoot = await canonicalize(path.resolve(root));
116
+ let real;
117
+ try {
118
+ real = await canonicalize(path.resolve(realRoot, p));
119
+ } catch (err) {
120
+ throw new ToolError(fsErrorMessage(err, `path ${JSON.stringify(p)}`));
121
+ }
122
+ if (isWithin(realRoot, real) || await containingRoot(allowedRoots, real) !== void 0) {
123
+ return real;
124
+ }
125
+ const permitted = allowedRoots.length ? "the session's working directory and its other permitted directories" : "the session's working directory";
126
+ throw new ToolError(`path ${JSON.stringify(p)} is outside ${permitted}`);
127
+ }
128
+ __name(confineToRoot, "confineToRoot");
129
+ async function atomicWriteFile(targetPath, content) {
130
+ const dir = path.dirname(targetPath);
131
+ const tempPath = path.join(dir, `.tmp-${process.pid}-${crypto.randomUUID()}`);
132
+ const existingMode = await fs2.stat(targetPath).then((st) => st.mode & 511, () => void 0);
133
+ let handle;
134
+ try {
135
+ handle = await fs2.open(tempPath, "wx", FILE_CREATE_MODE);
136
+ if (existingMode !== void 0)
137
+ await handle.chmod(existingMode);
138
+ await handle.writeFile(content, "utf-8");
139
+ await handle.sync();
140
+ await handle.close();
141
+ handle = void 0;
142
+ await fs2.rename(tempPath, targetPath);
143
+ } catch (err) {
144
+ if (handle)
145
+ await handle.close().catch(() => {
146
+ });
147
+ await fs2.unlink(tempPath).catch(() => {
148
+ });
149
+ throw err;
150
+ }
151
+ }
152
+ __name(atomicWriteFile, "atomicWriteFile");
153
+ function fsErrorMessage(err, file) {
154
+ const code = errnoCode(err);
155
+ switch (code) {
156
+ case "ENOENT":
157
+ return `${file}: no such file or directory`;
158
+ case "EACCES":
159
+ case "EPERM":
160
+ return `${file}: permission denied`;
161
+ case "ENOTDIR":
162
+ return `${file}: not a directory`;
163
+ case "EISDIR":
164
+ return `${file}: is a directory`;
165
+ case "ELOOP":
166
+ return `${file}: too many levels of symbolic links`;
167
+ case "ENAMETOOLONG":
168
+ return `${file}: file name too long`;
169
+ case "ENOSPC":
170
+ return `${file}: no space left on device`;
171
+ case "EMFILE":
172
+ case "ENFILE":
173
+ return `${file}: too many open files`;
174
+ default:
175
+ return `${file}: ${code !== void 0 ? `i/o error (${code})` : "i/o error"}`;
176
+ }
177
+ }
178
+ __name(fsErrorMessage, "fsErrorMessage");
179
+
180
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/tools/agent-toolset/skills.mjs
181
+ var fs3 = fs.promises;
182
+ var execFileAsync = util.promisify(child_process.execFile);
183
+ async function setupSkills(ctx) {
184
+ const { client, sessionId } = ctx;
185
+ if (!client)
186
+ return async () => {
187
+ };
188
+ const log = loggerFor(client);
189
+ let session = ctx.session;
190
+ if (!session) {
191
+ if (sessionId === void 0)
192
+ return async () => {
193
+ };
194
+ log.warn("AgentToolContext.sessionId is deprecated and costs an extra session fetch; fetch the session once and set `session` instead", { component: "agent-tool-context" });
195
+ session = await client.beta.sessions.retrieve(sessionId);
196
+ }
197
+ const skillsRoot = path.resolve(ctx.workdir, "skills");
198
+ const created = [];
199
+ for (const skill of session.agent.skills) {
200
+ try {
201
+ const version = await client.beta.skills.versions.retrieve(skill.version, { skill_id: skill.skill_id });
202
+ let dirname2 = path.basename(version.name.trim());
203
+ if (dirname2 === "" || dirname2 === "." || dirname2 === "..")
204
+ dirname2 = skill.skill_id;
205
+ const dest = path.resolve(skillsRoot, dirname2);
206
+ if (dest !== skillsRoot && !dest.startsWith(skillsRoot + path.sep)) {
207
+ log.warn("skill name escapes the skills dir; skipping", {
208
+ component: "agent-tool-context",
209
+ name: version.name
210
+ });
211
+ continue;
212
+ }
213
+ const resp = await client.beta.skills.versions.download(version.id, { skill_id: skill.skill_id });
214
+ await fs3.rm(dest, { recursive: true, force: true });
215
+ await fs3.mkdir(dest, { recursive: true, mode: DIR_CREATE_MODE });
216
+ created.push(dest);
217
+ await extractSkillArchive(resp, dest);
218
+ log.info("downloaded skill", {
219
+ component: "agent-tool-context",
220
+ skill_id: skill.skill_id,
221
+ version: version.id,
222
+ dest
223
+ });
224
+ } catch (e) {
225
+ log.warn("failed to download skill", {
226
+ component: "agent-tool-context",
227
+ skill_id: skill.skill_id,
228
+ error: String(e)
229
+ });
230
+ }
231
+ }
232
+ return async () => {
233
+ for (const dest of created) {
234
+ await fs3.rm(dest, { recursive: true, force: true }).catch((e) => {
235
+ log.warn("failed to clean up skill", { component: "agent-tool-context", dest, error: String(e) });
236
+ });
237
+ }
238
+ };
239
+ }
240
+ __name(setupSkills, "setupSkills");
241
+ function assertSafeMemberNames(names) {
242
+ for (const raw of names) {
243
+ const entry = raw.trim();
244
+ if (!entry)
245
+ continue;
246
+ if (path.isAbsolute(entry) || entry.split(/[\\/]/).includes("..")) {
247
+ throw new AnthropicError(`refusing to extract unsafe archive member: ${entry}`);
248
+ }
249
+ }
250
+ }
251
+ __name(assertSafeMemberNames, "assertSafeMemberNames");
252
+ var INCONSISTENT_LISTING = "skill archive listing is inconsistent; refusing to extract";
253
+ var PLAIN_TYPE_CHARS = { unzip: /* @__PURE__ */ new Set(["-", "d", "?"]), tar: /* @__PURE__ */ new Set(["-", "d", "C"]) };
254
+ function listingLines(listing) {
255
+ const lines = listing.split("\n");
256
+ if (lines[lines.length - 1] === "")
257
+ lines.pop();
258
+ return lines;
259
+ }
260
+ __name(listingLines, "listingLines");
261
+ function canExcludeVerbatim(cmd, name) {
262
+ return /^[\x20-\x7E]+$/.test(name) && !/[\\^#]/.test(name) && !(cmd === "unzip" && name.startsWith("-"));
263
+ }
264
+ __name(canExcludeVerbatim, "canExcludeVerbatim");
265
+ function classifyArchiveListing(cmd, names, typed) {
266
+ const nameLines = listingLines(names);
267
+ const typedLines = listingLines(typed);
268
+ if (nameLines.length !== typedLines.length)
269
+ throw new AnthropicError(INCONSISTENT_LISTING);
270
+ const plain = [];
271
+ const special = [];
272
+ nameLines.forEach((name, i) => {
273
+ if (PLAIN_TYPE_CHARS[cmd].has(typedLines[i].charAt(0))) {
274
+ plain.push(name);
275
+ return;
276
+ }
277
+ if (!canExcludeVerbatim(cmd, name)) {
278
+ throw new AnthropicError(`refusing to extract archive: cannot safely exclude member ${JSON.stringify(name)}`);
279
+ }
280
+ special.push(name);
281
+ });
282
+ return { plain, special };
283
+ }
284
+ __name(classifyArchiveListing, "classifyArchiveListing");
285
+ async function assertOnlyPlainEntries(dir) {
286
+ for (const entry of await fs3.readdir(dir, { withFileTypes: true })) {
287
+ if (entry.isDirectory())
288
+ await assertOnlyPlainEntries(path.join(dir, entry.name));
289
+ else if (!entry.isFile())
290
+ throw new AnthropicError(INCONSISTENT_LISTING);
291
+ }
292
+ }
293
+ __name(assertOnlyPlainEntries, "assertOnlyPlainEntries");
294
+ async function runArchiveTool(cmd, args) {
295
+ try {
296
+ const { stdout } = await execFileAsync(cmd, args);
297
+ return stdout;
298
+ } catch (e) {
299
+ if (errnoCode(e) === "ENOENT") {
300
+ throw new AnthropicError(`skill extraction requires the \`${cmd}\` command, but it was not found on PATH`);
301
+ }
302
+ throw e;
303
+ }
304
+ }
305
+ __name(runArchiveTool, "runArchiveTool");
306
+ function archiveTopDir(names) {
307
+ let top;
308
+ let nested = false;
309
+ for (const raw of names) {
310
+ const parts = raw.trim().split("/").filter((p) => p !== "" && p !== ".");
311
+ if (parts.length === 0)
312
+ continue;
313
+ const first = parts[0];
314
+ if (top === void 0)
315
+ top = first;
316
+ else if (first !== top)
317
+ return "";
318
+ if (parts.length > 1)
319
+ nested = true;
320
+ }
321
+ return top !== void 0 && nested ? top : "";
322
+ }
323
+ __name(archiveTopDir, "archiveTopDir");
324
+ async function extractSkillArchive(resp, dest) {
325
+ const tmp = path.join(dest, `.skill-archive-${process.pid}-${Date.now()}`);
326
+ if (!resp.body) {
327
+ throw new AnthropicError("skill download response had no body");
328
+ }
329
+ await stream.promises.pipeline(stream.Readable.fromWeb(resp.body), fs.createWriteStream(tmp));
330
+ const stage = path.join(path.dirname(dest), `.skill-stage-${process.pid}-${Date.now()}`);
331
+ const excludeFile = path.join(path.dirname(dest), `.skill-exclude-${process.pid}-${Date.now()}`);
332
+ try {
333
+ const head = await readHead(tmp, 4);
334
+ const isZip = head.length >= 4 && head[0] === 80 && head[1] === 75 && head[2] === 3 && head[3] === 4;
335
+ const archiveCmd = isZip ? "unzip" : "tar";
336
+ const names = await runArchiveTool(archiveCmd, isZip ? ["-Z1", tmp] : ["-tf", tmp]);
337
+ const typed = await runArchiveTool(archiveCmd, isZip ? ["-Z", "--h", "--t", tmp] : ["-tvf", tmp]);
338
+ const { plain, special } = classifyArchiveListing(archiveCmd, names, typed);
339
+ assertSafeMemberNames([...plain, ...special]);
340
+ const top = archiveTopDir(plain);
341
+ await fs3.mkdir(stage, { recursive: true, mode: DIR_CREATE_MODE });
342
+ if (plain.length > 0) {
343
+ await runArchiveTool(archiveCmd, await extractArgs(archiveCmd, tmp, stage, special, excludeFile));
344
+ }
345
+ await assertOnlyPlainEntries(stage);
346
+ const srcRoot = top ? path.join(stage, top) : stage;
347
+ const entries = await fs3.readdir(srcRoot).catch((e) => {
348
+ throw errnoCode(e) === "ENOENT" ? new AnthropicError(INCONSISTENT_LISTING) : e;
349
+ });
350
+ for (const entry of entries) {
351
+ await fs3.rename(path.join(srcRoot, entry), path.join(dest, entry));
352
+ }
353
+ } finally {
354
+ await fs3.rm(tmp, { force: true });
355
+ await fs3.rm(excludeFile, { force: true });
356
+ await fs3.rm(stage, { recursive: true, force: true });
357
+ }
358
+ }
359
+ __name(extractSkillArchive, "extractSkillArchive");
360
+ async function extractArgs(cmd, archive, stage, special, excludeFile) {
361
+ const patterns = special.map((name) => name.replace(/[*?[\\]/g, "\\$&"));
362
+ if (cmd === "unzip") {
363
+ return ["-oq", archive, "-d", stage, ...patterns.length > 0 ? ["-x", ...patterns] : []];
364
+ }
365
+ if (patterns.length === 0)
366
+ return ["-xf", archive, "-C", stage];
367
+ await fs3.writeFile(excludeFile, patterns.join("\n") + "\n", { flag: "wx", mode: 384 });
368
+ return ["-xf", archive, "-C", stage, "-X", excludeFile];
369
+ }
370
+ __name(extractArgs, "extractArgs");
371
+ async function readHead(file, n) {
372
+ const handle = await fs3.open(file, "r");
373
+ try {
374
+ const buf = Buffer.alloc(n);
375
+ const { bytesRead } = await handle.read(buf, 0, n, 0);
376
+ return buf.subarray(0, bytesRead);
377
+ } finally {
378
+ await handle.close();
379
+ }
380
+ }
381
+ __name(readHead, "readHead");
382
+
383
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/internal/file-store.mjs
384
+ var fsp = fs.promises;
385
+ var C = fs.constants;
386
+ var OWNER_ONLY_DIR_MODE = 448;
387
+ var OWNER_ONLY_FILE_MODE = 384;
388
+ var OWNER_ONLY_EXEC_MODE = 448;
389
+ var O_NOFOLLOW = C.O_NOFOLLOW ?? 0;
390
+ var O_NONBLOCK = C.O_NONBLOCK ?? 0;
391
+ var FileStoreError = /* @__PURE__ */ (() => {
392
+ class FileStoreError2 extends Error {
393
+ static {
394
+ __name(this, "FileStoreError");
395
+ }
396
+ constructor(reason, relPath) {
397
+ super(`path ${JSON.stringify(relPath)} ${reason}`);
398
+ this.name = "FileStoreError";
399
+ this.reason = reason;
400
+ this.relPath = relPath;
401
+ }
402
+ }
403
+ FileStoreError2.ESCAPES_ROOT = "escapes the store root";
404
+ FileStoreError2.IS_A_SYMLINK = "is a symlink";
405
+ FileStoreError2.NOT_A_FILE = "is not a regular file";
406
+ FileStoreError2.NOT_A_DIRECTORY = "is not a directory";
407
+ FileStoreError2.NOT_UTF8 = "is not valid utf-8";
408
+ FileStoreError2.MOVE_DESTINATION_EXISTS = "already exists";
409
+ return FileStoreError2;
410
+ })();
411
+ function isPathLegal(p) {
412
+ return p.startsWith("/") && !p.split("/").includes("..");
413
+ }
414
+ __name(isPathLegal, "isPathLegal");
415
+ var FileStore = /* @__PURE__ */ (() => {
416
+ class FileStore2 {
417
+ static {
418
+ __name(this, "FileStore");
419
+ }
420
+ /** @internal — use {@link FileStore.open} / {@link openFileStore}. */
421
+ constructor(root, removedOnDispose, utf8Only = false) {
422
+ this.hashes = /* @__PURE__ */ new Map();
423
+ this.rootPath = root;
424
+ this.removedOnDispose = removedOnDispose;
425
+ this.decoder = utf8Only ? new TextDecoder("utf-8", { fatal: true }) : void 0;
426
+ }
427
+ /** Resolve `root`; creates nothing — only {@link createRoot} makes the folder. */
428
+ static async open(root, opts) {
429
+ if (!platformSupported()) {
430
+ throw new Error("FileStore requires O_NOFOLLOW support on this platform");
431
+ }
432
+ let removedOnDispose = false;
433
+ try {
434
+ await fsp.lstat(root);
435
+ } catch (e) {
436
+ if (e.code !== "ENOENT")
437
+ throw e;
438
+ removedOnDispose = true;
439
+ }
440
+ return new FileStore2(path.resolve(root), removedOnDispose, opts?.utf8 ?? false);
441
+ }
442
+ /** Create the root directory and any missing ancestors; already existing is fine. */
443
+ async createRoot() {
444
+ await makeDirAndAncestors(this.rootPath);
445
+ }
446
+ /** The resolved root, and what {@link dispose} will do to it. */
447
+ root() {
448
+ return { path: this.rootPath, removedOnDispose: this.removedOnDispose };
449
+ }
450
+ /**
451
+ * Remove the root iff `open` created it; pre-existing roots are kept.
452
+ *
453
+ * Wired to `Symbol.asyncDispose` at runtime when the host provides it, so
454
+ * `await using` works on engines with explicit resource management.
455
+ */
456
+ async dispose() {
457
+ if (!this.removedOnDispose)
458
+ return;
459
+ await fsp.rm(this.rootPath, { recursive: true, force: true });
460
+ }
461
+ /**
462
+ * Write `data` (`string` UTF-8 or bytes) atomically to the file at `relPath`.
463
+ *
464
+ * Missing directories below the root are created; a missing root is not —
465
+ * the write fails with `ENOENT`.
466
+ */
467
+ async put(relPath, data, opts) {
468
+ const tail = relPath.replace(/\\/g, "/");
469
+ if (tail.endsWith("/") || tail.endsWith("/.") || tail === "" || tail === ".") {
470
+ throw new FileStoreError(FileStoreError.NOT_A_FILE, relPath);
471
+ }
472
+ const dest = this.resolveUnderRoot(relPath);
473
+ const payload = typeof data === "string" ? encodeUTF8(data) : data;
474
+ this.requireUtf8(relPath, payload);
475
+ await makeDirsBelowRoot(this.rootPath, path.dirname(dest));
476
+ await replaceViaTemp(dest, payload, opts?.executable ?? false);
477
+ }
478
+ /** The file's bytes; `null` when absent. */
479
+ async get(relPath) {
480
+ const dest = this.resolveUnderRoot(relPath);
481
+ let handle;
482
+ try {
483
+ handle = await openRegularFile(relPath, dest);
484
+ } catch (e) {
485
+ if (e.code === "ENOENT")
486
+ return null;
487
+ throw e;
488
+ }
489
+ let data;
490
+ try {
491
+ const buf = await handle.readFile();
492
+ data = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
493
+ } finally {
494
+ await handle.close();
495
+ }
496
+ this.requireUtf8(relPath, data);
497
+ return data;
498
+ }
499
+ /** The relative path of every file under the directory `under`. */
500
+ async ls(under = "/") {
501
+ const base = this.resolveUnderRoot(under);
502
+ return new Set((await filenamesInDir(this.rootPath, under, base)).map(([rel]) => rel));
503
+ }
504
+ /**
505
+ * Every symlink under `under` — listings skip them and reads refuse them,
506
+ * so a caller that must know they exist asks here.
507
+ */
508
+ async findSymlinks(under = "/") {
509
+ const base = this.resolveUnderRoot(under);
510
+ return symlinksInDir(this.rootPath, under, base);
511
+ }
512
+ /**
513
+ * `{relPath: sha256Hex}` of every file under the directory `under`.
514
+ *
515
+ * Unchanged files — same size, mtime, and ctime since the last call —
516
+ * reuse their recorded hash instead of being re-read.
517
+ */
518
+ async hashtree(under = "/") {
519
+ const base = this.resolveUnderRoot(under);
520
+ const walkStartNs = _internals.nowNs();
521
+ const out = /* @__PURE__ */ Object.create(null);
522
+ for (const [rel, full] of await filenamesInDir(this.rootPath, under, base)) {
523
+ const sha = await this.hashViaCache(rel, full, walkStartNs);
524
+ if (sha !== null)
525
+ out[rel] = sha;
526
+ }
527
+ return out;
528
+ }
529
+ /** One file's sha256; `null` when absent. Shares {@link hashtree}'s cache. */
530
+ async hashFile(relPath) {
531
+ const dest = this.resolveUnderRoot(relPath);
532
+ let st;
533
+ try {
534
+ st = await fsp.lstat(dest, { bigint: true });
535
+ } catch (e) {
536
+ if (e.code === "ENOENT")
537
+ return null;
538
+ throw e;
539
+ }
540
+ if (st.isSymbolicLink())
541
+ throw new FileStoreError(FileStoreError.IS_A_SYMLINK, relPath);
542
+ if (!st.isFile())
543
+ throw new FileStoreError(FileStoreError.NOT_A_FILE, relPath);
544
+ const rel = path.relative(this.rootPath, dest).split(path.sep).join("/");
545
+ return this.hashViaCache(rel, dest, _internals.nowNs());
546
+ }
547
+ /**
548
+ * Rename `src` to `dst`; an existing `dst` is refused. The banned store
549
+ * root as either end does nothing.
550
+ */
551
+ async move(src, dst) {
552
+ const s = this.resolveUnderRoot(src);
553
+ const d = this.resolveUnderRoot(dst);
554
+ if (s === this.rootPath || d === this.rootPath)
555
+ return;
556
+ const dstExists = await fsp.stat(d).then(() => true, () => false);
557
+ if (dstExists)
558
+ throw new FileStoreError(FileStoreError.MOVE_DESTINATION_EXISTS, dst);
559
+ await makeDirsBelowRoot(this.rootPath, path.dirname(d));
560
+ await fsp.rename(s, d);
561
+ }
562
+ /** Delete a file or subtree; absent — and the banned store root — do nothing. */
563
+ async remove(relPath) {
564
+ const dest = this.resolveUnderRoot(relPath);
565
+ if (dest === this.rootPath)
566
+ return;
567
+ let st;
568
+ try {
569
+ st = await fsp.lstat(dest, { bigint: true });
570
+ } catch (e) {
571
+ if (e.code === "ENOENT")
572
+ return;
573
+ throw e;
574
+ }
575
+ if (st.isDirectory()) {
576
+ await fsp.rm(dest, { recursive: true, force: true });
577
+ } else {
578
+ try {
579
+ await fsp.unlink(dest);
580
+ } catch (e) {
581
+ if (e.code !== "ENOENT")
582
+ throw e;
583
+ }
584
+ }
585
+ }
586
+ resolveUnderRoot(relPath) {
587
+ const norm = relPath.replace(/\\/g, "/").replace(/^\/+/, "");
588
+ const parts = norm.split("/").filter((p) => p !== "" && p !== ".");
589
+ if (path.posix.isAbsolute(norm) || parts.includes("..")) {
590
+ throw new FileStoreError(FileStoreError.ESCAPES_ROOT, relPath);
591
+ }
592
+ return parts.length === 0 ? this.rootPath : path.join(this.rootPath, ...parts);
593
+ }
594
+ requireUtf8(relPath, data) {
595
+ if (!this.decoder)
596
+ return;
597
+ try {
598
+ this.decoder.decode(data);
599
+ } catch {
600
+ throw new FileStoreError(FileStoreError.NOT_UTF8, relPath);
601
+ }
602
+ }
603
+ async hashViaCache(rel, full, walkStartNs) {
604
+ let st;
605
+ try {
606
+ st = await fsp.lstat(full, { bigint: true });
607
+ } catch (e) {
608
+ if (e.code === "ENOENT")
609
+ return null;
610
+ throw e;
611
+ }
612
+ if (!st.isFile())
613
+ return null;
614
+ const cached = this.hashes.get(rel);
615
+ let sha;
616
+ if (cached !== void 0 && unchangedSinceHashed(cached, st)) {
617
+ sha = cached.sha;
618
+ } else {
619
+ try {
620
+ sha = await _internals.hashFile(full);
621
+ } catch (e) {
622
+ const code = e.code;
623
+ if (code === "ENOENT" || e instanceof FileStoreError)
624
+ return null;
625
+ if (code === "ELOOP" || code === "EMLINK")
626
+ return null;
627
+ throw e;
628
+ }
629
+ }
630
+ if (oldEnoughToCache(st, walkStartNs)) {
631
+ this.hashes.set(rel, { mtimeNs: st.mtimeNs, ctimeNs: st.ctimeNs, size: st.size, sha });
632
+ }
633
+ return sha;
634
+ }
635
+ }
636
+ FileStore2.isPathLegal = isPathLegal;
637
+ return FileStore2;
638
+ })();
639
+ function platformSupported() {
640
+ return O_NOFOLLOW !== 0;
641
+ }
642
+ __name(platformSupported, "platformSupported");
643
+ async function makeDirAndAncestors(dir) {
644
+ const missing = [];
645
+ let current = dir;
646
+ for (; ; ) {
647
+ try {
648
+ await fsp.stat(current);
649
+ break;
650
+ } catch (e) {
651
+ const code = e.code;
652
+ if (code !== "ENOENT" && code !== "ENOTDIR" && code !== "ELOOP")
653
+ throw e;
654
+ }
655
+ missing.push(current);
656
+ const parent = path.dirname(current);
657
+ if (parent === current)
658
+ break;
659
+ current = parent;
660
+ }
661
+ for (const directory of missing.reverse()) {
662
+ try {
663
+ await fsp.mkdir(directory, { mode: OWNER_ONLY_DIR_MODE });
664
+ } catch (e) {
665
+ if (e.code !== "EEXIST")
666
+ throw e;
667
+ }
668
+ }
669
+ }
670
+ __name(makeDirAndAncestors, "makeDirAndAncestors");
671
+ async function makeDirsBelowRoot(root, dir) {
672
+ const below = path.relative(root, dir);
673
+ if (below === "")
674
+ return;
675
+ let current = root;
676
+ for (const part of below.split(path.sep)) {
677
+ current = path.join(current, part);
678
+ try {
679
+ await fsp.mkdir(current, { mode: OWNER_ONLY_DIR_MODE });
680
+ } catch (e) {
681
+ if (e.code !== "EEXIST")
682
+ throw e;
683
+ }
684
+ }
685
+ }
686
+ __name(makeDirsBelowRoot, "makeDirsBelowRoot");
687
+ async function replaceViaTemp(dest, data, isExecutable) {
688
+ const mode = isExecutable ? OWNER_ONLY_EXEC_MODE : OWNER_ONLY_FILE_MODE;
689
+ const tmp = path.join(path.dirname(dest), `.fs-${crypto.randomBytes(8).toString("hex")}.tmp`);
690
+ let handle;
691
+ try {
692
+ handle = await fsp.open(tmp, C.O_WRONLY | C.O_CREAT | C.O_EXCL | O_NOFOLLOW, mode);
693
+ await handle.writeFile(data);
694
+ await handle.close();
695
+ handle = void 0;
696
+ await fsp.rename(tmp, dest);
697
+ } catch (err) {
698
+ if (handle)
699
+ await handle.close().catch(() => {
700
+ });
701
+ await fsp.unlink(tmp).catch(() => {
702
+ });
703
+ throw err;
704
+ }
705
+ }
706
+ __name(replaceViaTemp, "replaceViaTemp");
707
+ async function openRegularFile(relPath, dest) {
708
+ let handle;
709
+ try {
710
+ handle = await fsp.open(dest, C.O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
711
+ } catch (e) {
712
+ const code = e.code;
713
+ if (code === "ELOOP" || code === "EMLINK") {
714
+ throw new FileStoreError(FileStoreError.IS_A_SYMLINK, relPath);
715
+ }
716
+ throw e;
717
+ }
718
+ try {
719
+ const st = await handle.stat();
720
+ if (!st.isFile())
721
+ throw new FileStoreError(FileStoreError.NOT_A_FILE, relPath);
722
+ } catch (e) {
723
+ await handle.close().catch(() => {
724
+ });
725
+ throw e;
726
+ }
727
+ return handle;
728
+ }
729
+ __name(openRegularFile, "openRegularFile");
730
+ async function hashFile(full) {
731
+ const digest = crypto.createHash("sha256");
732
+ const handle = await openRegularFile(path.basename(full), full);
733
+ const buf = new Uint8Array(1024 * 1024);
734
+ try {
735
+ for (; ; ) {
736
+ const { bytesRead } = await handle.read(buf, 0, buf.length);
737
+ if (bytesRead === 0)
738
+ break;
739
+ digest.update(buf.subarray(0, bytesRead));
740
+ }
741
+ } finally {
742
+ await handle.close();
743
+ }
744
+ return digest.digest("hex");
745
+ }
746
+ __name(hashFile, "hashFile");
747
+ async function filenamesInDir(root, under, base) {
748
+ if (!await requireDir(under, base))
749
+ return [];
750
+ const out = [];
751
+ await walk(base, (full, entry) => {
752
+ if (entry.isFile())
753
+ out.push([path.relative(root, full).split(path.sep).join("/"), full]);
754
+ });
755
+ out.sort();
756
+ return out;
757
+ }
758
+ __name(filenamesInDir, "filenamesInDir");
759
+ async function symlinksInDir(root, under, base) {
760
+ const relOf = /* @__PURE__ */ __name((full) => path.relative(root, full).split(path.sep).join("/"), "relOf");
761
+ let st;
762
+ try {
763
+ st = await fsp.lstat(base, { bigint: true });
764
+ } catch (e) {
765
+ const code = e.code;
766
+ if (code === "ENOENT" || code === "ENOTDIR")
767
+ return /* @__PURE__ */ new Set();
768
+ throw e;
769
+ }
770
+ if (st.isSymbolicLink())
771
+ return /* @__PURE__ */ new Set([relOf(base)]);
772
+ if (!st.isDirectory())
773
+ throw new FileStoreError(FileStoreError.NOT_A_DIRECTORY, under);
774
+ const out = /* @__PURE__ */ new Set();
775
+ await walk(base, (full, entry) => {
776
+ if (entry.isSymbolicLink())
777
+ out.add(relOf(full));
778
+ });
779
+ return out;
780
+ }
781
+ __name(symlinksInDir, "symlinksInDir");
782
+ async function requireDir(under, base) {
783
+ let st;
784
+ try {
785
+ st = await fsp.lstat(base, { bigint: true });
786
+ } catch (e) {
787
+ const code = e.code;
788
+ if (code === "ENOENT" || code === "ENOTDIR")
789
+ return false;
790
+ throw e;
791
+ }
792
+ if (!st.isDirectory())
793
+ throw new FileStoreError(FileStoreError.NOT_A_DIRECTORY, under);
794
+ return true;
795
+ }
796
+ __name(requireDir, "requireDir");
797
+ async function walk(base, visit) {
798
+ const stack = [base];
799
+ while (stack.length) {
800
+ const dir = stack.pop();
801
+ let entries;
802
+ try {
803
+ entries = await fsp.readdir(dir, { withFileTypes: true });
804
+ } catch (e) {
805
+ if (e.code === "ENOENT")
806
+ continue;
807
+ throw e;
808
+ }
809
+ for (const entry of entries) {
810
+ const full = path.join(dir, entry.name);
811
+ visit(full, entry);
812
+ if (entry.isDirectory() && !entry.isSymbolicLink())
813
+ stack.push(full);
814
+ }
815
+ }
816
+ }
817
+ __name(walk, "walk");
818
+ function unchangedSinceHashed(cached, st) {
819
+ return st.mtimeNs === cached.mtimeNs && st.ctimeNs === cached.ctimeNs && st.size === cached.size;
820
+ }
821
+ __name(unchangedSinceHashed, "unchangedSinceHashed");
822
+ function oldEnoughToCache(st, walkStartNs) {
823
+ const newestNs = st.mtimeNs > st.ctimeNs ? st.mtimeNs : st.ctimeNs;
824
+ return newestNs < walkStartNs - _internals.timestampTrustMarginNs;
825
+ }
826
+ __name(oldEnoughToCache, "oldEnoughToCache");
827
+ var TIMESTAMP_TRUST_MARGIN_NS = 2000000000n;
828
+ var _internals = {
829
+ hashFile,
830
+ timestampTrustMarginNs: TIMESTAMP_TRUST_MARGIN_NS,
831
+ nowNs: /* @__PURE__ */ __name(() => BigInt(Date.now()) * 1000000n, "nowNs")
832
+ };
833
+ var LocalFileStore = FileStore;
834
+ var asyncDispose = Symbol.asyncDispose;
835
+ if (asyncDispose) {
836
+ Object.defineProperty(FileStore.prototype, asyncDispose, {
837
+ value: FileStore.prototype.dispose,
838
+ configurable: true,
839
+ writable: true
840
+ });
841
+ }
842
+
843
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/tools/agent-toolset/memories.mjs
844
+ var _SessionMemoryStores_instances;
845
+ var _SessionMemoryStores_client;
846
+ var _SessionMemoryStores_workdir;
847
+ var _SessionMemoryStores_syncIntervalMs;
848
+ var _SessionMemoryStores_syncDeletions;
849
+ var _SessionMemoryStores_log;
850
+ var _SessionMemoryStores_lastSyncAt;
851
+ var _SessionMemoryStores_finished;
852
+ var _SessionMemoryStores_stores;
853
+ var _SessionMemoryStores_storeRoot;
854
+ var _SessionMemoryStores_scanMarker;
855
+ var _SessionMemoryStores_syncStore;
856
+ var _SessionMemoryStores_flushStore;
857
+ var _SessionMemoryStores_recover;
858
+ var _SessionMemoryStores_settleSent;
859
+ var _SessionMemoryStores_stampAndPull;
860
+ var _SessionMemoryStores_syncPath;
861
+ var _SessionMemoryStores_removeLocal;
862
+ var _SessionMemoryStores_write;
863
+ var _SessionMemoryStores_pullAll;
864
+ var _SessionMemoryStores_uploadAll;
865
+ var _SessionMemoryStores_listMemories;
866
+ var _SessionMemoryStores_upload;
867
+ var _SessionMemoryStores_corroboratedDelete;
868
+ var _SessionMemoryStores_deleteRemote;
869
+ var MEMORY_FLUSH_TIMEOUT_MS = 3e4;
870
+ var MARKER_PATH = ".anthropic-memory-store";
871
+ var MARKER_VERSION = 1;
872
+ function markerSha(memoryStoreId) {
873
+ return crypto.createHash("sha256").update(`version ${MARKER_VERSION}
874
+ ${memoryStoreId}`, "utf-8").digest("hex");
875
+ }
876
+ __name(markerSha, "markerSha");
877
+ var DELETE_CORROBORATION_MS = 3e4;
878
+ var LIST_PAGE_SIZE = 100;
879
+ var FULL_LIST_PAGE_SIZE = 20;
880
+ var FETCH_CONCURRENCY = 16;
881
+ var UPLOAD_CONCURRENCY = 32;
882
+ var DELETE_CAP_FLOOR = 8;
883
+ var DELETE_CAP_CEILING = 50;
884
+ var SessionMemoryError = class extends AnthropicError {
885
+ static {
886
+ __name(this, "SessionMemoryError");
887
+ }
888
+ constructor(message, cause) {
889
+ super(message);
890
+ this.name = "SessionMemoryError";
891
+ if (cause !== void 0)
892
+ this.cause = cause;
893
+ }
894
+ };
895
+ var DeletePass = class {
896
+ static {
897
+ __name(this, "DeletePass");
898
+ }
899
+ constructor(mode, cap, waiveWindow) {
900
+ this.mode = mode;
901
+ this.cap = cap;
902
+ this.waiveWindow = waiveWindow;
903
+ this.attempted = 0;
904
+ this.capped = 0;
905
+ this.suppressed = 0;
906
+ }
907
+ takeSlot() {
908
+ if (this.attempted >= this.cap) {
909
+ this.capped++;
910
+ return false;
911
+ }
912
+ this.attempted++;
913
+ return true;
914
+ }
915
+ };
916
+ var SessionMemoryStores = /* @__PURE__ */ (() => {
917
+ class SessionMemoryStores2 {
918
+ static {
919
+ __name(this, "SessionMemoryStores");
920
+ }
921
+ constructor(client, opts) {
922
+ _SessionMemoryStores_instances.add(this);
923
+ _SessionMemoryStores_client.set(this, void 0);
924
+ _SessionMemoryStores_workdir.set(this, void 0);
925
+ _SessionMemoryStores_syncIntervalMs.set(this, void 0);
926
+ _SessionMemoryStores_syncDeletions.set(this, void 0);
927
+ _SessionMemoryStores_log.set(this, void 0);
928
+ _SessionMemoryStores_lastSyncAt.set(this, void 0);
929
+ _SessionMemoryStores_finished.set(this, false);
930
+ _SessionMemoryStores_stores.set(this, []);
931
+ __classPrivateFieldSet(this, _SessionMemoryStores_client, client, "f");
932
+ __classPrivateFieldSet(this, _SessionMemoryStores_workdir, opts.workdir, "f");
933
+ __classPrivateFieldSet(this, _SessionMemoryStores_syncIntervalMs, opts.syncIntervalMs ?? DEFAULT_MEMORY_SYNC_INTERVAL_MS, "f");
934
+ checkMemorySyncInterval(__classPrivateFieldGet(this, _SessionMemoryStores_syncIntervalMs, "f"), "syncIntervalMs");
935
+ __classPrivateFieldSet(this, _SessionMemoryStores_syncDeletions, opts.syncDeletions ?? "enabled", "f");
936
+ __classPrivateFieldSet(this, _SessionMemoryStores_log, loggerFor(client), "f");
937
+ __classPrivateFieldSet(this, _SessionMemoryStores_lastSyncAt, Date.now(), "f");
938
+ }
939
+ /**
940
+ * Every attached store's root directory.
941
+ *
942
+ * The worker lists these as the file tools' allowed roots so a store
943
+ * mounted outside the workdir stays reachable.
944
+ */
945
+ get roots() {
946
+ return __classPrivateFieldGet(this, _SessionMemoryStores_stores, "f").map((s) => s.files.root().path);
947
+ }
948
+ /**
949
+ * Root directories of stores attached read-only.
950
+ *
951
+ * The file tools consult this to refuse writes into read-only stores.
952
+ */
953
+ get readOnlyRoots() {
954
+ return __classPrivateFieldGet(this, _SessionMemoryStores_stores, "f").filter((s) => s.readOnly).map((s) => s.files.root().path);
955
+ }
956
+ /**
957
+ * Download every attached store's memories to disk.
958
+ *
959
+ * `session` arrives already fetched — one snapshot shared with the skills
960
+ * download, so the two cannot disagree about the resources.
961
+ */
962
+ async download(session) {
963
+ for (const resource of session.resources) {
964
+ if (resource.type !== "memory_store")
965
+ continue;
966
+ const root = __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_storeRoot).call(this, resource);
967
+ let store;
968
+ try {
969
+ store = {
970
+ memoryStoreId: resource.memory_store_id,
971
+ // utf8: a binary file is refused at put/get, not mid-sync.
972
+ files: await LocalFileStore.open(root, { utf8: true }),
973
+ readOnly: resource.access === "read_only",
974
+ baseline: /* @__PURE__ */ new Map(),
975
+ refusedShas: /* @__PURE__ */ new Map(),
976
+ pendingDeletes: /* @__PURE__ */ new Map(),
977
+ sentShas: /* @__PURE__ */ new Map()
978
+ };
979
+ if (!store.files.root().removedOnDispose) {
980
+ throw new SessionMemoryError(`something already exists at the memory store's path: ${root} (memory_store_id=${resource.memory_store_id}); it must not exist when the session starts`);
981
+ }
982
+ try {
983
+ await store.files.createRoot();
984
+ } catch (e) {
985
+ if (!isErrno(e))
986
+ throw e;
987
+ throw new SessionMemoryError(`cannot create the memory store's folder: ${root} (memory_store_id=${resource.memory_store_id}): ${e}; the worker host must make this mount path writable`, e);
988
+ }
989
+ await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_stampAndPull).call(this, store);
990
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").info("downloaded memories", {
991
+ count: store.baseline.size,
992
+ memory_store_id: store.memoryStoreId,
993
+ dest: store.files.root().path
994
+ });
995
+ __classPrivateFieldGet(this, _SessionMemoryStores_stores, "f").push(store);
996
+ } catch (e) {
997
+ if (store)
998
+ await store.files.dispose().catch(() => {
999
+ });
1000
+ if (e instanceof SessionMemoryError)
1001
+ throw e;
1002
+ throw new SessionMemoryError(`failed to download memory store memory_store_id=${resource.memory_store_id}: ${e}`, e);
1003
+ }
1004
+ }
1005
+ __classPrivateFieldSet(this, _SessionMemoryStores_lastSyncAt, Date.now(), "f");
1006
+ }
1007
+ /**
1008
+ * The session's last sync — skips the delete wait, so calling it twice
1009
+ * would undo the protection; it throws instead.
1010
+ */
1011
+ async finish() {
1012
+ if (__classPrivateFieldGet(this, _SessionMemoryStores_finished, "f")) {
1013
+ throw new AnthropicError("finish() was already called: it is the session's last sync and runs once");
1014
+ }
1015
+ __classPrivateFieldSet(this, _SessionMemoryStores_finished, true, "f");
1016
+ await this.syncAll(true);
1017
+ }
1018
+ /** @internal — reconcile every store once; the tests' deterministic driver */
1019
+ async syncAll(final) {
1020
+ await Promise.all(__classPrivateFieldGet(this, _SessionMemoryStores_stores, "f").map((store) => __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_syncStore).call(this, store, final)));
1021
+ __classPrivateFieldSet(this, _SessionMemoryStores_lastSyncAt, Date.now(), "f");
1022
+ }
1023
+ /** Sync when `syncIntervalMs` has elapsed since the last one. Never throws. */
1024
+ async syncIfDue() {
1025
+ if (Date.now() - __classPrivateFieldGet(this, _SessionMemoryStores_lastSyncAt, "f") < __classPrivateFieldGet(this, _SessionMemoryStores_syncIntervalMs, "f"))
1026
+ return;
1027
+ await this.syncAll(false);
1028
+ }
1029
+ /**
1030
+ * Upload new and changed files; send no deletes and pull nothing.
1031
+ *
1032
+ * The push-only rescue pass for a session ending on an error or
1033
+ * cancel — best-effort, bounded by the caller: once `signal` aborts no
1034
+ * further upload starts, each store cut off part-way logs how many
1035
+ * changed files it had not finished uploading, and this resolves without
1036
+ * waiting for requests already in flight. Each store uploads up to
1037
+ * {@link UPLOAD_CONCURRENCY} files at a time. Skips read-only stores,
1038
+ * refused files, files the server already holds, and folders that fail
1039
+ * the marker check. Never throws.
1040
+ */
1041
+ async flushWrites(signal) {
1042
+ await Promise.all(__classPrivateFieldGet(this, _SessionMemoryStores_stores, "f").map((store) => __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_flushStore).call(this, store, signal)));
1043
+ }
1044
+ /**
1045
+ * Remove every store directory that {@link SessionMemoryStores.download}
1046
+ * created. Pre-existing directories are left alone — that is
1047
+ * {@link FileStore.dispose}'s own rule. A folder that fails the marker
1048
+ * check is kept too — sync left it as found, so must dispose.
1049
+ */
1050
+ async dispose() {
1051
+ for (const store of __classPrivateFieldGet(this, _SessionMemoryStores_stores, "f")) {
1052
+ const root = store.files.root();
1053
+ try {
1054
+ const scan = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_scanMarker).call(this, store);
1055
+ if (!scan.markerOk && Object.keys(scan.files).length > 0) {
1056
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn(`${scan.distrustReason}; leaving the memory store folder on disk`, {
1057
+ root: root.path,
1058
+ memory_store_id: store.memoryStoreId
1059
+ });
1060
+ continue;
1061
+ }
1062
+ await store.files.dispose();
1063
+ } catch (e) {
1064
+ if (!(e instanceof FileStoreError) && !isErrno(e))
1065
+ throw e;
1066
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("failed to remove the memory store folder", {
1067
+ root: store.files.root().path,
1068
+ memory_store_id: store.memoryStoreId,
1069
+ error: String(e)
1070
+ });
1071
+ continue;
1072
+ }
1073
+ if (root.removedOnDispose) {
1074
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").info("removed memory store dir", {
1075
+ dest: root.path,
1076
+ memory_store_id: store.memoryStoreId
1077
+ });
1078
+ }
1079
+ }
1080
+ }
1081
+ }
1082
+ _SessionMemoryStores_client = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_workdir = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_syncIntervalMs = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_syncDeletions = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_log = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_lastSyncAt = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_finished = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_stores = /* @__PURE__ */ new WeakMap(), _SessionMemoryStores_instances = /* @__PURE__ */ new WeakSet(), _SessionMemoryStores_storeRoot = /* @__PURE__ */ __name(function _SessionMemoryStores_storeRoot2(resource) {
1083
+ if (resource.mount_path) {
1084
+ if (!isPathLegal(resource.mount_path)) {
1085
+ throw new SessionMemoryError(`memory store mount_path is not a clean absolute path: ${JSON.stringify(resource.mount_path)} (memory_store_id=${resource.memory_store_id})`);
1086
+ }
1087
+ return resource.mount_path;
1088
+ }
1089
+ return path.join(__classPrivateFieldGet(this, _SessionMemoryStores_workdir, "f"), "memory", resource.name || resource.memory_store_id);
1090
+ }, "_SessionMemoryStores_storeRoot"), _SessionMemoryStores_scanMarker = /* @__PURE__ */ __name(async function _SessionMemoryStores_scanMarker2(store) {
1091
+ const local = await store.files.hashtree();
1092
+ const marker = local[MARKER_PATH];
1093
+ delete local[MARKER_PATH];
1094
+ if (marker === markerSha(store.memoryStoreId)) {
1095
+ return { files: local, markerOk: true, distrustReason: null };
1096
+ }
1097
+ return {
1098
+ files: local,
1099
+ markerOk: false,
1100
+ distrustReason: marker !== void 0 ? "the marker file does not match this store" : "the marker file is gone"
1101
+ };
1102
+ }, "_SessionMemoryStores_scanMarker"), _SessionMemoryStores_syncStore = /* @__PURE__ */ __name(async function _SessionMemoryStores_syncStore2(store, final) {
1103
+ try {
1104
+ const scan = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_scanMarker).call(this, store);
1105
+ const local = scan.files;
1106
+ if (!scan.markerOk) {
1107
+ if (Object.keys(local).length > 0) {
1108
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn(`${scan.distrustReason}; leaving the memory store folder as found and not syncing`, {
1109
+ root: store.files.root().path,
1110
+ memory_store_id: store.memoryStoreId
1111
+ });
1112
+ return;
1113
+ }
1114
+ await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_recover).call(this, store, "the folder or its marker is gone");
1115
+ return;
1116
+ }
1117
+ const remote = /* @__PURE__ */ new Map();
1118
+ for await (const [rel, item] of __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_listMemories).call(this, store.memoryStoreId)) {
1119
+ remote.set(rel, item);
1120
+ }
1121
+ __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_settleSent).call(this, store, remote);
1122
+ if (Object.keys(local).length === 0 && store.baseline.size > 1) {
1123
+ await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_recover).call(this, store, "every memory file is gone at once");
1124
+ return;
1125
+ }
1126
+ const deletes = new DeletePass(__classPrivateFieldGet(this, _SessionMemoryStores_syncDeletions, "f"), Math.max(DELETE_CAP_FLOOR, Math.min(DELETE_CAP_CEILING, Math.floor(store.baseline.size / 4))), final);
1127
+ const pulls = [];
1128
+ const baseline = /* @__PURE__ */ new Map();
1129
+ const paths = [.../* @__PURE__ */ new Set([...remote.keys(), ...Object.keys(local), ...store.baseline.keys()])].sort();
1130
+ for (const rel of paths) {
1131
+ const remoteItem = remote.get(rel);
1132
+ const localSha = local[rel];
1133
+ const baseSha = store.baseline.get(rel);
1134
+ let sha;
1135
+ if (localSha === void 0 && baseSha !== void 0 && remoteItem !== void 0 && remoteItem.content_sha256 === baseSha && !store.readOnly) {
1136
+ sha = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_corroboratedDelete).call(this, store, rel, remoteItem, baseSha, deletes);
1137
+ } else {
1138
+ sha = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_syncPath).call(this, store, rel, remoteItem, localSha, pulls);
1139
+ }
1140
+ if (sha !== void 0)
1141
+ baseline.set(rel, sha);
1142
+ }
1143
+ store.baseline = baseline;
1144
+ await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_pullAll).call(this, store, pulls);
1145
+ if (deletes.suppressed > 0) {
1146
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").debug("remote deletes are disabled; locally deleted memories stay on the server", {
1147
+ count: deletes.suppressed,
1148
+ memory_store_id: store.memoryStoreId
1149
+ });
1150
+ }
1151
+ if (deletes.capped > 0) {
1152
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn(`delete cap reached: ${deletes.mode === "log_only" ? "would send" : "sent"} ${deletes.attempted} deletes, held ${deletes.capped} for later syncs`, { memory_store_id: store.memoryStoreId });
1153
+ }
1154
+ } catch (e) {
1155
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory sync failed", { memory_store_id: store.memoryStoreId, error: String(e) });
1156
+ }
1157
+ }, "_SessionMemoryStores_syncStore"), _SessionMemoryStores_flushStore = /* @__PURE__ */ __name(async function _SessionMemoryStores_flushStore2(store, signal) {
1158
+ const dirty = /* @__PURE__ */ new Map();
1159
+ const unsent = /* @__PURE__ */ new Set();
1160
+ const push = /* @__PURE__ */ __name(async () => {
1161
+ if (store.readOnly)
1162
+ return;
1163
+ const scan = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_scanMarker).call(this, store);
1164
+ if (!scan.markerOk) {
1165
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn(`${scan.distrustReason}; not uploading anything from the memory store folder`, {
1166
+ root: store.files.root().path,
1167
+ memory_store_id: store.memoryStoreId
1168
+ });
1169
+ return;
1170
+ }
1171
+ for (const [rel, sha] of Object.entries(scan.files)) {
1172
+ const changed = sha !== store.baseline.get(rel) || store.sentShas.has(rel);
1173
+ if (changed && store.refusedShas.get(rel) !== sha) {
1174
+ dirty.set(rel, sha);
1175
+ unsent.add(rel);
1176
+ }
1177
+ }
1178
+ if (dirty.size === 0 || signal?.aborted)
1179
+ return;
1180
+ const remote = /* @__PURE__ */ new Map();
1181
+ for await (const [rel, item] of __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_listMemories).call(this, store.memoryStoreId)) {
1182
+ if (signal?.aborted)
1183
+ return;
1184
+ remote.set(rel, item);
1185
+ }
1186
+ __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_settleSent).call(this, store, remote);
1187
+ const uploads = [];
1188
+ for (const rel of [...dirty.keys()].sort()) {
1189
+ const localSha = dirty.get(rel);
1190
+ const baseSha = store.baseline.get(rel);
1191
+ const existing = remote.get(rel);
1192
+ if (localSha === baseSha) {
1193
+ unsent.delete(rel);
1194
+ continue;
1195
+ }
1196
+ if (existing !== void 0 && existing.content_sha256 === localSha) {
1197
+ store.baseline.set(rel, existing.content_sha256);
1198
+ unsent.delete(rel);
1199
+ continue;
1200
+ }
1201
+ if (existing !== void 0 && existing.content_sha256 !== baseSha) {
1202
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory changed both locally and remotely; the flush leaves the remote version", {
1203
+ path: rel,
1204
+ memory_store_id: store.memoryStoreId
1205
+ });
1206
+ unsent.delete(rel);
1207
+ continue;
1208
+ }
1209
+ uploads.push([rel, localSha, existing]);
1210
+ }
1211
+ await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_uploadAll).call(this, store, uploads, unsent, signal);
1212
+ }, "push");
1213
+ try {
1214
+ await settledOrAborted(push(), signal);
1215
+ if (signal?.aborted && unsent.size > 0) {
1216
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn(`memory flush cut off part-way; ${unsent.size} of ${dirty.size} changed files had not finished uploading`, { memory_store_id: store.memoryStoreId });
1217
+ }
1218
+ } catch (e) {
1219
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory flush failed", { memory_store_id: store.memoryStoreId, error: String(e) });
1220
+ }
1221
+ }, "_SessionMemoryStores_flushStore"), _SessionMemoryStores_recover = /** Rebuild a destroyed folder from the server; sends no deletes, no uploads. */
1222
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_recover2(store, reason) {
1223
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn(`${reason}; re-downloading the memory store folder instead of syncing`, {
1224
+ root: store.files.root().path,
1225
+ memory_store_id: store.memoryStoreId
1226
+ });
1227
+ await store.files.createRoot();
1228
+ await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_stampAndPull).call(this, store);
1229
+ }, "_SessionMemoryStores_recover"), _SessionMemoryStores_settleSent = /* @__PURE__ */ __name(function _SessionMemoryStores_settleSent2(store, remote) {
1230
+ for (const [rel, sha] of store.sentShas) {
1231
+ if (remote.get(rel)?.content_sha256 === sha)
1232
+ store.baseline.set(rel, sha);
1233
+ }
1234
+ store.sentShas.clear();
1235
+ }, "_SessionMemoryStores_settleSent"), _SessionMemoryStores_stampAndPull = /**
1236
+ * Write the marker, then pull every remote memory. Baseline is cleared
1237
+ * first so a failed write never leaves an entry whose file is not on disk.
1238
+ * Every memory is needed here, so the listing carries the content — pages
1239
+ * cost far fewer round-trips than a request per memory.
1240
+ */
1241
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_stampAndPull2(store) {
1242
+ store.baseline = /* @__PURE__ */ new Map();
1243
+ store.sentShas.clear();
1244
+ store.pendingDeletes.clear();
1245
+ await store.files.put(MARKER_PATH, `version ${MARKER_VERSION}
1246
+ ${store.memoryStoreId}`);
1247
+ for await (const [rel, item] of __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_listMemories).call(this, store.memoryStoreId, "full")) {
1248
+ if (await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_write).call(this, store, rel, item.content ?? "")) {
1249
+ store.baseline.set(rel, item.content_sha256);
1250
+ }
1251
+ }
1252
+ }, "_SessionMemoryStores_stampAndPull"), _SessionMemoryStores_syncPath = /**
1253
+ * Reconcile one path. Returns the sha to record in the baseline, or
1254
+ * `undefined` to drop the path from it.
1255
+ *
1256
+ * `pulls` is an output: when the remote version should be written to disk,
1257
+ * this appends `[rel, remote]` to it instead of writing — `rel` is the
1258
+ * file to write, `remote` the listed memory whose content `#pullAll` will
1259
+ * fetch and write there.
1260
+ */
1261
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_syncPath2(store, rel, remote, localSha, pulls) {
1262
+ const baseSha = store.baseline.get(rel);
1263
+ if (localSha !== void 0) {
1264
+ store.pendingDeletes.delete(rel);
1265
+ }
1266
+ if (!remote) {
1267
+ if (localSha === void 0) {
1268
+ store.pendingDeletes.delete(rel);
1269
+ return void 0;
1270
+ }
1271
+ if (baseSha !== void 0) {
1272
+ if (localSha === baseSha) {
1273
+ const fresh = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_removeLocal).call(this, store, rel, baseSha);
1274
+ if (fresh === void 0)
1275
+ return void 0;
1276
+ if (fresh === baseSha)
1277
+ return baseSha;
1278
+ localSha = fresh;
1279
+ }
1280
+ if (store.readOnly) {
1281
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory deleted remotely but edited locally; keeping the file, which a read-only store cannot push", { path: rel, memory_store_id: store.memoryStoreId });
1282
+ } else if (store.refusedShas.get(rel) !== localSha) {
1283
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").info("memory deleted remotely but edited locally; re-creating it from the file", {
1284
+ path: rel,
1285
+ memory_store_id: store.memoryStoreId
1286
+ });
1287
+ }
1288
+ }
1289
+ if (store.readOnly)
1290
+ return void 0;
1291
+ if (store.refusedShas.get(rel) === localSha)
1292
+ return void 0;
1293
+ return await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_upload).call(this, store, rel, localSha, void 0);
1294
+ }
1295
+ const remoteSha = remote.content_sha256;
1296
+ const remoteChanged = remoteSha !== baseSha;
1297
+ const locallyEdited = localSha !== void 0 && localSha !== baseSha && localSha !== remoteSha;
1298
+ const localChanged = !store.readOnly && locallyEdited;
1299
+ if (localSha === void 0 && baseSha !== void 0) {
1300
+ if (remoteChanged) {
1301
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory deleted locally but changed remotely; restoring the remote version", {
1302
+ path: rel,
1303
+ memory_store_id: store.memoryStoreId
1304
+ });
1305
+ store.pendingDeletes.delete(rel);
1306
+ pulls.push([rel, remote]);
1307
+ }
1308
+ return baseSha;
1309
+ }
1310
+ if (remoteChanged) {
1311
+ if (localSha === remoteSha)
1312
+ return remoteSha;
1313
+ if (locallyEdited) {
1314
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory changed both locally and remotely; keeping the remote version", {
1315
+ path: rel,
1316
+ memory_store_id: store.memoryStoreId
1317
+ });
1318
+ }
1319
+ pulls.push([rel, remote]);
1320
+ return baseSha;
1321
+ }
1322
+ if (localChanged) {
1323
+ if (store.refusedShas.get(rel) === localSha)
1324
+ return remoteSha;
1325
+ return await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_upload).call(this, store, rel, localSha, remote) ?? remoteSha;
1326
+ }
1327
+ return remoteSha;
1328
+ }, "_SessionMemoryStores_syncPath"), _SessionMemoryStores_removeLocal = /**
1329
+ * Remove the file for a memory the server no longer has, if it still holds
1330
+ * `expectSha`. Returns `undefined` when the file is gone from disk,
1331
+ * `expectSha` when it must stay in the baseline (I/O error), or the file's
1332
+ * fresh sha when it was edited since the scan.
1333
+ */
1334
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_removeLocal2(store, rel, expectSha) {
1335
+ let freshSha;
1336
+ try {
1337
+ freshSha = await store.files.hashFile(rel);
1338
+ } catch (e) {
1339
+ if (!(e instanceof FileStoreError) && !isErrno(e))
1340
+ throw e;
1341
+ return expectSha;
1342
+ }
1343
+ if (freshSha === null)
1344
+ return void 0;
1345
+ if (freshSha !== expectSha)
1346
+ return freshSha;
1347
+ try {
1348
+ await store.files.remove(rel);
1349
+ } catch (e) {
1350
+ if (!(e instanceof FileStoreError) && !isErrno(e))
1351
+ throw e;
1352
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("failed to remove memory deleted remotely", {
1353
+ path: rel,
1354
+ memory_store_id: store.memoryStoreId,
1355
+ error: String(e)
1356
+ });
1357
+ return expectSha;
1358
+ }
1359
+ return void 0;
1360
+ }, "_SessionMemoryStores_removeLocal"), _SessionMemoryStores_write = /**
1361
+ * Write a memory's content to disk; `false` (and a warning) on failure.
1362
+ *
1363
+ * A `..` component in the wire path reaches here as {@link FileStoreError} —
1364
+ * that is the escape guard.
1365
+ */
1366
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_write2(store, rel, content) {
1367
+ try {
1368
+ await store.files.put(rel, content);
1369
+ } catch (e) {
1370
+ if (!(e instanceof FileStoreError) && !isErrno(e))
1371
+ throw e;
1372
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("failed to write memory", {
1373
+ path: rel,
1374
+ memory_store_id: store.memoryStoreId,
1375
+ error: String(e)
1376
+ });
1377
+ return false;
1378
+ }
1379
+ return true;
1380
+ }, "_SessionMemoryStores_write"), _SessionMemoryStores_pullAll = /**
1381
+ * Fetch and write the given memories, {@link FETCH_CONCURRENCY} at a time.
1382
+ *
1383
+ * The sync's content pass: the listing carried no content, so each memory
1384
+ * is fetched individually and written as it arrives. On success the path's
1385
+ * baseline advances; on a failed fetch or write the old entry stays and the
1386
+ * next sync retries. A 404 means the memory was deleted after the listing —
1387
+ * the next sync reconciles it.
1388
+ */
1389
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_pullAll2(store, pulls) {
1390
+ if (pulls.length === 0)
1391
+ return;
1392
+ const pullOne = /* @__PURE__ */ __name(async (rel, listed) => {
1393
+ let item;
1394
+ try {
1395
+ item = await __classPrivateFieldGet(this, _SessionMemoryStores_client, "f").beta.memoryStores.memories.retrieve(listed.id, {
1396
+ memory_store_id: store.memoryStoreId,
1397
+ view: "full"
1398
+ });
1399
+ } catch (e) {
1400
+ if (isStatus(e, 404))
1401
+ return;
1402
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("failed to fetch memory content", {
1403
+ path: rel,
1404
+ memory_store_id: store.memoryStoreId,
1405
+ error: String(e)
1406
+ });
1407
+ return;
1408
+ }
1409
+ if (await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_write).call(this, store, rel, item.content ?? "")) {
1410
+ store.baseline.set(rel, item.content_sha256);
1411
+ }
1412
+ }, "pullOne");
1413
+ const queue = pulls[Symbol.iterator]();
1414
+ const worker = /* @__PURE__ */ __name(async () => {
1415
+ for (const [rel, listed] of queue)
1416
+ await pullOne(rel, listed);
1417
+ }, "worker");
1418
+ await Promise.all(Array.from({ length: Math.min(FETCH_CONCURRENCY, pulls.length) }, worker));
1419
+ }, "_SessionMemoryStores_pullAll"), _SessionMemoryStores_uploadAll = /**
1420
+ * Upload the given files, {@link UPLOAD_CONCURRENCY} at a time, taking each
1421
+ * path off `unsent` as its upload returns. No upload starts once `signal`
1422
+ * aborts; the ones already in flight run to completion.
1423
+ */
1424
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_uploadAll2(store, uploads, unsent, signal) {
1425
+ const queue = uploads[Symbol.iterator]();
1426
+ const worker = /* @__PURE__ */ __name(async () => {
1427
+ for (const [rel, localSha, existing] of queue) {
1428
+ if (signal?.aborted)
1429
+ return;
1430
+ const sha = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_upload).call(this, store, rel, localSha, existing);
1431
+ unsent.delete(rel);
1432
+ if (sha !== void 0)
1433
+ store.baseline.set(rel, sha);
1434
+ }
1435
+ }, "worker");
1436
+ await Promise.all(Array.from({ length: Math.min(UPLOAD_CONCURRENCY, uploads.length) }, worker));
1437
+ }, "_SessionMemoryStores_uploadAll"), _SessionMemoryStores_listMemories = /**
1438
+ * The store's memories keyed by relative path (the wire path's leading `/`
1439
+ * stripped — `#upload` re-prefixes it) — `basic` view (shas, no content) at
1440
+ * {@link LIST_PAGE_SIZE} per page unless the caller needs `full` pages.
1441
+ * `memory_prefix` rollups and the reserved marker path are skipped.
1442
+ */
1443
+ /* @__PURE__ */ __name(async function* _SessionMemoryStores_listMemories2(memoryStoreId, view = "basic") {
1444
+ const limit = view === "basic" ? LIST_PAGE_SIZE : FULL_LIST_PAGE_SIZE;
1445
+ for await (const item of __classPrivateFieldGet(this, _SessionMemoryStores_client, "f").beta.memoryStores.memories.list(memoryStoreId, { view, limit })) {
1446
+ if (item.type !== "memory")
1447
+ continue;
1448
+ const rel = item.path.replace(/^\/+/, "");
1449
+ if (rel === MARKER_PATH) {
1450
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("the server listed the reserved marker path; skipping", {
1451
+ path: item.path,
1452
+ memory_store_id: memoryStoreId
1453
+ });
1454
+ continue;
1455
+ }
1456
+ yield [rel, item];
1457
+ }
1458
+ }, "_SessionMemoryStores_listMemories"), _SessionMemoryStores_upload = /**
1459
+ * Push one local file; `undefined` keeps the old baseline so the next pass retries.
1460
+ *
1461
+ * A refusal the server would repeat (400/413, the utf-8 gate) enters
1462
+ * `refusedShas`: warned once, retried only after the file changes.
1463
+ */
1464
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_upload2(store, rel, localSha, existing) {
1465
+ try {
1466
+ const data = await store.files.get(rel);
1467
+ if (data === null)
1468
+ return void 0;
1469
+ const content = decodeUTF8(data);
1470
+ store.sentShas.set(rel, crypto.createHash("sha256").update(content, "utf-8").digest("hex"));
1471
+ const item = existing ? await __classPrivateFieldGet(this, _SessionMemoryStores_client, "f").beta.memoryStores.memories.update(existing.id, {
1472
+ memory_store_id: store.memoryStoreId,
1473
+ content,
1474
+ precondition: { type: "content_sha256", content_sha256: existing.content_sha256 }
1475
+ }) : await __classPrivateFieldGet(this, _SessionMemoryStores_client, "f").beta.memoryStores.memories.create(store.memoryStoreId, {
1476
+ path: "/" + rel,
1477
+ content
1478
+ });
1479
+ store.refusedShas.delete(rel);
1480
+ store.sentShas.delete(rel);
1481
+ return item.content_sha256;
1482
+ } catch (e) {
1483
+ if (existing && isStatus(e, 404)) {
1484
+ return await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_upload2).call(this, store, rel, localSha, void 0);
1485
+ }
1486
+ const permanent = e instanceof FileStoreError || isStatus(e, 400) || isStatus(e, 413);
1487
+ if (existing && isStatus(e, 409)) {
1488
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory changed both locally and remotely; the upload was refused and the local edit loses", {
1489
+ path: rel,
1490
+ memory_store_id: store.memoryStoreId
1491
+ });
1492
+ } else if (permanent && localSha !== void 0) {
1493
+ store.refusedShas.set(rel, localSha);
1494
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("the server rejected this memory file, so it stays un-synced until its content changes", { path: rel, memory_store_id: store.memoryStoreId, rejection: String(e) });
1495
+ } else {
1496
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("failed to upload memory", {
1497
+ path: rel,
1498
+ memory_store_id: store.memoryStoreId,
1499
+ error: String(e)
1500
+ });
1501
+ }
1502
+ return void 0;
1503
+ }
1504
+ }, "_SessionMemoryStores_upload"), _SessionMemoryStores_corroboratedDelete = /** Send the server delete only after the wait, the cap, and a fresh re-check all clear. */
1505
+ /* @__PURE__ */ __name(async function _SessionMemoryStores_corroboratedDelete2(store, rel, remote, baseSha, deletes) {
1506
+ if (deletes.mode === "disabled") {
1507
+ deletes.suppressed++;
1508
+ return baseSha;
1509
+ }
1510
+ let firstAbsent = store.pendingDeletes.get(rel);
1511
+ if (firstAbsent === void 0) {
1512
+ firstAbsent = Date.now();
1513
+ store.pendingDeletes.set(rel, firstAbsent);
1514
+ }
1515
+ if (!deletes.waiveWindow && Date.now() - firstAbsent < DELETE_CORROBORATION_MS) {
1516
+ return baseSha;
1517
+ }
1518
+ let markerOk;
1519
+ let stillAbsent;
1520
+ try {
1521
+ markerOk = await store.files.hashFile(MARKER_PATH) === markerSha(store.memoryStoreId);
1522
+ stillAbsent = await store.files.hashFile(rel) === null;
1523
+ } catch (e) {
1524
+ if (!(e instanceof FileStoreError) && !isErrno(e))
1525
+ throw e;
1526
+ markerOk = stillAbsent = false;
1527
+ }
1528
+ if (!markerOk)
1529
+ return baseSha;
1530
+ if (!stillAbsent) {
1531
+ store.pendingDeletes.delete(rel);
1532
+ return baseSha;
1533
+ }
1534
+ if (!deletes.takeSlot())
1535
+ return baseSha;
1536
+ if (deletes.mode === "log_only") {
1537
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").info("log-only: sync would delete this memory on the server", {
1538
+ path: rel,
1539
+ memory_store_id: store.memoryStoreId
1540
+ });
1541
+ return baseSha;
1542
+ }
1543
+ const sha = await __classPrivateFieldGet(this, _SessionMemoryStores_instances, "m", _SessionMemoryStores_deleteRemote).call(this, store, rel, remote, baseSha);
1544
+ if (sha === void 0) {
1545
+ store.pendingDeletes.delete(rel);
1546
+ }
1547
+ return sha;
1548
+ }, "_SessionMemoryStores_corroboratedDelete"), _SessionMemoryStores_deleteRemote = /* @__PURE__ */ __name(async function _SessionMemoryStores_deleteRemote2(store, rel, remote, baseSha) {
1549
+ try {
1550
+ await __classPrivateFieldGet(this, _SessionMemoryStores_client, "f").beta.memoryStores.memories.delete(remote.id, {
1551
+ memory_store_id: store.memoryStoreId,
1552
+ expected_content_sha256: baseSha
1553
+ });
1554
+ } catch (e) {
1555
+ if (isStatus(e, 404))
1556
+ return void 0;
1557
+ if (isStatus(e, 409) || isStatus(e, 412)) {
1558
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("memory deleted locally but changed remotely; keeping the remote version", {
1559
+ path: rel,
1560
+ memory_store_id: store.memoryStoreId
1561
+ });
1562
+ } else {
1563
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").warn("failed to delete memory", {
1564
+ path: rel,
1565
+ memory_store_id: store.memoryStoreId,
1566
+ error: String(e)
1567
+ });
1568
+ }
1569
+ return baseSha;
1570
+ }
1571
+ __classPrivateFieldGet(this, _SessionMemoryStores_log, "f").info("propagated local deletion", { path: rel, memory_store_id: store.memoryStoreId });
1572
+ return void 0;
1573
+ }, "_SessionMemoryStores_deleteRemote");
1574
+ return SessionMemoryStores2;
1575
+ })();
1576
+ function isErrno(e) {
1577
+ return typeof e === "object" && e !== null && typeof e.code === "string";
1578
+ }
1579
+ __name(isErrno, "isErrno");
1580
+ async function settledOrAborted(p, signal) {
1581
+ if (!signal) {
1582
+ await p;
1583
+ return;
1584
+ }
1585
+ let onAbort;
1586
+ const aborted = new Promise((resolve2) => {
1587
+ onAbort = resolve2;
1588
+ if (signal.aborted)
1589
+ resolve2();
1590
+ });
1591
+ signal.addEventListener("abort", onAbort, { once: true });
1592
+ try {
1593
+ await Promise.race([p, aborted]);
1594
+ } finally {
1595
+ signal.removeEventListener("abort", onAbort);
1596
+ }
1597
+ }
1598
+ __name(settledOrAborted, "settledOrAborted");
1599
+
1600
+ // node_modules/.pnpm/@anthropic-ai+sdk@1.3.0_zod@4.6.7/node_modules/@anthropic-ai/sdk/tools/agent-toolset/node.mjs
1601
+ var _BashSession_instances;
1602
+ var _BashSession_proc;
1603
+ var _BashSession_buf;
1604
+ var _BashSession_truncated;
1605
+ var _BashSession_closed;
1606
+ var _BashSession_waiting;
1607
+ var _BashSession_append;
1608
+ var _LineRangeCollector_instances;
1609
+ var _LineRangeCollector_filePath;
1610
+ var _LineRangeCollector_startLine;
1611
+ var _LineRangeCollector_endLine;
1612
+ var _LineRangeCollector_start;
1613
+ var _LineRangeCollector_end;
1614
+ var _LineRangeCollector_limit;
1615
+ var _LineRangeCollector_line;
1616
+ var _LineRangeCollector_collected;
1617
+ var _LineRangeCollector_collectedBytes;
1618
+ var _LineRangeCollector_collect;
1619
+ var _LineRangeCollector_overLimitError;
1620
+ var BASH_OUTPUT_LIMIT = 100 * 1024;
1621
+ var BASH_DEFAULT_TIMEOUT_MS = 12e4;
1622
+ var DEFAULT_MAX_FILE_BYTES = 256 * 1024;
1623
+ var READ_STREAM_CHUNK_BYTES = 64 * 1024;
1624
+ var NEWLINE = Buffer.from("\n");
1625
+ var GREP_OUTPUT_LIMIT = 100 * 1024;
1626
+ var GREP_MAX_LINE_LENGTH = 2e3;
1627
+ var GLOB_RESULT_LIMIT = 200;
1628
+ var BashTimeoutError = class extends AnthropicError {
1629
+ static {
1630
+ __name(this, "BashTimeoutError");
1631
+ }
1632
+ constructor(timeoutMs) {
1633
+ super(`bash command timed out after ${timeoutMs}ms`);
1634
+ this.name = "BashTimeoutError";
1635
+ this.timeoutMs = timeoutMs;
1636
+ }
1637
+ };
1638
+ var ANSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
1639
+ var fsGlob = fs4.glob;
1640
+ function resolveMaxBytes(configured) {
1641
+ return configured === void 0 ? DEFAULT_MAX_FILE_BYTES : configured;
1642
+ }
1643
+ __name(resolveMaxBytes, "resolveMaxBytes");
1644
+ function rejectUnrestrictedPaths(value) {
1645
+ if (value === void 0)
1646
+ return;
1647
+ throw new AnthropicError("The `unrestrictedPaths` option you passed to the agent toolset (AgentToolContext) is no longer supported. The toolset's file tools (read, write, edit, glob, grep) are now always confined to the working directory plus the directories listed in `allowedRoots`. Remove `unrestrictedPaths` from your context; to let the file tools reach any other directory, add it to `allowedRoots`.");
1648
+ }
1649
+ __name(rejectUnrestrictedPaths, "rejectUnrestrictedPaths");
1650
+ function betaAgentToolset20260401(ctx) {
1651
+ return [
1652
+ betaBashTool(ctx),
1653
+ betaReadTool(ctx),
1654
+ betaWriteTool(ctx),
1655
+ betaEditTool(ctx),
1656
+ betaGlobTool(ctx),
1657
+ betaGrepTool(ctx)
1658
+ ];
1659
+ }
1660
+ __name(betaAgentToolset20260401, "betaAgentToolset20260401");
1661
+ async function resolvePath(ctx, p) {
1662
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
1663
+ return confineToRoot(ctx.workdir, p, { allowedRoots: ctx.allowedRoots ?? [] });
1664
+ }
1665
+ __name(resolvePath, "resolvePath");
1666
+ function readOnlyRootFor(ctx, target) {
1667
+ return containingRoot(ctx.readOnlyRoots ?? [], target);
1668
+ }
1669
+ __name(readOnlyRootFor, "readOnlyRootFor");
1670
+ function scrubbedShellEnv() {
1671
+ const env = {};
1672
+ for (const [key, value] of Object.entries(process.env)) {
1673
+ if (key.startsWith("ANTHROPIC_"))
1674
+ continue;
1675
+ env[key] = value;
1676
+ }
1677
+ return env;
1678
+ }
1679
+ __name(scrubbedShellEnv, "scrubbedShellEnv");
1680
+ var BashSession = /* @__PURE__ */ (() => {
1681
+ class BashSession2 {
1682
+ static {
1683
+ __name(this, "BashSession");
1684
+ }
1685
+ constructor(dir, env = scrubbedShellEnv()) {
1686
+ _BashSession_instances.add(this);
1687
+ _BashSession_proc.set(this, void 0);
1688
+ _BashSession_buf.set(this, "");
1689
+ _BashSession_truncated.set(this, false);
1690
+ _BashSession_closed.set(this, false);
1691
+ _BashSession_waiting.set(this, null);
1692
+ __classPrivateFieldSet(this, _BashSession_proc, cp.spawn("/bin/bash", ["--noprofile", "--norc"], {
1693
+ cwd: dir,
1694
+ // `env` is the full base environment (the scrubbed process env by
1695
+ // default, or the verbatim replacement from `AgentToolContext.env`).
1696
+ // PS1/PS2/TERM are shell-control settings BashSession always applies so
1697
+ // the pipe-based sentinel exec parsing works — not part of the
1698
+ // user-facing environment.
1699
+ env: { ...env, PS1: "", PS2: "", TERM: "dumb" },
1700
+ stdio: ["pipe", "pipe", "pipe"],
1701
+ detached: true
1702
+ }), "f");
1703
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stdout.setEncoding("utf8");
1704
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stderr.setEncoding("utf8");
1705
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stdout.on("data", (d) => __classPrivateFieldGet(this, _BashSession_instances, "m", _BashSession_append).call(this, d));
1706
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stderr.on("data", (d) => __classPrivateFieldGet(this, _BashSession_instances, "m", _BashSession_append).call(this, d));
1707
+ __classPrivateFieldGet(this, _BashSession_proc, "f").once("close", () => {
1708
+ __classPrivateFieldSet(this, _BashSession_closed, true, "f");
1709
+ const w = __classPrivateFieldGet(this, _BashSession_waiting, "f");
1710
+ __classPrivateFieldSet(this, _BashSession_waiting, null, "f");
1711
+ w?.resolve();
1712
+ });
1713
+ }
1714
+ /** Whether the underlying shell process has exited. */
1715
+ get closed() {
1716
+ return __classPrivateFieldGet(this, _BashSession_closed, "f");
1717
+ }
1718
+ async exec(command, opts = {}) {
1719
+ if (__classPrivateFieldGet(this, _BashSession_closed, "f")) {
1720
+ throw new AnthropicError("bash session terminated");
1721
+ }
1722
+ const timeoutMs = opts.timeoutMs ?? BASH_DEFAULT_TIMEOUT_MS;
1723
+ const signal = opts.signal;
1724
+ signal?.throwIfAborted();
1725
+ __classPrivateFieldSet(this, _BashSession_buf, "", "f");
1726
+ __classPrivateFieldSet(this, _BashSession_truncated, false, "f");
1727
+ const sentinel = `__ANT_CMD_${crypto2.randomUUID()}_DONE__`;
1728
+ const sentinelSplit = `${sentinel.slice(0, 8)}''${sentinel.slice(8)}`;
1729
+ const wrapped = `{ ${command}
1730
+ } </dev/null 2>&1; printf '\\n${sentinelSplit}%d\\n' $?
1731
+ `;
1732
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stdin.write(wrapped);
1733
+ if (__classPrivateFieldGet(this, _BashSession_buf, "f").indexOf(sentinel) < 0) {
1734
+ const { promise: sentinelSeen, resolve: resolve2 } = promiseWithResolvers();
1735
+ __classPrivateFieldSet(this, _BashSession_waiting, { sentinel, resolve: resolve2 }, "f");
1736
+ let timer;
1737
+ let onAbort;
1738
+ try {
1739
+ await Promise.race([
1740
+ sentinelSeen,
1741
+ new Promise((_, reject) => {
1742
+ timer = setTimeout(() => reject(new BashTimeoutError(timeoutMs)), timeoutMs);
1743
+ }),
1744
+ new Promise((_, reject) => {
1745
+ if (!signal)
1746
+ return;
1747
+ onAbort = /* @__PURE__ */ __name(() => reject(signal.reason), "onAbort");
1748
+ signal.addEventListener("abort", onAbort, { once: true });
1749
+ })
1750
+ ]);
1751
+ } finally {
1752
+ if (timer)
1753
+ clearTimeout(timer);
1754
+ if (onAbort && signal)
1755
+ signal.removeEventListener("abort", onAbort);
1756
+ __classPrivateFieldSet(this, _BashSession_waiting, null, "f");
1757
+ }
1758
+ }
1759
+ const idx = __classPrivateFieldGet(this, _BashSession_buf, "f").indexOf(sentinel);
1760
+ if (idx < 0) {
1761
+ throw new AnthropicError("bash session terminated");
1762
+ }
1763
+ const tail = __classPrivateFieldGet(this, _BashSession_buf, "f").slice(idx + sentinel.length);
1764
+ const m = tail.match(/^(-?\d+)/);
1765
+ const exitCode = m ? parseInt(m[1], 10) : -1;
1766
+ let out = __classPrivateFieldGet(this, _BashSession_buf, "f").slice(0, idx).replace(ANSI_RE, "").replace(/\n+$/, "");
1767
+ if (__classPrivateFieldGet(this, _BashSession_truncated, "f")) {
1768
+ out = `[output truncated]
1769
+ ${out}`;
1770
+ }
1771
+ return { output: out, exitCode };
1772
+ }
1773
+ close() {
1774
+ if (__classPrivateFieldGet(this, _BashSession_closed, "f"))
1775
+ return;
1776
+ __classPrivateFieldSet(this, _BashSession_closed, true, "f");
1777
+ const w = __classPrivateFieldGet(this, _BashSession_waiting, "f");
1778
+ __classPrivateFieldSet(this, _BashSession_waiting, null, "f");
1779
+ w?.resolve();
1780
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stdout.destroy();
1781
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stderr.destroy();
1782
+ __classPrivateFieldGet(this, _BashSession_proc, "f").stdin.destroy();
1783
+ try {
1784
+ process.kill(-__classPrivateFieldGet(this, _BashSession_proc, "f").pid, "SIGKILL");
1785
+ } catch {
1786
+ __classPrivateFieldGet(this, _BashSession_proc, "f").kill("SIGKILL");
1787
+ }
1788
+ __classPrivateFieldGet(this, _BashSession_proc, "f").unref();
1789
+ }
1790
+ }
1791
+ _BashSession_proc = /* @__PURE__ */ new WeakMap(), _BashSession_buf = /* @__PURE__ */ new WeakMap(), _BashSession_truncated = /* @__PURE__ */ new WeakMap(), _BashSession_closed = /* @__PURE__ */ new WeakMap(), _BashSession_waiting = /* @__PURE__ */ new WeakMap(), _BashSession_instances = /* @__PURE__ */ new WeakSet(), _BashSession_append = /* @__PURE__ */ __name(function _BashSession_append2(d) {
1792
+ __classPrivateFieldSet(this, _BashSession_buf, __classPrivateFieldGet(this, _BashSession_buf, "f") + d, "f");
1793
+ if (__classPrivateFieldGet(this, _BashSession_buf, "f").length > BASH_OUTPUT_LIMIT) {
1794
+ __classPrivateFieldSet(this, _BashSession_buf, __classPrivateFieldGet(this, _BashSession_buf, "f").slice(__classPrivateFieldGet(this, _BashSession_buf, "f").length - BASH_OUTPUT_LIMIT), "f");
1795
+ __classPrivateFieldSet(this, _BashSession_truncated, true, "f");
1796
+ }
1797
+ if (__classPrivateFieldGet(this, _BashSession_waiting, "f") && __classPrivateFieldGet(this, _BashSession_buf, "f").indexOf(__classPrivateFieldGet(this, _BashSession_waiting, "f").sentinel) >= 0) {
1798
+ const w = __classPrivateFieldGet(this, _BashSession_waiting, "f");
1799
+ __classPrivateFieldSet(this, _BashSession_waiting, null, "f");
1800
+ w.resolve();
1801
+ }
1802
+ }, "_BashSession_append");
1803
+ return BashSession2;
1804
+ })();
1805
+ function betaBashTool(ctx) {
1806
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
1807
+ let session;
1808
+ let tail = Promise.resolve();
1809
+ return betaTool({
1810
+ name: "bash",
1811
+ description: "Run a bash command in a persistent shell. State (cwd, env vars) persists across calls.",
1812
+ inputSchema: {
1813
+ type: "object",
1814
+ properties: {
1815
+ command: { type: "string", description: "The command to run" },
1816
+ restart: { type: "boolean", description: "Restart the persistent shell before running" },
1817
+ timeout_ms: { type: "integer", description: "Per-call timeout in milliseconds" }
1818
+ }
1819
+ },
1820
+ run: /* @__PURE__ */ __name(async ({ command, restart, timeout_ms }, context) => {
1821
+ const prev = tail;
1822
+ const gate = promiseWithResolvers();
1823
+ tail = gate.promise;
1824
+ try {
1825
+ await prev;
1826
+ } catch {
1827
+ }
1828
+ try {
1829
+ if (restart) {
1830
+ session?.close();
1831
+ session = void 0;
1832
+ }
1833
+ if (!command) {
1834
+ if (restart)
1835
+ return "bash session restarted";
1836
+ throw new ToolError("bash: command is required");
1837
+ }
1838
+ session ?? (session = new BashSession(ctx.workdir, ctx.env));
1839
+ try {
1840
+ const { output, exitCode } = await session.exec(command, {
1841
+ timeoutMs: timeout_ms ?? BASH_DEFAULT_TIMEOUT_MS,
1842
+ signal: context?.signal
1843
+ });
1844
+ if (exitCode !== 0)
1845
+ throw new ToolError(output || `exit ${exitCode}`);
1846
+ return output;
1847
+ } catch (e) {
1848
+ if (e instanceof ToolError)
1849
+ throw e;
1850
+ session.close();
1851
+ session = void 0;
1852
+ throw new ToolError(`bash: ${e instanceof Error ? e.message : String(e)}`);
1853
+ }
1854
+ } finally {
1855
+ gate.resolve();
1856
+ }
1857
+ }, "run"),
1858
+ close: /* @__PURE__ */ __name(() => {
1859
+ session?.close();
1860
+ session = void 0;
1861
+ }, "close")
1862
+ });
1863
+ }
1864
+ __name(betaBashTool, "betaBashTool");
1865
+ function betaReadTool(ctx) {
1866
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
1867
+ return betaTool({
1868
+ name: "read",
1869
+ description: "Read a UTF-8 text file relative to the workdir.",
1870
+ inputSchema: {
1871
+ type: "object",
1872
+ properties: {
1873
+ file_path: { type: "string" },
1874
+ view_range: {
1875
+ type: "array",
1876
+ items: { type: "integer" },
1877
+ description: "[start_line, end_line] 1-indexed inclusive"
1878
+ }
1879
+ },
1880
+ required: ["file_path"]
1881
+ },
1882
+ run: /* @__PURE__ */ __name(async ({ file_path, view_range }) => {
1883
+ if (!file_path)
1884
+ throw new ToolError("read: file_path is required");
1885
+ const abs = await resolvePath(ctx, file_path);
1886
+ if (view_range?.length && view_range.length !== 2) {
1887
+ throw new ToolError("read: view_range must be [start_line, end_line]");
1888
+ }
1889
+ let data;
1890
+ try {
1891
+ const st = await fs4.stat(abs);
1892
+ if (!st.isFile()) {
1893
+ throw new ToolError(`read: ${file_path} is not a regular file`);
1894
+ }
1895
+ const limit = resolveMaxBytes(ctx.maxFileBytes);
1896
+ if (limit !== null && st.size > limit) {
1897
+ if (!view_range?.length) {
1898
+ throw new ToolError(`read: ${file_path} is ${st.size} bytes, exceeds ${limit}-byte limit. Use the view_range parameter to read specific line ranges, e.g. view_range: [1, 500].`);
1899
+ }
1900
+ const [startLine2, endLine2] = view_range;
1901
+ return await readRangeStreaming(abs, file_path, startLine2, endLine2, limit);
1902
+ }
1903
+ data = await fs4.readFile(abs, "utf8");
1904
+ } catch (e) {
1905
+ if (e instanceof ToolError)
1906
+ throw e;
1907
+ throw new ToolError(`read: ${fsErrorMessage(e, file_path)}`);
1908
+ }
1909
+ if (!view_range?.length)
1910
+ return data;
1911
+ const [startLine, endLine] = view_range;
1912
+ const lines = data.split("\n");
1913
+ const start = Math.max(0, startLine - 1);
1914
+ const end = endLine > 0 ? endLine : lines.length;
1915
+ return lines.slice(start, end).join("\n");
1916
+ }, "run")
1917
+ });
1918
+ }
1919
+ __name(betaReadTool, "betaReadTool");
1920
+ async function readRangeStreaming(abs, filePath, startLine, endLine, limit) {
1921
+ const lines = new LineRangeCollector(filePath, startLine, endLine, limit);
1922
+ if (lines.rangeIsEmpty())
1923
+ return "";
1924
+ const stream2 = fssync.createReadStream(abs, { highWaterMark: READ_STREAM_CHUNK_BYTES });
1925
+ try {
1926
+ for await (const chunk of stream2) {
1927
+ lines.collectFrom(chunk);
1928
+ if (lines.rangeIsCollected())
1929
+ break;
1930
+ }
1931
+ } finally {
1932
+ stream2.destroy();
1933
+ }
1934
+ return lines.text();
1935
+ }
1936
+ __name(readRangeStreaming, "readRangeStreaming");
1937
+ var LineRangeCollector = /* @__PURE__ */ (() => {
1938
+ class LineRangeCollector2 {
1939
+ static {
1940
+ __name(this, "LineRangeCollector");
1941
+ }
1942
+ constructor(filePath, startLine, endLine, limit) {
1943
+ _LineRangeCollector_instances.add(this);
1944
+ _LineRangeCollector_filePath.set(this, void 0);
1945
+ _LineRangeCollector_startLine.set(this, void 0);
1946
+ _LineRangeCollector_endLine.set(this, void 0);
1947
+ _LineRangeCollector_start.set(this, void 0);
1948
+ _LineRangeCollector_end.set(this, void 0);
1949
+ _LineRangeCollector_limit.set(this, void 0);
1950
+ _LineRangeCollector_line.set(this, 0);
1951
+ _LineRangeCollector_collected.set(this, []);
1952
+ _LineRangeCollector_collectedBytes.set(this, 0);
1953
+ __classPrivateFieldSet(this, _LineRangeCollector_filePath, filePath, "f");
1954
+ __classPrivateFieldSet(this, _LineRangeCollector_startLine, startLine, "f");
1955
+ __classPrivateFieldSet(this, _LineRangeCollector_endLine, endLine, "f");
1956
+ __classPrivateFieldSet(this, _LineRangeCollector_start, Math.max(0, startLine - 1), "f");
1957
+ __classPrivateFieldSet(this, _LineRangeCollector_end, endLine > 0 ? endLine : Infinity, "f");
1958
+ __classPrivateFieldSet(this, _LineRangeCollector_limit, limit, "f");
1959
+ }
1960
+ rangeIsEmpty() {
1961
+ return __classPrivateFieldGet(this, _LineRangeCollector_end, "f") <= __classPrivateFieldGet(this, _LineRangeCollector_start, "f");
1962
+ }
1963
+ rangeIsCollected() {
1964
+ return __classPrivateFieldGet(this, _LineRangeCollector_line, "f") >= __classPrivateFieldGet(this, _LineRangeCollector_end, "f");
1965
+ }
1966
+ collectFrom(chunk) {
1967
+ var _a;
1968
+ let lineStart = 0;
1969
+ while (lineStart < chunk.length && !this.rangeIsCollected()) {
1970
+ const newline = chunk.indexOf(10, lineStart);
1971
+ const lineEnd = newline < 0 ? chunk.length : newline;
1972
+ if (__classPrivateFieldGet(this, _LineRangeCollector_line, "f") >= __classPrivateFieldGet(this, _LineRangeCollector_start, "f")) {
1973
+ __classPrivateFieldGet(this, _LineRangeCollector_instances, "m", _LineRangeCollector_collect).call(this, chunk.subarray(lineStart, lineEnd), newline >= 0);
1974
+ }
1975
+ if (newline < 0)
1976
+ break;
1977
+ __classPrivateFieldSet(this, _LineRangeCollector_line, (_a = __classPrivateFieldGet(this, _LineRangeCollector_line, "f"), _a++, _a), "f");
1978
+ lineStart = newline + 1;
1979
+ }
1980
+ }
1981
+ text() {
1982
+ return Buffer.concat(__classPrivateFieldGet(this, _LineRangeCollector_collected, "f"), __classPrivateFieldGet(this, _LineRangeCollector_collectedBytes, "f")).toString("utf8");
1983
+ }
1984
+ }
1985
+ _LineRangeCollector_filePath = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_startLine = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_endLine = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_start = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_end = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_limit = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_line = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_collected = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_collectedBytes = /* @__PURE__ */ new WeakMap(), _LineRangeCollector_instances = /* @__PURE__ */ new WeakSet(), _LineRangeCollector_collect = /* @__PURE__ */ __name(function _LineRangeCollector_collect2(lineBytes, newlineTerminated) {
1986
+ __classPrivateFieldGet(this, _LineRangeCollector_collected, "f").push(lineBytes);
1987
+ __classPrivateFieldSet(this, _LineRangeCollector_collectedBytes, __classPrivateFieldGet(this, _LineRangeCollector_collectedBytes, "f") + lineBytes.length, "f");
1988
+ if (newlineTerminated && __classPrivateFieldGet(this, _LineRangeCollector_line, "f") + 1 < __classPrivateFieldGet(this, _LineRangeCollector_end, "f")) {
1989
+ __classPrivateFieldGet(this, _LineRangeCollector_collected, "f").push(NEWLINE);
1990
+ __classPrivateFieldSet(this, _LineRangeCollector_collectedBytes, __classPrivateFieldGet(this, _LineRangeCollector_collectedBytes, "f") + NEWLINE.length, "f");
1991
+ }
1992
+ if (__classPrivateFieldGet(this, _LineRangeCollector_collectedBytes, "f") > __classPrivateFieldGet(this, _LineRangeCollector_limit, "f"))
1993
+ throw __classPrivateFieldGet(this, _LineRangeCollector_instances, "m", _LineRangeCollector_overLimitError).call(this);
1994
+ }, "_LineRangeCollector_collect"), _LineRangeCollector_overLimitError = /* @__PURE__ */ __name(function _LineRangeCollector_overLimitError2() {
1995
+ if (__classPrivateFieldGet(this, _LineRangeCollector_end, "f") - __classPrivateFieldGet(this, _LineRangeCollector_start, "f") === 1) {
1996
+ return new ToolError(`read: line ${__classPrivateFieldGet(this, _LineRangeCollector_start, "f") + 1} of ${__classPrivateFieldGet(this, _LineRangeCollector_filePath, "f")} alone exceeds ${__classPrivateFieldGet(this, _LineRangeCollector_limit, "f")}-byte limit. The read tool cannot return part of a line, so view_range cannot narrow this further.`);
1997
+ }
1998
+ return new ToolError(`read: view_range [${__classPrivateFieldGet(this, _LineRangeCollector_startLine, "f")}, ${__classPrivateFieldGet(this, _LineRangeCollector_endLine, "f")}] of ${__classPrivateFieldGet(this, _LineRangeCollector_filePath, "f")} exceeds ${__classPrivateFieldGet(this, _LineRangeCollector_limit, "f")}-byte limit. Narrow the view_range to read a smaller portion.`);
1999
+ }, "_LineRangeCollector_overLimitError");
2000
+ return LineRangeCollector2;
2001
+ })();
2002
+ function betaWriteTool(ctx) {
2003
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
2004
+ return betaTool({
2005
+ name: "write",
2006
+ description: "Write a UTF-8 text file relative to the workdir, creating parent directories as needed.",
2007
+ inputSchema: {
2008
+ type: "object",
2009
+ properties: { file_path: { type: "string" }, content: { type: "string" } },
2010
+ required: ["file_path", "content"]
2011
+ },
2012
+ run: /* @__PURE__ */ __name(async ({ file_path, content }) => {
2013
+ if (!file_path)
2014
+ throw new ToolError("write: file_path is required");
2015
+ const abs = await resolvePath(ctx, file_path);
2016
+ const ro = await readOnlyRootFor(ctx, abs);
2017
+ if (ro !== void 0) {
2018
+ throw new ToolError(`write: ${file_path} is inside read-only directory ${ro}`);
2019
+ }
2020
+ try {
2021
+ await fs4.mkdir(path2.dirname(abs), { recursive: true, mode: DIR_CREATE_MODE });
2022
+ await atomicWriteFile(abs, content ?? "");
2023
+ } catch (e) {
2024
+ throw new ToolError(`write: ${fsErrorMessage(e, file_path)}`);
2025
+ }
2026
+ return `wrote ${Buffer.byteLength(content ?? "")} bytes to ${file_path}`;
2027
+ }, "run")
2028
+ });
2029
+ }
2030
+ __name(betaWriteTool, "betaWriteTool");
2031
+ function betaEditTool(ctx) {
2032
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
2033
+ return betaTool({
2034
+ name: "edit",
2035
+ description: "Replace old_string with new_string in a file. old_string must be unique unless replace_all.",
2036
+ inputSchema: {
2037
+ type: "object",
2038
+ properties: {
2039
+ file_path: { type: "string" },
2040
+ old_string: { type: "string" },
2041
+ new_string: { type: "string" },
2042
+ replace_all: { type: "boolean" }
2043
+ },
2044
+ required: ["file_path", "old_string", "new_string"]
2045
+ },
2046
+ run: /* @__PURE__ */ __name(async ({ file_path, old_string, new_string, replace_all }) => {
2047
+ if (!file_path)
2048
+ throw new ToolError("edit: file_path is required");
2049
+ if (!old_string)
2050
+ throw new ToolError("edit: old_string is required");
2051
+ const abs = await resolvePath(ctx, file_path);
2052
+ const ro = await readOnlyRootFor(ctx, abs);
2053
+ if (ro !== void 0) {
2054
+ throw new ToolError(`edit: ${file_path} is inside read-only directory ${ro}`);
2055
+ }
2056
+ let data;
2057
+ try {
2058
+ const st = await fs4.stat(abs);
2059
+ if (!st.isFile()) {
2060
+ throw new ToolError(`edit: ${file_path} is not a regular file`);
2061
+ }
2062
+ const limit = resolveMaxBytes(ctx.maxFileBytes);
2063
+ if (limit !== null && st.size > limit) {
2064
+ throw new ToolError(`edit: ${file_path} is ${st.size} bytes, exceeds ${limit}-byte limit. The edit tool loads the whole file and cannot modify a file this large.`);
2065
+ }
2066
+ data = await fs4.readFile(abs, "utf8");
2067
+ } catch (e) {
2068
+ if (e instanceof ToolError)
2069
+ throw e;
2070
+ throw new ToolError(`edit: ${fsErrorMessage(e, file_path)}`);
2071
+ }
2072
+ const count = data.split(old_string).length - 1;
2073
+ if (count === 0)
2074
+ throw new ToolError(`edit: old_string not found in ${file_path}`);
2075
+ let updated;
2076
+ if (replace_all) {
2077
+ updated = data.split(old_string).join(new_string);
2078
+ } else {
2079
+ if (count > 1)
2080
+ throw new ToolError(`edit: old_string appears ${count} times in ${file_path} (must be unique)`);
2081
+ updated = data.replace(old_string, () => new_string);
2082
+ }
2083
+ try {
2084
+ await atomicWriteFile(abs, updated);
2085
+ } catch (e) {
2086
+ throw new ToolError(`edit: write: ${fsErrorMessage(e, file_path)}`);
2087
+ }
2088
+ return `edited ${file_path} (${replace_all ? count : 1} replacement(s))`;
2089
+ }, "run")
2090
+ });
2091
+ }
2092
+ __name(betaEditTool, "betaEditTool");
2093
+ function patternCanAscend(pattern) {
2094
+ return pattern.split(/[\\/{},]/).includes("..");
2095
+ }
2096
+ __name(patternCanAscend, "patternCanAscend");
2097
+ function betaGlobTool(ctx) {
2098
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
2099
+ return betaTool({
2100
+ name: "glob",
2101
+ description: "Match files under the workdir against a glob pattern. Results are mtime-sorted, newest first.",
2102
+ inputSchema: {
2103
+ type: "object",
2104
+ properties: {
2105
+ pattern: { type: "string" },
2106
+ path: { type: "string", description: "Directory to search in. Defaults to the workdir." }
2107
+ },
2108
+ required: ["pattern"]
2109
+ },
2110
+ run: /* @__PURE__ */ __name(async ({ pattern, path: searchPath }) => {
2111
+ if (!pattern)
2112
+ throw new ToolError("glob: pattern is required");
2113
+ if (path2.isAbsolute(pattern)) {
2114
+ throw new ToolError("glob: absolute pattern not permitted; pass a relative pattern (and optionally path)");
2115
+ }
2116
+ if (patternCanAscend(pattern)) {
2117
+ throw new ToolError('glob: ".." is not permitted in the pattern');
2118
+ }
2119
+ const root = searchPath ? await resolvePath(ctx, searchPath) : path2.resolve(ctx.workdir);
2120
+ const realRoot = searchPath ? root : await canonicalize(root);
2121
+ const matches = [];
2122
+ let remaining = WALK_MAX_ENTRIES;
2123
+ try {
2124
+ for await (const entry of fsGlob(pattern, {
2125
+ cwd: root,
2126
+ withFileTypes: true,
2127
+ exclude: /* @__PURE__ */ __name((d) => d.name === ".git" || d.name === "node_modules", "exclude")
2128
+ })) {
2129
+ if (remaining-- <= 0)
2130
+ break;
2131
+ if (!entry.isFile())
2132
+ continue;
2133
+ const full = path2.join(entry.parentPath, entry.name);
2134
+ let real;
2135
+ try {
2136
+ real = await fs4.realpath(full);
2137
+ } catch {
2138
+ continue;
2139
+ }
2140
+ if (!isWithin(realRoot, real))
2141
+ continue;
2142
+ let mtime = 0;
2143
+ try {
2144
+ mtime = (await fs4.stat(full)).mtimeMs;
2145
+ } catch {
2146
+ }
2147
+ matches.push({ path: full, mtime });
2148
+ }
2149
+ } catch (e) {
2150
+ throw new ToolError(`glob: ${e instanceof Error ? e.message : String(e)}`);
2151
+ }
2152
+ if (matches.length === 0)
2153
+ return "no matches";
2154
+ matches.sort((a, b) => b.mtime - a.mtime);
2155
+ return matches.slice(0, GLOB_RESULT_LIMIT).map((m) => m.path).join("\n");
2156
+ }, "run")
2157
+ });
2158
+ }
2159
+ __name(betaGlobTool, "betaGlobTool");
2160
+ function betaGrepTool(ctx) {
2161
+ rejectUnrestrictedPaths(ctx.unrestrictedPaths);
2162
+ return betaTool({
2163
+ name: "grep",
2164
+ description: "Search file contents for a regex. Uses ripgrep if available, otherwise a built-in walker.",
2165
+ inputSchema: {
2166
+ type: "object",
2167
+ properties: { pattern: { type: "string" }, path: { type: "string" } },
2168
+ required: ["pattern"]
2169
+ },
2170
+ run: /* @__PURE__ */ __name(async ({ pattern, path: p }, context) => {
2171
+ if (!pattern)
2172
+ throw new ToolError("grep: pattern is required");
2173
+ let searchPath = path2.resolve(ctx.workdir);
2174
+ if (p)
2175
+ searchPath = await resolvePath(ctx, p);
2176
+ const rg = await findRg();
2177
+ return rg ? runRipgrep(rg, pattern, searchPath, context?.signal) : runWalkGrep(pattern, searchPath, context?.signal);
2178
+ }, "run")
2179
+ });
2180
+ }
2181
+ __name(betaGrepTool, "betaGrepTool");
2182
+ function runRipgrep(rg, pattern, searchPath, signal) {
2183
+ return new Promise((resolve2, reject) => {
2184
+ const proc = cp.spawn(rg, ["-n", "--no-heading", "-e", pattern, "--", searchPath], {
2185
+ ...signal ? { signal } : {}
2186
+ });
2187
+ let out = "";
2188
+ let errOut = "";
2189
+ let truncated = false;
2190
+ proc.stdout.on("data", (d) => {
2191
+ if (truncated)
2192
+ return;
2193
+ out += d;
2194
+ if (out.length > GREP_OUTPUT_LIMIT) {
2195
+ truncated = true;
2196
+ out = out.slice(0, GREP_OUTPUT_LIMIT);
2197
+ proc.kill("SIGKILL");
2198
+ }
2199
+ });
2200
+ proc.stderr.on("data", (d) => errOut += d);
2201
+ proc.on("close", (code) => {
2202
+ if (signal?.aborted)
2203
+ return reject(new ToolError("grep: aborted"));
2204
+ if (truncated)
2205
+ return resolve2(out + `
2206
+ [output truncated at ${GREP_OUTPUT_LIMIT} bytes]`);
2207
+ if (code === 0)
2208
+ return resolve2(out);
2209
+ if (code === 1)
2210
+ return resolve2("no matches");
2211
+ reject(new ToolError(`grep: rg failed: ${errOut || `exit ${code}`}`));
2212
+ });
2213
+ proc.on("error", (e) => {
2214
+ if (signal?.aborted)
2215
+ return reject(new ToolError("grep: aborted"));
2216
+ reject(new ToolError(`grep: rg failed: ${e.message}`));
2217
+ });
2218
+ });
2219
+ }
2220
+ __name(runRipgrep, "runRipgrep");
2221
+ async function runWalkGrep(pattern, root, signal) {
2222
+ let re;
2223
+ try {
2224
+ re = new RegExp(pattern);
2225
+ } catch (e) {
2226
+ throw new ToolError(`grep: invalid regex: ${e instanceof Error ? e.message : String(e)}`);
2227
+ }
2228
+ const hits = [];
2229
+ let budget = GREP_OUTPUT_LIMIT;
2230
+ const push = /* @__PURE__ */ __name((line) => {
2231
+ budget -= line.length + 1;
2232
+ if (budget < 0) {
2233
+ hits.push(`[output truncated at ${GREP_OUTPUT_LIMIT} bytes]`);
2234
+ return false;
2235
+ }
2236
+ hits.push(line);
2237
+ return true;
2238
+ }, "push");
2239
+ const stat2 = await fs4.stat(root).catch(() => null);
2240
+ if (stat2?.isFile()) {
2241
+ await grepFile(root, re, push);
2242
+ } else {
2243
+ await walk2(root, "", (rel) => grepFile(path2.join(root, rel), re, push), signal);
2244
+ }
2245
+ if (signal?.aborted)
2246
+ throw new ToolError("grep: aborted");
2247
+ if (hits.length === 0)
2248
+ return "no matches";
2249
+ return hits.join("\n");
2250
+ }
2251
+ __name(runWalkGrep, "runWalkGrep");
2252
+ async function grepFile(file, re, push) {
2253
+ const stream2 = fssync.createReadStream(file, { encoding: "utf8" });
2254
+ const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
2255
+ let i = 0;
2256
+ try {
2257
+ for await (const line of rl) {
2258
+ i++;
2259
+ if (line.length > GREP_MAX_LINE_LENGTH)
2260
+ continue;
2261
+ if (re.test(line) && !push(`${file}:${i}:${line}`))
2262
+ return false;
2263
+ }
2264
+ } catch {
2265
+ } finally {
2266
+ stream2.destroy();
2267
+ }
2268
+ return true;
2269
+ }
2270
+ __name(grepFile, "grepFile");
2271
+ var WALK_MAX_DEPTH = 40;
2272
+ var WALK_MAX_ENTRIES = 5e4;
2273
+ async function walk2(root, rel, fn, signal) {
2274
+ let remaining = WALK_MAX_ENTRIES;
2275
+ async function inner(rel2, depth) {
2276
+ if (depth > WALK_MAX_DEPTH)
2277
+ return true;
2278
+ if (signal?.aborted)
2279
+ return false;
2280
+ let entries;
2281
+ try {
2282
+ entries = await fs4.readdir(path2.join(root, rel2), { withFileTypes: true });
2283
+ } catch {
2284
+ return true;
2285
+ }
2286
+ for (const e of entries) {
2287
+ if (e.name === ".git" || e.name === "node_modules")
2288
+ continue;
2289
+ if (remaining-- <= 0)
2290
+ return false;
2291
+ if (signal?.aborted)
2292
+ return false;
2293
+ const childRel = rel2 ? path2.join(rel2, e.name) : e.name;
2294
+ if (e.isDirectory()) {
2295
+ if (!await inner(childRel, depth + 1))
2296
+ return false;
2297
+ } else if (e.isFile()) {
2298
+ if (await fn(childRel) === false)
2299
+ return false;
2300
+ }
2301
+ }
2302
+ return true;
2303
+ }
2304
+ __name(inner, "inner");
2305
+ await inner(rel, 0);
2306
+ }
2307
+ __name(walk2, "walk");
2308
+ async function findRg() {
2309
+ const dirs = (process.env["PATH"] ?? "").split(path2.delimiter);
2310
+ for (const d of dirs) {
2311
+ const candidate = path2.join(d, "rg");
2312
+ try {
2313
+ await fs4.access(candidate, fssync.constants.X_OK);
2314
+ return candidate;
2315
+ } catch {
2316
+ }
2317
+ }
2318
+ return null;
2319
+ }
2320
+ __name(findRg, "findRg");
2321
+ export {
2322
+ BashSession,
2323
+ BashTimeoutError,
2324
+ DEFAULT_MEMORY_SYNC_INTERVAL_MS,
2325
+ MARKER_PATH,
2326
+ MEMORY_FLUSH_TIMEOUT_MS,
2327
+ MIN_MEMORY_SYNC_INTERVAL_MS,
2328
+ SessionMemoryError,
2329
+ SessionMemoryStores,
2330
+ betaAgentToolset20260401,
2331
+ betaBashTool,
2332
+ betaEditTool,
2333
+ betaGlobTool,
2334
+ betaGrepTool,
2335
+ betaReadTool,
2336
+ betaWriteTool,
2337
+ extractSkillArchive,
2338
+ resolvePath,
2339
+ setupSkills
2340
+ };