@cursor/july 0.1.103 → 0.1.104

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 (186) hide show
  1. package/dist/channels/change-monitors/change-monitors-channel.d.ts +5 -0
  2. package/dist/channels/change-monitors/change-monitors-channel.d.ts.map +1 -0
  3. package/dist/channels/change-monitors/change-monitors-channel.js +41 -0
  4. package/dist/channels/change-monitors/index.d.ts +4 -0
  5. package/dist/channels/change-monitors/index.d.ts.map +1 -0
  6. package/dist/channels/change-monitors/index.js +2 -0
  7. package/dist/channels/change-monitors/types.d.ts +39 -0
  8. package/dist/channels/change-monitors/types.d.ts.map +1 -0
  9. package/dist/channels/change-monitors/types.js +1 -0
  10. package/dist/channels/github/defaults.d.ts.map +1 -1
  11. package/dist/channels/github/defaults.js +4 -0
  12. package/dist/channels/github/progress.d.ts +22 -0
  13. package/dist/channels/github/progress.d.ts.map +1 -1
  14. package/dist/channels/github/progress.js +32 -5
  15. package/dist/channels/issues/index.d.ts +4 -0
  16. package/dist/channels/issues/index.d.ts.map +1 -0
  17. package/dist/channels/issues/index.js +2 -0
  18. package/dist/channels/issues/issues-channel.d.ts +5 -0
  19. package/dist/channels/issues/issues-channel.d.ts.map +1 -0
  20. package/dist/channels/issues/issues-channel.js +37 -0
  21. package/dist/channels/issues/types.d.ts +33 -0
  22. package/dist/channels/issues/types.d.ts.map +1 -0
  23. package/dist/channels/issues/types.js +1 -0
  24. package/dist/docs/404.html +2 -2
  25. package/dist/docs/ab.html +4 -4
  26. package/dist/docs/assets/{app.DW9pXkpL.js → app.DbMWUyGb.js} +1 -1
  27. package/dist/docs/assets/chunks/@localSearchIndexroot.Bqsulb9K.js +1 -0
  28. package/dist/docs/assets/chunks/{VPLocalSearchBox.CdEIUwDg.js → VPLocalSearchBox.DcNeTh9o.js} +1 -1
  29. package/dist/docs/assets/chunks/{theme.YZMHgPgg.js → theme.DMjhY3gl.js} +2 -2
  30. package/dist/docs/assets/{guides_github.md.DKYiT9do.js → guides_github.md.c0gdGJ-D.js} +1 -1
  31. package/dist/docs/assets/{guides_github.md.DKYiT9do.lean.js → guides_github.md.c0gdGJ-D.lean.js} +1 -1
  32. package/dist/docs/assets/{reference_channels.md.Dz8Cnudp.js → reference_channels.md.DBGcaB7m.js} +2 -2
  33. package/dist/docs/assets/{reference_channels.md.Dz8Cnudp.lean.js → reference_channels.md.DBGcaB7m.lean.js} +1 -1
  34. package/dist/docs/building-with-agents.html +4 -4
  35. package/dist/docs/concepts.html +4 -4
  36. package/dist/docs/deployment.html +4 -4
  37. package/dist/docs/design/filesystem.md +376 -0
  38. package/dist/docs/evals.html +4 -4
  39. package/dist/docs/guides/agent-to-agent.html +4 -4
  40. package/dist/docs/guides/cloud-agents.html +4 -4
  41. package/dist/docs/guides/convert-automation.html +4 -4
  42. package/dist/docs/guides/github.html +6 -6
  43. package/dist/docs/guides/github.md +5 -0
  44. package/dist/docs/guides/human-in-the-loop.html +4 -4
  45. package/dist/docs/guides/mcp-oauth.html +4 -4
  46. package/dist/docs/guides/opentelemetry.html +4 -4
  47. package/dist/docs/guides/slack.html +4 -4
  48. package/dist/docs/guides/webhooks.html +4 -4
  49. package/dist/docs/hashmap.json +1 -1
  50. package/dist/docs/hillclimbing.html +4 -4
  51. package/dist/docs/index.html +4 -4
  52. package/dist/docs/llms-full.txt +406 -0
  53. package/dist/docs/llms.txt +1 -0
  54. package/dist/docs/quickstart.html +4 -4
  55. package/dist/docs/reference/agent-config.html +4 -4
  56. package/dist/docs/reference/artifacts.html +4 -4
  57. package/dist/docs/reference/channels.html +6 -6
  58. package/dist/docs/reference/channels.md +20 -0
  59. package/dist/docs/reference/cli.html +4 -4
  60. package/dist/docs/reference/connections.html +4 -4
  61. package/dist/docs/reference/extensions.html +4 -4
  62. package/dist/docs/reference/hooks.html +4 -4
  63. package/dist/docs/reference/http-api.html +4 -4
  64. package/dist/docs/reference/instructions.html +4 -4
  65. package/dist/docs/reference/playground.html +4 -4
  66. package/dist/docs/reference/project-layout.html +4 -4
  67. package/dist/docs/reference/prompt.html +4 -4
  68. package/dist/docs/reference/result.html +4 -4
  69. package/dist/docs/reference/schedules.html +4 -4
  70. package/dist/docs/reference/sessions.html +4 -4
  71. package/dist/docs/reference/skills.html +4 -4
  72. package/dist/docs/reference/subagents.html +4 -4
  73. package/dist/docs/reference/tools.html +4 -4
  74. package/dist/docs/scaffolding-agents.html +4 -4
  75. package/dist/docs/skills/ab.html +4 -4
  76. package/dist/docs/skills/create-agent.html +4 -4
  77. package/dist/docs/skills/debug.html +4 -4
  78. package/dist/docs/skills/evals.html +4 -4
  79. package/dist/docs/skills/framework-map.html +4 -4
  80. package/dist/docs/skills/github.html +4 -4
  81. package/dist/docs/skills/hillclimb.html +4 -4
  82. package/dist/docs/skills/index.html +4 -4
  83. package/dist/docs/skills/mcp-auth.html +4 -4
  84. package/dist/docs/skills/otel.html +4 -4
  85. package/dist/docs/skills/setup-slack.html +4 -4
  86. package/dist/docs/storage.html +4 -4
  87. package/dist/docs/templates/agentic-owners.html +4 -4
  88. package/dist/docs/templates/agents-md.html +4 -4
  89. package/dist/docs/templates/code-wiki.html +4 -4
  90. package/dist/docs/templates/demo.html +4 -4
  91. package/dist/docs/templates/pr-autofixer.html +4 -4
  92. package/dist/docs/templates/security-help.html +4 -4
  93. package/dist/docs/templates/security-reviewer.html +4 -4
  94. package/dist/docs/templates/triage.html +4 -4
  95. package/dist/docs/troubleshooting.html +4 -4
  96. package/dist/filesystem.d.ts +440 -0
  97. package/dist/filesystem.d.ts.map +1 -0
  98. package/dist/filesystem.js +1694 -0
  99. package/dist/index.d.ts +2 -0
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +1 -0
  102. package/dist/internal/continuation-channel.d.ts +4 -2
  103. package/dist/internal/continuation-channel.d.ts.map +1 -1
  104. package/dist/internal/continuation-channel.js +21 -12
  105. package/dist/internal/continuation-identity.d.ts +13 -5
  106. package/dist/internal/continuation-identity.d.ts.map +1 -1
  107. package/dist/internal/continuation-identity.js +74 -35
  108. package/dist/internal/discovery/agent.d.ts.map +1 -1
  109. package/dist/internal/discovery/agent.js +80 -8
  110. package/dist/internal/discovery/info.d.ts.map +1 -1
  111. package/dist/internal/discovery/info.js +3 -0
  112. package/dist/internal/factory-resource-channel.d.ts +33 -0
  113. package/dist/internal/factory-resource-channel.d.ts.map +1 -0
  114. package/dist/internal/factory-resource-channel.js +77 -0
  115. package/dist/internal/filesystem/errors.d.ts +64 -0
  116. package/dist/internal/filesystem/errors.d.ts.map +1 -0
  117. package/dist/internal/filesystem/errors.js +175 -0
  118. package/dist/internal/filesystem/format.d.ts +28 -0
  119. package/dist/internal/filesystem/format.d.ts.map +1 -0
  120. package/dist/internal/filesystem/format.js +213 -0
  121. package/dist/internal/filesystem/merge.d.ts +34 -0
  122. package/dist/internal/filesystem/merge.d.ts.map +1 -0
  123. package/dist/internal/filesystem/merge.js +196 -0
  124. package/dist/internal/filesystem/scratch.d.ts +59 -0
  125. package/dist/internal/filesystem/scratch.d.ts.map +1 -0
  126. package/dist/internal/filesystem/scratch.js +212 -0
  127. package/dist/internal/filesystem/sdk-schemas.d.ts +29 -0
  128. package/dist/internal/filesystem/sdk-schemas.d.ts.map +1 -0
  129. package/dist/internal/filesystem/sdk-schemas.js +153 -0
  130. package/dist/internal/filesystem/tools.d.ts +42 -0
  131. package/dist/internal/filesystem/tools.d.ts.map +1 -0
  132. package/dist/internal/filesystem/tools.js +618 -0
  133. package/dist/internal/filesystem/walk.d.ts +74 -0
  134. package/dist/internal/filesystem/walk.d.ts.map +1 -0
  135. package/dist/internal/filesystem/walk.js +339 -0
  136. package/dist/internal/guest-network.d.ts +5 -2
  137. package/dist/internal/guest-network.d.ts.map +1 -1
  138. package/dist/internal/guest-network.js +7 -2
  139. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  140. package/dist/internal/hosted-delivery.js +12 -2
  141. package/dist/internal/sdk-runner.d.ts +1 -1
  142. package/dist/internal/sdk-runner.d.ts.map +1 -1
  143. package/dist/internal/sdk-runner.js +3 -1
  144. package/dist/internal/session-engine.d.ts +22 -0
  145. package/dist/internal/session-engine.d.ts.map +1 -1
  146. package/dist/internal/session-engine.js +362 -40
  147. package/dist/internal/testing/factory-resource-fixtures.d.ts +48 -0
  148. package/dist/internal/testing/factory-resource-fixtures.d.ts.map +1 -0
  149. package/dist/internal/testing/factory-resource-fixtures.js +41 -0
  150. package/dist/playground/assets/{index-59KvgREd.js → index-8YiozU89.js} +38 -38
  151. package/dist/playground/index.html +1 -1
  152. package/dist/types.d.ts +51 -3
  153. package/dist/types.d.ts.map +1 -1
  154. package/docs/design/filesystem.md +376 -0
  155. package/docs/guides/github.md +5 -0
  156. package/docs/reference/channels.md +20 -0
  157. package/package.json +16 -2
  158. package/src/channels/change-monitors/change-monitors-channel.ts +62 -0
  159. package/src/channels/change-monitors/index.ts +8 -0
  160. package/src/channels/change-monitors/types.ts +44 -0
  161. package/src/channels/github/defaults.ts +4 -0
  162. package/src/channels/github/progress.ts +76 -10
  163. package/src/channels/issues/index.ts +9 -0
  164. package/src/channels/issues/issues-channel.ts +51 -0
  165. package/src/channels/issues/types.ts +41 -0
  166. package/src/filesystem.ts +2074 -0
  167. package/src/index.ts +28 -0
  168. package/src/internal/continuation-channel.ts +29 -12
  169. package/src/internal/continuation-identity.ts +122 -37
  170. package/src/internal/discovery/agent.ts +87 -1
  171. package/src/internal/discovery/info.ts +3 -0
  172. package/src/internal/factory-resource-channel.ts +122 -0
  173. package/src/internal/filesystem/errors.ts +220 -0
  174. package/src/internal/filesystem/format.ts +276 -0
  175. package/src/internal/filesystem/merge.ts +195 -0
  176. package/src/internal/filesystem/scratch.ts +255 -0
  177. package/src/internal/filesystem/sdk-schemas.ts +204 -0
  178. package/src/internal/filesystem/tools.ts +821 -0
  179. package/src/internal/filesystem/walk.ts +369 -0
  180. package/src/internal/guest-network.ts +8 -2
  181. package/src/internal/hosted-delivery.ts +18 -1
  182. package/src/internal/sdk-runner.ts +4 -0
  183. package/src/internal/session-engine.ts +439 -29
  184. package/src/internal/testing/factory-resource-fixtures.ts +85 -0
  185. package/src/types.ts +49 -3
  186. package/dist/docs/assets/chunks/@localSearchIndexroot.nrl1ifBq.js +0 -1
@@ -0,0 +1,1694 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
22
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
23
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
24
+ var m = o[Symbol.asyncIterator], i;
25
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
26
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
27
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
28
+ };
29
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
30
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
31
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
32
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
33
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
34
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
35
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
36
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
37
+ function fulfill(value) { resume("next", value); }
38
+ function reject(value) { resume("throw", value); }
39
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
40
+ };
41
+ var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
42
+ var i, p;
43
+ return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
44
+ function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
45
+ };
46
+ import { Buffer } from "node:buffer";
47
+ import { mkdir, readdir, readFile, rm, stat, writeFile, } from "node:fs/promises";
48
+ import path from "node:path";
49
+ import { minimatch } from "minimatch";
50
+ import { FileConflictError } from "./files.js";
51
+ import { EditError, FileNotFoundError, InvalidGrepPatternError, isFileNotFoundError, isInvalidGrepPatternError, NoMountError, PathError, ReadOnlyMountError, remapPathError, WriteFailedError, } from "./internal/filesystem/errors.js";
52
+ import { MEMORY_DIR_NAME } from "./memory.js";
53
+ export { DeleteNotSupportedError, EditError, FileNotFoundError, InvalidGrepPatternError, isFileNotFoundError, isInvalidGrepPatternError, NoMountError, PathError, ReadOnlyMountError, WriteFailedError, } from "./internal/filesystem/errors.js";
54
+ import { mergeSorted } from "./internal/filesystem/merge.js";
55
+ import { listFilesFromPaths, mergeSortedByPath, statFromFilePaths, } from "./internal/filesystem/walk.js";
56
+ export const FILE_SYSTEM_TOOL_NAMES = [
57
+ "Read",
58
+ "LS",
59
+ "Glob",
60
+ "Grep",
61
+ "Write",
62
+ "StrReplace",
63
+ "Delete",
64
+ "SemanticSearch",
65
+ ];
66
+ const FILE_SYSTEM_TOOL_NAME_SET = new Set(FILE_SYSTEM_TOOL_NAMES);
67
+ const FILE_SYSTEM_TOOL_ALIASES = {
68
+ read: "Read",
69
+ Read: "Read",
70
+ ls: "LS",
71
+ LS: "LS",
72
+ glob: "Glob",
73
+ Glob: "Glob",
74
+ grep: "Grep",
75
+ Grep: "Grep",
76
+ write: "Write",
77
+ Write: "Write",
78
+ edit: "StrReplace",
79
+ StrReplace: "StrReplace",
80
+ delete: "Delete",
81
+ Delete: "Delete",
82
+ semSearch: "SemanticSearch",
83
+ SemanticSearch: "SemanticSearch",
84
+ };
85
+ export function canonicalizeFileSystemToolName(name) {
86
+ return FILE_SYSTEM_TOOL_ALIASES[name];
87
+ }
88
+ export function isFileSystemToolName(name) {
89
+ return FILE_SYSTEM_TOOL_NAME_SET.has(name);
90
+ }
91
+ export function isFileSystemToolAlias(name) {
92
+ return canonicalizeFileSystemToolName(name) !== undefined;
93
+ }
94
+ /** Direct `callTool` names that mutate the tree and must wait on a busy turn. */
95
+ export function isMutatingFileSystemTool(name) {
96
+ const canonical = canonicalizeFileSystemToolName(name);
97
+ return (canonical === "Write" ||
98
+ canonical === "StrReplace" ||
99
+ canonical === "Delete");
100
+ }
101
+ export function isFileSystemMethodPresent(root, method) {
102
+ return typeof root[method] === "function";
103
+ }
104
+ const ADVERTISED_FILE_SYSTEM_TOOL_NAMES = [
105
+ "Read",
106
+ "LS",
107
+ "Glob",
108
+ "Grep",
109
+ "Write",
110
+ "StrReplace",
111
+ "Delete",
112
+ "SemanticSearch",
113
+ ];
114
+ export function fileSystemToolNames(_root) {
115
+ return [...ADVERTISED_FILE_SYSTEM_TOOL_NAMES];
116
+ }
117
+ function fileSystemMethodForTool(name) {
118
+ switch (name) {
119
+ case "Read":
120
+ return "read";
121
+ case "LS":
122
+ return "list";
123
+ case "Glob":
124
+ return "glob";
125
+ case "Grep":
126
+ return "grep";
127
+ case "Write":
128
+ case "StrReplace":
129
+ return "write";
130
+ case "Delete":
131
+ return "delete";
132
+ case "SemanticSearch":
133
+ return "search";
134
+ }
135
+ }
136
+ function fileSystemSatisfiesFileTool(root, name) {
137
+ const canonical = canonicalizeFileSystemToolName(name);
138
+ if (canonical === undefined) {
139
+ return true;
140
+ }
141
+ const method = fileSystemMethodForTool(canonical);
142
+ return method !== undefined && isFileSystemMethodPresent(root, method);
143
+ }
144
+ export class FileSystemConfigError extends Error {
145
+ constructor(message) {
146
+ super(message);
147
+ this.name = "FileSystemConfigError";
148
+ }
149
+ }
150
+ function allowlistHas(tools, ...names) {
151
+ return tools.some((name) => names.includes(name));
152
+ }
153
+ export function resolveRootHarnessAllowlist(tools) {
154
+ if (tools === undefined) {
155
+ // File verbs are synthesized, including SemanticSearch from
156
+ // `search`. Web tools are safe under the `/tmp` scratch
157
+ // overlay. Todos are harness conversation state. Do not
158
+ // unlock shell or task.
159
+ return ["webSearch", "webFetch", "updateTodos", "readTodos", "mcp"];
160
+ }
161
+ if (allowlistHas(tools, "shell", "Shell")) {
162
+ throw new FileSystemConfigError('`root` cannot be combined with `tools` containing `"shell"`. ' +
163
+ "Shell is not a FileSystem method and must not bind the host shell onto a virtual tree.");
164
+ }
165
+ if (allowlistHas(tools, "task", "Task")) {
166
+ throw new FileSystemConfigError("`root` cannot list `task`: a child keeps the host toolset and " +
167
+ "would read the real workspace. Sharing `root` with subagents " +
168
+ "needs a Cursor SDK inherit, not an overridden Task tool.");
169
+ }
170
+ if (allowlistHas(tools, "readLints", "ReadLints")) {
171
+ throw new FileSystemConfigError("`root` cannot list `readLints`: FileSystem has no diagnostics " +
172
+ "verb, so the host language service would run against the real workspace.");
173
+ }
174
+ const extras = tools.filter((name) => !isFileSystemToolAlias(name));
175
+ return withMcpGrant(extras);
176
+ }
177
+ export function resolveFileSystemTools(options) {
178
+ const harness = resolveRootHarnessAllowlist(options.tools);
179
+ if (options.tools === undefined) {
180
+ return harness;
181
+ }
182
+ const implemented = fileSystemToolNames(options.root);
183
+ const missing = [];
184
+ for (const name of options.tools) {
185
+ if (!fileSystemSatisfiesFileTool(options.root, name)) {
186
+ missing.push(name);
187
+ }
188
+ }
189
+ if (missing.length > 0) {
190
+ throw new FileSystemConfigError(`\`tools\` names FileSystem method(s) that are not implemented: ${missing.join(", ")}. ` +
191
+ `Implemented file tools: ${implemented.length > 0 ? implemented.join(", ") : "(none)"}.`);
192
+ }
193
+ return harness;
194
+ }
195
+ export function withMcpGrant(tools) {
196
+ return tools.includes("mcp") ? [...tools] : [...tools, "mcp"];
197
+ }
198
+ /**
199
+ * Native Cursor SDK file tools replaced by synthesized FileSystem tools
200
+ * on every local turn. SDK allowlist names (`edit`, not `Write`).
201
+ */
202
+ export const REPLACED_NATIVE_FILE_TOOLS = [
203
+ "read",
204
+ "ls",
205
+ "grep",
206
+ "glob",
207
+ "edit",
208
+ "delete",
209
+ ];
210
+ /**
211
+ * Host-default harness options: keep shell / webSearch / sandbox, but
212
+ * hide the native file tools the synthesized FileSystem now owns.
213
+ *
214
+ * Omitted `tools` leaves the SDK default set and only excludes the
215
+ * replaced natives. `[]` stays empty. A non-empty allowlist drops file
216
+ * aliases (those ride synthesized tools) and grants `mcp`.
217
+ */
218
+ export function resolveHostHarnessToolOptions(tools) {
219
+ if (tools === undefined) {
220
+ return { disallowedTools: [...REPLACED_NATIVE_FILE_TOOLS] };
221
+ }
222
+ if (tools.length === 0) {
223
+ return { tools: [] };
224
+ }
225
+ return {
226
+ tools: withMcpGrant(tools.filter((name) => !isReplacedHostFileAlias(name))),
227
+ };
228
+ }
229
+ /** File aliases host-default synthesizes. Native `semSearch` stays. */
230
+ function isReplacedHostFileAlias(name) {
231
+ const canonical = canonicalizeFileSystemToolName(name);
232
+ return canonical !== undefined && canonical !== "SemanticSearch";
233
+ }
234
+ /** Decode a {@link FileSystem.read} result as UTF-8 text. */
235
+ export function fileSystemText(content) {
236
+ return typeof content === "string"
237
+ ? content
238
+ : Buffer.from(content).toString("utf8");
239
+ }
240
+ /**
241
+ * Native Read image formats. Magic bytes first, then extension.
242
+ * Returns undefined for text (and for any other binary).
243
+ */
244
+ export function detectImageMimeType(bytes, filePath) {
245
+ if (bytes.length >= 3 &&
246
+ bytes[0] === 0xff &&
247
+ bytes[1] === 0xd8 &&
248
+ bytes[2] === 0xff) {
249
+ return "image/jpeg";
250
+ }
251
+ if (bytes.length >= 8 &&
252
+ bytes[0] === 0x89 &&
253
+ bytes[1] === 0x50 &&
254
+ bytes[2] === 0x4e &&
255
+ bytes[3] === 0x47) {
256
+ return "image/png";
257
+ }
258
+ if (bytes.length >= 6 &&
259
+ bytes[0] === 0x47 &&
260
+ bytes[1] === 0x49 &&
261
+ bytes[2] === 0x46) {
262
+ return "image/gif";
263
+ }
264
+ if (bytes.length >= 12 &&
265
+ bytes[0] === 0x52 &&
266
+ bytes[1] === 0x49 &&
267
+ bytes[2] === 0x46 &&
268
+ bytes[3] === 0x46 &&
269
+ bytes[8] === 0x57 &&
270
+ bytes[9] === 0x45 &&
271
+ bytes[10] === 0x42 &&
272
+ bytes[11] === 0x50) {
273
+ return "image/webp";
274
+ }
275
+ if (filePath === undefined) {
276
+ return undefined;
277
+ }
278
+ const lower = filePath.toLowerCase();
279
+ if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) {
280
+ return "image/jpeg";
281
+ }
282
+ if (lower.endsWith(".png")) {
283
+ return "image/png";
284
+ }
285
+ if (lower.endsWith(".gif")) {
286
+ return "image/gif";
287
+ }
288
+ if (lower.endsWith(".webp")) {
289
+ return "image/webp";
290
+ }
291
+ return undefined;
292
+ }
293
+ export function fileSystemImage(content, path) {
294
+ if (!(content instanceof Uint8Array)) {
295
+ return undefined;
296
+ }
297
+ const mimeType = detectImageMimeType(content, path);
298
+ if (mimeType === undefined) {
299
+ return undefined;
300
+ }
301
+ return { mimeType, bytes: content };
302
+ }
303
+ function compileGrepPattern(pattern, caseInsensitive, path = "/") {
304
+ try {
305
+ return new RegExp(pattern, caseInsensitive === true ? "i" : undefined);
306
+ }
307
+ catch (_a) {
308
+ throw new InvalidGrepPatternError(pattern, path);
309
+ }
310
+ }
311
+ function* grepFileContent(args) {
312
+ const lines = args.content.split("\n");
313
+ for (let i = 0; i < lines.length; i++) {
314
+ const line = lines[i];
315
+ if (args.regex.test(line)) {
316
+ yield { path: args.path, lineNumber: i + 1, line };
317
+ }
318
+ }
319
+ }
320
+ function normalizeMaxResults(maxResults) {
321
+ if (maxResults === undefined || !Number.isFinite(maxResults)) {
322
+ return undefined;
323
+ }
324
+ return Math.max(0, Math.floor(maxResults));
325
+ }
326
+ function limitResults(source, maxResults) {
327
+ return __asyncGenerator(this, arguments, function* limitResults_1() {
328
+ var _a, e_1, _b, _c;
329
+ const cap = normalizeMaxResults(maxResults);
330
+ if (cap === 0) {
331
+ return yield __await(void 0);
332
+ }
333
+ let n = 0;
334
+ try {
335
+ for (var _d = true, source_1 = __asyncValues(source), source_1_1; source_1_1 = yield __await(source_1.next()), _a = source_1_1.done, !_a; _d = true) {
336
+ _c = source_1_1.value;
337
+ _d = false;
338
+ const item = _c;
339
+ yield yield __await(item);
340
+ n++;
341
+ if (cap !== undefined && n >= cap) {
342
+ return yield __await(void 0);
343
+ }
344
+ }
345
+ }
346
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
347
+ finally {
348
+ try {
349
+ if (!_d && !_a && (_b = source_1.return)) yield __await(_b.call(source_1));
350
+ }
351
+ finally { if (e_1) throw e_1.error; }
352
+ }
353
+ });
354
+ }
355
+ function grepPushdownLimit(query, opts) {
356
+ // Count and files_with_matches paginate after grouping by file.
357
+ // A line-level cap would hide later files once one file fills the window.
358
+ if (opts.outputMode === "count" || opts.outputMode === "files_with_matches") {
359
+ return query.maxResults;
360
+ }
361
+ const headLimit = opts.headLimit !== undefined && opts.headLimit > 0
362
+ ? opts.headLimit
363
+ : undefined;
364
+ if (headLimit === undefined) {
365
+ return query.maxResults;
366
+ }
367
+ const toolCap = opts.offset + headLimit;
368
+ return query.maxResults === undefined
369
+ ? toolCap
370
+ : Math.min(query.maxResults, toolCap);
371
+ }
372
+ function compareGrepResult(left, right) {
373
+ return left.path < right.path
374
+ ? -1
375
+ : left.path > right.path
376
+ ? 1
377
+ : left.lineNumber - right.lineNumber;
378
+ }
379
+ function compareSearchResult(left, right) {
380
+ if (right.score !== left.score) {
381
+ return right.score - left.score;
382
+ }
383
+ return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;
384
+ }
385
+ export function collectGrepMatches(root, query, opts) {
386
+ return __awaiter(this, void 0, void 0, function* () {
387
+ var _a, e_2, _b, _c;
388
+ const matches = [];
389
+ const offset = opts.offset !== undefined && opts.offset > 0 ? opts.offset : 0;
390
+ const headLimit = opts.headLimit !== undefined && opts.headLimit > 0
391
+ ? opts.headLimit
392
+ : undefined;
393
+ const skippedFiles = new Set();
394
+ const acceptedFiles = new Set();
395
+ let skippedItems = 0;
396
+ let takenItems = 0;
397
+ const pushdown = grepPushdownLimit(query, Object.assign({ outputMode: opts.outputMode, offset }, (opts.headLimit === undefined ? {} : { headLimit: opts.headLimit })));
398
+ const grepQuery = pushdown === undefined ? query : Object.assign(Object.assign({}, query), { maxResults: pushdown });
399
+ try {
400
+ for (var _d = true, _e = __asyncValues(root.grep(grepQuery)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
401
+ _c = _f.value;
402
+ _d = false;
403
+ const match = _c;
404
+ if (opts.outputMode === "content") {
405
+ if (skippedItems < offset) {
406
+ skippedItems++;
407
+ continue;
408
+ }
409
+ matches.push(match);
410
+ takenItems++;
411
+ if (headLimit !== undefined && takenItems >= headLimit) {
412
+ break;
413
+ }
414
+ continue;
415
+ }
416
+ if (skippedFiles.has(match.path)) {
417
+ continue;
418
+ }
419
+ if (!acceptedFiles.has(match.path)) {
420
+ if (skippedItems < offset) {
421
+ skippedFiles.add(match.path);
422
+ skippedItems++;
423
+ continue;
424
+ }
425
+ if (headLimit !== undefined && takenItems >= headLimit) {
426
+ break;
427
+ }
428
+ acceptedFiles.add(match.path);
429
+ takenItems++;
430
+ }
431
+ matches.push(match);
432
+ }
433
+ }
434
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
435
+ finally {
436
+ try {
437
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
438
+ }
439
+ finally { if (e_2) throw e_2.error; }
440
+ }
441
+ return matches;
442
+ });
443
+ }
444
+ export function shapeGrepUnion(matches, outputMode) {
445
+ var _a;
446
+ if (outputMode === "files_with_matches") {
447
+ const files = [...new Set(matches.map((match) => match.path))];
448
+ return { type: "files", output: { files, count: files.length } };
449
+ }
450
+ if (outputMode === "count") {
451
+ const counts = new Map();
452
+ for (const match of matches) {
453
+ counts.set(match.path, ((_a = counts.get(match.path)) !== null && _a !== void 0 ? _a : 0) + 1);
454
+ }
455
+ return {
456
+ type: "count",
457
+ output: {
458
+ counts: [...counts].map(([file, count]) => ({ file, count })),
459
+ total: matches.length,
460
+ },
461
+ };
462
+ }
463
+ return {
464
+ type: "content",
465
+ output: {
466
+ matches: matches.map((match) => (Object.assign(Object.assign({ file: match.path, lineNumber: match.lineNumber, line: match.line }, (match.beforeContext === undefined
467
+ ? {}
468
+ : { beforeContext: match.beforeContext })), (match.afterContext === undefined
469
+ ? {}
470
+ : { afterContext: match.afterContext })))),
471
+ totalMatches: matches.length,
472
+ },
473
+ };
474
+ }
475
+ export function normalizeFsPath(input) {
476
+ const slashes = input.replace(/\\/g, "/");
477
+ if (slashes === "") {
478
+ return "/";
479
+ }
480
+ const withSlash = slashes.startsWith("/") ? slashes : `/${slashes}`;
481
+ const resolved = path.posix.normalize(withSlash);
482
+ if (resolved.length > 1 && resolved.endsWith("/")) {
483
+ return resolved.slice(0, -1);
484
+ }
485
+ return resolved === "." || resolved === "" ? "/" : resolved;
486
+ }
487
+ /** Path-segment prefix: `/agent` matches `/agent/skills`, not `/agent-tools`. */
488
+ export function pathHasSegmentPrefix(args) {
489
+ const p = normalizeFsPath(args.path);
490
+ const pre = normalizeFsPath(args.prefix);
491
+ if (pre === "/") {
492
+ return true;
493
+ }
494
+ return p === pre || p.startsWith(`${pre}/`);
495
+ }
496
+ function matchGlob(relativePath, globPattern) {
497
+ return minimatch(relativePath, globPattern, { dot: true, nocase: false });
498
+ }
499
+ function pathMatchesGlob(filePath, dir, globPattern, options = {}) {
500
+ const posixFile = filePath.replace(/\\/g, "/");
501
+ const posixDir = dir.replace(/\\/g, "/");
502
+ const relative = posixDir === "/" || posixFile.startsWith(`${posixDir}/`)
503
+ ? posixDir === "/"
504
+ ? posixFile.replace(/^\//, "")
505
+ : posixFile.slice(posixDir.length + 1)
506
+ : posixFile.replace(/^\//, "");
507
+ if (matchGlob(relative, globPattern) ||
508
+ matchGlob(posixFile.replace(/^\//, ""), globPattern)) {
509
+ return true;
510
+ }
511
+ // Native grep `--glob '*.ts'` matches the basename at any depth.
512
+ // Glob `*.ts` stays relative to `targetDirectory` and does not.
513
+ if (options.matchBasename === true && !globPattern.includes("/")) {
514
+ const slash = relative.lastIndexOf("/");
515
+ const base = slash === -1 ? relative : relative.slice(slash + 1);
516
+ return matchGlob(base, globPattern);
517
+ }
518
+ return false;
519
+ }
520
+ /**
521
+ * Resolve a per-send `workspaceFiles` key onto the virtual `/` namespace.
522
+ * Refuses paths that escape the root, and the reserved `memory` name.
523
+ * Host-default workspaces symlink `memory/` to durable agent state, so a
524
+ * seed under that name would write through the link.
525
+ */
526
+ export function virtualWorkspaceWritePath(relativePath) {
527
+ if (relativePath.includes("\0")) {
528
+ throw new FileSystemConfigError(`Refusing to write outside the virtual root: ${relativePath}`);
529
+ }
530
+ const posix = relativePath.replaceAll("\\", "/");
531
+ const base = "/virtual-root";
532
+ const target = path.posix.normalize(path.posix.join(base, posix));
533
+ if (target !== base && !target.startsWith(`${base}/`)) {
534
+ throw new FileSystemConfigError(`Refusing to write outside the virtual root: ${relativePath}`);
535
+ }
536
+ const sliced = target.slice(base.length);
537
+ const dest = sliced === "" ? "/" : sliced;
538
+ if (pathHasSegmentPrefix({
539
+ path: dest,
540
+ prefix: `/${MEMORY_DIR_NAME}`,
541
+ })) {
542
+ throw new FileSystemConfigError(`"${MEMORY_DIR_NAME}" is reserved for shared session memory; refusing to write ${relativePath}`);
543
+ }
544
+ return dest;
545
+ }
546
+ export function writeWorkspaceFilesToRoot(root, files) {
547
+ return __awaiter(this, void 0, void 0, function* () {
548
+ for (const [relativePath, contents] of Object.entries(files)) {
549
+ // Refuse escapes, then write the sanitized relative dest so
550
+ // `localFileSystem` joins against cwd and `tempFs` still normalizes
551
+ // `a.txt` → `/a.txt`. Never forward an absolute host path.
552
+ const dest = virtualWorkspaceWritePath(relativePath);
553
+ const relativeDest = dest.replace(/^\//, "");
554
+ if (relativeDest === "") {
555
+ throw new FileSystemConfigError(`Refusing to write the virtual root: ${relativePath}`);
556
+ }
557
+ const fileText = typeof contents === "string"
558
+ ? contents
559
+ : Buffer.from(contents.data, "base64").toString("utf8");
560
+ try {
561
+ yield root.write(relativeDest, fileText);
562
+ }
563
+ catch (error) {
564
+ throw new FileSystemConfigError(`workspaceFiles failed to write ${relativePath}: ${error instanceof Error ? error.message : "write failed"}`);
565
+ }
566
+ }
567
+ });
568
+ }
569
+ function replaceLiteral(args) {
570
+ if (args.replaceAll) {
571
+ return args.existing.split(args.oldText).join(args.newText);
572
+ }
573
+ const index = args.existing.indexOf(args.oldText);
574
+ if (index === -1) {
575
+ return args.existing;
576
+ }
577
+ return (args.existing.slice(0, index) +
578
+ args.newText +
579
+ args.existing.slice(index + args.oldText.length));
580
+ }
581
+ function countNonOverlapping(haystack, needle) {
582
+ let count = 0;
583
+ let from = 0;
584
+ while (from <= haystack.length - needle.length) {
585
+ const index = haystack.indexOf(needle, from);
586
+ if (index === -1) {
587
+ break;
588
+ }
589
+ count++;
590
+ from = index + needle.length;
591
+ }
592
+ return count;
593
+ }
594
+ /**
595
+ * Exact, non-overlapping str-replace. Uniqueness is the FileSystem
596
+ * contract: more than one match fails unless `replaceAll`.
597
+ */
598
+ function applyExactEdit(args) {
599
+ if (args.oldText === "") {
600
+ throw new EditError(args.path, "oldText is empty");
601
+ }
602
+ if (args.oldText === args.newText) {
603
+ throw new EditError(args.path, "oldText and newText are exactly the same");
604
+ }
605
+ const occurrences = countNonOverlapping(args.existing, args.oldText);
606
+ if (occurrences === 0) {
607
+ throw new EditError(args.path, "The string to replace was not found in the file");
608
+ }
609
+ if (occurrences > 1 && !args.replaceAll) {
610
+ throw new EditError(args.path, "The string to replace was found multiple times in the file. Use replace_all to replace all occurrences, or include more context to only edit one occurrence.");
611
+ }
612
+ return {
613
+ contents: replaceLiteral({
614
+ existing: args.existing,
615
+ oldText: args.oldText,
616
+ newText: args.newText,
617
+ replaceAll: args.replaceAll,
618
+ }),
619
+ occurrencesModified: occurrences,
620
+ };
621
+ }
622
+ /**
623
+ * Exact str-replace as `read` + apply + `write`. Uniqueness is
624
+ * this helper's contract; FileSystem implementations do not
625
+ * implement edit. Native StrReplace calls this.
626
+ */
627
+ export function strReplaceOnFileSystem(root, query) {
628
+ return __awaiter(this, void 0, void 0, function* () {
629
+ const existing = yield root.read(query.path);
630
+ if (typeof existing !== "string") {
631
+ throw new EditError(query.path, `${query.path} is not text`);
632
+ }
633
+ const applied = applyExactEdit({
634
+ existing,
635
+ oldText: query.oldText,
636
+ newText: query.newText,
637
+ replaceAll: query.replaceAll === true,
638
+ path: query.path,
639
+ });
640
+ yield root.write(query.path, applied.contents);
641
+ return { occurrencesModified: applied.occurrencesModified };
642
+ });
643
+ }
644
+ /** Native Read offset/limit: 1-indexed, negative offset counts from the end. */
645
+ export function sliceReadContent(content, offset, limit) {
646
+ if (offset === undefined && limit === undefined) {
647
+ return content;
648
+ }
649
+ const lines = content === "" ? [] : content.split("\n");
650
+ const total = lines.length;
651
+ const effectiveOffset = offset !== null && offset !== void 0 ? offset : 1;
652
+ const effectiveLimit = limit !== null && limit !== void 0 ? limit : (effectiveOffset < 0 ? Math.abs(effectiveOffset) : total);
653
+ const startIndex = effectiveOffset < 0
654
+ ? Math.max(0, total + effectiveOffset)
655
+ : Math.max(0, effectiveOffset - 1);
656
+ const endIndex = Math.min(total, startIndex + effectiveLimit);
657
+ return lines.slice(startIndex, endIndex).join("\n");
658
+ }
659
+ function emptySearch(_query) { return __asyncGenerator(this, arguments, function* emptySearch_1() { }); }
660
+ function emptyStream() { return __asyncGenerator(this, arguments, function* emptyStream_1() { }); }
661
+ /**
662
+ * A FileSystem with no files. Use as an overlay leaf or a missing
663
+ * catalog so a miss stays {@link FileNotFoundError} instead of
664
+ * {@link NoMountError}. Writes and deletes throw
665
+ * {@link ReadOnlyMountError} — an empty tree is never a sink.
666
+ */
667
+ export function emptyFs() {
668
+ return {
669
+ list: () => emptyStream(),
670
+ glob: () => emptyStream(),
671
+ grep(query) {
672
+ return __asyncGenerator(this, arguments, function* grep_1() {
673
+ compileGrepPattern(query.pattern, query.caseInsensitive, query.path === undefined || query.path === ""
674
+ ? "/"
675
+ : normalizeFsPath(query.path));
676
+ yield __await(yield* __asyncDelegator(__asyncValues(emptyStream())));
677
+ });
678
+ },
679
+ search: emptySearch,
680
+ stat(path) {
681
+ return __awaiter(this, void 0, void 0, function* () {
682
+ return statFromFilePaths([], path);
683
+ });
684
+ },
685
+ read(path) {
686
+ return __awaiter(this, void 0, void 0, function* () {
687
+ throw new FileNotFoundError(normalizeFsPath(path));
688
+ });
689
+ },
690
+ write(path) {
691
+ return __awaiter(this, void 0, void 0, function* () {
692
+ throw new ReadOnlyMountError(normalizeFsPath(path));
693
+ });
694
+ },
695
+ delete(path) {
696
+ return __awaiter(this, void 0, void 0, function* () {
697
+ throw new ReadOnlyMountError(normalizeFsPath(path));
698
+ });
699
+ },
700
+ };
701
+ }
702
+ /**
703
+ * In-memory FileSystem for tests and fixtures. Keys are absolute
704
+ * posix paths (`/a.txt`) and are normalized on ingest. Honors the
705
+ * {@link FileSystem} order and path contracts.
706
+ * `search` is empty. Creates `/agent-tools` on first scratch
707
+ * write the same way any other path is created.
708
+ */
709
+ export function tempFs(files = {}) {
710
+ const store = new Map();
711
+ for (const [path, content] of Object.entries(files)) {
712
+ store.set(normalizeFsPath(path), content);
713
+ }
714
+ const listed = {
715
+ list(prefix) {
716
+ return listFilesFromPaths([...store.entries()].map(([filePath, content]) => ({
717
+ path: filePath,
718
+ size: typeof content === "string" ? content.length : content.byteLength,
719
+ })), prefix);
720
+ },
721
+ stat(path) {
722
+ return __awaiter(this, void 0, void 0, function* () {
723
+ return statFromFilePaths(store.keys(), path);
724
+ });
725
+ },
726
+ };
727
+ return {
728
+ list(prefix) {
729
+ return listed.list(prefix);
730
+ },
731
+ stat(path) {
732
+ return __awaiter(this, void 0, void 0, function* () {
733
+ return listed.stat(path);
734
+ });
735
+ },
736
+ read(inputPath) {
737
+ return __awaiter(this, void 0, void 0, function* () {
738
+ const path = normalizeFsPath(inputPath);
739
+ const content = store.get(path);
740
+ if (content === undefined) {
741
+ throw new FileNotFoundError(path);
742
+ }
743
+ return content;
744
+ });
745
+ },
746
+ grep(query) {
747
+ return __asyncGenerator(this, arguments, function* grep_2() {
748
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(uncapped(), query.maxResults))));
749
+ function uncapped() {
750
+ return __asyncGenerator(this, arguments, function* uncapped_1() {
751
+ var _a, e_3, _b, _c;
752
+ const regex = compileGrepPattern(query.pattern, query.caseInsensitive, query.path === undefined || query.path === ""
753
+ ? "/"
754
+ : normalizeFsPath(query.path));
755
+ const scope = query.path === undefined || query.path === ""
756
+ ? "/"
757
+ : normalizeFsPath(query.path);
758
+ const exact = store.get(scope);
759
+ if (scope !== "/" && exact !== undefined) {
760
+ if (query.glob !== undefined &&
761
+ !pathMatchesGlob(scope, scope, query.glob, {
762
+ matchBasename: true,
763
+ })) {
764
+ return yield __await(void 0);
765
+ }
766
+ yield __await(yield* __asyncDelegator(__asyncValues(grepFileContent({
767
+ path: scope,
768
+ content: fileSystemText(exact),
769
+ regex,
770
+ }))));
771
+ return yield __await(void 0);
772
+ }
773
+ try {
774
+ for (var _d = true, _e = __asyncValues(listed.list(scope === "/" ? undefined : scope)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
775
+ _c = _f.value;
776
+ _d = false;
777
+ const entry = _c;
778
+ if (query.glob !== undefined &&
779
+ !pathMatchesGlob(entry.path, scope, query.glob, {
780
+ matchBasename: true,
781
+ })) {
782
+ continue;
783
+ }
784
+ const content = store.get(entry.path);
785
+ if (content === undefined) {
786
+ continue;
787
+ }
788
+ yield __await(yield* __asyncDelegator(__asyncValues(grepFileContent({
789
+ path: entry.path,
790
+ content: fileSystemText(content),
791
+ regex,
792
+ }))));
793
+ }
794
+ }
795
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
796
+ finally {
797
+ try {
798
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
799
+ }
800
+ finally { if (e_3) throw e_3.error; }
801
+ }
802
+ });
803
+ }
804
+ });
805
+ },
806
+ glob(pattern, dir) {
807
+ return __asyncGenerator(this, arguments, function* glob_1() {
808
+ const scope = dir === undefined || dir === "" ? "/" : normalizeFsPath(dir);
809
+ yield __await(yield* __asyncDelegator(__asyncValues(globFromList(listed.list(scope === "/" ? undefined : scope), {
810
+ pattern,
811
+ dir: scope,
812
+ }))));
813
+ });
814
+ },
815
+ write(inputPath, contents) {
816
+ return __awaiter(this, void 0, void 0, function* () {
817
+ store.set(normalizeFsPath(inputPath), contents);
818
+ });
819
+ },
820
+ delete(inputPath) {
821
+ return __awaiter(this, void 0, void 0, function* () {
822
+ const path = normalizeFsPath(inputPath);
823
+ if (!store.has(path)) {
824
+ throw new FileNotFoundError(path);
825
+ }
826
+ store.delete(path);
827
+ });
828
+ },
829
+ search: emptySearch,
830
+ };
831
+ }
832
+ function fsErrorMessage(error, fallback) {
833
+ return error instanceof Error ? error.message : fallback;
834
+ }
835
+ function throwLocalReadError(error, filePath) {
836
+ throw new FileNotFoundError(filePath, fsErrorMessage(error, `not found: ${filePath}`));
837
+ }
838
+ function skipWalkDir(name) {
839
+ return name === ".git" || name === "node_modules";
840
+ }
841
+ function walkLocalFiles(rootDir) {
842
+ return __awaiter(this, void 0, void 0, function* () {
843
+ const found = [];
844
+ const stack = [rootDir];
845
+ while (stack.length > 0) {
846
+ const current = stack.pop();
847
+ if (current === undefined) {
848
+ break;
849
+ }
850
+ let entries;
851
+ try {
852
+ entries = yield readdir(current, { withFileTypes: true });
853
+ }
854
+ catch (_a) {
855
+ continue;
856
+ }
857
+ for (const entry of entries) {
858
+ const full = path.join(current, entry.name);
859
+ // Same as the pre-root host walk and native LS/Glob/Grep: Dirent
860
+ // isDirectory/isFile do not follow links, so workspace `memory/`
861
+ // and other symlinks are not enumerated. Exact-path read/stat still
862
+ // follow.
863
+ if (entry.isDirectory()) {
864
+ if (!skipWalkDir(entry.name)) {
865
+ stack.push(full);
866
+ }
867
+ }
868
+ else if (entry.isFile()) {
869
+ found.push(full);
870
+ }
871
+ }
872
+ }
873
+ found.sort((left, right) => left.localeCompare(right));
874
+ return found;
875
+ });
876
+ }
877
+ function listLocalFiles(rootDir) {
878
+ return __asyncGenerator(this, arguments, function* listLocalFiles_1() {
879
+ for (const filePath of yield __await(walkLocalFiles(rootDir))) {
880
+ yield yield __await({ path: filePath });
881
+ }
882
+ });
883
+ }
884
+ /**
885
+ * Host-disk FileSystem. Relative paths resolve against `cwd`; absolute
886
+ * paths are used as-is — the same contract as Cursor SDK native file
887
+ * tools. `search` yields empty results (no host index).
888
+ *
889
+ * Internal. Not part of the public Agent SDK surface.
890
+ */
891
+ export function localFileSystem(options) {
892
+ const cwd = path.resolve(options.cwd);
893
+ const resolvePath = (input) => path.isAbsolute(input) ? path.resolve(input) : path.resolve(cwd, input);
894
+ return {
895
+ list(prefix) {
896
+ return __asyncGenerator(this, arguments, function* list_1() {
897
+ const dirPath = prefix === undefined || prefix === "" || prefix === "."
898
+ ? cwd
899
+ : resolvePath(prefix);
900
+ yield __await(yield* __asyncDelegator(__asyncValues(listLocalFiles(dirPath))));
901
+ });
902
+ },
903
+ stat(probePath) {
904
+ return __awaiter(this, void 0, void 0, function* () {
905
+ const filePath = resolvePath(probePath);
906
+ try {
907
+ const info = yield stat(filePath);
908
+ return { kind: info.isDirectory() ? "directory" : "file" };
909
+ }
910
+ catch (_a) {
911
+ return { kind: "missing" };
912
+ }
913
+ });
914
+ },
915
+ read(inputPath) {
916
+ return __awaiter(this, void 0, void 0, function* () {
917
+ const filePath = resolvePath(inputPath);
918
+ try {
919
+ const bytes = yield readFile(filePath);
920
+ if (detectImageMimeType(bytes, filePath) !== undefined) {
921
+ return new Uint8Array(bytes);
922
+ }
923
+ return bytes.toString("utf8");
924
+ }
925
+ catch (error) {
926
+ throwLocalReadError(error, filePath);
927
+ }
928
+ });
929
+ },
930
+ grep(query) {
931
+ return __asyncGenerator(this, arguments, function* grep_3() {
932
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(uncapped(), query.maxResults))));
933
+ function uncapped() {
934
+ return __asyncGenerator(this, arguments, function* uncapped_2() {
935
+ var _a;
936
+ const searchRoot = resolvePath((_a = query.path) !== null && _a !== void 0 ? _a : cwd);
937
+ const regex = compileGrepPattern(query.pattern, query.caseInsensitive, searchRoot);
938
+ let filesToSearch;
939
+ try {
940
+ const info = yield __await(stat(searchRoot));
941
+ filesToSearch = info.isFile()
942
+ ? [searchRoot]
943
+ : yield __await(walkLocalFiles(searchRoot));
944
+ }
945
+ catch (error) {
946
+ throwLocalReadError(error, searchRoot);
947
+ }
948
+ for (const filePath of filesToSearch) {
949
+ if (query.glob !== undefined &&
950
+ !pathMatchesGlob(filePath, searchRoot, query.glob, {
951
+ matchBasename: true,
952
+ })) {
953
+ continue;
954
+ }
955
+ let content;
956
+ try {
957
+ content = yield __await(readFile(filePath, "utf8"));
958
+ }
959
+ catch (_b) {
960
+ continue;
961
+ }
962
+ yield __await(yield* __asyncDelegator(__asyncValues(grepFileContent({ path: filePath, content, regex }))));
963
+ }
964
+ });
965
+ }
966
+ });
967
+ },
968
+ glob(pattern, dir) {
969
+ return __asyncGenerator(this, arguments, function* glob_2() {
970
+ const dirPath = dir === undefined || dir === "" || dir === "." ? cwd : resolvePath(dir);
971
+ yield __await(yield* __asyncDelegator(__asyncValues(globFromList(listLocalFiles(dirPath), {
972
+ pattern,
973
+ dir: dirPath,
974
+ }))));
975
+ });
976
+ },
977
+ write(inputPath, contents) {
978
+ return __awaiter(this, void 0, void 0, function* () {
979
+ const filePath = resolvePath(inputPath);
980
+ try {
981
+ yield mkdir(path.dirname(filePath), { recursive: true });
982
+ yield writeFile(filePath, contents, "utf8");
983
+ }
984
+ catch (error) {
985
+ throw new WriteFailedError(filePath, fsErrorMessage(error, `write failed: ${filePath}`));
986
+ }
987
+ });
988
+ },
989
+ delete(inputPath) {
990
+ return __awaiter(this, void 0, void 0, function* () {
991
+ const filePath = resolvePath(inputPath);
992
+ try {
993
+ yield rm(filePath);
994
+ }
995
+ catch (error) {
996
+ throwLocalReadError(error, filePath);
997
+ }
998
+ });
999
+ },
1000
+ search: emptySearch,
1001
+ };
1002
+ }
1003
+ function longestMount(path, mounts) {
1004
+ let best;
1005
+ for (const mount of mounts) {
1006
+ if (!pathHasSegmentPrefix({ path, prefix: mount.prefix })) {
1007
+ continue;
1008
+ }
1009
+ if (best === undefined || mount.prefix.length > best.prefix.length) {
1010
+ best = mount;
1011
+ }
1012
+ }
1013
+ return best;
1014
+ }
1015
+ /** Namespace path → child path. `/host/a.md` on `/host` is `/a.md`. */
1016
+ function toChildPath(path, prefix) {
1017
+ if (prefix === "/") {
1018
+ return path;
1019
+ }
1020
+ if (path === prefix) {
1021
+ return "/";
1022
+ }
1023
+ if (path.startsWith(`${prefix}/`)) {
1024
+ return path.slice(prefix.length);
1025
+ }
1026
+ return path;
1027
+ }
1028
+ /** Child path → namespace path. `/a.md` on `/host` is `/host/a.md`. */
1029
+ function toParentPath(path, prefix) {
1030
+ if (prefix === "/") {
1031
+ return path;
1032
+ }
1033
+ if (path === "/" || path === "") {
1034
+ return prefix;
1035
+ }
1036
+ return path.startsWith("/") ? `${prefix}${path}` : `${prefix}/${path}`;
1037
+ }
1038
+ function mapMountEntries(source, prefix) {
1039
+ return __asyncGenerator(this, arguments, function* mapMountEntries_1() {
1040
+ var _a, e_4, _b, _c;
1041
+ try {
1042
+ try {
1043
+ for (var _d = true, source_2 = __asyncValues(source), source_2_1; source_2_1 = yield __await(source_2.next()), _a = source_2_1.done, !_a; _d = true) {
1044
+ _c = source_2_1.value;
1045
+ _d = false;
1046
+ const entry = _c;
1047
+ yield yield __await(Object.assign(Object.assign({}, entry), { path: toParentPath(entry.path, prefix) }));
1048
+ }
1049
+ }
1050
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
1051
+ finally {
1052
+ try {
1053
+ if (!_d && !_a && (_b = source_2.return)) yield __await(_b.call(source_2));
1054
+ }
1055
+ finally { if (e_4) throw e_4.error; }
1056
+ }
1057
+ }
1058
+ catch (error) {
1059
+ throw remapPathError(error, prefix);
1060
+ }
1061
+ });
1062
+ }
1063
+ function mapMountGrep(source, prefix) {
1064
+ return __asyncGenerator(this, arguments, function* mapMountGrep_1() {
1065
+ var _a, e_5, _b, _c;
1066
+ try {
1067
+ try {
1068
+ for (var _d = true, source_3 = __asyncValues(source), source_3_1; source_3_1 = yield __await(source_3.next()), _a = source_3_1.done, !_a; _d = true) {
1069
+ _c = source_3_1.value;
1070
+ _d = false;
1071
+ const hit = _c;
1072
+ yield yield __await(Object.assign(Object.assign({}, hit), { path: toParentPath(hit.path, prefix) }));
1073
+ }
1074
+ }
1075
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
1076
+ finally {
1077
+ try {
1078
+ if (!_d && !_a && (_b = source_3.return)) yield __await(_b.call(source_3));
1079
+ }
1080
+ finally { if (e_5) throw e_5.error; }
1081
+ }
1082
+ }
1083
+ catch (error) {
1084
+ throw remapPathError(error, prefix);
1085
+ }
1086
+ });
1087
+ }
1088
+ function mapMountSearch(source, prefix) {
1089
+ return __asyncGenerator(this, arguments, function* mapMountSearch_1() {
1090
+ var _a, e_6, _b, _c;
1091
+ try {
1092
+ try {
1093
+ for (var _d = true, source_4 = __asyncValues(source), source_4_1; source_4_1 = yield __await(source_4.next()), _a = source_4_1.done, !_a; _d = true) {
1094
+ _c = source_4_1.value;
1095
+ _d = false;
1096
+ const hit = _c;
1097
+ yield yield __await(Object.assign(Object.assign({}, hit), { path: toParentPath(hit.path, prefix) }));
1098
+ }
1099
+ }
1100
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
1101
+ finally {
1102
+ try {
1103
+ if (!_d && !_a && (_b = source_4.return)) yield __await(_b.call(source_4));
1104
+ }
1105
+ finally { if (e_6) throw e_6.error; }
1106
+ }
1107
+ }
1108
+ catch (error) {
1109
+ throw remapPathError(error, prefix);
1110
+ }
1111
+ });
1112
+ }
1113
+ function childSearchQuery(query, prefix) {
1114
+ if (query.targetDirectories === undefined ||
1115
+ query.targetDirectories.length === 0) {
1116
+ return query;
1117
+ }
1118
+ const dirs = [];
1119
+ for (const dir of query.targetDirectories) {
1120
+ const normalized = normalizeFsPath(dir);
1121
+ // `/` is every mount, the same way grep at `/` fans out.
1122
+ if (normalized === "/") {
1123
+ return Object.assign(Object.assign({}, query), { targetDirectories: undefined });
1124
+ }
1125
+ if (!pathHasSegmentPrefix({ path: normalized, prefix })) {
1126
+ continue;
1127
+ }
1128
+ const child = toChildPath(normalized, prefix);
1129
+ if (child === "/") {
1130
+ return Object.assign(Object.assign({}, query), { targetDirectories: undefined });
1131
+ }
1132
+ dirs.push(child);
1133
+ }
1134
+ if (dirs.length === 0) {
1135
+ return undefined;
1136
+ }
1137
+ return Object.assign(Object.assign({}, query), { targetDirectories: dirs });
1138
+ }
1139
+ /**
1140
+ * Longest-prefix compose, path-segment match. Every verb is
1141
+ * defined. Does not synthesize `shell`. `/agent` is not a
1142
+ * prefix of `/agent-tools`.
1143
+ *
1144
+ * The record keys are mount points. Each child is a FileSystem
1145
+ * rooted at `/`. `unionFs` strips the prefix on the way in and
1146
+ * re-prefixes yields (and error paths) on the way out:
1147
+ * `unionFs({ "/host": hostFs(...) })` — the child never sees
1148
+ * `/host`.
1149
+ *
1150
+ * A path with no mount:
1151
+ * - `read` / `write` / `delete`: throw
1152
+ * `no mount for path: ${path}`
1153
+ * - `list` / `glob` / `grep`: empty iterator
1154
+ * - `stat`: `{ kind: "missing" }` (`/` and exact mount prefixes
1155
+ * are `{ kind: "directory" }`)
1156
+ *
1157
+ * Root `list` / `glob` / `grep` / `search` k-way merge already
1158
+ * sorted sources. List and glob use `unique` so an earlier
1159
+ * mount shadows a later one; grep and search keep every hit.
1160
+ */
1161
+ export function unionFs(mounts) {
1162
+ const entries = Object.entries(mounts).map(([prefix, fs]) => ({
1163
+ prefix: normalizeFsPath(prefix),
1164
+ fs,
1165
+ }));
1166
+ entries.sort((a, b) => b.prefix.length - a.prefix.length);
1167
+ const noMount = (path) => {
1168
+ throw new NoMountError(path);
1169
+ };
1170
+ const forward = (path, run) => __awaiter(this, void 0, void 0, function* () {
1171
+ const mount = longestMount(path, entries);
1172
+ if (mount === undefined) {
1173
+ return noMount(path);
1174
+ }
1175
+ const childPath = toChildPath(path, mount.prefix);
1176
+ try {
1177
+ return yield run(mount.fs, childPath);
1178
+ }
1179
+ catch (error) {
1180
+ throw remapPathError(error, mount.prefix);
1181
+ }
1182
+ });
1183
+ const isRootPath = (value) => value === undefined || value === "" || value === "/";
1184
+ return {
1185
+ list(prefix) {
1186
+ return __asyncGenerator(this, arguments, function* list_2() {
1187
+ if (isRootPath(prefix)) {
1188
+ yield __await(yield* __asyncDelegator(__asyncValues(mergeSortedByPath(entries.map((mount) => mapMountEntries(mount.fs.list(), mount.prefix)), { unique: true }))));
1189
+ return yield __await(void 0);
1190
+ }
1191
+ const path = normalizeFsPath(prefix !== null && prefix !== void 0 ? prefix : "/");
1192
+ const mount = longestMount(path, entries);
1193
+ if (mount === undefined) {
1194
+ return yield __await(void 0);
1195
+ }
1196
+ const childPath = toChildPath(path, mount.prefix);
1197
+ yield __await(yield* __asyncDelegator(__asyncValues(mapMountEntries(mount.fs.list(childPath === "/" ? undefined : childPath), mount.prefix))));
1198
+ });
1199
+ },
1200
+ stat(path) {
1201
+ return __awaiter(this, void 0, void 0, function* () {
1202
+ const normalized = normalizeFsPath(path);
1203
+ if (normalized === "/") {
1204
+ return { kind: "directory" };
1205
+ }
1206
+ if (entries.some((entry) => entry.prefix === normalized)) {
1207
+ return { kind: "directory" };
1208
+ }
1209
+ const mount = longestMount(normalized, entries);
1210
+ if (mount === undefined) {
1211
+ return { kind: "missing" };
1212
+ }
1213
+ return mount.fs.stat(toChildPath(normalized, mount.prefix));
1214
+ });
1215
+ },
1216
+ read(path) {
1217
+ return __awaiter(this, void 0, void 0, function* () {
1218
+ const normalized = normalizeFsPath(path);
1219
+ return forward(normalized, (fs, childPath) => fs.read(childPath));
1220
+ });
1221
+ },
1222
+ write(path, contents) {
1223
+ return __awaiter(this, void 0, void 0, function* () {
1224
+ const normalized = normalizeFsPath(path);
1225
+ return forward(normalized, (fs, childPath) => fs.write(childPath, contents));
1226
+ });
1227
+ },
1228
+ delete(path) {
1229
+ return __awaiter(this, void 0, void 0, function* () {
1230
+ const normalized = normalizeFsPath(path);
1231
+ return forward(normalized, (fs, childPath) => fs.delete(childPath));
1232
+ });
1233
+ },
1234
+ grep(query) {
1235
+ return __asyncGenerator(this, arguments, function* grep_4() {
1236
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(uncapped(), query.maxResults))));
1237
+ function uncapped() {
1238
+ return __asyncGenerator(this, arguments, function* uncapped_3() {
1239
+ const scope = query.path === undefined || query.path === ""
1240
+ ? "/"
1241
+ : normalizeFsPath(query.path);
1242
+ if (scope === "/") {
1243
+ yield __await(yield* __asyncDelegator(__asyncValues(mergeSorted(entries.map((mount) => mapMountGrep(mount.fs.grep(Object.assign(Object.assign({}, query), { path: undefined })), mount.prefix)), { compare: compareGrepResult }))));
1244
+ return yield __await(void 0);
1245
+ }
1246
+ const mount = longestMount(scope, entries);
1247
+ if (mount === undefined) {
1248
+ return yield __await(void 0);
1249
+ }
1250
+ const childPath = toChildPath(scope, mount.prefix);
1251
+ yield __await(yield* __asyncDelegator(__asyncValues(mapMountGrep(mount.fs.grep(Object.assign(Object.assign({}, query), { path: childPath === "/" ? undefined : childPath })), mount.prefix))));
1252
+ });
1253
+ }
1254
+ });
1255
+ },
1256
+ search(query) {
1257
+ return __asyncGenerator(this, arguments, function* search_1() {
1258
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(uncapped(), query.maxResults))));
1259
+ function uncapped() {
1260
+ return __asyncGenerator(this, arguments, function* uncapped_4() {
1261
+ const sources = [];
1262
+ for (const mount of entries) {
1263
+ const childQuery = childSearchQuery(query, mount.prefix);
1264
+ if (childQuery === undefined) {
1265
+ continue;
1266
+ }
1267
+ sources.push(mapMountSearch(mount.fs.search(childQuery), mount.prefix));
1268
+ }
1269
+ yield __await(yield* __asyncDelegator(__asyncValues(mergeSorted(sources, { compare: compareSearchResult }))));
1270
+ });
1271
+ }
1272
+ });
1273
+ },
1274
+ glob(pattern, dir) {
1275
+ return __asyncGenerator(this, arguments, function* glob_3() {
1276
+ const scope = dir === undefined || dir === "" ? "/" : normalizeFsPath(dir);
1277
+ if (scope === "/") {
1278
+ yield __await(yield* __asyncDelegator(__asyncValues(mergeSortedByPath(entries.map((mount) => mapMountEntries(mount.fs.glob(pattern), mount.prefix)), { unique: true }))));
1279
+ return yield __await(void 0);
1280
+ }
1281
+ const mount = longestMount(scope, entries);
1282
+ if (mount === undefined) {
1283
+ return yield __await(void 0);
1284
+ }
1285
+ const childPath = toChildPath(scope, mount.prefix);
1286
+ yield __await(yield* __asyncDelegator(__asyncValues(mapMountEntries(mount.fs.glob(pattern, childPath === "/" ? undefined : childPath), mount.prefix))));
1287
+ });
1288
+ },
1289
+ };
1290
+ }
1291
+ function collectLayerPaths(layer) {
1292
+ return __awaiter(this, void 0, void 0, function* () {
1293
+ var _a, e_7, _b, _c;
1294
+ const paths = [];
1295
+ try {
1296
+ try {
1297
+ for (var _d = true, _e = __asyncValues(layer.list()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
1298
+ _c = _f.value;
1299
+ _d = false;
1300
+ const entry = _c;
1301
+ paths.push(entry.path);
1302
+ }
1303
+ }
1304
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
1305
+ finally {
1306
+ try {
1307
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
1308
+ }
1309
+ finally { if (e_7) throw e_7.error; }
1310
+ }
1311
+ }
1312
+ catch (_g) {
1313
+ // A layer that cannot list also cannot own paths.
1314
+ }
1315
+ return paths;
1316
+ });
1317
+ }
1318
+ /**
1319
+ * Same-root overlay: earlier layers win. Read-only.
1320
+ *
1321
+ * A downed layer costs its own files, not the overlay. Mutations
1322
+ * throw `read-only mount` / `read-only mount: ${path}`. Empty
1323
+ * `layers` throws `overlayFs needs at least one layer.`
1324
+ */
1325
+ export function overlayFs(layers) {
1326
+ if (layers.length === 0) {
1327
+ throw new Error("overlayFs needs at least one layer.");
1328
+ }
1329
+ const walkLayers = (collect) => __awaiter(this, void 0, void 0, function* () {
1330
+ var _a, e_8, _b, _c;
1331
+ const streams = [];
1332
+ let failure;
1333
+ let served = false;
1334
+ for (const layer of layers) {
1335
+ const collected = [];
1336
+ try {
1337
+ try {
1338
+ for (var _d = true, _e = (e_8 = void 0, __asyncValues(yield collect(layer))), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
1339
+ _c = _f.value;
1340
+ _d = false;
1341
+ const entry = _c;
1342
+ collected.push(entry);
1343
+ }
1344
+ }
1345
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
1346
+ finally {
1347
+ try {
1348
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
1349
+ }
1350
+ finally { if (e_8) throw e_8.error; }
1351
+ }
1352
+ }
1353
+ catch (error) {
1354
+ failure !== null && failure !== void 0 ? failure : (failure = error);
1355
+ continue;
1356
+ }
1357
+ served = true;
1358
+ streams.push(collected);
1359
+ }
1360
+ return { streams, failure, served };
1361
+ });
1362
+ const collectOverlayHits = (queryFn, rethrow) => __awaiter(this, void 0, void 0, function* () {
1363
+ var _a, e_9, _b, _c;
1364
+ const streams = [];
1365
+ const shadowed = new Set();
1366
+ let failure;
1367
+ let served = false;
1368
+ for (const layer of layers) {
1369
+ const collected = [];
1370
+ try {
1371
+ try {
1372
+ for (var _d = true, _e = (e_9 = void 0, __asyncValues(queryFn(layer))), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
1373
+ _c = _f.value;
1374
+ _d = false;
1375
+ const hit = _c;
1376
+ if (!shadowed.has(hit.path)) {
1377
+ collected.push(hit);
1378
+ }
1379
+ }
1380
+ }
1381
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
1382
+ finally {
1383
+ try {
1384
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
1385
+ }
1386
+ finally { if (e_9) throw e_9.error; }
1387
+ }
1388
+ served = true;
1389
+ }
1390
+ catch (error) {
1391
+ if ((rethrow === null || rethrow === void 0 ? void 0 : rethrow(error)) === true) {
1392
+ throw error;
1393
+ }
1394
+ failure !== null && failure !== void 0 ? failure : (failure = error);
1395
+ continue;
1396
+ }
1397
+ streams.push(collected);
1398
+ for (const path of yield collectLayerPaths(layer)) {
1399
+ shadowed.add(path);
1400
+ }
1401
+ }
1402
+ if (!served && failure !== undefined) {
1403
+ throw failure;
1404
+ }
1405
+ return streams;
1406
+ });
1407
+ return {
1408
+ list(prefix) {
1409
+ return __asyncGenerator(this, arguments, function* list_3() {
1410
+ const { streams, failure, served } = yield __await(walkLayers((layer) => layer.list(prefix)));
1411
+ if (!served && failure !== undefined) {
1412
+ throw failure;
1413
+ }
1414
+ yield __await(yield* __asyncDelegator(__asyncValues(mergeSortedByPath(streams, { unique: true }))));
1415
+ });
1416
+ },
1417
+ stat(path) {
1418
+ return __awaiter(this, void 0, void 0, function* () {
1419
+ let failure;
1420
+ let sawMissing = false;
1421
+ for (const layer of layers) {
1422
+ try {
1423
+ const info = yield layer.stat(path);
1424
+ if (info.kind !== "missing") {
1425
+ return info;
1426
+ }
1427
+ sawMissing = true;
1428
+ }
1429
+ catch (error) {
1430
+ failure !== null && failure !== void 0 ? failure : (failure = error);
1431
+ }
1432
+ }
1433
+ if (!sawMissing && failure !== undefined) {
1434
+ throw failure;
1435
+ }
1436
+ return { kind: "missing" };
1437
+ });
1438
+ },
1439
+ glob(pattern, dir) {
1440
+ return __asyncGenerator(this, arguments, function* glob_4() {
1441
+ const { streams, failure, served } = yield __await(walkLayers((layer) => layer.glob(pattern, dir)));
1442
+ if (!served && failure !== undefined) {
1443
+ throw failure;
1444
+ }
1445
+ yield __await(yield* __asyncDelegator(__asyncValues(mergeSortedByPath(streams, { unique: true }))));
1446
+ });
1447
+ },
1448
+ read(path) {
1449
+ return __awaiter(this, void 0, void 0, function* () {
1450
+ let failure;
1451
+ for (const layer of layers) {
1452
+ try {
1453
+ return yield layer.read(path);
1454
+ }
1455
+ catch (error) {
1456
+ if (isFileNotFoundError(error)) {
1457
+ continue;
1458
+ }
1459
+ failure !== null && failure !== void 0 ? failure : (failure = error);
1460
+ }
1461
+ }
1462
+ if (failure !== undefined) {
1463
+ throw failure;
1464
+ }
1465
+ throw new FileNotFoundError(path);
1466
+ });
1467
+ },
1468
+ grep(query) {
1469
+ return __asyncGenerator(this, arguments, function* grep_5() {
1470
+ const { maxResults } = query, uncappedQuery = __rest(query, ["maxResults"]);
1471
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(mergeSorted(yield __await(collectOverlayHits((layer) => layer.grep(uncappedQuery), (error) => isInvalidGrepPatternError(error))), { compare: compareGrepResult }), maxResults))));
1472
+ });
1473
+ },
1474
+ write(path) {
1475
+ return __awaiter(this, void 0, void 0, function* () {
1476
+ throw new ReadOnlyMountError(path);
1477
+ });
1478
+ },
1479
+ delete(path) {
1480
+ return __awaiter(this, void 0, void 0, function* () {
1481
+ throw new ReadOnlyMountError(path);
1482
+ });
1483
+ },
1484
+ search(query) {
1485
+ return __asyncGenerator(this, arguments, function* search_2() {
1486
+ const { maxResults } = query, uncappedQuery = __rest(query, ["maxResults"]);
1487
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(mergeSorted(yield __await(collectOverlayHits((layer) => layer.search(uncappedQuery))), { compare: compareSearchResult }), maxResults))));
1488
+ });
1489
+ },
1490
+ };
1491
+ }
1492
+ function hostKey(path) {
1493
+ const normalized = normalizeFsPath(path);
1494
+ return normalized === "/" ? "" : normalized.slice(1);
1495
+ }
1496
+ function isHostConflict(error) {
1497
+ return (error instanceof FileConflictError ||
1498
+ (error instanceof Error &&
1499
+ (error.name === "FileConflictError" ||
1500
+ error.message.includes("lost a race"))));
1501
+ }
1502
+ /**
1503
+ * `HostFilesApi` as a FileSystem rooted at `/`.
1504
+ *
1505
+ * Mount it with `unionFs({ "/host": hostFs(files, scope) })`. The
1506
+ * child never sees `/host` — `unionFs` owns the prefix. `scope` is
1507
+ * the HostFiles partition, not a path prefix. `search` is empty
1508
+ * (HostFiles is not an index).
1509
+ */
1510
+ export function hostFs(files, scope) {
1511
+ const callOptions = { scope };
1512
+ const readEtags = new Map();
1513
+ const listed = {
1514
+ list(prefix) {
1515
+ return __asyncGenerator(this, arguments, function* list_4() {
1516
+ const entries = yield __await(files.list(undefined, callOptions));
1517
+ yield __await(yield* __asyncDelegator(__asyncValues(listFilesFromPaths(entries.map((entry) => ({
1518
+ path: normalizeFsPath(entry.path),
1519
+ size: entry.size,
1520
+ })), prefix))));
1521
+ });
1522
+ },
1523
+ stat(path) {
1524
+ return __awaiter(this, void 0, void 0, function* () {
1525
+ const entries = yield files.list(undefined, callOptions);
1526
+ return statFromFilePaths(entries.map((entry) => normalizeFsPath(entry.path)), path);
1527
+ });
1528
+ },
1529
+ };
1530
+ const readText = (inputPath) => __awaiter(this, void 0, void 0, function* () {
1531
+ const path = normalizeFsPath(inputPath);
1532
+ const key = hostKey(path);
1533
+ if (key === "") {
1534
+ throw new FileNotFoundError(path);
1535
+ }
1536
+ const [content, stat] = yield Promise.all([
1537
+ files.read(key, callOptions),
1538
+ files.stat(key, callOptions),
1539
+ ]);
1540
+ if (content === undefined) {
1541
+ throw new FileNotFoundError(path);
1542
+ }
1543
+ if ((stat === null || stat === void 0 ? void 0 : stat.etag) !== undefined) {
1544
+ readEtags.set(key, stat.etag);
1545
+ }
1546
+ return content;
1547
+ });
1548
+ const writeHost = (inputPath, contents) => __awaiter(this, void 0, void 0, function* () {
1549
+ const path = normalizeFsPath(inputPath);
1550
+ const key = hostKey(path);
1551
+ if (key === "") {
1552
+ throw new FileNotFoundError(path);
1553
+ }
1554
+ try {
1555
+ if (files.capabilities.conflictDetection) {
1556
+ const etag = readEtags.get(key);
1557
+ yield files.write(key, contents, Object.assign(Object.assign({}, callOptions), (etag === undefined ? {} : { ifMatch: etag })));
1558
+ }
1559
+ else {
1560
+ yield files.write(key, contents, callOptions);
1561
+ }
1562
+ }
1563
+ catch (error) {
1564
+ if (isHostConflict(error)) {
1565
+ throw new PathError(path, `${path} changed since you read it — read it again and rewrite.`);
1566
+ }
1567
+ throw error;
1568
+ }
1569
+ const stat = yield files.stat(key, callOptions);
1570
+ if ((stat === null || stat === void 0 ? void 0 : stat.etag) !== undefined) {
1571
+ readEtags.set(key, stat.etag);
1572
+ }
1573
+ else {
1574
+ readEtags.delete(key);
1575
+ }
1576
+ });
1577
+ return {
1578
+ list(prefix) {
1579
+ return listed.list(prefix);
1580
+ },
1581
+ stat(path) {
1582
+ return __awaiter(this, void 0, void 0, function* () {
1583
+ return listed.stat(path);
1584
+ });
1585
+ },
1586
+ read(path) {
1587
+ return __awaiter(this, void 0, void 0, function* () {
1588
+ return readText(path);
1589
+ });
1590
+ },
1591
+ grep(query) {
1592
+ return __asyncGenerator(this, arguments, function* grep_6() {
1593
+ yield __await(yield* __asyncDelegator(__asyncValues(limitResults(uncapped(), query.maxResults))));
1594
+ function uncapped() {
1595
+ return __asyncGenerator(this, arguments, function* uncapped_5() {
1596
+ var _a, e_10, _b, _c;
1597
+ const scopePath = query.path === undefined || query.path === ""
1598
+ ? "/"
1599
+ : normalizeFsPath(query.path);
1600
+ const regex = compileGrepPattern(query.pattern, query.caseInsensitive, scopePath);
1601
+ const info = yield __await(listed.stat(scopePath));
1602
+ if (scopePath !== "/" && info.kind === "file") {
1603
+ if (query.glob !== undefined &&
1604
+ !pathMatchesGlob(scopePath, scopePath, query.glob, {
1605
+ matchBasename: true,
1606
+ })) {
1607
+ return yield __await(void 0);
1608
+ }
1609
+ yield __await(yield* __asyncDelegator(__asyncValues(grepFileContent({
1610
+ path: scopePath,
1611
+ content: yield __await(readText(scopePath)),
1612
+ regex,
1613
+ }))));
1614
+ return yield __await(void 0);
1615
+ }
1616
+ try {
1617
+ for (var _d = true, _e = __asyncValues(listed.list(scopePath === "/" ? undefined : scopePath)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
1618
+ _c = _f.value;
1619
+ _d = false;
1620
+ const entry = _c;
1621
+ if (query.glob !== undefined &&
1622
+ !pathMatchesGlob(entry.path, scopePath, query.glob, {
1623
+ matchBasename: true,
1624
+ })) {
1625
+ continue;
1626
+ }
1627
+ yield __await(yield* __asyncDelegator(__asyncValues(grepFileContent({
1628
+ path: entry.path,
1629
+ content: yield __await(readText(entry.path)),
1630
+ regex,
1631
+ }))));
1632
+ }
1633
+ }
1634
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
1635
+ finally {
1636
+ try {
1637
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
1638
+ }
1639
+ finally { if (e_10) throw e_10.error; }
1640
+ }
1641
+ });
1642
+ }
1643
+ });
1644
+ },
1645
+ glob(pattern, dir) {
1646
+ return __asyncGenerator(this, arguments, function* glob_5() {
1647
+ const dirPath = dir === undefined || dir === "" ? "/" : normalizeFsPath(dir);
1648
+ yield __await(yield* __asyncDelegator(__asyncValues(globFromList(listed.list(dirPath === "/" ? undefined : dirPath), {
1649
+ pattern,
1650
+ dir: dirPath,
1651
+ }))));
1652
+ });
1653
+ },
1654
+ write(inputPath, contents) {
1655
+ return __awaiter(this, void 0, void 0, function* () {
1656
+ yield writeHost(inputPath, contents);
1657
+ });
1658
+ },
1659
+ delete(inputPath) {
1660
+ return __awaiter(this, void 0, void 0, function* () {
1661
+ const path = normalizeFsPath(inputPath);
1662
+ const key = hostKey(path);
1663
+ if (key === "" || !(yield files.exists(key, callOptions))) {
1664
+ throw new FileNotFoundError(path);
1665
+ }
1666
+ yield files.remove(key, callOptions);
1667
+ readEtags.delete(key);
1668
+ });
1669
+ },
1670
+ search: emptySearch,
1671
+ };
1672
+ }
1673
+ function globFromList(source, options) {
1674
+ return __asyncGenerator(this, arguments, function* globFromList_1() {
1675
+ var _a, e_11, _b, _c;
1676
+ try {
1677
+ for (var _d = true, source_5 = __asyncValues(source), source_5_1; source_5_1 = yield __await(source_5.next()), _a = source_5_1.done, !_a; _d = true) {
1678
+ _c = source_5_1.value;
1679
+ _d = false;
1680
+ const entry = _c;
1681
+ if (pathMatchesGlob(entry.path, options.dir, options.pattern)) {
1682
+ yield yield __await(entry);
1683
+ }
1684
+ }
1685
+ }
1686
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
1687
+ finally {
1688
+ try {
1689
+ if (!_d && !_a && (_b = source_5.return)) yield __await(_b.call(source_5));
1690
+ }
1691
+ finally { if (e_11) throw e_11.error; }
1692
+ }
1693
+ });
1694
+ }