stitchkit 0.119.0 → 0.121.0

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 (163) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +10 -7
  3. package/dist/agent-runtime/coding-discovery.d.ts +25 -0
  4. package/dist/agent-runtime/coding-discovery.d.ts.map +1 -0
  5. package/dist/agent-runtime/coding-search-automaton.d.ts +37 -0
  6. package/dist/agent-runtime/coding-search-automaton.d.ts.map +1 -0
  7. package/dist/agent-runtime/coding-search-case-fold.d.ts +4 -0
  8. package/dist/agent-runtime/coding-search-case-fold.d.ts.map +1 -0
  9. package/dist/agent-runtime/coding-search-class-ranges.d.ts +10 -0
  10. package/dist/agent-runtime/coding-search-class-ranges.d.ts.map +1 -0
  11. package/dist/agent-runtime/coding-search-contract.d.ts +86 -0
  12. package/dist/agent-runtime/coding-search-contract.d.ts.map +1 -0
  13. package/dist/agent-runtime/coding-search-limits.d.ts +13 -0
  14. package/dist/agent-runtime/coding-search-limits.d.ts.map +1 -0
  15. package/dist/agent-runtime/coding-search-matcher.d.ts +33 -0
  16. package/dist/agent-runtime/coding-search-matcher.d.ts.map +1 -0
  17. package/dist/agent-runtime/coding-search-output.d.ts +5 -0
  18. package/dist/agent-runtime/coding-search-output.d.ts.map +1 -0
  19. package/dist/agent-runtime/coding-search-regex-syntax.d.ts +39 -0
  20. package/dist/agent-runtime/coding-search-regex-syntax.d.ts.map +1 -0
  21. package/dist/agent-runtime/coding-search-unit-classes.d.ts +31 -0
  22. package/dist/agent-runtime/coding-search-unit-classes.d.ts.map +1 -0
  23. package/dist/agent-runtime/coding-shell-process.d.ts +1 -0
  24. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  25. package/dist/agent-runtime/coding-tool-contract.d.ts +8 -3
  26. package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
  27. package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
  28. package/dist/agent-runtime/coding-tool-listing.d.ts +1 -11
  29. package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
  30. package/dist/agent-runtime/coding-tool-paths.d.ts +6 -2
  31. package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
  32. package/dist/agent-runtime/coding-tool-refusals.d.ts +6 -0
  33. package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
  34. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
  35. package/dist/agent-runtime/coding-tool-search.d.ts +113 -0
  36. package/dist/agent-runtime/coding-tool-search.d.ts.map +1 -0
  37. package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
  38. package/dist/agent-runtime/contained-scan-budget.d.ts +32 -0
  39. package/dist/agent-runtime/contained-scan-budget.d.ts.map +1 -0
  40. package/dist/agent-runtime/contained-scan-contract.d.ts +52 -0
  41. package/dist/agent-runtime/contained-scan-contract.d.ts.map +1 -0
  42. package/dist/agent-runtime/contained-scan.d.ts +48 -13
  43. package/dist/agent-runtime/contained-scan.d.ts.map +1 -1
  44. package/dist/agent-runtime/sandbox.d.ts +5 -1
  45. package/dist/agent-runtime/sandbox.d.ts.map +1 -1
  46. package/dist/agent-runtime/workspace-glob.d.ts +6 -0
  47. package/dist/agent-runtime/workspace-glob.d.ts.map +1 -0
  48. package/dist/entrypoints/agent-runtime/coding-tools.js +7 -7
  49. package/dist/entrypoints/agent-runtime/harness.js +5 -5
  50. package/dist/entrypoints/agent-runtime/realtime.js +3 -3
  51. package/dist/entrypoints/agent-runtime/sandbox.js +8 -8
  52. package/dist/entrypoints/agent-runtime/sqlite/bun.js +9 -9
  53. package/dist/entrypoints/agent-runtime/sqlite/node.js +9 -9
  54. package/dist/entrypoints/agent-runtime/testing.js +9 -9
  55. package/dist/entrypoints/agent-runtime.js +16 -14
  56. package/dist/entrypoints/application/diagnostic-journal.js +3 -3
  57. package/dist/entrypoints/application/directory-inbox.js +5 -5
  58. package/dist/entrypoints/application.js +6 -6
  59. package/dist/entrypoints/cli/publish.js +5 -5
  60. package/dist/entrypoints/cli.js +8 -8
  61. package/dist/entrypoints/contract.js +4 -4
  62. package/dist/entrypoints/files.js +4 -4
  63. package/dist/entrypoints/http.js +2 -2
  64. package/dist/entrypoints/index.js +2 -2
  65. package/dist/entrypoints/node.js +1 -1
  66. package/dist/entrypoints/process/owner-loss.js +2 -1
  67. package/dist/entrypoints/process.js +4 -4
  68. package/dist/entrypoints/remote.js +1 -1
  69. package/dist/entrypoints/server.js +12 -12
  70. package/dist/entrypoints/telegram/screens.js +5 -5
  71. package/dist/entrypoints/telegram.js +8 -8
  72. package/dist/entrypoints/testing.js +2 -2
  73. package/dist/entrypoints/tools/agent.d.ts +9 -0
  74. package/dist/entrypoints/tools/agent.d.ts.map +1 -0
  75. package/dist/entrypoints/tools/agent.js +16 -0
  76. package/dist/entrypoints/tools/connections.js +4 -4
  77. package/dist/entrypoints/tools/mcp.js +104 -4
  78. package/dist/entrypoints/tools/toolkit.d.ts +9 -0
  79. package/dist/entrypoints/tools/toolkit.d.ts.map +1 -0
  80. package/dist/entrypoints/tools/toolkit.js +40 -0
  81. package/dist/entrypoints/tools.d.ts +0 -10
  82. package/dist/entrypoints/tools.d.ts.map +1 -1
  83. package/dist/entrypoints/tools.js +25 -69
  84. package/dist/{index-s0qjs6ee.js → index-0fra8xvy.js} +9 -81
  85. package/dist/{index-rxcgp4b9.js → index-10rg78vf.js} +1 -1
  86. package/dist/index-1psbyyhj.js +21 -0
  87. package/dist/index-3prvb42w.js +30 -0
  88. package/dist/{index-ba7are04.js → index-4tyt1qya.js} +1 -1
  89. package/dist/index-568w258r.js +76 -0
  90. package/dist/{index-fqd4yqwd.js → index-6j15ktag.js} +1 -1
  91. package/dist/{index-zrdcmg6j.js → index-72xtvcvr.js} +40 -6
  92. package/dist/{index-6a69xzrx.js → index-7zwtbak8.js} +5 -46
  93. package/dist/{index-fcqj44mb.js → index-8ryydawp.js} +4 -4
  94. package/dist/{index-q968hy6y.js → index-aqmadanx.js} +2 -2
  95. package/dist/{index-s20s2mad.js → index-bgcwxhxh.js} +16 -14
  96. package/dist/index-bph35vpy.js +77 -0
  97. package/dist/{index-arjmb6de.js → index-eeahxwvg.js} +60 -76
  98. package/dist/{index-57gqaq8b.js → index-f6pw75e1.js} +1 -1
  99. package/dist/{index-f4njz9j0.js → index-gq3fnq3f.js} +1 -1
  100. package/dist/{index-ynrf908v.js → index-gtx3eknx.js} +1 -1
  101. package/dist/index-h1j71dr1.js +48 -0
  102. package/dist/{index-nn9qvkww.js → index-j95jp7ee.js} +45 -9
  103. package/dist/{index-mgb7r8b8.js → index-jswst0h3.js} +1 -1
  104. package/dist/{index-bbvc59gw.js → index-knmnj11j.js} +9 -180
  105. package/dist/{index-2kbysk9s.js → index-m5m9rmvt.js} +2 -0
  106. package/dist/{index-g444vfz2.js → index-nwm3ww60.js} +1 -1
  107. package/dist/{index-yk4g8805.js → index-pq7rkwkk.js} +1 -30
  108. package/dist/index-qaqxdbxf.js +2857 -0
  109. package/dist/{index-x8d9fdeg.js → index-qctbzmg9.js} +8 -4
  110. package/dist/index-s9a0fjh3.js +305 -0
  111. package/dist/index-sb9dr3tq.js +14 -0
  112. package/dist/{index-tvtacc9a.js → index-zyc64nbh.js} +1 -34
  113. package/dist/internal/contained-directory.d.ts +1 -1
  114. package/dist/internal/contained-directory.d.ts.map +1 -1
  115. package/dist/internal/contained-files.d.ts +18 -51
  116. package/dist/internal/contained-files.d.ts.map +1 -1
  117. package/dist/internal/contained-read.d.ts +17 -0
  118. package/dist/internal/contained-read.d.ts.map +1 -0
  119. package/dist/internal/darwin-binding.d.ts +3 -1
  120. package/dist/internal/darwin-binding.d.ts.map +1 -1
  121. package/dist/process/bun-child.d.ts.map +1 -1
  122. package/dist/process/command-owner.d.ts.map +1 -1
  123. package/dist/process/group.d.ts +2 -0
  124. package/dist/process/group.d.ts.map +1 -1
  125. package/dist/process/launch.d.ts +1 -0
  126. package/dist/process/launch.d.ts.map +1 -1
  127. package/dist/process/owned-child.d.ts.map +1 -1
  128. package/dist/process/owner-loss-guard.d.ts.map +1 -1
  129. package/dist/process/owner-loss-protocol.d.ts +1 -0
  130. package/dist/process/owner-loss-protocol.d.ts.map +1 -1
  131. package/llms/agent-runtime-coding-tools.txt +9 -9
  132. package/llms/agent-runtime-harness.txt +4 -3
  133. package/llms/agent-runtime-sandbox.txt +1 -1
  134. package/llms/agent-runtime.2.txt +20 -2
  135. package/llms/agent-runtime.3.txt +4 -46
  136. package/llms/agent-runtime.4.txt +113 -0
  137. package/llms/agent-runtime.txt +70 -37
  138. package/llms/application.3.txt +5 -2
  139. package/llms/cli.txt +1 -1
  140. package/llms/contract.txt +1 -1
  141. package/llms/process.txt +3 -1
  142. package/llms/server.5.txt +2 -0
  143. package/llms/stitchkit.txt +15 -9
  144. package/llms/testing.txt +4 -6
  145. package/llms/tools-agent.txt +24 -0
  146. package/llms/tools-mcp.txt +71 -6
  147. package/llms/tools-toolkit.txt +23 -0
  148. package/llms/tools.2.txt +6 -3
  149. package/llms/tools.3.txt +8 -77
  150. package/llms/tools.txt +8 -8
  151. package/llms/{upgrading-0.106.0-0.119.0.txt → upgrading-0.106.0-0.121.0.txt} +84 -3
  152. package/llms/upgrading.txt +1 -1
  153. package/llms-full.txt +360 -139
  154. package/llms.txt +11 -9
  155. package/native/darwin-arm64.node +0 -0
  156. package/native/darwin-x64.node +0 -0
  157. package/native-assets.json +4 -4
  158. package/package.json +10 -2
  159. package/dist/index-1k18qzqa.js +0 -1478
  160. package/dist/index-6f49krb5.js +0 -107
  161. package/dist/{index-2dfvv1jg.js → index-2fc1k9k2.js} +0 -0
  162. package/dist/{index-qndsr7f0.js → index-5efrpfmj.js} +3 -3
  163. /package/dist/{index-cyxp8rbf.js → index-mtwh9hyp.js} +0 -0
@@ -1,1478 +0,0 @@
1
- import {
2
- NativeCommandError2
3
- } from "./index-zrdcmg6j.js";
4
- import {
5
- CommandStopped,
6
- startNativeCommand
7
- } from "./index-nn9qvkww.js";
8
- import {
9
- scanContainedFiles
10
- } from "./index-6f49krb5.js";
11
- import {
12
- writeContainedFile
13
- } from "./index-q968hy6y.js";
14
- import {
15
- listContainedDirectory,
16
- missingContainedDirectories,
17
- misspelledContainedSegment,
18
- UnapprovedContainedDirectoryError,
19
- openContainedParent,
20
- openContainedFile,
21
- ContainedPathChangedError,
22
- assertContainedFileCurrent,
23
- assertContainedParentCurrent,
24
- containedEntryMetadata,
25
- openContainedParentFile,
26
- readContainedUtf8Handle
27
- } from "./index-arjmb6de.js";
28
- import {
29
- defineRuntimeTool2
30
- } from "./index-aqwg2dm5.js";
31
- import {
32
- errnoOf
33
- } from "./index-jj9228tt.js";
34
- import {
35
- AppError2,
36
- forbidden2,
37
- conflict2,
38
- STITCH_ERROR_STATUS2
39
- } from "./index-qcn84byh.js";
40
-
41
- // src/agent-runtime/coding-tool-contract.ts
42
- import { z } from "zod";
43
- var AgentCodingToolLimitsSchema2 = z.object({
44
- maxPathBytes: z.int().positive(),
45
- maxReadBytes: z.int().positive(),
46
- maxWriteBytes: z.int().positive(),
47
- maxShellArguments: z.int().positive(),
48
- maxShellArgumentBytes: z.int().positive(),
49
- maxShellOutputBytes: z.int().positive(),
50
- maxArtifactBytes: z.int().positive(),
51
- maxListEntries: z.int().positive(),
52
- maxSearchResults: z.int().positive(),
53
- maxSearchFiles: z.int().positive(),
54
- maxSearchDepth: z.int().nonnegative(),
55
- shellTimeoutMs: z.int().positive(),
56
- shellTerminationGraceMs: z.int().positive()
57
- }).strict();
58
- var AgentCodingToolAuthorizationSchema2 = z.discriminatedUnion("operation", [
59
- z.object({ operation: z.literal("read"), path: z.string().min(1) }).strict(),
60
- z.object({
61
- operation: z.literal("write"),
62
- path: z.string().min(1),
63
- bytes: z.int().nonnegative(),
64
- overwrite: z.boolean(),
65
- createsDirectories: z.array(z.string().min(1))
66
- }).strict(),
67
- z.object({
68
- operation: z.literal("search"),
69
- query: z.string().min(1),
70
- mode: z.enum(["path", "content"])
71
- }).strict(),
72
- z.object({
73
- operation: z.literal("edit"),
74
- path: z.string().min(1),
75
- baseSha256: z.string().length(64),
76
- resultSha256: z.string().length(64),
77
- resultBytes: z.int().nonnegative(),
78
- replacements: z.int().positive(),
79
- dryRun: z.boolean()
80
- }).strict(),
81
- z.object({ operation: z.literal("list"), path: z.string().min(1) }).strict(),
82
- z.object({
83
- operation: z.literal("glob"),
84
- pattern: z.string().min(1),
85
- path: z.string().min(1)
86
- }).strict(),
87
- z.object({
88
- operation: z.literal("artifact-read"),
89
- reference: z.string().min(1),
90
- offset: z.int().nonnegative(),
91
- maxBytes: z.int().positive()
92
- }).strict(),
93
- z.object({
94
- operation: z.literal("artifact-search"),
95
- reference: z.string().min(1),
96
- query: z.string().min(1),
97
- maxMatches: z.int().positive()
98
- }).strict(),
99
- z.object({
100
- operation: z.literal("shell"),
101
- executable: z.string().min(1),
102
- args: z.array(z.string()),
103
- cwd: z.string().min(1)
104
- }).strict()
105
- ]);
106
- var AgentCodingToolPathAuthorizationSchema2 = z.object({ path: z.string().min(1) }).strict();
107
- var CodingDeniedEntrySchema = z.object({
108
- path: z.string().min(1),
109
- kind: z.enum(["file", "directory", "symlink", "other"])
110
- }).strict();
111
- var FileReadInputSchema = z.object({
112
- path: z.string().min(1),
113
- offset: z.int().nonnegative().default(0),
114
- maxBytes: z.int().positive().optional()
115
- }).strict();
116
- var FileReadOutputSchema = z.object({
117
- path: z.string().min(1),
118
- text: z.string(),
119
- bytes: z.int().nonnegative(),
120
- sha256: z.string().length(64),
121
- truncated: z.boolean(),
122
- nextOffset: z.int().nonnegative().optional()
123
- }).strict();
124
- var FileWriteInputSchema = z.object({
125
- path: z.string().min(1),
126
- content: z.string(),
127
- overwrite: z.boolean().default(false)
128
- }).strict();
129
- var FileWriteOutputSchema = z.object({
130
- path: z.string().min(1),
131
- bytes: z.int().nonnegative(),
132
- createdDirectories: z.array(z.string().min(1))
133
- }).strict();
134
- function createShellInputSchema(executableNames) {
135
- if (executableNames.length === 0) {
136
- throw new Error("A command tool requires at least one executable alias");
137
- }
138
- return z.object({
139
- executable: z.enum(executableNames),
140
- args: z.array(z.string()).default([]),
141
- cwd: z.string().min(1).default(".")
142
- }).strict();
143
- }
144
- var ShellInputSchema = z.object({
145
- executable: z.string().min(1),
146
- args: z.array(z.string()).default([]),
147
- cwd: z.string().min(1).default(".")
148
- }).strict();
149
- var ShellOutputSchema = z.object({
150
- executable: z.string().min(1),
151
- exitCode: z.int().nullable(),
152
- signal: z.string().nullable(),
153
- stdout: z.string(),
154
- stderr: z.string(),
155
- outcome: z.enum(["exited", "timeout", "output-limit", "cancelled"]),
156
- artifact: z.object({
157
- reference: z.string().min(1),
158
- bytes: z.int().nonnegative(),
159
- truncated: z.boolean(),
160
- headBytes: z.int().nonnegative(),
161
- tailBytes: z.int().nonnegative(),
162
- omittedBytes: z.int().nonnegative()
163
- }).strict().optional()
164
- }).strict();
165
- var DEFAULT_LIMITS = {
166
- maxPathBytes: 4096,
167
- maxReadBytes: 262144,
168
- maxWriteBytes: 262144,
169
- maxShellArguments: 128,
170
- maxShellArgumentBytes: 65536,
171
- maxShellOutputBytes: 262144,
172
- maxArtifactBytes: 4194304,
173
- maxListEntries: 500,
174
- maxSearchResults: 100,
175
- maxSearchFiles: 1e4,
176
- maxSearchDepth: 32,
177
- shellTimeoutMs: 30000,
178
- shellTerminationGraceMs: 250
179
- };
180
- function resolveCodingToolLimits(input) {
181
- return AgentCodingToolLimitsSchema2.parse({ ...DEFAULT_LIMITS, ...input });
182
- }
183
-
184
- // src/agent-runtime/sandbox.ts
185
- import { z as z2 } from "zod";
186
- var AgentSandboxRestrictionSchema2 = z2.enum([
187
- "network-denied",
188
- "write-contained",
189
- "secrets-hidden",
190
- "process-contained"
191
- ]);
192
- var AgentSandboxGradeSchema2 = z2.discriminatedUnion("grade", [
193
- z2.object({ grade: z2.literal("full"), restrictions: z2.array(AgentSandboxRestrictionSchema2) }).strict(),
194
- z2.object({
195
- grade: z2.literal("partial"),
196
- restrictions: z2.array(AgentSandboxRestrictionSchema2),
197
- gaps: z2.array(AgentSandboxRestrictionSchema2)
198
- }).strict(),
199
- z2.object({ grade: z2.literal("unavailable"), reason: z2.string().min(1) }).strict()
200
- ]);
201
- var probes = new WeakMap;
202
- var PROBE_FAILED = "sandbox probe failed";
203
- var PROBE_INVALID = "sandbox probe returned no valid grade";
204
- async function runProbe(sandbox) {
205
- let value;
206
- try {
207
- value = await sandbox.probe();
208
- } catch (cause) {
209
- return { grade: { grade: "unavailable", reason: PROBE_FAILED }, cause };
210
- }
211
- const parsed = AgentSandboxGradeSchema2.safeParse(value);
212
- if (parsed.success)
213
- return { grade: parsed.data };
214
- return { grade: { grade: "unavailable", reason: PROBE_INVALID }, cause: parsed.error };
215
- }
216
- function probeAgentProcessSandboxOutcome(sandbox, options = {}) {
217
- if (options.refresh)
218
- probes.delete(sandbox);
219
- const present = probes.get(sandbox);
220
- if (present)
221
- return present;
222
- const pending = runProbe(sandbox);
223
- probes.set(sandbox, pending);
224
- return pending;
225
- }
226
- async function probeAgentProcessSandbox2(sandbox, options = {}) {
227
- const fresh = options.refresh === true || !probes.has(sandbox);
228
- const outcome = await probeAgentProcessSandboxOutcome(sandbox, options);
229
- if (fresh && outcome.cause !== undefined) {
230
- process.emitWarning(new Error("Sandbox probe failed", { cause: outcome.cause }));
231
- }
232
- return outcome.grade;
233
- }
234
- function missingSandboxRestrictions2(grade, required) {
235
- if (grade.grade === "unavailable")
236
- return required;
237
- const present = new Set(grade.restrictions);
238
- return required.filter((restriction) => !present.has(restriction));
239
- }
240
- async function recordAgentSandboxProbe2(input) {
241
- const grade = await probeAgentProcessSandbox2(input.sandbox);
242
- const missing = missingSandboxRestrictions2(grade, input.required);
243
- await input.store.appendEvent({
244
- conversationId: input.conversationId,
245
- kind: "sandbox/probed",
246
- payload: {
247
- result: grade,
248
- required: [...input.required],
249
- missing: [...missing]
250
- }
251
- });
252
- return grade;
253
- }
254
-
255
- // src/agent-runtime/coding-tool-refusals.ts
256
- function codingRefusal(code, message, options = {}) {
257
- throw new AppError2(code, {
258
- message,
259
- status: STITCH_ERROR_STATUS2[code],
260
- details: { message, ...options.details },
261
- hint: options.hint,
262
- ..."cause" in options && { cause: options.cause }
263
- });
264
- }
265
- function codingPathRefusal(code, message, path, options = {}) {
266
- codingRefusal(code, message, {
267
- details: { path, ...options.details },
268
- ...options.hint && { hint: options.hint }
269
- });
270
- }
271
- function refuseMissingCodingPath(error, relative) {
272
- refuseChangedPath(error, relative);
273
- const code = errnoOf(error);
274
- if (error instanceof Error && error.message.includes("is not a regular file")) {
275
- codingPathRefusal("BAD_REQUEST", "This path is not a regular file", relative, {
276
- hint: "Use list_directory to see what is here."
277
- });
278
- }
279
- if (code === "ENOENT") {
280
- codingPathRefusal("NOT_FOUND", "This path does not exist", relative, {
281
- hint: "Use list_directory or glob to find the right path."
282
- });
283
- }
284
- if (code === "ENOTDIR") {
285
- codingPathRefusal("BAD_REQUEST", "A segment of this path is not a directory", relative, {
286
- hint: "Check the path with list_directory."
287
- });
288
- }
289
- if (code === "ELOOP") {
290
- codingPathRefusal("FORBIDDEN", "This path is a symlink, which is not followed", relative, {
291
- hint: "Read or write the target directly, by its own workspace-relative path."
292
- });
293
- }
294
- if (code === "EISDIR" || code === "ENXIO" || code === "EOPNOTSUPP") {
295
- codingPathRefusal("BAD_REQUEST", "This path is not a regular file", relative, {
296
- hint: "Use list_directory to see what is here."
297
- });
298
- }
299
- throw error;
300
- }
301
- function refuseChangedPath(error, relative) {
302
- if (error instanceof ContainedPathChangedError) {
303
- codingPathRefusal("CONFLICT", "This path changed while it was being authorized", relative, {
304
- hint: "Read it again and retry."
305
- });
306
- }
307
- }
308
- function refuseWriteConflict(error, relative, details = {}) {
309
- refuseChangedPath(error, relative);
310
- const code = errnoOf(error);
311
- if (code === "ENOENT") {
312
- codingPathRefusal("CONFLICT", "This path changed while it was being written", relative, {
313
- details,
314
- hint: "Read it again and retry."
315
- });
316
- }
317
- if (code === "ENOTDIR") {
318
- codingPathRefusal("CONFLICT", "A segment of this path is not a directory", relative, {
319
- details,
320
- hint: "Write under a different path, or remove the file blocking it."
321
- });
322
- }
323
- if (code === "ELOOP") {
324
- codingPathRefusal("FORBIDDEN", "This path is a symlink, which is not followed", relative, {
325
- details,
326
- hint: "Write to the target directly, by its own workspace-relative path."
327
- });
328
- }
329
- if (code === "EISDIR") {
330
- codingPathRefusal("CONFLICT", "This path is a directory", relative, {
331
- details,
332
- hint: "Write to a file path inside it, or choose another name."
333
- });
334
- }
335
- if (code === "EEXIST") {
336
- codingPathRefusal("CONFLICT", "This file already exists", relative, {
337
- details,
338
- hint: "Pass overwrite: true to replace it, or edit_file to change part of it."
339
- });
340
- }
341
- throw error;
342
- }
343
- function refuseUnknownSpillReference(reference) {
344
- codingRefusal("SPILL_REFERENCE_UNKNOWN", `No spilled output is held under \`${reference}\``, {
345
- details: { reference },
346
- hint: "Use the reference returned by the command that spilled its output, not a session or call id."
347
- });
348
- }
349
-
350
- // src/agent-runtime/coding-tools.ts
351
- import path4 from "node:path";
352
- import { z as z5 } from "zod";
353
-
354
- // src/agent-runtime/coding-tool-files.ts
355
- import { createHash } from "node:crypto";
356
- import { realpath as realpath2 } from "node:fs/promises";
357
-
358
- // src/agent-runtime/coding-tool-paths.ts
359
- import { lstat, realpath } from "node:fs/promises";
360
- import path from "node:path";
361
- function within(root, target) {
362
- const relative = path.relative(root, target);
363
- return relative === "" || !relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative);
364
- }
365
- function inputPath(root, requested, maxPathBytes) {
366
- if (new TextEncoder().encode(requested).byteLength > maxPathBytes) {
367
- codingRefusal("BAD_REQUEST", `Path exceeds the ${maxPathBytes}-byte limit`, {
368
- details: { maxPathBytes },
369
- hint: "Use a shorter workspace-relative path."
370
- });
371
- }
372
- if (path.isAbsolute(requested)) {
373
- const relative = path.relative(root, requested);
374
- const recoveryPath = within(root, requested) ? relative.split(path.sep).join("/") || "." : undefined;
375
- codingRefusal("BAD_REQUEST", "Paths must be relative to the workspace root", {
376
- details: { path: requested, ...recoveryPath && { recoveryPath } },
377
- hint: recoveryPath ? `Use the workspace-relative path \`${recoveryPath}\`.` : "Pass a path relative to the workspace root; absolute paths outside it have no workspace-relative equivalent."
378
- });
379
- }
380
- const resolved = path.resolve(root, requested);
381
- if (!within(root, resolved)) {
382
- codingRefusal("FORBIDDEN", "Path escapes the workspace root", {
383
- details: { path: requested },
384
- hint: "Stay inside the workspace; `..` segments that leave the root are refused."
385
- });
386
- }
387
- return resolved;
388
- }
389
- function boundedCodingRelativePath(root, requested, maxPathBytes) {
390
- if (requested.includes("\x00")) {
391
- codingRefusal("BAD_REQUEST", "Path segments cannot contain a NUL byte", {
392
- details: { path: requested },
393
- hint: "Pass the exact workspace-relative entry name without NUL bytes."
394
- });
395
- }
396
- if (path.isAbsolute(requested))
397
- inputPath(root, requested, maxPathBytes);
398
- if (requested.includes("\\")) {
399
- codingRefusal("FORBIDDEN", "Path separators must be `/`", {
400
- details: { path: requested },
401
- hint: "Use `/` between segments; a backslash is refused because the workspace walk reads it as a separator."
402
- });
403
- }
404
- const segments = requested.split("/");
405
- if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
406
- codingRefusal("FORBIDDEN", "Path segments must name real entries under the root", {
407
- details: { path: requested },
408
- hint: "Pass a plain workspace-relative path — `.`, `..` and empty segments are refused."
409
- });
410
- }
411
- inputPath(root, requested, maxPathBytes);
412
- return requested;
413
- }
414
- async function existingCodingPath(root, requested, maxPathBytes) {
415
- const resolved = await realpath(inputPath(root, requested, maxPathBytes));
416
- if (!within(root, resolved))
417
- throw new Error("Coding tool path resolves outside its root");
418
- return { absolute: resolved, relative: path.relative(root, resolved) || "." };
419
- }
420
- async function authorizeCodingTool(config, request) {
421
- const parsed = AgentCodingToolAuthorizationSchema2.parse(request);
422
- if (!await config.authorize(parsed))
423
- forbidden2("Coding tool permission denied");
424
- }
425
- async function isCodingPathAuthorized(config, path2) {
426
- if (!config.authorizePath)
427
- return true;
428
- const parsed = AgentCodingToolPathAuthorizationSchema2.parse({ path: path2 });
429
- return await config.authorizePath(parsed);
430
- }
431
- async function authorizeCodingPath(config, path2) {
432
- if (!await isCodingPathAuthorized(config, path2)) {
433
- codingRefusal("FORBIDDEN", "Coding tool path permission denied", {
434
- details: { path: path2 },
435
- hint: "The host policy refused this path or a directory above it."
436
- });
437
- }
438
- }
439
- async function authorizeCodingPathChain(config, relative) {
440
- if (relative !== ".") {
441
- const misspelled = await misspelledContainedSegment(await realpath(config.root), relative);
442
- if (misspelled !== undefined) {
443
- codingPathRefusal("BAD_REQUEST", "This path differs from the name stored on disk", relative, {
444
- hint: "Use list_directory to see the stored spelling."
445
- });
446
- }
447
- }
448
- if (!config.authorizePath)
449
- return;
450
- const segments = relative === "." ? ["."] : relative.split("/");
451
- for (let depth = 1;depth <= segments.length; depth += 1) {
452
- await authorizeCodingPath(config, segments.slice(0, depth).join("/"));
453
- }
454
- }
455
- var codingPathLocks = new Map;
456
- async function withCodingPathLock(target, work) {
457
- const previous = codingPathLocks.get(target) ?? Promise.resolve();
458
- let release = () => {
459
- return;
460
- };
461
- const current = new Promise((resolve) => {
462
- release = resolve;
463
- });
464
- const queued = previous.then(() => current);
465
- codingPathLocks.set(target, queued);
466
- await previous;
467
- try {
468
- return await work();
469
- } finally {
470
- release();
471
- if (codingPathLocks.get(target) === queued)
472
- codingPathLocks.delete(target);
473
- }
474
- }
475
- function textOccurrences(source, search) {
476
- let count = 0;
477
- let offset = 0;
478
- while (offset <= source.length - search.length) {
479
- const found = source.indexOf(search, offset);
480
- if (found < 0)
481
- break;
482
- count += 1;
483
- offset = found + search.length;
484
- }
485
- return count;
486
- }
487
-
488
- // src/agent-runtime/coding-tool-utf8.ts
489
- function sequenceLength(lead) {
490
- if (lead < 128)
491
- return 1;
492
- if ((lead & 224) === 192)
493
- return 2;
494
- if ((lead & 240) === 224)
495
- return 3;
496
- if ((lead & 248) === 240)
497
- return 4;
498
- return;
499
- }
500
- function utf8AlignedEnd(data, start, limit) {
501
- const safe = Math.max(start, Math.min(start + limit, data.byteLength));
502
- for (let back = 1;back <= 4 && safe - back >= start; back += 1) {
503
- const byte = data[safe - back];
504
- if ((byte & 192) === 128)
505
- continue;
506
- const length = sequenceLength(byte);
507
- if (length === undefined)
508
- return safe;
509
- if (back >= length)
510
- return safe;
511
- const sequenceEnd = safe - back + length;
512
- return sequenceEnd <= data.byteLength ? sequenceEnd : safe - back;
513
- }
514
- return safe;
515
- }
516
- function utf8AlignedStart(data, start, end) {
517
- let safe = Math.max(0, Math.min(start, end));
518
- while (safe < end && (data[safe] & 192) === 128)
519
- safe += 1;
520
- return safe;
521
- }
522
-
523
- // src/agent-runtime/coding-tool-files.ts
524
- async function digestFile(handle, size) {
525
- const hash = createHash("sha256");
526
- const chunk = Buffer.alloc(Math.min(64 * 1024, Math.max(1, size)));
527
- for (let position = 0;position < size; ) {
528
- const length = Math.min(chunk.byteLength, size - position);
529
- const { bytesRead } = await handle.read(chunk, 0, length, position);
530
- if (bytesRead === 0)
531
- break;
532
- hash.update(chunk.subarray(0, bytesRead));
533
- position += bytesRead;
534
- }
535
- return hash.digest("hex");
536
- }
537
- async function openAuthorizedWriteParent(root, relative, createsDirectories) {
538
- return openContainedParent(root, relative, { createDirectories: createsDirectories }).catch((error) => {
539
- if (error instanceof UnapprovedContainedDirectoryError) {
540
- codingPathRefusal("CONFLICT", "The directory creation plan changed during authorization", relative, {
541
- details: { createsDirectories },
542
- hint: "Retry the write so the host can authorize the current directories."
543
- });
544
- }
545
- refuseWriteConflict(error, relative, { createsDirectories });
546
- });
547
- }
548
- function createFileCodingTools(config, limits) {
549
- const read = defineRuntimeTool2({
550
- name: "read_file",
551
- description: "Read a bounded UTF-8 slice from a host-authorized workspace file.",
552
- identity: { serviceName: "coding", action: "read-file", method: "POST" },
553
- input: FileReadInputSchema,
554
- output: FileReadOutputSchema,
555
- transports: ["AGENT"],
556
- handler: async ({ input }) => {
557
- const root = await realpath2(config.root);
558
- const relative = boundedCodingRelativePath(root, input.path, limits.maxPathBytes);
559
- await authorizeCodingPathChain(config, relative);
560
- const handle = await openContainedFile(root, relative).catch((error) => refuseMissingCodingPath(error, relative));
561
- const maximum = Math.min(input.maxBytes ?? limits.maxReadBytes, limits.maxReadBytes);
562
- let selected;
563
- let start = input.offset;
564
- let size;
565
- let sha256;
566
- try {
567
- await authorizeCodingTool(config, { operation: "read", path: relative });
568
- await assertContainedFileCurrent(root, relative, handle).catch((error) => refuseMissingCodingPath(error, relative));
569
- const metadata = await handle.stat();
570
- if (!metadata.isFile()) {
571
- codingPathRefusal("BAD_REQUEST", "This path is not a regular file", relative, {
572
- hint: "Use list_directory to see what is here."
573
- });
574
- }
575
- size = metadata.size;
576
- const length = Math.min(maximum + 4, Math.max(0, size - input.offset));
577
- selected = Buffer.alloc(length);
578
- const { bytesRead } = await handle.read(selected, 0, length, input.offset);
579
- selected = selected.subarray(0, bytesRead);
580
- if (input.offset > 0) {
581
- const aligned = utf8AlignedStart(selected, 0, selected.byteLength);
582
- start = input.offset + aligned;
583
- selected = selected.subarray(aligned);
584
- }
585
- if (selected.byteLength > maximum) {
586
- selected = selected.subarray(0, utf8AlignedEnd(selected, 0, maximum));
587
- }
588
- sha256 = await digestFile(handle, size);
589
- } finally {
590
- await handle.close();
591
- }
592
- let text;
593
- try {
594
- text = new TextDecoder("utf-8", { fatal: true }).decode(selected);
595
- } catch {
596
- codingPathRefusal("BAD_REQUEST", "The selected file bytes are not valid UTF-8", relative, {
597
- details: { reason: "invalid_utf8" },
598
- hint: "Use a binary-capable reader or convert the file to UTF-8."
599
- });
600
- }
601
- const end = start + selected.byteLength;
602
- const truncated = end < size;
603
- return {
604
- path: relative,
605
- text,
606
- bytes: selected.byteLength,
607
- sha256,
608
- truncated,
609
- ...truncated && { nextOffset: end }
610
- };
611
- }
612
- });
613
- const write = defineRuntimeTool2({
614
- name: "write_file",
615
- description: "Write bounded UTF-8 content to a host-authorized workspace file.",
616
- identity: { serviceName: "coding", action: "write-file", method: "POST" },
617
- input: FileWriteInputSchema,
618
- output: FileWriteOutputSchema,
619
- transports: ["AGENT"],
620
- handler: async ({ input }) => {
621
- const root = await realpath2(config.root);
622
- const relative = boundedCodingRelativePath(root, input.path, limits.maxPathBytes);
623
- await authorizeCodingPathChain(config, relative);
624
- const bytes = Buffer.byteLength(input.content);
625
- if (bytes > limits.maxWriteBytes) {
626
- codingPathRefusal("BAD_REQUEST", `The content is ${bytes} bytes, over the ${limits.maxWriteBytes}-byte limit`, relative, {
627
- details: { bytes, maxWriteBytes: limits.maxWriteBytes },
628
- hint: "Write a smaller file, or split it."
629
- });
630
- }
631
- const createsDirectories = await missingContainedDirectories(root, relative).catch((error) => refuseWriteConflict(error, relative));
632
- await authorizeCodingTool(config, {
633
- operation: "write",
634
- path: relative,
635
- bytes,
636
- overwrite: input.overwrite,
637
- createsDirectories
638
- });
639
- await withCodingPathLock(`${root}:${relative}`, async () => {
640
- const parent = await openAuthorizedWriteParent(root, relative, createsDirectories);
641
- try {
642
- await assertContainedParentCurrent(root, relative, parent.handle).catch((error) => refuseWriteConflict(error, relative));
643
- const current = await containedEntryMetadata(parent);
644
- if (input.overwrite) {
645
- if (current?.isSymbolicLink()) {
646
- codingPathRefusal("FORBIDDEN", "This path is a symlink", relative, {
647
- hint: "Coding tools never write through symlinks; write to the target directly."
648
- });
649
- }
650
- await writeContainedFile({
651
- parent,
652
- content: input.content,
653
- replace: true,
654
- ...current && { mode: current.mode }
655
- }).catch((error) => refuseWriteConflict(error, relative));
656
- } else {
657
- if (current) {
658
- codingPathRefusal("CONFLICT", "This file already exists", relative, {
659
- hint: "Pass overwrite: true to replace it, or edit_file to change part of it."
660
- });
661
- }
662
- await writeContainedFile({
663
- parent,
664
- content: input.content,
665
- replace: false
666
- }).catch((error) => refuseWriteConflict(error, relative));
667
- }
668
- } finally {
669
- await parent.handle.close();
670
- }
671
- });
672
- return { path: relative, bytes, createdDirectories: createsDirectories };
673
- }
674
- });
675
- return [read, write];
676
- }
677
-
678
- // src/agent-runtime/coding-tool-listing.ts
679
- import { realpath as realpath3 } from "node:fs/promises";
680
- import path2 from "node:path";
681
- import { z as z3 } from "zod";
682
- var DEFAULT_EXCLUDED_DIRECTORIES = [
683
- ".git",
684
- ".next",
685
- ".stitchkit",
686
- "build",
687
- "coverage",
688
- "dist",
689
- "node_modules"
690
- ];
691
- var ListInputSchema = z3.object({ path: z3.string().min(1).default(".") }).strict();
692
- var ListOutputSchema = z3.object({
693
- path: z3.string().min(1),
694
- entries: z3.array(z3.object({
695
- name: z3.string().min(1),
696
- kind: z3.enum(["file", "directory", "symlink", "other"]),
697
- bytes: z3.int().nonnegative().optional(),
698
- excluded: z3.boolean().optional()
699
- }).strict()),
700
- truncated: z3.boolean(),
701
- denied: z3.array(CodingDeniedEntrySchema).optional(),
702
- deniedTruncated: z3.boolean().optional()
703
- }).strict();
704
- var GlobInputSchema = z3.object({ pattern: z3.string().min(1), path: z3.string().min(1).default(".") }).strict();
705
- var GlobOutputSchema = z3.object({
706
- paths: z3.array(z3.string().min(1)),
707
- truncated: z3.boolean(),
708
- resultTruncated: z3.boolean(),
709
- skippedDirectories: z3.int().nonnegative(),
710
- scannedFiles: z3.int().nonnegative(),
711
- denied: z3.array(CodingDeniedEntrySchema).optional(),
712
- deniedTruncated: z3.boolean().optional()
713
- }).strict();
714
- function compileWorkspaceGlob(pattern) {
715
- let source = "";
716
- for (let index = 0;index < pattern.length; index += 1) {
717
- const character = pattern[index];
718
- if (character === "*") {
719
- if (pattern[index + 1] === "*") {
720
- if (pattern[index + 2] === "/") {
721
- source += "(?:[^/]+/)*";
722
- index += 2;
723
- continue;
724
- }
725
- source += ".*";
726
- index += 1;
727
- continue;
728
- }
729
- source += "[^/]*";
730
- continue;
731
- }
732
- if (character === "?") {
733
- source += "[^/]";
734
- continue;
735
- }
736
- source += character?.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") ?? "";
737
- }
738
- return new RegExp(`^${source}$`);
739
- }
740
- function createListingCodingTools(config, limits) {
741
- const excluded = new Set(config.search?.excludeDirectories ?? DEFAULT_EXCLUDED_DIRECTORIES);
742
- const list = defineRuntimeTool2({
743
- name: "list_directory",
744
- description: "List the direct entries of one workspace directory.",
745
- identity: { serviceName: "coding", action: "list-directory", method: "POST" },
746
- input: ListInputSchema,
747
- output: ListOutputSchema,
748
- transports: ["AGENT"],
749
- handler: async ({ input }) => {
750
- const root = await realpath3(config.root);
751
- const relative = input.path === "." ? "." : boundedCodingRelativePath(root, input.path, limits.maxPathBytes);
752
- await authorizeCodingPathChain(config, relative);
753
- await authorizeCodingTool(config, { operation: "list", path: relative });
754
- const listing = await listContainedDirectory(root, relative, limits.maxListEntries, (candidate) => isCodingPathAuthorized(config, candidate)).catch((error) => {
755
- if (errnoOf(error) === "ENOENT") {
756
- codingPathRefusal("NOT_FOUND", "This directory does not exist", relative, {
757
- hint: "List a parent directory to see what is there."
758
- });
759
- }
760
- return refuseMissingCodingPath(error, relative);
761
- });
762
- return {
763
- path: relative,
764
- entries: listing.entries.map((entry) => ({
765
- ...entry,
766
- ...entry.kind === "directory" && excluded.has(entry.name) && { excluded: true }
767
- })),
768
- truncated: listing.truncated,
769
- ...listing.denied.length > 0 && {
770
- denied: listing.denied.map((entry) => ({
771
- path: relative === "." ? entry.name : path2.join(relative, entry.name),
772
- kind: entry.kind
773
- })),
774
- deniedTruncated: listing.deniedTruncated
775
- }
776
- };
777
- }
778
- });
779
- const glob = defineRuntimeTool2({
780
- name: "glob",
781
- description: "List workspace files matching a `**`/`*`/`?` pattern.",
782
- identity: { serviceName: "coding", action: "glob", method: "POST" },
783
- input: GlobInputSchema,
784
- output: GlobOutputSchema,
785
- transports: ["AGENT"],
786
- handler: async ({ input }) => {
787
- const root = await realpath3(config.root);
788
- const relative = input.path === "." ? "." : boundedCodingRelativePath(root, input.path, limits.maxPathBytes);
789
- await authorizeCodingPathChain(config, relative);
790
- await authorizeCodingTool(config, {
791
- operation: "glob",
792
- pattern: input.pattern,
793
- path: relative
794
- });
795
- let matcher;
796
- try {
797
- matcher = compileWorkspaceGlob(input.pattern);
798
- } catch {
799
- codingRefusal("BAD_REQUEST", "This glob pattern could not be compiled", {
800
- details: { pattern: input.pattern },
801
- hint: "Use only `**`, `*` and `?`."
802
- });
803
- }
804
- const scan = await scanContainedFiles({
805
- root,
806
- maxDepth: limits.maxSearchDepth,
807
- maxFiles: limits.maxSearchFiles,
808
- symlinks: "skip",
809
- excludeDirectory: (directory) => directory.split(path2.sep).some((segment) => excluded.has(segment)),
810
- authorizePath: (candidate) => isCodingPathAuthorized(config, candidate)
811
- });
812
- const prefix = relative === "." ? "" : `${relative}${path2.sep}`;
813
- const matched = scan.files.filter((file) => file.relative.startsWith(prefix)).map((file) => file.relative).filter((candidate) => matcher.test(candidate.slice(prefix.length))).sort();
814
- const paths = matched.slice(0, limits.maxSearchResults);
815
- const scopedDenied = scan.denied.filter((entry) => entry.relative.startsWith(prefix));
816
- const denied = scopedDenied.slice(0, limits.maxSearchResults).map((entry) => ({
817
- path: entry.relative,
818
- kind: entry.kind
819
- }));
820
- return {
821
- paths,
822
- truncated: scan.truncated,
823
- resultTruncated: matched.length > paths.length,
824
- skippedDirectories: scan.skippedDirectories,
825
- scannedFiles: scan.files.length,
826
- ...denied.length > 0 && {
827
- denied,
828
- deniedTruncated: scan.deniedTruncated || scopedDenied.length > denied.length
829
- }
830
- };
831
- }
832
- });
833
- return [list, glob];
834
- }
835
-
836
- // src/agent-runtime/coding-tool-search-patch.ts
837
- import { createHash as createHash2 } from "node:crypto";
838
- import { realpath as realpath4 } from "node:fs/promises";
839
- import path3 from "node:path";
840
- import { z as z4 } from "zod";
841
- var SearchInputSchema = z4.object({
842
- query: z4.string().min(1),
843
- mode: z4.enum(["path", "content"]).default("content"),
844
- regex: z4.boolean().default(false),
845
- context: z4.int().nonnegative().max(10).default(0),
846
- include: z4.string().min(1).describe("Anchored `**`/`*`/`?` pattern matched against the whole workspace-relative path. `*` does not cross `/`; use `**/` to include matching files in subdirectories.").optional()
847
- }).strict();
848
- var SearchOutputSchema = z4.object({
849
- matches: z4.array(z4.object({
850
- path: z4.string().min(1),
851
- line: z4.int().positive().optional(),
852
- text: z4.string().optional(),
853
- before: z4.array(z4.string()).optional(),
854
- after: z4.array(z4.string()).optional()
855
- }).strict()),
856
- truncated: z4.boolean(),
857
- scannedFiles: z4.int().nonnegative().describe("Files admitted by include and host authorization that reached path or content comparison."),
858
- skippedDirectories: z4.int().nonnegative(),
859
- skippedSymlinks: z4.int().nonnegative(),
860
- denied: z4.array(CodingDeniedEntrySchema).optional(),
861
- deniedTruncated: z4.boolean().optional(),
862
- hint: z4.string().min(1).optional()
863
- }).strict();
864
- function compileSearchRegex(pattern) {
865
- if (/\\[1-9]/.test(pattern) || /\(\?<?[=!]/.test(pattern)) {
866
- codingRefusal("BAD_REQUEST", "This pattern uses a construct search does not allow", {
867
- details: { pattern },
868
- hint: "Backreferences and lookaround are refused because they cannot be bounded. Rewrite without them."
869
- });
870
- }
871
- try {
872
- return new RegExp(pattern);
873
- } catch (error) {
874
- codingRefusal("BAD_REQUEST", "This pattern is not a valid regular expression", {
875
- details: { pattern, reason: error instanceof Error ? error.message : "unknown" },
876
- hint: "Fix the expression, or pass regex: false to search for it literally."
877
- });
878
- }
879
- }
880
- var MAX_SEARCHED_LINE_BYTES = 8192;
881
- var EditInputSchema = z4.object({
882
- path: z4.string().min(1),
883
- oldText: z4.string().min(1),
884
- newText: z4.string(),
885
- replaceAll: z4.boolean().default(false),
886
- expectedSha256: z4.string().length(64).optional(),
887
- dryRun: z4.boolean().default(false)
888
- }).strict();
889
- var EditOutputSchema = z4.object({
890
- path: z4.string().min(1),
891
- baseSha256: z4.string().length(64),
892
- sha256: z4.string().length(64),
893
- replacements: z4.int().positive(),
894
- bytes: z4.int().nonnegative(),
895
- applied: z4.boolean()
896
- }).strict();
897
- function sha256(value) {
898
- return createHash2("sha256").update(value).digest("hex");
899
- }
900
- async function searchFiles(config, limits, input) {
901
- await authorizeCodingTool(config, {
902
- operation: "search",
903
- query: input.query,
904
- mode: input.mode
905
- });
906
- const root = await realpath4(config.root);
907
- await authorizeCodingPath(config, ".");
908
- const excluded = new Set(config.search?.excludeDirectories ?? DEFAULT_EXCLUDED_DIRECTORIES);
909
- const included = input.include ? compileWorkspaceGlob(input.include) : null;
910
- let rejectedByInclude = 0;
911
- const scan = await scanContainedFiles({
912
- root,
913
- maxDepth: limits.maxSearchDepth,
914
- maxFiles: limits.maxSearchFiles,
915
- symlinks: "skip",
916
- ...input.mode === "content" && {
917
- readMaxBytes: limits.maxReadBytes,
918
- skipUnreadable: true
919
- },
920
- excludeDirectory: (relative) => relative.split(path3.sep).some((segment) => excluded.has(segment)),
921
- includeFile: (candidate) => {
922
- if (included && !included.test(candidate)) {
923
- rejectedByInclude += 1;
924
- return false;
925
- }
926
- return true;
927
- },
928
- authorizePath: (candidate) => isCodingPathAuthorized(config, candidate)
929
- });
930
- const matcher = input.regex ? compileSearchRegex(input.query) : null;
931
- const hit = (line) => {
932
- if (line.length > MAX_SEARCHED_LINE_BYTES)
933
- return false;
934
- if (matcher) {
935
- matcher.lastIndex = 0;
936
- return matcher.test(line);
937
- }
938
- return line.includes(input.query);
939
- };
940
- const matches = [];
941
- let truncated = false;
942
- for (const file of scan.files) {
943
- if (input.mode === "path") {
944
- if (hit(file.relative))
945
- matches.push({ path: file.relative });
946
- } else {
947
- const text = file.content?.text;
948
- if (text === undefined)
949
- continue;
950
- const lines = text.split(`
951
- `);
952
- for (let index = 0;index < lines.length; index += 1) {
953
- const line = lines[index];
954
- if (line === undefined || !hit(line))
955
- continue;
956
- matches.push({
957
- path: file.relative,
958
- line: index + 1,
959
- text: line,
960
- ...input.context > 0 && {
961
- before: lines.slice(Math.max(0, index - input.context), index),
962
- after: lines.slice(index + 1, index + 1 + input.context)
963
- }
964
- });
965
- if (matches.length >= limits.maxSearchResults)
966
- break;
967
- }
968
- }
969
- if (matches.length >= limits.maxSearchResults) {
970
- truncated = true;
971
- break;
972
- }
973
- }
974
- return {
975
- matches,
976
- truncated: truncated || scan.truncated,
977
- scannedFiles: scan.files.length,
978
- skippedDirectories: scan.skippedDirectories,
979
- skippedSymlinks: scan.skippedSymlinks,
980
- ...scan.denied.length > 0 && {
981
- denied: scan.denied.slice(0, limits.maxSearchResults).map(({ relative, kind }) => ({ path: relative, kind })),
982
- deniedTruncated: scan.deniedTruncated || scan.denied.length > limits.maxSearchResults
983
- },
984
- ...input.include && scan.files.length === 0 && rejectedByInclude > 0 && {
985
- hint: `The anchored include pattern \`${input.include}\` rejected all ${rejectedByInclude} ${rejectedByInclude === 1 ? "file" : "files"} the scan reached. \`*\` does not cross \`/\`; use a pattern such as \`**/*.ts\` for matching files in subdirectories.`
986
- }
987
- };
988
- }
989
- async function editFile(config, limits, input) {
990
- const root = await realpath4(config.root);
991
- const relative = boundedCodingRelativePath(root, input.path, limits.maxPathBytes);
992
- await authorizeCodingPathChain(config, relative);
993
- const parent = await openContainedParent(root, relative).catch((error) => refuseMissingCodingPath(error, relative));
994
- try {
995
- return await withCodingPathLock(`${root}:${relative}`, async () => {
996
- const readCurrent = async () => {
997
- const handle = await openContainedParentFile(parent).catch((error) => refuseMissingCodingPath(error, relative));
998
- return readContainedUtf8Handle(handle, limits.maxWriteBytes).finally(() => handle.close());
999
- };
1000
- await authorizeCodingTool(config, { operation: "read", path: relative });
1001
- const read = await readCurrent();
1002
- const source = read.text;
1003
- const baseSha256 = sha256(source);
1004
- if (input.expectedSha256 !== undefined && baseSha256 !== input.expectedSha256) {
1005
- conflict2("The file changed since it was read", {
1006
- message: "The file changed since it was read",
1007
- path: relative,
1008
- expectedSha256: input.expectedSha256,
1009
- actualSha256: baseSha256
1010
- });
1011
- }
1012
- const count = textOccurrences(source, input.oldText);
1013
- if (count === 0) {
1014
- codingPathRefusal("NOT_FOUND", "oldText does not appear in this file", relative, {
1015
- details: { occurrences: 0 },
1016
- hint: "Read the file and copy the snippet exactly, including indentation."
1017
- });
1018
- }
1019
- if (!input.replaceAll && count !== 1) {
1020
- codingPathRefusal("CONFLICT", `oldText appears ${count} times, so the edit is ambiguous`, relative, {
1021
- details: { occurrences: count },
1022
- hint: "Lengthen the snippet until it is unique, or pass replaceAll: true."
1023
- });
1024
- }
1025
- const replacements = input.replaceAll ? count : 1;
1026
- const literalReplacement = () => input.newText;
1027
- const changed = input.replaceAll ? source.replaceAll(input.oldText, literalReplacement) : source.replace(input.oldText, literalReplacement);
1028
- const bytes = Buffer.byteLength(changed);
1029
- const resultSha256 = sha256(changed);
1030
- if (bytes > limits.maxWriteBytes) {
1031
- codingPathRefusal("BAD_REQUEST", `The result would be ${bytes} bytes, over the ${limits.maxWriteBytes}-byte limit`, relative, {
1032
- details: { bytes, maxWriteBytes: limits.maxWriteBytes },
1033
- hint: "Make a smaller edit, or split the file."
1034
- });
1035
- }
1036
- await authorizeCodingTool(config, {
1037
- operation: "edit",
1038
- path: relative,
1039
- baseSha256,
1040
- resultSha256,
1041
- resultBytes: bytes,
1042
- replacements,
1043
- dryRun: input.dryRun
1044
- });
1045
- await assertContainedParentCurrent(root, relative, parent.handle).catch((error) => refuseWriteConflict(error, relative));
1046
- if (!input.dryRun) {
1047
- if (sha256((await readCurrent()).text) !== baseSha256) {
1048
- conflict2("The file changed since it was read", {
1049
- message: "The file changed since it was read",
1050
- path: relative
1051
- });
1052
- }
1053
- await writeContainedFile({
1054
- parent,
1055
- content: changed,
1056
- replace: true,
1057
- mode: read.mode
1058
- }).catch((error) => refuseWriteConflict(error, relative));
1059
- }
1060
- return {
1061
- path: relative,
1062
- baseSha256,
1063
- sha256: resultSha256,
1064
- replacements,
1065
- bytes,
1066
- applied: !input.dryRun
1067
- };
1068
- });
1069
- } finally {
1070
- await parent.handle.close();
1071
- }
1072
- }
1073
- function createSearchAndPatchCodingTools(config, limits) {
1074
- const search = defineRuntimeTool2({
1075
- name: "search_files",
1076
- description: "Search bounded relative paths or UTF-8 file content under the workspace root.",
1077
- identity: { serviceName: "coding", action: "search", method: "POST" },
1078
- input: SearchInputSchema,
1079
- output: SearchOutputSchema,
1080
- transports: ["AGENT"],
1081
- handler: ({ input }) => searchFiles(config, limits, input)
1082
- });
1083
- const edit = defineRuntimeTool2({
1084
- name: "edit_file",
1085
- description: "Replace an exact snippet in one workspace file.",
1086
- identity: { serviceName: "coding", action: "edit-file", method: "POST" },
1087
- input: EditInputSchema,
1088
- output: EditOutputSchema,
1089
- transports: ["AGENT"],
1090
- handler: ({ input }) => editFile(config, limits, input)
1091
- });
1092
- return [search, edit];
1093
- }
1094
-
1095
- // src/agent-runtime/coding-tool-shell.ts
1096
- import { realpath as realpath5, stat } from "node:fs/promises";
1097
-
1098
- // src/agent-runtime/coding-shell-process.ts
1099
- function preview(data, budget) {
1100
- if (data.byteLength <= budget) {
1101
- return { data, headBytes: data.byteLength, tailBytes: 0, omittedBytes: 0 };
1102
- }
1103
- const headEnd = utf8AlignedEnd(data, 0, Math.ceil(budget / 2));
1104
- const tailStart = Math.max(headEnd, utf8AlignedStart(data, data.byteLength - Math.floor(budget / 2), data.byteLength));
1105
- const tailBytes = data.byteLength - tailStart;
1106
- return {
1107
- data: Buffer.concat([data.subarray(0, headEnd), data.subarray(tailStart)]),
1108
- headBytes: headEnd,
1109
- tailBytes,
1110
- omittedBytes: data.byteLength - headEnd - tailBytes
1111
- };
1112
- }
1113
- function retainedPreview(data) {
1114
- const end = utf8AlignedEnd(data, 0, data.byteLength);
1115
- return {
1116
- data: data.subarray(0, end),
1117
- headBytes: end,
1118
- tailBytes: 0,
1119
- omittedBytes: data.byteLength - end
1120
- };
1121
- }
1122
- async function runCodingShell(input) {
1123
- const stdoutHeader = Buffer.from(`--- stdout ---
1124
- `);
1125
- const stderrHeader = Buffer.from(`
1126
- --- stderr ---
1127
- `);
1128
- const artifactPayloadLimit = input.maxArtifactBytes - stdoutHeader.byteLength - stderrHeader.byteLength;
1129
- if (input.artifacts && artifactPayloadLimit < 0)
1130
- throw new Error("maxArtifactBytes is smaller than the shell artifact envelope");
1131
- if (input.signal?.aborted) {
1132
- return ShellOutputSchema.parse({
1133
- executable: input.executableName,
1134
- exitCode: null,
1135
- signal: null,
1136
- stdout: "",
1137
- stderr: "",
1138
- outcome: "cancelled"
1139
- });
1140
- }
1141
- const stdout = [];
1142
- const stderr = [];
1143
- const artifactStdout = [];
1144
- const artifactStderr = [];
1145
- let retained = 0;
1146
- let artifactBytes = 0;
1147
- let outcome = "exited";
1148
- let child;
1149
- let exitCode = null;
1150
- let signal = null;
1151
- const outputLimit = new Error("Coding command output retention budget exceeded");
1152
- const launch = input.spawn;
1153
- const retain = (target, artifactTarget, chunk) => {
1154
- const remaining = Math.max(0, input.maxOutputBytes - retained);
1155
- if (remaining > 0) {
1156
- const kept = Buffer.from(chunk.subarray(0, remaining));
1157
- target.push(kept);
1158
- retained += kept.byteLength;
1159
- }
1160
- if (input.artifacts) {
1161
- const artifactRemaining = Math.max(0, artifactPayloadLimit - artifactBytes);
1162
- if (artifactRemaining > 0) {
1163
- const kept = Buffer.from(chunk.subarray(0, artifactRemaining));
1164
- artifactTarget.push(kept);
1165
- artifactBytes += kept.byteLength;
1166
- }
1167
- if (chunk.byteLength > artifactRemaining)
1168
- throw outputLimit;
1169
- } else if (chunk.byteLength > remaining)
1170
- throw outputLimit;
1171
- };
1172
- const command = startNativeCommand({
1173
- executable: input.executable,
1174
- args: [...input.args],
1175
- cwd: input.cwd,
1176
- env: { ...input.environment },
1177
- envPolicy: "declared-only",
1178
- signal: input.signal ?? new AbortController().signal,
1179
- stop: { target: "group", graceMs: 0 },
1180
- descendants: "terminate-after-leader",
1181
- onOutput: (bytes, channel) => retain(channel === "stdout" ? stdout : stderr, channel === "stdout" ? artifactStdout : artifactStderr, bytes),
1182
- onLeaderSettled: (event) => {
1183
- if (event.kind === "error")
1184
- return;
1185
- exitCode = event.exitCode;
1186
- signal = event.signal;
1187
- }
1188
- }, (started) => {
1189
- child = started;
1190
- }, {
1191
- group: process.platform !== "win32",
1192
- force: true,
1193
- timeoutMs: input.timeoutMs,
1194
- cleanupTimeoutMs: input.terminationGraceMs,
1195
- closeTimeoutMs: input.terminationGraceMs,
1196
- ...launch ? {
1197
- launch: () => {
1198
- child = launch();
1199
- return child;
1200
- }
1201
- } : {},
1202
- maxBufferedBytes: Math.max(64 * 1024, input.maxOutputBytes, input.artifacts ? artifactPayloadLimit : 0)
1203
- });
1204
- try {
1205
- const result = await command.result;
1206
- exitCode = result.exitCode;
1207
- signal = result.signal;
1208
- } catch (error) {
1209
- if (error === outputLimit)
1210
- outcome = "output-limit";
1211
- else if (input.signal?.aborted && error === input.signal.reason)
1212
- outcome = "cancelled";
1213
- else if (error instanceof NativeCommandError2 && error.code === "COMMAND_LIMIT" && (error.reason === "deadline" || error.reason === "output-budget"))
1214
- outcome = error.reason === "deadline" ? "timeout" : "output-limit";
1215
- else if (error instanceof CommandStopped)
1216
- outcome = "cancelled";
1217
- else
1218
- throw error;
1219
- }
1220
- const hasArtifact = input.artifacts && artifactBytes > input.maxOutputBytes;
1221
- const completeStdout = Buffer.concat(artifactStdout);
1222
- const completeStderr = Buffer.concat(artifactStderr);
1223
- const artifactData = hasArtifact ? Buffer.concat([stdoutHeader, completeStdout, stderrHeader, completeStderr]) : undefined;
1224
- const stdoutBudget = completeStderr.byteLength === 0 ? input.maxOutputBytes : Math.ceil(input.maxOutputBytes / 2);
1225
- const stderrBudget = completeStdout.byteLength === 0 ? input.maxOutputBytes : Math.floor(input.maxOutputBytes / 2);
1226
- const stdoutPreview = hasArtifact ? preview(completeStdout, stdoutBudget) : retainedPreview(Buffer.concat(stdout));
1227
- const stderrPreview = hasArtifact ? preview(completeStderr, stderrBudget) : retainedPreview(Buffer.concat(stderr));
1228
- const persisted = hasArtifact ? await input.artifacts?.write({
1229
- mediaType: "text/plain; charset=utf-8",
1230
- data: artifactData ?? new Uint8Array,
1231
- ...input.authorization && { authorization: input.authorization }
1232
- }) : undefined;
1233
- return ShellOutputSchema.parse({
1234
- executable: input.executableName,
1235
- exitCode,
1236
- signal,
1237
- stdout: stdoutPreview.data.toString("utf8"),
1238
- stderr: stderrPreview.data.toString("utf8"),
1239
- outcome,
1240
- ...persisted && {
1241
- artifact: {
1242
- reference: persisted.reference,
1243
- bytes: artifactData?.byteLength ?? 0,
1244
- truncated: outcome === "output-limit",
1245
- headBytes: stdoutPreview.headBytes + stderrPreview.headBytes,
1246
- tailBytes: stdoutPreview.tailBytes + stderrPreview.tailBytes,
1247
- omittedBytes: stdoutPreview.omittedBytes + stderrPreview.omittedBytes
1248
- }
1249
- }
1250
- });
1251
- }
1252
-
1253
- // src/agent-runtime/coding-tool-shell.ts
1254
- function createShellCodingTool(config, limits) {
1255
- const executables = config.executables ?? {};
1256
- const executableNames = Object.keys(executables).sort();
1257
- return defineRuntimeTool2({
1258
- name: "run_command",
1259
- description: "Run a finite host-declared executable with bounded arguments, time and output.",
1260
- identity: { serviceName: "coding", action: "shell", method: "POST" },
1261
- input: createShellInputSchema(executableNames),
1262
- output: ShellOutputSchema,
1263
- transports: ["AGENT"],
1264
- handler: async ({ input, signal }) => {
1265
- if (input.args.length > limits.maxShellArguments) {
1266
- throw new Error("Coding tool shell arguments exceed maxShellArguments");
1267
- }
1268
- const argumentBytes = input.args.reduce((total, argument) => total + Buffer.byteLength(argument), 0);
1269
- if (argumentBytes > limits.maxShellArgumentBytes) {
1270
- throw new Error("Coding tool shell arguments exceed maxShellArgumentBytes");
1271
- }
1272
- const executable = executables[input.executable];
1273
- if (!executable)
1274
- throw new Error("Coding tool executable is not declared");
1275
- const root = await realpath5(config.root);
1276
- const cwd = await existingCodingPath(root, input.cwd === "." ? "." : boundedCodingRelativePath(root, input.cwd, limits.maxPathBytes), limits.maxPathBytes);
1277
- if (!(await stat(cwd.absolute)).isDirectory()) {
1278
- throw new Error("Coding tool cwd is not a directory");
1279
- }
1280
- const shellAuthorization = {
1281
- operation: "shell",
1282
- executable: input.executable,
1283
- args: input.args,
1284
- cwd: cwd.relative
1285
- };
1286
- await authorizeCodingTool(config, shellAuthorization);
1287
- let executablePath = executable;
1288
- let executableArgs = input.args;
1289
- let environment = config.environment ?? {};
1290
- if (config.sandbox) {
1291
- const probed = await probeAgentProcessSandboxOutcome(config.sandbox.adapter);
1292
- const grade = probed.grade;
1293
- if (grade.grade === "unavailable") {
1294
- codingRefusal("SANDBOX_UNAVAILABLE", "The configured process sandbox is unavailable", {
1295
- details: { reason: grade.reason },
1296
- ...probed.cause !== undefined && { cause: probed.cause }
1297
- });
1298
- }
1299
- const missing = missingSandboxRestrictions2(grade, config.sandbox.required);
1300
- if (missing.length > 0) {
1301
- codingRefusal("SANDBOX_INSUFFICIENT", "The process sandbox lacks required restrictions", {
1302
- details: { missing, grade: grade.grade }
1303
- });
1304
- }
1305
- try {
1306
- const prepared = await config.sandbox.adapter.prepare({
1307
- required: config.sandbox.required,
1308
- executable,
1309
- args: input.args,
1310
- cwd: cwd.absolute,
1311
- environment
1312
- });
1313
- executablePath = prepared.executable;
1314
- executableArgs = [...prepared.args];
1315
- environment = prepared.environment ?? environment;
1316
- } catch (error) {
1317
- const refreshed = await probeAgentProcessSandboxOutcome(config.sandbox.adapter, {
1318
- refresh: true
1319
- });
1320
- codingRefusal("SANDBOX_UNAVAILABLE", "The process sandbox failed while preparing a command", {
1321
- details: { grade: refreshed.grade.grade, reason: "sandbox prepare failed" },
1322
- cause: refreshed.cause === undefined ? error : new AggregateError([error, refreshed.cause], "Sandbox prepare failed and probing it again failed")
1323
- });
1324
- }
1325
- }
1326
- return runCodingShell({
1327
- ...config.sandbox?.adapter.spawn && {
1328
- spawn: () => {
1329
- const adapter = config.sandbox?.adapter;
1330
- if (!adapter?.spawn)
1331
- throw new Error("Sandbox launcher is unavailable");
1332
- return adapter.spawn({
1333
- executable: executablePath,
1334
- args: executableArgs,
1335
- cwd: cwd.absolute,
1336
- environment
1337
- });
1338
- }
1339
- },
1340
- executableName: input.executable,
1341
- executable: executablePath,
1342
- args: executableArgs,
1343
- cwd: cwd.absolute,
1344
- environment,
1345
- ...signal && { signal },
1346
- timeoutMs: limits.shellTimeoutMs,
1347
- terminationGraceMs: limits.shellTerminationGraceMs,
1348
- maxOutputBytes: limits.maxShellOutputBytes,
1349
- maxArtifactBytes: limits.maxArtifactBytes,
1350
- ...config.artifacts && { artifacts: config.artifacts },
1351
- authorization: shellAuthorization
1352
- });
1353
- }
1354
- });
1355
- }
1356
-
1357
- // src/agent-runtime/coding-tools.ts
1358
- var AGENT_CODING_TOOL_NAMES = {
1359
- editFile: "edit_file",
1360
- glob: "glob",
1361
- listDirectory: "list_directory",
1362
- readFile: "read_file",
1363
- readOutput: "read_output",
1364
- searchOutput: "search_output",
1365
- runCommand: "run_command",
1366
- searchFiles: "search_files",
1367
- writeFile: "write_file"
1368
- };
1369
- function createAgentCodingTools2(config) {
1370
- if (!path4.isAbsolute(config.root))
1371
- throw new Error("Coding tool root must be absolute");
1372
- for (const executable of Object.values(config.executables ?? {})) {
1373
- if (!path4.isAbsolute(executable)) {
1374
- throw new Error("Coding tool executables must be absolute paths");
1375
- }
1376
- }
1377
- const limits = resolveCodingToolLimits(config.limits);
1378
- const artifactTools = [];
1379
- if (config.artifacts) {
1380
- const artifacts = config.artifacts;
1381
- artifactTools.push(defineRuntimeTool2({
1382
- name: AGENT_CODING_TOOL_NAMES.readOutput,
1383
- description: "Read a bounded byte slice from one opaque coding output artifact.",
1384
- identity: { serviceName: "coding", action: "read-artifact", method: "POST" },
1385
- input: z5.object({
1386
- reference: z5.string().min(1),
1387
- offset: z5.int().nonnegative().default(0),
1388
- maxBytes: z5.int().positive().optional()
1389
- }).strict(),
1390
- output: z5.object({
1391
- reference: z5.string().min(1),
1392
- offset: z5.int().nonnegative(),
1393
- text: z5.string(),
1394
- bytes: z5.int().nonnegative(),
1395
- totalBytes: z5.int().nonnegative().optional()
1396
- }).strict(),
1397
- transports: ["AGENT"],
1398
- handler: async ({ input }) => {
1399
- const maxBytes = Math.min(input.maxBytes ?? limits.maxReadBytes, limits.maxReadBytes);
1400
- await authorizeCodingTool(config, {
1401
- operation: "artifact-read",
1402
- reference: input.reference,
1403
- offset: input.offset,
1404
- maxBytes
1405
- });
1406
- const originAuthorization = await artifacts.authorization?.(input.reference);
1407
- if (originAuthorization)
1408
- await authorizeCodingTool(config, originAuthorization);
1409
- const result = await artifacts.read({
1410
- reference: input.reference,
1411
- offset: input.offset,
1412
- maxBytes
1413
- });
1414
- if (result.data.byteLength > maxBytes)
1415
- throw new Error("Coding artifact store exceeded the requested byte budget");
1416
- if (result.totalBytes !== undefined && result.totalBytes < input.offset + result.data.byteLength) {
1417
- throw new Error("Coding artifact store returned inconsistent totalBytes");
1418
- }
1419
- return {
1420
- reference: input.reference,
1421
- offset: input.offset,
1422
- text: new TextDecoder("utf-8", { fatal: true }).decode(result.data),
1423
- bytes: result.data.byteLength,
1424
- ...result.totalBytes !== undefined && { totalBytes: result.totalBytes }
1425
- };
1426
- }
1427
- }));
1428
- if (artifacts.search) {
1429
- const search = artifacts.search;
1430
- artifactTools.push(defineRuntimeTool2({
1431
- name: AGENT_CODING_TOOL_NAMES.searchOutput,
1432
- description: "Search a durable spilled output without loading it into context.",
1433
- identity: { serviceName: "coding", action: "search-artifact", method: "POST" },
1434
- input: z5.object({
1435
- reference: z5.string().min(1),
1436
- query: z5.string().min(1),
1437
- maxMatches: z5.int().positive().max(limits.maxSearchResults).default(20)
1438
- }).strict(),
1439
- output: z5.object({
1440
- reference: z5.string(),
1441
- matches: z5.array(z5.object({ line: z5.int().positive(), text: z5.string() }))
1442
- }).strict(),
1443
- transports: ["AGENT"],
1444
- handler: async ({ input }) => {
1445
- await authorizeCodingTool(config, {
1446
- operation: "artifact-search",
1447
- reference: input.reference,
1448
- query: input.query,
1449
- maxMatches: input.maxMatches
1450
- });
1451
- const originAuthorization = await artifacts.authorization?.(input.reference);
1452
- if (originAuthorization)
1453
- await authorizeCodingTool(config, originAuthorization);
1454
- return {
1455
- reference: input.reference,
1456
- matches: [
1457
- ...await search({
1458
- reference: input.reference,
1459
- query: input.query,
1460
- maxMatches: input.maxMatches
1461
- })
1462
- ]
1463
- };
1464
- }
1465
- }));
1466
- }
1467
- }
1468
- const commandTools = Object.keys(config.executables ?? {}).length ? [createShellCodingTool(config, limits)] : [];
1469
- return [
1470
- ...createFileCodingTools(config, limits),
1471
- ...createListingCodingTools(config, limits),
1472
- ...createSearchAndPatchCodingTools(config, limits),
1473
- ...commandTools,
1474
- ...artifactTools
1475
- ];
1476
- }
1477
-
1478
- export { AgentCodingToolLimitsSchema2, AgentCodingToolAuthorizationSchema2, AgentCodingToolPathAuthorizationSchema2, ShellOutputSchema, AgentSandboxRestrictionSchema2, AgentSandboxGradeSchema2, probeAgentProcessSandbox2, missingSandboxRestrictions2, recordAgentSandboxProbe2, codingRefusal, refuseUnknownSpillReference, AGENT_CODING_TOOL_NAMES, createAgentCodingTools2 };