stitchkit 0.69.0 → 0.70.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) 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 -1
  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 +52 -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 +202 -145
  14. package/dist/agent-runtime-harness.js +12 -8
  15. package/dist/agent-runtime.js +9 -7
  16. package/dist/application/server-resource.d.ts +1 -0
  17. package/dist/application/server-resource.d.ts.map +1 -1
  18. package/dist/application.js +5 -2
  19. package/dist/cli.js +7 -6
  20. package/dist/{index-t4dpby6e.js → index-0yphgata.js} +1 -1
  21. package/dist/index-1z5xxfst.js +397 -0
  22. package/dist/index-3xnq72rz.js +21 -0
  23. package/dist/{index-444747ww.js → index-4g196jmf.js} +14 -9
  24. package/dist/{index-kg9xx84n.js → index-7rey2b8s.js} +1 -1
  25. package/dist/{index-dk6e56g0.js → index-7wpgrqa8.js} +37 -2
  26. package/dist/{index-zh459sfj.js → index-aczggrty.js} +1 -1
  27. package/dist/index-bd17ytae.js +192 -0
  28. package/dist/{index-q7gdep2c.js → index-da1aqnhb.js} +2 -2
  29. package/dist/{index-p1be103g.js → index-ktsps64f.js} +4 -2
  30. package/dist/{index-mbxds404.js → index-mjx0wt4c.js} +8 -6
  31. package/dist/{index-h8vn1jcr.js → index-qzbg46b6.js} +6 -4
  32. package/dist/{index-h7ctj1kp.js → index-s8nt8c22.js} +14 -11
  33. package/dist/{index-d1jsvkyk.js → index-vbf2p6me.js} +1 -1
  34. package/dist/{index-xxsq3ca1.js → index-vc498pst.js} +1 -1
  35. package/dist/{index-x18ndp4p.js → index-vj3vvpaa.js} +1 -192
  36. package/dist/{index-3eqrkqhg.js → index-vy5bjy07.js} +7 -3
  37. package/dist/{index-6wzr93cg.js → index-w0445741.js} +1 -1
  38. package/dist/{index-kxxyvkka.js → index-wc80at9n.js} +2 -2
  39. package/dist/{index-gqdfpv4n.js → index-y3w12g8d.js} +2 -2
  40. package/dist/node.js +26 -5
  41. package/dist/observability/index.js +4 -3
  42. package/dist/remote.js +4 -3
  43. package/dist/server/bun.d.ts.map +1 -1
  44. package/dist/server/index.js +20 -10
  45. package/dist/server/node.d.ts.map +1 -1
  46. package/dist/server/process-signals.d.ts.map +1 -1
  47. package/dist/server/shutdown.d.ts +2 -0
  48. package/dist/server/shutdown.d.ts.map +1 -1
  49. package/dist/testing.js +6 -5
  50. package/dist/tool-invoker.js +6 -5
  51. package/dist/tools/agent-tool-error.d.ts +14 -0
  52. package/dist/tools/agent-tool-error.d.ts.map +1 -0
  53. package/dist/tools/agent.d.ts.map +1 -1
  54. package/dist/tools.js +15 -12
  55. package/llms-full.txt +73 -22
  56. package/native/darwin-arm64.node +0 -0
  57. package/native/darwin-x64.node +0 -0
  58. package/package.json +3 -1
  59. package/dist/index-v3dpzpjw.js +0 -92
@@ -1,13 +1,26 @@
1
1
  import {
2
- readContainedUtf8File,
3
- scanContainedFiles
4
- } from "./index-v3dpzpjw.js";
2
+ assertContainedFileCurrent,
3
+ assertContainedParentCurrent,
4
+ containedEntryMetadata,
5
+ openContainedFile,
6
+ openContainedParent,
7
+ openContainedParentFile,
8
+ readContainedUtf8Handle,
9
+ scanContainedFiles,
10
+ writeContainedFile
11
+ } from "./index-1z5xxfst.js";
5
12
  import {
6
13
  defineRuntimeTool
7
14
  } from "./index-wwst0td5.js";
8
15
  import"./index-22by16v6.js";
9
16
  import"./index-cby4ar3v.js";
17
+ import"./index-vj3vvpaa.js";
18
+ import {
19
+ conflict,
20
+ forbidden
21
+ } from "./index-0w9abg87.js";
10
22
  import"./index-qyrqwr4c.js";
23
+ import"./index-6k1937bx.js";
11
24
 
12
25
  // src/agent-runtime/coding-tools.ts
13
26
  import path3 from "node:path";
@@ -26,7 +39,8 @@ var AgentCodingToolLimitsSchema = z.object({
26
39
  maxSearchResults: z.int().positive(),
27
40
  maxSearchFiles: z.int().positive(),
28
41
  maxSearchDepth: z.int().nonnegative(),
29
- shellTimeoutMs: z.int().positive()
42
+ shellTimeoutMs: z.int().positive(),
43
+ shellTerminationGraceMs: z.int().positive()
30
44
  }).strict();
31
45
  var AgentCodingToolAuthorizationSchema = z.discriminatedUnion("operation", [
32
46
  z.object({ operation: z.literal("read"), path: z.string().min(1) }).strict(),
@@ -121,7 +135,8 @@ var DEFAULT_LIMITS = {
121
135
  maxSearchResults: 100,
122
136
  maxSearchFiles: 1e4,
123
137
  maxSearchDepth: 32,
124
- shellTimeoutMs: 30000
138
+ shellTimeoutMs: 30000,
139
+ shellTerminationGraceMs: 250
125
140
  };
126
141
  function resolveCodingToolLimits(input) {
127
142
  return AgentCodingToolLimitsSchema.parse({ ...DEFAULT_LIMITS, ...input });
@@ -129,11 +144,10 @@ function resolveCodingToolLimits(input) {
129
144
 
130
145
  // src/agent-runtime/coding-tool-files.ts
131
146
  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";
147
+ import { realpath as realpath2 } from "node:fs/promises";
134
148
 
135
149
  // src/agent-runtime/coding-tool-paths.ts
136
- import { lstat, realpath, rename, unlink, writeFile } from "node:fs/promises";
150
+ import { lstat, realpath } from "node:fs/promises";
137
151
  import path from "node:path";
138
152
  function within(root, target) {
139
153
  const relative = path.relative(root, target);
@@ -150,53 +164,20 @@ function inputPath(root, requested, maxPathBytes) {
150
164
  throw new Error("Coding tool path escapes its root");
151
165
  return resolved;
152
166
  }
167
+ function boundedCodingRelativePath(requested, maxPathBytes) {
168
+ inputPath(path.parse(process.cwd()).root, requested, maxPathBytes);
169
+ return requested;
170
+ }
153
171
  async function existingCodingPath(root, requested, maxPathBytes) {
154
172
  const resolved = await realpath(inputPath(root, requested, maxPathBytes));
155
173
  if (!within(root, resolved))
156
174
  throw new Error("Coding tool path resolves outside its root");
157
175
  return { absolute: resolved, relative: path.relative(root, resolved) || "." };
158
176
  }
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
177
  async function authorizeCodingTool(config, request) {
185
178
  const parsed = AgentCodingToolAuthorizationSchema.parse(request);
186
179
  if (!await config.authorize(parsed))
187
- throw new Error("Coding tool permission denied");
188
- }
189
- async function atomicCodingReplace(target, content, mode) {
190
- const temporary = path.join(path.dirname(target), `.${path.basename(target)}.${process.pid}.${crypto.randomUUID()}.tmp`);
191
- try {
192
- await writeFile(temporary, content, { flag: "wx", ...mode !== undefined && { mode } });
193
- await rename(temporary, target);
194
- } catch (error) {
195
- await unlink(temporary).catch(() => {
196
- return;
197
- });
198
- throw error;
199
- }
180
+ forbidden("Coding tool permission denied");
200
181
  }
201
182
  var codingPathLocks = new Map;
202
183
  async function withCodingPathLock(target, work) {
@@ -255,14 +236,15 @@ function createFileCodingTools(config, limits) {
255
236
  transports: ["AGENT"],
256
237
  handler: async ({ input }) => {
257
238
  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 });
239
+ const relative = boundedCodingRelativePath(input.path, limits.maxPathBytes);
240
+ const handle = await openContainedFile(root, relative);
260
241
  const maximum = Math.min(input.maxBytes ?? limits.maxReadBytes, limits.maxReadBytes);
261
- const handle = await open(target.absolute, constants.O_RDONLY | constants.O_NOFOLLOW);
262
242
  let selected;
263
243
  let size;
264
244
  let sha256;
265
245
  try {
246
+ await authorizeCodingTool(config, { operation: "read", path: relative });
247
+ await assertContainedFileCurrent(root, relative, handle);
266
248
  const metadata = await handle.stat();
267
249
  if (!metadata.isFile())
268
250
  throw new Error("Coding read path is not a regular file");
@@ -279,7 +261,7 @@ function createFileCodingTools(config, limits) {
279
261
  const end = input.offset + selected.byteLength;
280
262
  const truncated = end < size;
281
263
  return {
282
- path: target.relative,
264
+ path: relative,
283
265
  text,
284
266
  bytes: selected.byteLength,
285
267
  sha256,
@@ -297,23 +279,36 @@ function createFileCodingTools(config, limits) {
297
279
  transports: ["AGENT"],
298
280
  handler: async ({ input }) => {
299
281
  const root = await realpath2(config.root);
300
- const target = await writableCodingPath(root, input.path, limits.maxPathBytes);
282
+ const relative = boundedCodingRelativePath(input.path, limits.maxPathBytes);
301
283
  const bytes = Buffer.byteLength(input.content);
302
284
  if (bytes > limits.maxWriteBytes)
303
285
  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" });
286
+ const parent = await openContainedParent(root, relative);
287
+ try {
288
+ await authorizeCodingTool(config, {
289
+ operation: "write",
290
+ path: relative,
291
+ bytes,
292
+ overwrite: input.overwrite
293
+ });
294
+ await assertContainedParentCurrent(root, relative, parent.handle);
295
+ if (input.overwrite) {
296
+ const current = await containedEntryMetadata(parent);
297
+ if (current?.isSymbolicLink())
298
+ throw new Error("Coding tools do not overwrite symlinks");
299
+ await writeContainedFile({
300
+ parent,
301
+ content: input.content,
302
+ replace: true,
303
+ ...current && { mode: current.mode }
304
+ });
305
+ } else {
306
+ await writeContainedFile({ parent, content: input.content, replace: false });
307
+ }
308
+ } finally {
309
+ await parent.handle.close();
315
310
  }
316
- return { path: target.relative, bytes };
311
+ return { path: relative, bytes };
317
312
  }
318
313
  });
319
314
  return [read, write];
@@ -381,6 +376,10 @@ function createSearchAndPatchCodingTools(config, limits) {
381
376
  maxDepth: limits.maxSearchDepth,
382
377
  maxFiles: limits.maxSearchFiles,
383
378
  symlinks: "skip",
379
+ ...input.mode === "content" && {
380
+ readMaxBytes: limits.maxReadBytes,
381
+ skipUnreadable: true
382
+ },
384
383
  excludeDirectory: (relative) => relative.split(path2.sep).some((segment) => excluded.has(segment))
385
384
  });
386
385
  const matches = [];
@@ -390,12 +389,9 @@ function createSearchAndPatchCodingTools(config, limits) {
390
389
  if (file.relative.includes(input.query))
391
390
  matches.push({ path: file.relative });
392
391
  } else {
393
- let text;
394
- try {
395
- text = (await readContainedUtf8File(file.absolute, limits.maxReadBytes)).text;
396
- } catch {
392
+ const text = file.content?.text;
393
+ if (text === undefined)
397
394
  continue;
398
- }
399
395
  const lines = text.split(`
400
396
  `);
401
397
  for (let index = 0;index < lines.length; index += 1) {
@@ -429,48 +425,61 @@ function createSearchAndPatchCodingTools(config, limits) {
429
425
  transports: ["AGENT"],
430
426
  handler: async ({ input }) => {
431
427
  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);
428
+ const relative = boundedCodingRelativePath(input.path, limits.maxPathBytes);
429
+ const parent = await openContainedParent(root, relative);
430
+ try {
431
+ const initial = await openContainedParentFile(parent);
432
+ const read = await readContainedUtf8Handle(initial, limits.maxWriteBytes).finally(() => initial.close());
433
+ const source = read.text;
434
+ const baseSha256 = sha256(source);
435
+ if (baseSha256 !== input.baseSha256)
436
+ conflict("Coding patch base digest is stale");
437
+ const count = textOccurrences(source, input.oldText);
438
+ if (count === 0)
439
+ throw new Error("Coding patch text was not found");
440
+ if (!input.replaceAll && count !== 1)
441
+ throw new Error("Coding patch text is not unique");
442
+ const replacements = input.replaceAll ? count : 1;
443
+ const changed = input.replaceAll ? source.replaceAll(input.oldText, input.newText) : source.replace(input.oldText, input.newText);
444
+ const bytes = Buffer.byteLength(changed);
445
+ const resultSha256 = sha256(changed);
446
+ if (bytes > limits.maxWriteBytes)
447
+ throw new Error("Coding patch exceeds maxWriteBytes");
448
+ await authorizeCodingTool(config, {
449
+ operation: "patch",
450
+ path: relative,
451
+ baseSha256,
452
+ resultSha256,
453
+ resultBytes: bytes,
454
+ replacements,
455
+ dryRun: input.dryRun
464
456
  });
457
+ await assertContainedParentCurrent(root, relative, parent.handle);
458
+ if (!input.dryRun) {
459
+ await withCodingPathLock(`${root}:${relative}`, async () => {
460
+ const currentHandle = await openContainedParentFile(parent);
461
+ const current = await readContainedUtf8Handle(currentHandle, limits.maxWriteBytes).finally(() => currentHandle.close());
462
+ if (sha256(current.text) !== baseSha256)
463
+ conflict("Coding patch base digest became stale before apply");
464
+ await writeContainedFile({
465
+ parent,
466
+ content: changed,
467
+ replace: true,
468
+ mode: current.mode
469
+ });
470
+ });
471
+ }
472
+ return {
473
+ path: relative,
474
+ baseSha256,
475
+ resultSha256,
476
+ replacements,
477
+ bytes,
478
+ applied: !input.dryRun
479
+ };
480
+ } finally {
481
+ await parent.handle.close();
465
482
  }
466
- return {
467
- path: target.relative,
468
- baseSha256,
469
- resultSha256,
470
- replacements,
471
- bytes,
472
- applied: !input.dryRun
473
- };
474
483
  }
475
484
  });
476
485
  return [search, patch];
@@ -478,7 +487,7 @@ function createSearchAndPatchCodingTools(config, limits) {
478
487
 
479
488
  // src/agent-runtime/coding-tool-shell.ts
480
489
  import { spawn } from "node:child_process";
481
- import { realpath as realpath4, stat as stat2 } from "node:fs/promises";
490
+ import { realpath as realpath4, stat } from "node:fs/promises";
482
491
  async function runShell(input) {
483
492
  const stdoutHeader = Buffer.from(`--- stdout ---
484
493
  `);
@@ -488,11 +497,23 @@ async function runShell(input) {
488
497
  const artifactPayloadLimit = input.maxArtifactBytes - stdoutHeader.byteLength - stderrHeader.byteLength;
489
498
  if (input.artifacts && artifactPayloadLimit < 0)
490
499
  throw new Error("maxArtifactBytes is smaller than the shell artifact envelope");
500
+ if (input.signal?.aborted) {
501
+ return ShellOutputSchema.parse({
502
+ executable: input.executableName,
503
+ exitCode: null,
504
+ signal: null,
505
+ stdout: "",
506
+ stderr: "",
507
+ outcome: "cancelled"
508
+ });
509
+ }
491
510
  return await new Promise((resolve, reject) => {
511
+ const ownsProcessGroup = process.platform !== "win32";
492
512
  const child = spawn(input.executable, input.args, {
493
513
  cwd: input.cwd,
494
514
  env: input.environment,
495
- stdio: ["ignore", "pipe", "pipe"]
515
+ stdio: ["ignore", "pipe", "pipe"],
516
+ detached: ownsProcessGroup
496
517
  });
497
518
  const stdout = [];
498
519
  const stderr = [];
@@ -502,15 +523,74 @@ async function runShell(input) {
502
523
  let artifactBytes = 0;
503
524
  let outcome = "exited";
504
525
  let settled = false;
526
+ let settlementTimer;
527
+ const cancel = () => terminate("cancelled");
528
+ const cleanup = () => {
529
+ clearTimeout(timer);
530
+ if (settlementTimer)
531
+ clearTimeout(settlementTimer);
532
+ input.signal?.removeEventListener("abort", cancel);
533
+ };
534
+ const persistAndResolve = async (exitCode, signal) => {
535
+ if (settled)
536
+ return;
537
+ settled = true;
538
+ cleanup();
539
+ try {
540
+ const hasArtifact = input.artifacts && artifactBytes > input.maxOutputBytes;
541
+ const artifactData = hasArtifact ? Buffer.concat([stdoutHeader, ...artifactStdout, stderrHeader, ...artifactStderr]) : undefined;
542
+ const persisted = hasArtifact ? await input.artifacts?.write({
543
+ mediaType: "text/plain; charset=utf-8",
544
+ data: artifactData ?? new Uint8Array
545
+ }) : undefined;
546
+ resolve(ShellOutputSchema.parse({
547
+ executable: input.executableName,
548
+ exitCode,
549
+ signal,
550
+ stdout: Buffer.concat(stdout).toString("utf8"),
551
+ stderr: Buffer.concat(stderr).toString("utf8"),
552
+ outcome,
553
+ ...persisted && {
554
+ artifact: {
555
+ reference: persisted.reference,
556
+ bytes: artifactData?.byteLength ?? 0,
557
+ truncated: outcome === "output-limit"
558
+ }
559
+ }
560
+ }));
561
+ } catch (error) {
562
+ reject(error);
563
+ }
564
+ };
565
+ const killOwnedProcessGroup = () => {
566
+ if (!ownsProcessGroup || child.pid === undefined)
567
+ return false;
568
+ try {
569
+ process.kill(-child.pid, "SIGKILL");
570
+ return true;
571
+ } catch {
572
+ return false;
573
+ }
574
+ };
575
+ const boundStreamSettlement = () => {
576
+ if (settlementTimer)
577
+ return;
578
+ settlementTimer = setTimeout(() => {
579
+ child.stdout.destroy();
580
+ child.stderr.destroy();
581
+ persistAndResolve(child.exitCode, child.signalCode);
582
+ }, input.terminationGraceMs);
583
+ };
505
584
  const terminate = (reason) => {
506
585
  if (settled || outcome !== "exited")
507
586
  return;
508
587
  outcome = reason;
509
- child.kill("SIGKILL");
588
+ if (!killOwnedProcessGroup())
589
+ child.kill("SIGKILL");
590
+ boundStreamSettlement();
510
591
  };
511
592
  const timer = setTimeout(() => terminate("timeout"), input.timeoutMs);
512
593
  timer.unref();
513
- const cancel = () => terminate("cancelled");
514
594
  const retain = (target, artifactTarget, chunk) => {
515
595
  const remaining = Math.max(0, input.maxOutputBytes - retained);
516
596
  if (remaining > 0) {
@@ -536,42 +616,18 @@ async function runShell(input) {
536
616
  if (settled)
537
617
  return;
538
618
  settled = true;
539
- clearTimeout(timer);
540
- input.signal?.removeEventListener("abort", cancel);
619
+ cleanup();
541
620
  reject(error);
542
621
  });
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);
622
+ child.on("exit", (exitCode, signal) => {
623
+ if (outcome === "exited")
624
+ killOwnedProcessGroup();
625
+ boundStreamSettlement();
626
+ if (child.stdout.destroyed && child.stderr.destroyed) {
627
+ persistAndResolve(exitCode, signal);
573
628
  }
574
629
  });
630
+ child.on("close", (exitCode, signal) => void persistAndResolve(exitCode, signal));
575
631
  input.signal?.addEventListener("abort", cancel, { once: true });
576
632
  if (input.signal?.aborted)
577
633
  cancel();
@@ -600,7 +656,7 @@ function createShellCodingTool(config, limits) {
600
656
  throw new Error("Coding tool executable is not declared");
601
657
  const root = await realpath4(config.root);
602
658
  const cwd = await existingCodingPath(root, input.cwd, limits.maxPathBytes);
603
- if (!(await stat2(cwd.absolute)).isDirectory()) {
659
+ if (!(await stat(cwd.absolute)).isDirectory()) {
604
660
  throw new Error("Coding tool cwd is not a directory");
605
661
  }
606
662
  await authorizeCodingTool(config, {
@@ -617,6 +673,7 @@ function createShellCodingTool(config, limits) {
617
673
  environment: config.environment ?? {},
618
674
  ...signal && { signal },
619
675
  timeoutMs: limits.shellTimeoutMs,
676
+ terminationGraceMs: limits.shellTerminationGraceMs,
620
677
  maxOutputBytes: limits.maxShellOutputBytes,
621
678
  maxArtifactBytes: limits.maxArtifactBytes,
622
679
  ...config.artifacts && { artifacts: config.artifacts }
@@ -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-1z5xxfst.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
@@ -14,6 +14,7 @@ export interface ManagedServerResourceConfig<TRuntime> {
14
14
  readonly dependsOn?: readonly ManagedResourceDependency[];
15
15
  readonly required?: boolean;
16
16
  readonly retryAfterSeconds?: number;
17
+ readonly realtimeCloseTimeoutMs?: number;
17
18
  }
18
19
  /**
19
20
  * A managed resource that owns a managed server.
@@ -1 +1 @@
1
- {"version":3,"file":"server-resource.d.ts","sourceRoot":"","sources":["../../src/application/server-resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAmC,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,2BAA2B,CAAC,QAAQ;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EACX,mBAAmB,CAAC,QAAQ,CAAC,GAC7B,CAAC,CACC,OAAO,EAAE,sBAAsB,KAC5B,mBAAmB,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB,CAAC,QAAQ,CAAE,SAAQ,eAAe;IACtE,KAAK,CACH,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC;QAAE,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,QAAQ,EAC5C,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC,GAC5C,qBAAqB,CAAC,QAAQ,CAAC,CAwIjC"}
1
+ {"version":3,"file":"server-resource.d.ts","sourceRoot":"","sources":["../../src/application/server-resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAmC,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,2BAA2B,CAAC,QAAQ;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EACX,mBAAmB,CAAC,QAAQ,CAAC,GAC7B,CAAC,CACC,OAAO,EAAE,sBAAsB,KAC5B,mBAAmB,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB,CAAC,QAAQ,CAAE,SAAQ,eAAe;IACtE,KAAK,CACH,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC;QAAE,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,QAAQ,EAC5C,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC,GAC5C,qBAAqB,CAAC,QAAQ,CAAC,CA2IjC"}
@@ -29,7 +29,7 @@ import {
29
29
  ApplicationShutdownBudgetSchema,
30
30
  ApplicationShutdownOptionsSchema,
31
31
  createApplication
32
- } from "./index-6wzr93cg.js";
32
+ } from "./index-w0445741.js";
33
33
  import {
34
34
  defineManagedResource,
35
35
  managedResourceDependencyId
@@ -47,7 +47,7 @@ import {
47
47
  ManagedResourceStateSchema,
48
48
  projectApplicationStatus
49
49
  } from "./index-8eywc9zv.js";
50
- import"./index-dk6e56g0.js";
50
+ import"./index-7wpgrqa8.js";
51
51
  import"./index-0w9abg87.js";
52
52
  import {
53
53
  isRecord
@@ -1030,6 +1030,9 @@ function managedServerResource(config) {
1030
1030
  ...gracePeriodMs !== undefined && { gracePeriodMs },
1031
1031
  ...forceTimeoutMs !== undefined && { forceTimeoutMs },
1032
1032
  retryAfterSeconds: grace(config.retryAfterSeconds ?? 5),
1033
+ ...config.realtimeCloseTimeoutMs !== undefined && {
1034
+ realtimeCloseTimeoutMs: grace(config.realtimeCloseTimeoutMs)
1035
+ },
1033
1036
  signal: context.signal
1034
1037
  };
1035
1038
  shutdownPromise = isHandle(server) ? server.shutdown(options) : server.then((handle) => handle.shutdown(options));
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";