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
@@ -0,0 +1,202 @@
1
+ // src/agent-runtime/contained-files.ts
2
+ import { constants } from "node:fs";
3
+ import { open, readdir, realpath } from "node:fs/promises";
4
+ import path from "node:path";
5
+ function descriptorPath(handle) {
6
+ if (process.platform === "linux")
7
+ return `/proc/self/fd/${handle.fd}`;
8
+ if (process.platform === "darwin" || process.platform === "freebsd") {
9
+ return `/dev/fd/${handle.fd}`;
10
+ }
11
+ throw new Error("Contained filesystem operations require descriptor paths on this platform");
12
+ }
13
+ async function openPinnedDirectory(absolute) {
14
+ const expected = await realpath(absolute);
15
+ const handle = await open(expected, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
16
+ try {
17
+ if (await realpath(descriptorPath(handle)) !== expected) {
18
+ throw new Error("Contained directory identity changed while opening");
19
+ }
20
+ return handle;
21
+ } catch (error) {
22
+ await handle.close();
23
+ throw error;
24
+ }
25
+ }
26
+ function safeSegments(relative) {
27
+ if (path.isAbsolute(relative))
28
+ throw new Error("Contained paths must be relative");
29
+ const segments = relative.split(/[\\/]/u);
30
+ if (segments.length === 0 || segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
31
+ throw new Error("Contained path has invalid segments");
32
+ }
33
+ return segments;
34
+ }
35
+ async function openContainedParent(root, relative) {
36
+ const segments = safeSegments(relative);
37
+ const basename = segments.pop();
38
+ if (!basename)
39
+ throw new Error("Contained path is missing a basename");
40
+ let current = await openPinnedDirectory(root);
41
+ try {
42
+ for (const segment of segments) {
43
+ const next = await open(path.join(descriptorPath(current), segment), constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
44
+ const metadata = await next.stat();
45
+ if (!metadata.isDirectory()) {
46
+ await next.close();
47
+ throw new Error("Contained ancestor is not a directory");
48
+ }
49
+ await current.close();
50
+ current = next;
51
+ }
52
+ return { handle: current, path: descriptorPath(current), basename };
53
+ } catch (error) {
54
+ await current.close();
55
+ throw error;
56
+ }
57
+ }
58
+ async function openContainedFile(root, relative) {
59
+ const parent = await openContainedParent(root, relative);
60
+ try {
61
+ const handle = await open(path.join(parent.path, parent.basename), constants.O_RDONLY | constants.O_NOFOLLOW);
62
+ const metadata = await handle.stat();
63
+ if (!metadata.isFile()) {
64
+ await handle.close();
65
+ throw new Error("Contained path is not a regular file");
66
+ }
67
+ return handle;
68
+ } finally {
69
+ await parent.handle.close();
70
+ }
71
+ }
72
+ function sameIdentity(left, right) {
73
+ return left.dev === right.dev && left.ino === right.ino;
74
+ }
75
+ async function assertContainedFileCurrent(root, relative, expected) {
76
+ const current = await openContainedFile(root, relative);
77
+ try {
78
+ if (!sameIdentity(await expected.stat(), await current.stat())) {
79
+ throw new Error("Contained file identity changed during authorization");
80
+ }
81
+ } finally {
82
+ await current.close();
83
+ }
84
+ }
85
+ async function assertContainedParentCurrent(root, relative, expected) {
86
+ const current = await openContainedParent(root, relative);
87
+ try {
88
+ if (!sameIdentity(await expected.stat(), await current.handle.stat())) {
89
+ throw new Error("Contained parent identity changed during authorization");
90
+ }
91
+ } finally {
92
+ await current.handle.close();
93
+ }
94
+ }
95
+ async function readContainedUtf8Handle(handle, maxBytes) {
96
+ const metadata = await handle.stat();
97
+ if (!metadata.isFile())
98
+ throw new Error("Contained path is not a regular file");
99
+ if (metadata.size > maxBytes)
100
+ throw new Error("Contained file exceeds byte budget");
101
+ const buffer = Buffer.alloc(metadata.size);
102
+ let offset = 0;
103
+ while (offset < buffer.byteLength) {
104
+ const { bytesRead } = await handle.read(buffer, offset, buffer.byteLength - offset, offset);
105
+ if (bytesRead === 0)
106
+ break;
107
+ offset += bytesRead;
108
+ }
109
+ if (offset !== metadata.size)
110
+ throw new Error("Contained file changed while being read");
111
+ return {
112
+ text: new TextDecoder("utf-8", { fatal: true }).decode(buffer),
113
+ bytes: offset,
114
+ mode: metadata.mode
115
+ };
116
+ }
117
+ async function walkContainedFiles(input) {
118
+ const scan = await scanContainedFiles({ ...input, symlinks: "refuse" });
119
+ if (scan.truncated)
120
+ throw new Error("Contained file traversal exceeded its bounds");
121
+ return scan.files;
122
+ }
123
+ async function scanContainedFiles(input) {
124
+ const files = [];
125
+ let truncated = false;
126
+ let skippedDirectories = 0;
127
+ let skippedSymlinks = 0;
128
+ const root = await openPinnedDirectory(input.root);
129
+ const visit = async (directory, relativeDirectory, depth) => {
130
+ if (truncated)
131
+ return;
132
+ if (depth > input.maxDepth) {
133
+ truncated = true;
134
+ return;
135
+ }
136
+ const entries = await readdir(descriptorPath(directory), { withFileTypes: true });
137
+ entries.sort((left, right) => left.name.localeCompare(right.name));
138
+ for (const entry of entries) {
139
+ const relative = relativeDirectory ? path.join(relativeDirectory, entry.name) : entry.name;
140
+ const anchored = path.join(descriptorPath(directory), entry.name);
141
+ if (entry.isSymbolicLink()) {
142
+ if (input.symlinks === "refuse") {
143
+ throw new Error(`Contained file traversal refuses symlink: ${relative}`);
144
+ }
145
+ skippedSymlinks += 1;
146
+ continue;
147
+ }
148
+ if (entry.isDirectory()) {
149
+ if (input.excludeDirectory?.(relative)) {
150
+ skippedDirectories += 1;
151
+ continue;
152
+ }
153
+ let child;
154
+ try {
155
+ child = await open(anchored, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
156
+ } catch (error) {
157
+ if (input.symlinks === "skip") {
158
+ skippedSymlinks += 1;
159
+ continue;
160
+ }
161
+ throw error;
162
+ }
163
+ try {
164
+ await visit(child, relative, depth + 1);
165
+ } finally {
166
+ await child.close();
167
+ }
168
+ continue;
169
+ }
170
+ if (!entry.isFile())
171
+ continue;
172
+ if (files.length >= input.maxFiles) {
173
+ truncated = true;
174
+ return;
175
+ }
176
+ let content;
177
+ if (input.readMaxBytes !== undefined) {
178
+ try {
179
+ const handle = await open(anchored, constants.O_RDONLY | constants.O_NOFOLLOW);
180
+ try {
181
+ content = await readContainedUtf8Handle(handle, input.readMaxBytes);
182
+ } finally {
183
+ await handle.close();
184
+ }
185
+ } catch (error) {
186
+ if (input.skipUnreadable)
187
+ continue;
188
+ throw error;
189
+ }
190
+ }
191
+ files.push({ absolute: relative, relative, ...content && { content } });
192
+ }
193
+ };
194
+ try {
195
+ await visit(root, "", 0);
196
+ } finally {
197
+ await root.close();
198
+ }
199
+ return { files, truncated, skippedDirectories, skippedSymlinks };
200
+ }
201
+
202
+ export { openContainedParent, openContainedFile, assertContainedFileCurrent, assertContainedParentCurrent, readContainedUtf8Handle, walkContainedFiles, scanContainedFiles };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  collectTools,
3
3
  createToolRunner
4
- } from "./index-kg9xx84n.js";
4
+ } from "./index-7rey2b8s.js";
5
5
  import {
6
6
  toolErrorFromResult
7
- } from "./index-h8vn1jcr.js";
7
+ } from "./index-qzbg46b6.js";
8
8
  import {
9
9
  assertUniqueToolName
10
10
  } from "./index-22by16v6.js";
package/dist/node.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  createHandler,
6
6
  createSocketIOServer,
7
7
  createUnixClientTransport
8
- } from "./index-444747ww.js";
8
+ } from "./index-38hs3a58.js";
9
9
  import {
10
10
  createImplement,
11
11
  createImplementRegistry,
@@ -14,8 +14,8 @@ import {
14
14
  createScopedImplementRegistry,
15
15
  implement,
16
16
  implementRegistry
17
- } from "./index-d1jsvkyk.js";
18
- import"./index-p1be103g.js";
17
+ } from "./index-vbf2p6me.js";
18
+ import"./index-ktsps64f.js";
19
19
  import"./index-7b188kmz.js";
20
20
  import {
21
21
  ShutdownOptionsSchema,
@@ -24,7 +24,8 @@ import {
24
24
  ShutdownStatusSchema,
25
25
  createServerLifecycle
26
26
  } from "./index-dk6e56g0.js";
27
- import"./index-x18ndp4p.js";
27
+ import"./index-bd17ytae.js";
28
+ import"./index-vj3vvpaa.js";
28
29
  import {
29
30
  AppError,
30
31
  appError,
@@ -10,7 +10,7 @@ import {
10
10
  redact,
11
11
  sanitizePayload,
12
12
  truncatePreview
13
- } from "../index-zh459sfj.js";
13
+ } from "../index-aczggrty.js";
14
14
  import {
15
15
  getRequestContext,
16
16
  getTraceId,
@@ -21,7 +21,7 @@ import {
21
21
  setRequestError,
22
22
  setRequestUser,
23
23
  wrapInRequestContext
24
- } from "../index-p1be103g.js";
24
+ } from "../index-ktsps64f.js";
25
25
  import {
26
26
  childSpan,
27
27
  createTraceContext,
@@ -30,7 +30,8 @@ import {
30
30
  recordedErrorMessage,
31
31
  resolvePropagationContext,
32
32
  resolveTraceContext
33
- } from "../index-x18ndp4p.js";
33
+ } from "../index-bd17ytae.js";
34
+ import"../index-vj3vvpaa.js";
34
35
  import"../index-0w9abg87.js";
35
36
  import {
36
37
  isRecord
package/dist/remote.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  ApiError,
3
3
  createClient
4
- } from "./index-kxxyvkka.js";
5
- import"./index-t4dpby6e.js";
4
+ } from "./index-wc80at9n.js";
5
+ import"./index-0yphgata.js";
6
+ import"./index-bd17ytae.js";
6
7
  import {
7
8
  mergeMeta
8
- } from "./index-x18ndp4p.js";
9
+ } from "./index-vj3vvpaa.js";
9
10
  import {
10
11
  AppError
11
12
  } from "./index-0w9abg87.js";
@@ -13,7 +13,7 @@ import {
13
13
  sseRoute,
14
14
  streamingRoute,
15
15
  webSocketLane
16
- } from "../index-444747ww.js";
16
+ } from "../index-38hs3a58.js";
17
17
  import {
18
18
  composeAuthHooks,
19
19
  createAuthHook,
@@ -26,7 +26,7 @@ import {
26
26
  signJwt,
27
27
  verifyJwt,
28
28
  verifyPkce
29
- } from "../index-q7gdep2c.js";
29
+ } from "../index-da1aqnhb.js";
30
30
  import {
31
31
  DEFAULT_CORS_ALLOW_HEADERS,
32
32
  DEFAULT_CORS_EXPOSE_HEADERS,
@@ -40,7 +40,7 @@ import {
40
40
  defineMultipartStream,
41
41
  implement,
42
42
  implementRegistry
43
- } from "../index-d1jsvkyk.js";
43
+ } from "../index-vbf2p6me.js";
44
44
  import {
45
45
  extractIp,
46
46
  generateTraceId,
@@ -48,7 +48,7 @@ import {
48
48
  getTraceId,
49
49
  resolveSocketIp,
50
50
  resolveTraceId
51
- } from "../index-p1be103g.js";
51
+ } from "../index-ktsps64f.js";
52
52
  import {
53
53
  isWithinDir,
54
54
  realPathWithinDir
@@ -69,16 +69,18 @@ import {
69
69
  inputIsQuery,
70
70
  parseSSE,
71
71
  streamSSE
72
- } from "../index-t4dpby6e.js";
72
+ } from "../index-0yphgata.js";
73
73
  import {
74
- DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
75
74
  errorCode,
76
75
  formatZodError,
77
- joinRoutePath,
78
76
  normalizeError,
79
- parseTrailingWildcard,
80
77
  zodIssues
81
- } from "../index-x18ndp4p.js";
78
+ } from "../index-bd17ytae.js";
79
+ import {
80
+ DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
81
+ joinRoutePath,
82
+ parseTrailingWildcard
83
+ } from "../index-vj3vvpaa.js";
82
84
  import {
83
85
  AppError,
84
86
  STITCH_ERROR_STATUS,
package/dist/testing.js CHANGED
@@ -24,11 +24,12 @@ import {
24
24
  import {
25
25
  createClient,
26
26
  createClients
27
- } from "./index-kxxyvkka.js";
28
- import"./index-t4dpby6e.js";
27
+ } from "./index-wc80at9n.js";
28
+ import"./index-0yphgata.js";
29
+ import"./index-bd17ytae.js";
29
30
  import {
30
31
  joinRoutePath
31
- } from "./index-x18ndp4p.js";
32
+ } from "./index-vj3vvpaa.js";
32
33
  import"./index-0w9abg87.js";
33
34
  import {
34
35
  isRecord
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  createToolInvoker
3
- } from "./index-gqdfpv4n.js";
4
- import"./index-kg9xx84n.js";
5
- import"./index-h8vn1jcr.js";
6
- import"./index-p1be103g.js";
3
+ } from "./index-y3w12g8d.js";
4
+ import"./index-7rey2b8s.js";
5
+ import"./index-qzbg46b6.js";
6
+ import"./index-ktsps64f.js";
7
7
  import"./index-22by16v6.js";
8
8
  import"./index-cby4ar3v.js";
9
- import"./index-x18ndp4p.js";
9
+ import"./index-bd17ytae.js";
10
+ import"./index-vj3vvpaa.js";
10
11
  import"./index-0w9abg87.js";
11
12
  import"./index-qyrqwr4c.js";
12
13
  import"./index-6k1937bx.js";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A mounted tool failed with a model-safe, transport-shaped error envelope.
3
+ *
4
+ * The AI SDK must observe a throw so it emits `tool-error`; returning this
5
+ * envelope would incorrectly mark the call successful. The original cause is
6
+ * retained for local observability while `message` contains only the safe
7
+ * envelope that may be sent to the model provider.
8
+ */
9
+ export declare class AgentToolError extends Error {
10
+ readonly output: Record<string, unknown>;
11
+ constructor(output: Record<string, unknown>, cause?: unknown);
12
+ }
13
+ export declare function isAgentToolError(value: unknown): value is AgentToolError;
14
+ //# sourceMappingURL=agent-tool-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tool-error.d.ts","sourceRoot":"","sources":["../../src/tools/agent-tool-error.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAgB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEhD,YAAY,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,EAW3D;CACF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAExE"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/tools/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qCAAqC;IACrC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACjD;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,UAAU,GAAG,UAAU,EAAE,EACnC,MAAM,GAAE,gBAAqB,GAC5B,OAAO,CAyET"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/tools/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qCAAqC;IACrC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACjD;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,UAAU,GAAG,UAAU,EAAE,EACnC,MAAM,GAAE,gBAAqB,GAC5B,OAAO,CA4ET"}
package/dist/tools.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  redact
3
- } from "./index-zh459sfj.js";
3
+ } from "./index-aczggrty.js";
4
4
  import {
5
5
  buildToolManifest,
6
6
  mountAgent
7
- } from "./index-h7ctj1kp.js";
7
+ } from "./index-s8nt8c22.js";
8
+ import"./index-3xnq72rz.js";
8
9
  import {
9
10
  signJwt,
10
11
  verifyPkce
11
- } from "./index-q7gdep2c.js";
12
+ } from "./index-da1aqnhb.js";
12
13
  import {
13
14
  DEFAULT_CORS_ALLOW_HEADERS,
14
15
  DEFAULT_PROCESS_SIGNALS,
@@ -16,10 +17,10 @@ import {
16
17
  defaultSignalSource,
17
18
  guardSignalCallback,
18
19
  reportSignalError
19
- } from "./index-d1jsvkyk.js";
20
+ } from "./index-vbf2p6me.js";
20
21
  import {
21
22
  createToolInvoker
22
- } from "./index-gqdfpv4n.js";
23
+ } from "./index-y3w12g8d.js";
23
24
  import {
24
25
  WaitTimeoutError,
25
26
  createCli,
@@ -28,10 +29,10 @@ import {
28
29
  fetchPinnedDocument,
29
30
  readCapped,
30
31
  runWaitOperation
31
- } from "./index-mbxds404.js";
32
+ } from "./index-mjx0wt4c.js";
32
33
  import {
33
34
  collectToolSurface
34
- } from "./index-xxsq3ca1.js";
35
+ } from "./index-vc498pst.js";
35
36
  import {
36
37
  createRuntimeToolFactory,
37
38
  defineRuntimeTool
@@ -40,19 +41,19 @@ import {
40
41
  collectTools,
41
42
  createToolRunner,
42
43
  formatToolError
43
- } from "./index-kg9xx84n.js";
44
+ } from "./index-7rey2b8s.js";
44
45
  import {
45
46
  ToolExecutionControlError,
46
47
  coerceJsonArgs,
47
48
  executeToolMethod,
48
49
  isToolExecutionControlError,
49
50
  toolResultFromError
50
- } from "./index-h8vn1jcr.js";
51
+ } from "./index-qzbg46b6.js";
51
52
  import {
52
53
  getRequestContext,
53
54
  getTraceId,
54
55
  runWithRequestContext
55
- } from "./index-p1be103g.js";
56
+ } from "./index-ktsps64f.js";
56
57
  import {
57
58
  ManagedFileError
58
59
  } from "./index-bfcpjw20.js";
@@ -70,10 +71,12 @@ import {
70
71
  } from "./index-22by16v6.js";
71
72
  import"./index-cby4ar3v.js";
72
73
  import {
73
- defineContract,
74
74
  normalizeError,
75
75
  resolvePropagationContext
76
- } from "./index-x18ndp4p.js";
76
+ } from "./index-bd17ytae.js";
77
+ import {
78
+ defineContract
79
+ } from "./index-vj3vvpaa.js";
77
80
  import {
78
81
  AppError,
79
82
  STITCH_ERROR_STATUS
package/llms-full.txt CHANGED
@@ -59,15 +59,15 @@ own, recorded as an ADR.
59
59
  | `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
60
60
  | `stitchkit/declaration` | build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
61
61
  | `stitchkit/react` | browser | stable | `createCursorQuery`, `createCacheBridge` |
62
- | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the 14 minors since 0.56.2, most recently 0.69.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
62
+ | `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the 15 minors since 0.56.2, most recently 0.69.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
63
63
  | `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
64
64
  | `stitchkit/agent-runtime/coding-tools` | server (Bun or Node) | evolving | bounded host-authorized direct file and shell tools; a root boundary, not an OS sandbox |
65
65
  | `stitchkit/agent-runtime/openrouter` | server | evolving | isolated OpenRouter language-model adapter |
66
66
  | `stitchkit/agent-runtime/browser` | browser + server | evolving | canonical agent records, events and reconnect cursor without execution or sinks |
67
67
  | `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
68
68
  | `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
69
- | `@stitchkit/tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
70
- | `stitchkit/application` | server | evolving<br>_redefined in 3 of the 14 minors since 0.56.2, most recently 0.67.0_ | managed resource graph, readiness, admission, schedules and bounded shutdown |
69
+ | `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
70
+ | `stitchkit/application` | server | evolving<br>_redefined in 3 of the 15 minors since 0.56.2, most recently 0.67.0_ | managed resource graph, readiness, admission, schedules and bounded shutdown |
71
71
  | `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
72
72
  | `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
73
73
 
@@ -224,7 +224,7 @@ set `OPENROUTER_API_KEY`, then run `bun run dev` and choose a live tool-capable
224
224
  model with `/model`. The provider catalog owns the exact model id and context window and presents
225
225
  weekly popularity separately from sourced benchmark observations; `OPENROUTER_MODEL` is only an
226
226
  optional preferred row. That profile is a thin `stitchkit.agent.ts` composition over the official
227
- `@stitchkit/tui` package and canonical headless harness:
227
+ `stitchkit-tui` package and canonical headless harness:
228
228
  durable SQLite history, lazy skills, direct coding tools, approval continuations
229
229
  and recovery stay framework-owned primitives, while model choice, permissions,
230
230
  executables and OS isolation remain application policy.
@@ -4066,8 +4066,13 @@ cross-crash exactly-once guarantee remain application concerns.
4066
4066
  `stitchkit/agent-runtime/coding-tools` returns ordinary direct runtime tools named `read_file`,
4067
4067
  `write_file`, `search_files`, `apply_patch`, `run_command` and optional `read_output`. Every call passes a
4068
4068
  required host authorization callback. File paths are relative, bounded and contained after
4069
- realpath resolution; writes/edits reject symlink targets, content is strict UTF-8 and retained
4070
- bytes are finite. Shell accepts a finite alias mapped by the host to an absolute executable plus an
4069
+ descriptor-relative resolution: each ancestor is opened without following symlinks and remains
4070
+ pinned through authorization and the filesystem effect. Reads revalidate the pinned file identity;
4071
+ writes and patches revalidate the pinned parent identity; search and resource discovery descend
4072
+ only through opened directories. Linux uses `/proc/self/fd`; macOS and FreeBSD use `/dev/fd`.
4073
+ Other platforms fail these filesystem operations closed because Node exposes no equivalent
4074
+ portable directory-handle-relative API. Writes/edits reject symlink targets, content is strict
4075
+ UTF-8 and retained bytes are finite. Shell accepts a finite alias mapped by the host to an absolute executable plus an
4071
4076
  argument array — never a shell command string — and uses only the explicitly supplied environment.
4072
4077
  Arguments, output and time are bounded, while cancellation terminates the child. The configured
4073
4078
  root and cwd are path boundaries, not a security sandbox: isolate the process when an executable
@@ -4080,9 +4085,19 @@ multi-file atomicity. With an optional `AgentCodingArtifactStore`, shell output
4080
4085
  preview continues into an opaque bounded artifact and `read_output` reads slices without
4081
4086
  exposing a host path. Without a store, the previous finite output-limit behavior is unchanged.
4082
4087
 
4088
+ `run_command` treats every invocation as finite. `shellTimeoutMs` bounds normal execution and
4089
+ `shellTerminationGraceMs` bounds settlement after timeout, caller cancellation, output overflow or
4090
+ parent exit. POSIX hosts launch a dedicated process group and kill every descendant remaining in
4091
+ that group; a process that deliberately escapes the group is outside the guarantee. Node's
4092
+ portable Windows child-process API cannot kill a complete descendant tree without invoking a
4093
+ second host executable, so Windows kills the direct child, destroys retained pipes at the grace
4094
+ deadline and makes no descendant-cleanup claim. A signal already aborted before execution returns
4095
+ `cancelled` without spawning.
4096
+
4083
4097
  One `createAgentHarnessFileResources` instance represents one immutable discovery generation:
4084
4098
  concurrent and repeated `load()` calls share it, so a direct resource read cannot cross into a
4085
- new catalog unexpectedly. Construct a new loader to refresh after filesystem changes.
4099
+ new catalog unexpectedly. Discovery uses the same descriptor-anchored traversal as coding search;
4100
+ construct a new loader to refresh after filesystem changes.
4086
4101
 
4087
4102
  Runtime events preserve reasoning/text/tool lifecycle order. Durable admission,
4088
4103
  checkpoint, run-state and terminal events carry stable identities; transient
@@ -4509,7 +4524,9 @@ or silently accept an unknown future version.
4509
4524
  - `assistant-checkpoint` follows a successful checkpoint CAS;
4510
4525
  - `run-state` follows durable queue/acquire/interrupt transitions;
4511
4526
  - `tool-status` is transient lifecycle presentation with JSON-safe input on
4512
- start and output on completion; internal tool failures remain generic;
4527
+ start and output on completion. A mounted typed failure carries the same safe
4528
+ `{ error, details?, _hint? }` envelope as the durable result; an unknown
4529
+ internal cause remains generic and stays in local observability only;
4513
4530
  - `terminal` follows the winning terminal CAS.
4514
4531
 
4515
4532
  These are post-commit notifications, not a transactional outbox: a process can
@@ -4625,6 +4642,14 @@ before a managed side effect and again before accepting its result. Fence loss
4625
4642
  uses an internal control signal: it stops the old loop and is not sent to the
4626
4643
  model as a tool error.
4627
4644
 
4645
+ `mountAgent` sends failed runner outcomes through the AI SDK's tool-error
4646
+ channel. AgentRuntime persists them with `outcome: 'error'`, publishes the same
4647
+ safe envelope, and replays them as an error result on later turns. Classification
4648
+ comes from the execution channel, never from inspecting output fields: a valid
4649
+ successful result such as `{ error: 'domain value' }` remains successful. Typed
4650
+ `AppError` codes and safe details may reach the model; arbitrary thrown causes
4651
+ are retained for local hooks and reduced to `INTERNAL_SERVER_ERROR` outside.
4652
+
4628
4653
  The framework cannot undo an already-started non-cooperative external effect.
4629
4654
  Pass the stable call/run idempotency identity into business mutations when the
4630
4655
  effect must be replay-safe.
@@ -8869,6 +8894,21 @@ additive** — adopting it changes nothing in your code. (See
8869
8894
  So upgrading is: read the `### ⚠️ Breaking changes` of every version *above* your
8870
8895
  current one *up to* your target, and apply each snippet.
8871
8896
 
8897
+ ## Released migration: 0.70.0
8898
+
8899
+ ### Descriptor-backed Agent filesystem containment
8900
+
8901
+ Built-in coding file/search tools and `createAgentHarnessFileResources` now require a runtime
8902
+ that can address an opened directory descriptor: Linux `/proc/self/fd`, or macOS/FreeBSD
8903
+ `/dev/fd`. This is what keeps a mutable parent rename or outside-symlink replacement from changing
8904
+ the authorized target between validation and the actual effect.
8905
+
8906
+ No call-site change is needed on those platforms. On Windows or another platform without that
8907
+ boundary, move the built-in filesystem operations to a supported worker or replace them with
8908
+ application-owned tools backed by an equivalent native handle API. They fail closed rather than
8909
+ falling back to path spelling. `run_command` remains separately available under its explicit
8910
+ executable alias and authorization policy; this change does not claim an executable sandbox.
8911
+
8872
8912
  ## Released migration: 0.69.0
8873
8913
 
8874
8914
  ### Direct coding-tool operation names
@@ -12204,17 +12244,19 @@ artifact store is supplied, `read_output`.
12204
12244
 
12205
12245
  | Export | Kind | Summary |
12206
12246
  |--------|------|---------|
12207
- | `createAgentCodingTools` | function | construct direct host-authorized bounded file, search, guarded patch, shell and artifact runtime-tool definitions |
12247
+ | `createAgentCodingTools` | function | construct direct host-authorized bounded file, search, guarded patch, shell and artifact runtime-tool definitions; filesystem operations require Linux `/proc/self/fd` or macOS/FreeBSD `/dev/fd` descriptor paths and otherwise fail closed |
12208
12248
  | `AgentCodingToolDefinition` | _type_ | peer-free structural direct-tool shape accepted by the canonical runtime-tool surface |
12209
12249
  | `AgentCodingToolConfig` | _type_ | absolute root, required authorization callback, finite executable alias map, exact child environment and optional limits |
12210
12250
  | `AgentCodingToolAuthorizationSchema` / `AgentCodingToolAuthorization` | schema / _type_ | discriminated read/write/search/patch/shell/artifact decision presented to host policy before effect |
12211
- | `AgentCodingToolLimitsSchema` / `AgentCodingToolLimits` | schema / _type_ | explicit path/read/write/argument-count/argument-byte/output/artifact/timeout ceilings |
12251
+ | `AgentCodingToolLimitsSchema` / `AgentCodingToolLimits` | schema / _type_ | explicit path/read/write/argument-count/argument-byte/output/artifact/timeout/termination-grace ceilings |
12212
12252
  | `AgentCodingArtifactStore` | _type_ | host-owned opaque artifact write and bounded read boundary |
12213
12253
  | `FileReadInputSchema` / `FileReadOutputSchema` | schema | bounded strict-UTF-8 byte slice; offsets must align with UTF-8 code-point boundaries |
12214
12254
  | `FileWriteInputSchema` / `FileWriteOutputSchema` | schema | create-only by default or explicit atomic replacement; symlink targets fail closed |
12215
12255
  | `createShellInputSchema` / `ShellOutputSchema` | schema | enumerated executable alias plus arguments and concrete relative cwd; explicit exited/timeout/output-limit/cancelled outcome |
12216
12256
 
12217
- The default ceilings are 4,096 path bytes, 256 KiB read/write/output, 128 shell arguments, 64 KiB
12257
+ File/search operations pin directory descriptors across authorization and the actual effect;
12258
+ resource discovery uses the same ancestor-safe traversal. This closes parent rename/symlink races
12259
+ without claiming an executable sandbox. The default ceilings are 4,096 path bytes, 256 KiB read/write/output, 128 shell arguments, 64 KiB
12218
12260
  of aggregate argument text, 4 MiB per artifact and 30 seconds. The root is a path-resolution
12219
12261
  boundary, not an OS sandbox; executable behavior, process
12220
12262
  isolation, credentials and external-effect idempotency remain host responsibilities.
@@ -12263,7 +12305,7 @@ loaded by the neutral, browser or Node runtime surfaces.
12263
12305
 
12264
12306
  ---
12265
12307
 
12266
- ## `@stitchkit/tui`
12308
+ ## `stitchkit-tui`
12267
12309
 
12268
12310
  Separate optional evolving Bun/OpenTUI package over a caller-composed headless harness.
12269
12311
 
@@ -12290,7 +12332,7 @@ The slash palette owns its highlighted selection: Up/Down move it, Tab completes
12290
12332
  the exact command and Escape dismisses it. Partial input is never submitted while the palette is
12291
12333
  active; unknown slash text with no match remains an ordinary model prompt.
12292
12334
 
12293
- ### `@stitchkit/tui/core`
12335
+ ### `stitchkit-tui/core`
12294
12336
 
12295
12337
  Renderer-neutral state only. This entrypoint imports neither React/OpenTUI nor the agent runtime.
12296
12338
 
@@ -12415,7 +12457,7 @@ payload.
12415
12457
  | `bindStdioProcessSignals` | function | explicitly bind OS signals to one close-only stdio handle — [guide](../guide/testing-and-deployment.md#stdio-process-signals) |
12416
12458
  | `buildMcpServer` | function | build an `McpServer` from contract/runtime surfaces; no-auth configs omit the second argument |
12417
12459
  | `mountMcp` | function | add contract tools to an existing `McpServer` — [guide](../guide/mcp-and-agents.md#mountmcp) |
12418
- | `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
12460
+ | `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service; failed executions reject through the SDK tool-error channel with a safe typed envelope, while successful output is never classified by field name — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
12419
12461
  | `defineRuntimeTool` | function | define one validated pathless operation for explicit MCP, Agent and/or CLI surfaces — [guide](../guide/mcp-and-agents.md#pathless-runtime-tools-and-multimodal-results) |
12420
12462
  | `createRuntimeToolFactory` | function | bind shared identity and Zod-validated per-call context for runtime tools — [guide](../guide/mcp-and-agents.md#pathless-runtime-tools-and-multimodal-results) |
12421
12463
  | `createToolInvoker` | function | compile an exposure-aware in-process dispatcher over the canonical tool runner; use peer-free `stitchkit/tools/invoker`, or the full `stitchkit/tools` adapter barrel — [guide](../guide/mcp-and-agents.md#in-process-calls--createtoolinvoker) |