stitchkit 0.69.0 → 0.70.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 (47) hide show
  1. package/README.md +4 -4
  2. package/dist/agent-runtime/coding-tool-contract.d.ts +1 -0
  3. package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
  4. package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
  5. package/dist/agent-runtime/coding-tool-paths.d.ts +1 -0
  6. package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
  7. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
  8. package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
  9. package/dist/agent-runtime/contained-files.d.ts +29 -4
  10. package/dist/agent-runtime/contained-files.d.ts.map +1 -1
  11. package/dist/agent-runtime/harness-file-resources.d.ts.map +1 -1
  12. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  13. package/dist/agent-runtime-coding-tools.js +197 -137
  14. package/dist/agent-runtime-harness.js +12 -8
  15. package/dist/agent-runtime.js +9 -7
  16. package/dist/cli.js +7 -6
  17. package/dist/{index-t4dpby6e.js → index-0yphgata.js} +1 -1
  18. package/dist/{index-444747ww.js → index-38hs3a58.js} +10 -8
  19. package/dist/index-3xnq72rz.js +21 -0
  20. package/dist/{index-kg9xx84n.js → index-7rey2b8s.js} +1 -1
  21. package/dist/{index-zh459sfj.js → index-aczggrty.js} +1 -1
  22. package/dist/index-bd17ytae.js +192 -0
  23. package/dist/{index-q7gdep2c.js → index-da1aqnhb.js} +2 -2
  24. package/dist/{index-p1be103g.js → index-ktsps64f.js} +4 -2
  25. package/dist/{index-mbxds404.js → index-mjx0wt4c.js} +8 -6
  26. package/dist/{index-h8vn1jcr.js → index-qzbg46b6.js} +6 -4
  27. package/dist/{index-h7ctj1kp.js → index-s8nt8c22.js} +14 -11
  28. package/dist/{index-d1jsvkyk.js → index-vbf2p6me.js} +1 -1
  29. package/dist/{index-xxsq3ca1.js → index-vc498pst.js} +1 -1
  30. package/dist/{index-x18ndp4p.js → index-vj3vvpaa.js} +1 -192
  31. package/dist/{index-3eqrkqhg.js → index-vy5bjy07.js} +7 -3
  32. package/dist/{index-kxxyvkka.js → index-wc80at9n.js} +2 -2
  33. package/dist/index-xbtcszs7.js +202 -0
  34. package/dist/{index-gqdfpv4n.js → index-y3w12g8d.js} +2 -2
  35. package/dist/node.js +5 -4
  36. package/dist/observability/index.js +4 -3
  37. package/dist/remote.js +4 -3
  38. package/dist/server/index.js +11 -9
  39. package/dist/testing.js +4 -3
  40. package/dist/tool-invoker.js +6 -5
  41. package/dist/tools/agent-tool-error.d.ts +14 -0
  42. package/dist/tools/agent-tool-error.d.ts.map +1 -0
  43. package/dist/tools/agent.d.ts.map +1 -1
  44. package/dist/tools.js +15 -12
  45. package/llms-full.txt +56 -14
  46. package/package.json +1 -1
  47. package/dist/index-v3dpzpjw.js +0 -92
@@ -1,16 +1,26 @@
1
1
  import {
2
- readContainedUtf8File,
2
+ assertContainedFileCurrent,
3
+ assertContainedParentCurrent,
4
+ openContainedFile,
5
+ openContainedParent,
6
+ readContainedUtf8Handle,
3
7
  scanContainedFiles
4
- } from "./index-v3dpzpjw.js";
8
+ } from "./index-xbtcszs7.js";
5
9
  import {
6
10
  defineRuntimeTool
7
11
  } from "./index-wwst0td5.js";
8
12
  import"./index-22by16v6.js";
9
13
  import"./index-cby4ar3v.js";
14
+ import"./index-vj3vvpaa.js";
15
+ import {
16
+ conflict,
17
+ forbidden
18
+ } from "./index-0w9abg87.js";
10
19
  import"./index-qyrqwr4c.js";
20
+ import"./index-6k1937bx.js";
11
21
 
12
22
  // src/agent-runtime/coding-tools.ts
13
- import path3 from "node:path";
23
+ import path4 from "node:path";
14
24
  import { z as z3 } from "zod";
15
25
 
16
26
  // src/agent-runtime/coding-tool-contract.ts
@@ -26,7 +36,8 @@ var AgentCodingToolLimitsSchema = z.object({
26
36
  maxSearchResults: z.int().positive(),
27
37
  maxSearchFiles: z.int().positive(),
28
38
  maxSearchDepth: z.int().nonnegative(),
29
- shellTimeoutMs: z.int().positive()
39
+ shellTimeoutMs: z.int().positive(),
40
+ shellTerminationGraceMs: z.int().positive()
30
41
  }).strict();
31
42
  var AgentCodingToolAuthorizationSchema = z.discriminatedUnion("operation", [
32
43
  z.object({ operation: z.literal("read"), path: z.string().min(1) }).strict(),
@@ -121,7 +132,8 @@ var DEFAULT_LIMITS = {
121
132
  maxSearchResults: 100,
122
133
  maxSearchFiles: 1e4,
123
134
  maxSearchDepth: 32,
124
- shellTimeoutMs: 30000
135
+ shellTimeoutMs: 30000,
136
+ shellTerminationGraceMs: 250
125
137
  };
126
138
  function resolveCodingToolLimits(input) {
127
139
  return AgentCodingToolLimitsSchema.parse({ ...DEFAULT_LIMITS, ...input });
@@ -129,8 +141,8 @@ function resolveCodingToolLimits(input) {
129
141
 
130
142
  // src/agent-runtime/coding-tool-files.ts
131
143
  import { createHash } from "node:crypto";
132
- import { constants } from "node:fs";
133
- import { open, realpath as realpath2, stat, writeFile as writeFile2 } from "node:fs/promises";
144
+ import { lstat as lstat2, realpath as realpath2, writeFile as writeFile2 } from "node:fs/promises";
145
+ import path2 from "node:path";
134
146
 
135
147
  // src/agent-runtime/coding-tool-paths.ts
136
148
  import { lstat, realpath, rename, unlink, writeFile } from "node:fs/promises";
@@ -150,41 +162,20 @@ function inputPath(root, requested, maxPathBytes) {
150
162
  throw new Error("Coding tool path escapes its root");
151
163
  return resolved;
152
164
  }
165
+ function boundedCodingRelativePath(requested, maxPathBytes) {
166
+ inputPath(path.parse(process.cwd()).root, requested, maxPathBytes);
167
+ return requested;
168
+ }
153
169
  async function existingCodingPath(root, requested, maxPathBytes) {
154
170
  const resolved = await realpath(inputPath(root, requested, maxPathBytes));
155
171
  if (!within(root, resolved))
156
172
  throw new Error("Coding tool path resolves outside its root");
157
173
  return { absolute: resolved, relative: path.relative(root, resolved) || "." };
158
174
  }
159
- async function writableCodingPath(root, requested, maxPathBytes) {
160
- const candidate = inputPath(root, requested, maxPathBytes);
161
- const parent = await realpath(path.dirname(candidate));
162
- if (!within(root, parent))
163
- throw new Error("Coding tool parent resolves outside its root");
164
- const target = path.join(parent, path.basename(candidate));
165
- const metadata = await lstat(target).catch((error) => {
166
- if (error.code === "ENOENT")
167
- return null;
168
- throw error;
169
- });
170
- if (metadata?.isSymbolicLink())
171
- throw new Error("Coding tools do not write through symlinks");
172
- return { absolute: target, relative: path.relative(root, target) || "." };
173
- }
174
- async function editableCodingPath(root, requested, maxPathBytes) {
175
- const candidate = inputPath(root, requested, maxPathBytes);
176
- const metadata = await lstat(candidate);
177
- if (metadata.isSymbolicLink())
178
- throw new Error("Coding tools do not edit symlinks");
179
- const resolved = await realpath(candidate);
180
- if (!within(root, resolved))
181
- throw new Error("Coding tool path resolves outside its root");
182
- return { absolute: resolved, relative: path.relative(root, resolved) || "." };
183
- }
184
175
  async function authorizeCodingTool(config, request) {
185
176
  const parsed = AgentCodingToolAuthorizationSchema.parse(request);
186
177
  if (!await config.authorize(parsed))
187
- throw new Error("Coding tool permission denied");
178
+ forbidden("Coding tool permission denied");
188
179
  }
189
180
  async function atomicCodingReplace(target, content, mode) {
190
181
  const temporary = path.join(path.dirname(target), `.${path.basename(target)}.${process.pid}.${crypto.randomUUID()}.tmp`);
@@ -255,14 +246,15 @@ function createFileCodingTools(config, limits) {
255
246
  transports: ["AGENT"],
256
247
  handler: async ({ input }) => {
257
248
  const root = await realpath2(config.root);
258
- const target = await existingCodingPath(root, input.path, limits.maxPathBytes);
259
- await authorizeCodingTool(config, { operation: "read", path: target.relative });
249
+ const relative = boundedCodingRelativePath(input.path, limits.maxPathBytes);
250
+ const handle = await openContainedFile(root, relative);
260
251
  const maximum = Math.min(input.maxBytes ?? limits.maxReadBytes, limits.maxReadBytes);
261
- const handle = await open(target.absolute, constants.O_RDONLY | constants.O_NOFOLLOW);
262
252
  let selected;
263
253
  let size;
264
254
  let sha256;
265
255
  try {
256
+ await authorizeCodingTool(config, { operation: "read", path: relative });
257
+ await assertContainedFileCurrent(root, relative, handle);
266
258
  const metadata = await handle.stat();
267
259
  if (!metadata.isFile())
268
260
  throw new Error("Coding read path is not a regular file");
@@ -279,7 +271,7 @@ function createFileCodingTools(config, limits) {
279
271
  const end = input.offset + selected.byteLength;
280
272
  const truncated = end < size;
281
273
  return {
282
- path: target.relative,
274
+ path: relative,
283
275
  text,
284
276
  bytes: selected.byteLength,
285
277
  sha256,
@@ -297,23 +289,32 @@ function createFileCodingTools(config, limits) {
297
289
  transports: ["AGENT"],
298
290
  handler: async ({ input }) => {
299
291
  const root = await realpath2(config.root);
300
- const target = await writableCodingPath(root, input.path, limits.maxPathBytes);
292
+ const relative = boundedCodingRelativePath(input.path, limits.maxPathBytes);
301
293
  const bytes = Buffer.byteLength(input.content);
302
294
  if (bytes > limits.maxWriteBytes)
303
295
  throw new Error("Coding tool write exceeds maxWriteBytes");
304
- await authorizeCodingTool(config, {
305
- operation: "write",
306
- path: target.relative,
307
- bytes,
308
- overwrite: input.overwrite
309
- });
310
- if (input.overwrite) {
311
- const current = await stat(target.absolute).catch(() => null);
312
- await atomicCodingReplace(target.absolute, input.content, current?.mode);
313
- } else {
314
- await writeFile2(target.absolute, input.content, { flag: "wx" });
296
+ const parent = await openContainedParent(root, relative);
297
+ const target = path2.join(parent.path, parent.basename);
298
+ try {
299
+ await authorizeCodingTool(config, {
300
+ operation: "write",
301
+ path: relative,
302
+ bytes,
303
+ overwrite: input.overwrite
304
+ });
305
+ await assertContainedParentCurrent(root, relative, parent.handle);
306
+ if (input.overwrite) {
307
+ const current = await lstat2(target).catch(() => null);
308
+ if (current?.isSymbolicLink())
309
+ throw new Error("Coding tools do not overwrite symlinks");
310
+ await atomicCodingReplace(target, input.content, current?.mode);
311
+ } else {
312
+ await writeFile2(target, input.content, { flag: "wx" });
313
+ }
314
+ } finally {
315
+ await parent.handle.close();
315
316
  }
316
- return { path: target.relative, bytes };
317
+ return { path: relative, bytes };
317
318
  }
318
319
  });
319
320
  return [read, write];
@@ -321,8 +322,9 @@ function createFileCodingTools(config, limits) {
321
322
 
322
323
  // src/agent-runtime/coding-tool-search-patch.ts
323
324
  import { createHash as createHash2 } from "node:crypto";
324
- import { realpath as realpath3 } from "node:fs/promises";
325
- import path2 from "node:path";
325
+ import { constants } from "node:fs";
326
+ import { open, realpath as realpath3 } from "node:fs/promises";
327
+ import path3 from "node:path";
326
328
  import { z as z2 } from "zod";
327
329
  var DEFAULT_EXCLUDED_DIRECTORIES = [
328
330
  ".git",
@@ -381,7 +383,11 @@ function createSearchAndPatchCodingTools(config, limits) {
381
383
  maxDepth: limits.maxSearchDepth,
382
384
  maxFiles: limits.maxSearchFiles,
383
385
  symlinks: "skip",
384
- excludeDirectory: (relative) => relative.split(path2.sep).some((segment) => excluded.has(segment))
386
+ ...input.mode === "content" && {
387
+ readMaxBytes: limits.maxReadBytes,
388
+ skipUnreadable: true
389
+ },
390
+ excludeDirectory: (relative) => relative.split(path3.sep).some((segment) => excluded.has(segment))
385
391
  });
386
392
  const matches = [];
387
393
  let truncated = false;
@@ -390,12 +396,9 @@ function createSearchAndPatchCodingTools(config, limits) {
390
396
  if (file.relative.includes(input.query))
391
397
  matches.push({ path: file.relative });
392
398
  } else {
393
- let text;
394
- try {
395
- text = (await readContainedUtf8File(file.absolute, limits.maxReadBytes)).text;
396
- } catch {
399
+ const text = file.content?.text;
400
+ if (text === undefined)
397
401
  continue;
398
- }
399
402
  const lines = text.split(`
400
403
  `);
401
404
  for (let index = 0;index < lines.length; index += 1) {
@@ -429,48 +432,57 @@ function createSearchAndPatchCodingTools(config, limits) {
429
432
  transports: ["AGENT"],
430
433
  handler: async ({ input }) => {
431
434
  const root = await realpath3(config.root);
432
- const target = await editableCodingPath(root, input.path, limits.maxPathBytes);
433
- const read = await readContainedUtf8File(target.absolute, limits.maxWriteBytes);
434
- const source = read.text;
435
- const baseSha256 = sha256(source);
436
- if (baseSha256 !== input.baseSha256)
437
- throw new Error("Coding patch base digest is stale");
438
- const count = textOccurrences(source, input.oldText);
439
- if (count === 0)
440
- throw new Error("Coding patch text was not found");
441
- if (!input.replaceAll && count !== 1)
442
- throw new Error("Coding patch text is not unique");
443
- const replacements = input.replaceAll ? count : 1;
444
- const changed = input.replaceAll ? source.replaceAll(input.oldText, input.newText) : source.replace(input.oldText, input.newText);
445
- const bytes = Buffer.byteLength(changed);
446
- const resultSha256 = sha256(changed);
447
- if (bytes > limits.maxWriteBytes)
448
- throw new Error("Coding patch exceeds maxWriteBytes");
449
- await authorizeCodingTool(config, {
450
- operation: "patch",
451
- path: target.relative,
452
- baseSha256,
453
- resultSha256,
454
- resultBytes: bytes,
455
- replacements,
456
- dryRun: input.dryRun
457
- });
458
- if (!input.dryRun) {
459
- await withCodingPathLock(target.absolute, async () => {
460
- const current = await readContainedUtf8File(target.absolute, limits.maxWriteBytes);
461
- if (sha256(current.text) !== baseSha256)
462
- throw new Error("Coding patch base digest became stale before apply");
463
- await atomicCodingReplace(target.absolute, changed, current.mode);
435
+ const relative = boundedCodingRelativePath(input.path, limits.maxPathBytes);
436
+ const parent = await openContainedParent(root, relative);
437
+ try {
438
+ const target = path3.join(parent.path, parent.basename);
439
+ const initial = await open(target, constants.O_RDONLY | constants.O_NOFOLLOW);
440
+ const read = await readContainedUtf8Handle(initial, limits.maxWriteBytes).finally(() => initial.close());
441
+ const source = read.text;
442
+ const baseSha256 = sha256(source);
443
+ if (baseSha256 !== input.baseSha256)
444
+ conflict("Coding patch base digest is stale");
445
+ const count = textOccurrences(source, input.oldText);
446
+ if (count === 0)
447
+ throw new Error("Coding patch text was not found");
448
+ if (!input.replaceAll && count !== 1)
449
+ throw new Error("Coding patch text is not unique");
450
+ const replacements = input.replaceAll ? count : 1;
451
+ const changed = input.replaceAll ? source.replaceAll(input.oldText, input.newText) : source.replace(input.oldText, input.newText);
452
+ const bytes = Buffer.byteLength(changed);
453
+ const resultSha256 = sha256(changed);
454
+ if (bytes > limits.maxWriteBytes)
455
+ throw new Error("Coding patch exceeds maxWriteBytes");
456
+ await authorizeCodingTool(config, {
457
+ operation: "patch",
458
+ path: relative,
459
+ baseSha256,
460
+ resultSha256,
461
+ resultBytes: bytes,
462
+ replacements,
463
+ dryRun: input.dryRun
464
464
  });
465
+ await assertContainedParentCurrent(root, relative, parent.handle);
466
+ if (!input.dryRun) {
467
+ await withCodingPathLock(`${root}:${relative}`, async () => {
468
+ const currentHandle = await open(target, constants.O_RDONLY | constants.O_NOFOLLOW);
469
+ const current = await readContainedUtf8Handle(currentHandle, limits.maxWriteBytes).finally(() => currentHandle.close());
470
+ if (sha256(current.text) !== baseSha256)
471
+ conflict("Coding patch base digest became stale before apply");
472
+ await atomicCodingReplace(target, changed, current.mode);
473
+ });
474
+ }
475
+ return {
476
+ path: relative,
477
+ baseSha256,
478
+ resultSha256,
479
+ replacements,
480
+ bytes,
481
+ applied: !input.dryRun
482
+ };
483
+ } finally {
484
+ await parent.handle.close();
465
485
  }
466
- return {
467
- path: target.relative,
468
- baseSha256,
469
- resultSha256,
470
- replacements,
471
- bytes,
472
- applied: !input.dryRun
473
- };
474
486
  }
475
487
  });
476
488
  return [search, patch];
@@ -478,7 +490,7 @@ function createSearchAndPatchCodingTools(config, limits) {
478
490
 
479
491
  // src/agent-runtime/coding-tool-shell.ts
480
492
  import { spawn } from "node:child_process";
481
- import { realpath as realpath4, stat as stat2 } from "node:fs/promises";
493
+ import { realpath as realpath4, stat } from "node:fs/promises";
482
494
  async function runShell(input) {
483
495
  const stdoutHeader = Buffer.from(`--- stdout ---
484
496
  `);
@@ -488,11 +500,23 @@ async function runShell(input) {
488
500
  const artifactPayloadLimit = input.maxArtifactBytes - stdoutHeader.byteLength - stderrHeader.byteLength;
489
501
  if (input.artifacts && artifactPayloadLimit < 0)
490
502
  throw new Error("maxArtifactBytes is smaller than the shell artifact envelope");
503
+ if (input.signal?.aborted) {
504
+ return ShellOutputSchema.parse({
505
+ executable: input.executableName,
506
+ exitCode: null,
507
+ signal: null,
508
+ stdout: "",
509
+ stderr: "",
510
+ outcome: "cancelled"
511
+ });
512
+ }
491
513
  return await new Promise((resolve, reject) => {
514
+ const ownsProcessGroup = process.platform !== "win32";
492
515
  const child = spawn(input.executable, input.args, {
493
516
  cwd: input.cwd,
494
517
  env: input.environment,
495
- stdio: ["ignore", "pipe", "pipe"]
518
+ stdio: ["ignore", "pipe", "pipe"],
519
+ detached: ownsProcessGroup
496
520
  });
497
521
  const stdout = [];
498
522
  const stderr = [];
@@ -502,15 +526,74 @@ async function runShell(input) {
502
526
  let artifactBytes = 0;
503
527
  let outcome = "exited";
504
528
  let settled = false;
529
+ let settlementTimer;
530
+ const cancel = () => terminate("cancelled");
531
+ const cleanup = () => {
532
+ clearTimeout(timer);
533
+ if (settlementTimer)
534
+ clearTimeout(settlementTimer);
535
+ input.signal?.removeEventListener("abort", cancel);
536
+ };
537
+ const persistAndResolve = async (exitCode, signal) => {
538
+ if (settled)
539
+ return;
540
+ settled = true;
541
+ cleanup();
542
+ try {
543
+ const hasArtifact = input.artifacts && artifactBytes > input.maxOutputBytes;
544
+ const artifactData = hasArtifact ? Buffer.concat([stdoutHeader, ...artifactStdout, stderrHeader, ...artifactStderr]) : undefined;
545
+ const persisted = hasArtifact ? await input.artifacts?.write({
546
+ mediaType: "text/plain; charset=utf-8",
547
+ data: artifactData ?? new Uint8Array
548
+ }) : undefined;
549
+ resolve(ShellOutputSchema.parse({
550
+ executable: input.executableName,
551
+ exitCode,
552
+ signal,
553
+ stdout: Buffer.concat(stdout).toString("utf8"),
554
+ stderr: Buffer.concat(stderr).toString("utf8"),
555
+ outcome,
556
+ ...persisted && {
557
+ artifact: {
558
+ reference: persisted.reference,
559
+ bytes: artifactData?.byteLength ?? 0,
560
+ truncated: outcome === "output-limit"
561
+ }
562
+ }
563
+ }));
564
+ } catch (error) {
565
+ reject(error);
566
+ }
567
+ };
568
+ const killOwnedProcessGroup = () => {
569
+ if (!ownsProcessGroup || child.pid === undefined)
570
+ return false;
571
+ try {
572
+ process.kill(-child.pid, "SIGKILL");
573
+ return true;
574
+ } catch {
575
+ return false;
576
+ }
577
+ };
578
+ const boundStreamSettlement = () => {
579
+ if (settlementTimer)
580
+ return;
581
+ settlementTimer = setTimeout(() => {
582
+ child.stdout.destroy();
583
+ child.stderr.destroy();
584
+ persistAndResolve(child.exitCode, child.signalCode);
585
+ }, input.terminationGraceMs);
586
+ };
505
587
  const terminate = (reason) => {
506
588
  if (settled || outcome !== "exited")
507
589
  return;
508
590
  outcome = reason;
509
- child.kill("SIGKILL");
591
+ if (!killOwnedProcessGroup())
592
+ child.kill("SIGKILL");
593
+ boundStreamSettlement();
510
594
  };
511
595
  const timer = setTimeout(() => terminate("timeout"), input.timeoutMs);
512
596
  timer.unref();
513
- const cancel = () => terminate("cancelled");
514
597
  const retain = (target, artifactTarget, chunk) => {
515
598
  const remaining = Math.max(0, input.maxOutputBytes - retained);
516
599
  if (remaining > 0) {
@@ -536,42 +619,18 @@ async function runShell(input) {
536
619
  if (settled)
537
620
  return;
538
621
  settled = true;
539
- clearTimeout(timer);
540
- input.signal?.removeEventListener("abort", cancel);
622
+ cleanup();
541
623
  reject(error);
542
624
  });
543
- child.on("close", async (exitCode, signal) => {
544
- if (settled)
545
- return;
546
- settled = true;
547
- clearTimeout(timer);
548
- input.signal?.removeEventListener("abort", cancel);
549
- try {
550
- const hasArtifact = input.artifacts && artifactBytes > input.maxOutputBytes;
551
- const artifactData = hasArtifact ? Buffer.concat([stdoutHeader, ...artifactStdout, stderrHeader, ...artifactStderr]) : undefined;
552
- const persisted = hasArtifact ? await input.artifacts?.write({
553
- mediaType: "text/plain; charset=utf-8",
554
- data: artifactData ?? new Uint8Array
555
- }) : undefined;
556
- resolve(ShellOutputSchema.parse({
557
- executable: input.executableName,
558
- exitCode,
559
- signal,
560
- stdout: Buffer.concat(stdout).toString("utf8"),
561
- stderr: Buffer.concat(stderr).toString("utf8"),
562
- outcome,
563
- ...persisted && {
564
- artifact: {
565
- reference: persisted.reference,
566
- bytes: artifactData?.byteLength ?? 0,
567
- truncated: outcome === "output-limit"
568
- }
569
- }
570
- }));
571
- } catch (error) {
572
- reject(error);
625
+ child.on("exit", (exitCode, signal) => {
626
+ if (outcome === "exited")
627
+ killOwnedProcessGroup();
628
+ boundStreamSettlement();
629
+ if (child.stdout.destroyed && child.stderr.destroyed) {
630
+ persistAndResolve(exitCode, signal);
573
631
  }
574
632
  });
633
+ child.on("close", (exitCode, signal) => void persistAndResolve(exitCode, signal));
575
634
  input.signal?.addEventListener("abort", cancel, { once: true });
576
635
  if (input.signal?.aborted)
577
636
  cancel();
@@ -600,7 +659,7 @@ function createShellCodingTool(config, limits) {
600
659
  throw new Error("Coding tool executable is not declared");
601
660
  const root = await realpath4(config.root);
602
661
  const cwd = await existingCodingPath(root, input.cwd, limits.maxPathBytes);
603
- if (!(await stat2(cwd.absolute)).isDirectory()) {
662
+ if (!(await stat(cwd.absolute)).isDirectory()) {
604
663
  throw new Error("Coding tool cwd is not a directory");
605
664
  }
606
665
  await authorizeCodingTool(config, {
@@ -617,6 +676,7 @@ function createShellCodingTool(config, limits) {
617
676
  environment: config.environment ?? {},
618
677
  ...signal && { signal },
619
678
  timeoutMs: limits.shellTimeoutMs,
679
+ terminationGraceMs: limits.shellTerminationGraceMs,
620
680
  maxOutputBytes: limits.maxShellOutputBytes,
621
681
  maxArtifactBytes: limits.maxArtifactBytes,
622
682
  ...config.artifacts && { artifacts: config.artifacts }
@@ -635,10 +695,10 @@ var AGENT_CODING_TOOL_NAMES = {
635
695
  writeFile: "write_file"
636
696
  };
637
697
  function createAgentCodingTools(config) {
638
- if (!path3.isAbsolute(config.root))
698
+ if (!path4.isAbsolute(config.root))
639
699
  throw new Error("Coding tool root must be absolute");
640
700
  for (const executable of Object.values(config.executables ?? {})) {
641
- if (!path3.isAbsolute(executable)) {
701
+ if (!path4.isAbsolute(executable)) {
642
702
  throw new Error("Coding tool executables must be absolute paths");
643
703
  }
644
704
  }
@@ -3,28 +3,29 @@ import {
3
3
  composeAgentPrompt,
4
4
  createAgentRuntime,
5
5
  createAgentRuntimeEventSink
6
- } from "./index-3eqrkqhg.js";
6
+ } from "./index-vy5bjy07.js";
7
7
  import {
8
- readContainedUtf8File,
9
8
  walkContainedFiles
10
- } from "./index-v3dpzpjw.js";
9
+ } from "./index-xbtcszs7.js";
11
10
  import {
12
11
  AgentModelDescriptorSchema
13
12
  } from "./index-tg3m2ec5.js";
14
13
  import"./index-es0h4w26.js";
15
14
  import"./index-a59da114.js";
15
+ import"./index-3xnq72rz.js";
16
16
  import {
17
17
  defineRuntimeTool
18
18
  } from "./index-wwst0td5.js";
19
- import"./index-h8vn1jcr.js";
20
- import"./index-p1be103g.js";
19
+ import"./index-qzbg46b6.js";
20
+ import"./index-ktsps64f.js";
21
21
  import {
22
22
  AgentMessagePartSchema,
23
23
  AgentSnapshotSchema
24
24
  } from "./index-x1th9s8c.js";
25
25
  import"./index-22by16v6.js";
26
26
  import"./index-cby4ar3v.js";
27
- import"./index-x18ndp4p.js";
27
+ import"./index-bd17ytae.js";
28
+ import"./index-vj3vvpaa.js";
28
29
  import"./index-0w9abg87.js";
29
30
  import"./index-qyrqwr4c.js";
30
31
  import"./index-6k1937bx.js";
@@ -202,13 +203,16 @@ function createAgentHarnessFileResources(config) {
202
203
  const files = await walkContainedFiles({
203
204
  root: resolvedRoot,
204
205
  maxDepth: limits.maxDepth,
205
- maxFiles: limits.maxFiles - fileCount
206
+ maxFiles: limits.maxFiles - fileCount,
207
+ readMaxBytes: limits.maxFileBytes
206
208
  });
207
209
  fileCount += files.length;
208
210
  for (const file of files) {
209
211
  if (root.kind === "skill" && path.basename(file.absolute) !== "SKILL.md")
210
212
  continue;
211
- const read = await readContainedUtf8File(file.absolute, limits.maxFileBytes);
213
+ const read = file.content;
214
+ if (!read)
215
+ throw new Error("Agent harness resource content is unavailable");
212
216
  totalBytes += read.bytes;
213
217
  if (totalBytes > limits.maxTotalBytes) {
214
218
  throw new Error("Agent harness resources exceed maxTotalBytes");
@@ -27,7 +27,7 @@ import {
27
27
  registerDeferredToolRepair,
28
28
  repairedSearchCall,
29
29
  selectAgentHistory
30
- } from "./index-3eqrkqhg.js";
30
+ } from "./index-vy5bjy07.js";
31
31
  import {
32
32
  AgentModelCapabilitySchema,
33
33
  AgentModelCatalogEntrySchema,
@@ -82,14 +82,15 @@ import {
82
82
  import {
83
83
  buildToolManifest,
84
84
  mountAgent
85
- } from "./index-h7ctj1kp.js";
86
- import"./index-xxsq3ca1.js";
85
+ } from "./index-s8nt8c22.js";
86
+ import"./index-3xnq72rz.js";
87
+ import"./index-vc498pst.js";
87
88
  import {
88
89
  defineRuntimeTool
89
90
  } from "./index-wwst0td5.js";
90
- import"./index-kg9xx84n.js";
91
- import"./index-h8vn1jcr.js";
92
- import"./index-p1be103g.js";
91
+ import"./index-7rey2b8s.js";
92
+ import"./index-qzbg46b6.js";
93
+ import"./index-ktsps64f.js";
93
94
  import {
94
95
  AgentAssistantPlaceholderSchema,
95
96
  AgentControlPartSchema,
@@ -128,7 +129,8 @@ import"./index-cby4ar3v.js";
128
129
  import {
129
130
  childSpan,
130
131
  createTraceContext
131
- } from "./index-x18ndp4p.js";
132
+ } from "./index-bd17ytae.js";
133
+ import"./index-vj3vvpaa.js";
132
134
  import"./index-0w9abg87.js";
133
135
  import {
134
136
  executableAgentRuntimeTools
package/dist/cli.js CHANGED
@@ -5,16 +5,17 @@ import {
5
5
  emitResult,
6
6
  parseCliArgs,
7
7
  pollUntilDone
8
- } from "./index-mbxds404.js";
9
- import"./index-xxsq3ca1.js";
8
+ } from "./index-mjx0wt4c.js";
9
+ import"./index-vc498pst.js";
10
10
  import"./index-wwst0td5.js";
11
- import"./index-kg9xx84n.js";
12
- import"./index-h8vn1jcr.js";
13
- import"./index-p1be103g.js";
11
+ import"./index-7rey2b8s.js";
12
+ import"./index-qzbg46b6.js";
13
+ import"./index-ktsps64f.js";
14
14
  import"./index-sbdmyz75.js";
15
15
  import"./index-22by16v6.js";
16
16
  import"./index-cby4ar3v.js";
17
- import"./index-x18ndp4p.js";
17
+ import"./index-bd17ytae.js";
18
+ import"./index-vj3vvpaa.js";
18
19
  import"./index-0w9abg87.js";
19
20
  import"./index-qyrqwr4c.js";
20
21
  import"./index-6k1937bx.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  normalizeError
3
- } from "./index-x18ndp4p.js";
3
+ } from "./index-bd17ytae.js";
4
4
 
5
5
  // src/internal/bounded-lines.ts
6
6
  var DEFAULT_STREAM_LINE_BYTES = 1024 * 1024;