stitchkit 0.103.13 → 0.104.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 (223) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/darwin-native.cjs +1 -3
  3. package/dist/agent-runtime/store-conformance-lifecycle.d.ts +10 -10
  4. package/dist/agent-runtime/store-conformance-support.d.ts +5 -5
  5. package/dist/application/directory-inbox-accept.d.ts +13 -0
  6. package/dist/application/directory-inbox-accept.d.ts.map +1 -0
  7. package/dist/application/directory-inbox-contract.d.ts +42 -5
  8. package/dist/application/directory-inbox-contract.d.ts.map +1 -1
  9. package/dist/application/directory-inbox-delivery.d.ts +14 -0
  10. package/dist/application/directory-inbox-delivery.d.ts.map +1 -0
  11. package/dist/application/directory-inbox-files.d.ts +28 -0
  12. package/dist/application/directory-inbox-files.d.ts.map +1 -0
  13. package/dist/application/directory-inbox-state.d.ts +14 -0
  14. package/dist/application/directory-inbox-state.d.ts.map +1 -0
  15. package/dist/application/directory-inbox.d.ts +2 -1
  16. package/dist/application/directory-inbox.d.ts.map +1 -1
  17. package/dist/application/file-state-store.d.ts +2 -8
  18. package/dist/application/file-state-store.d.ts.map +1 -1
  19. package/dist/application/state-store.d.ts +6 -1
  20. package/dist/application/state-store.d.ts.map +1 -1
  21. package/dist/browser/client-arguments.d.ts +4 -0
  22. package/dist/browser/client-arguments.d.ts.map +1 -0
  23. package/dist/browser/client-executors.d.ts.map +1 -1
  24. package/dist/browser/client.d.ts.map +1 -1
  25. package/dist/browser/contract-stream.d.ts.map +1 -1
  26. package/dist/browser/http.d.ts +2 -1
  27. package/dist/browser/http.d.ts.map +1 -1
  28. package/dist/browser/native-fetch.d.ts +8 -0
  29. package/dist/browser/native-fetch.d.ts.map +1 -0
  30. package/dist/contract/errors.d.ts +16 -12
  31. package/dist/contract/errors.d.ts.map +1 -1
  32. package/dist/contract/normalize.d.ts +5 -1
  33. package/dist/contract/normalize.d.ts.map +1 -1
  34. package/dist/contract/stream.d.ts +1 -0
  35. package/dist/contract/stream.d.ts.map +1 -1
  36. package/dist/entrypoints/agent-runtime/browser.js +3 -3
  37. package/dist/entrypoints/agent-runtime/coding-tools.js +6 -6
  38. package/dist/entrypoints/agent-runtime/harness-tools.js +8 -8
  39. package/dist/entrypoints/agent-runtime/harness.js +11 -11
  40. package/dist/entrypoints/agent-runtime/realtime.js +3 -3
  41. package/dist/entrypoints/agent-runtime/sandbox.js +6 -6
  42. package/dist/entrypoints/agent-runtime.js +13 -13
  43. package/dist/entrypoints/application/diagnostic-journal.js +1 -1
  44. package/dist/entrypoints/application/directory-inbox.js +424 -119
  45. package/dist/entrypoints/application/grammy.js +1 -1
  46. package/dist/entrypoints/application.d.ts +2 -2
  47. package/dist/entrypoints/application.d.ts.map +1 -1
  48. package/dist/entrypoints/application.js +7 -3
  49. package/dist/entrypoints/cli.d.ts +2 -0
  50. package/dist/entrypoints/cli.d.ts.map +1 -1
  51. package/dist/entrypoints/cli.js +757 -136
  52. package/dist/entrypoints/contract.js +3 -3
  53. package/dist/entrypoints/files/packaging.d.ts +3 -0
  54. package/dist/entrypoints/files/packaging.d.ts.map +1 -0
  55. package/dist/entrypoints/files/packaging.js +133 -0
  56. package/dist/entrypoints/files.js +10 -107
  57. package/dist/entrypoints/index.js +7 -7
  58. package/dist/entrypoints/node.js +8 -8
  59. package/dist/entrypoints/observability.js +2 -2
  60. package/dist/entrypoints/react.js +1 -1
  61. package/dist/entrypoints/remote.js +19 -6
  62. package/dist/entrypoints/server.d.ts +1 -1
  63. package/dist/entrypoints/server.d.ts.map +1 -1
  64. package/dist/entrypoints/server.js +23 -17
  65. package/dist/entrypoints/telegram.d.ts +1 -0
  66. package/dist/entrypoints/telegram.d.ts.map +1 -1
  67. package/dist/entrypoints/telegram.js +214 -98
  68. package/dist/entrypoints/testing.js +7 -7
  69. package/dist/entrypoints/tools/connections.d.ts +2 -2
  70. package/dist/entrypoints/tools/connections.d.ts.map +1 -1
  71. package/dist/entrypoints/tools/connections.js +427 -294
  72. package/dist/entrypoints/tools/invoker.js +6 -6
  73. package/dist/entrypoints/tools/mcp.d.ts +12 -0
  74. package/dist/entrypoints/tools/mcp.d.ts.map +1 -0
  75. package/dist/entrypoints/tools/mcp.js +45 -0
  76. package/dist/entrypoints/tools.d.ts +1 -0
  77. package/dist/entrypoints/tools.d.ts.map +1 -1
  78. package/dist/entrypoints/tools.js +82 -1147
  79. package/dist/entrypoints/tracking.js +1 -1
  80. package/dist/files/boundary.d.ts +2 -8
  81. package/dist/files/boundary.d.ts.map +1 -1
  82. package/dist/files/file-io.d.ts +0 -5
  83. package/dist/files/file-io.d.ts.map +1 -1
  84. package/dist/files/native-packaging-layout.d.ts +12 -0
  85. package/dist/files/native-packaging-layout.d.ts.map +1 -0
  86. package/dist/files/native-packaging.d.ts +72 -0
  87. package/dist/files/native-packaging.d.ts.map +1 -0
  88. package/dist/files/read.d.ts +2 -2
  89. package/dist/files/read.d.ts.map +1 -1
  90. package/dist/index-1a6jtnd9.js +88 -0
  91. package/dist/index-269zqj8m.js +77 -0
  92. package/dist/{index-r34mvse1.js → index-27a2pj09.js} +1 -1
  93. package/dist/{index-r956rndn.js → index-2hyavjjj.js} +3 -3
  94. package/dist/{index-m2xqkv55.js → index-2vnh05w4.js} +83 -14
  95. package/dist/{index-pw99k9h5.js → index-43p08g7t.js} +1 -1
  96. package/dist/{index-xwq9j1sf.js → index-4e0ah203.js} +9 -7
  97. package/dist/{index-qapzv4p5.js → index-5z6jn897.js} +1 -1
  98. package/dist/{index-ahvsksw5.js → index-6d9xaxw1.js} +1 -1
  99. package/dist/{index-8zfsgar0.js → index-6drst9sg.js} +11 -5
  100. package/dist/{index-x87j7csh.js → index-77nxk6ay.js} +2 -2
  101. package/dist/{index-dnn9z96q.js → index-a0zzh8ak.js} +3 -3
  102. package/dist/{index-kmpzj1cq.js → index-a3wma1hk.js} +1 -1
  103. package/dist/{index-j8aw2c0e.js → index-bakgedh8.js} +35 -7
  104. package/dist/index-bhb950qs.js +1145 -0
  105. package/dist/{index-tgzhq07n.js → index-cvda079a.js} +1 -1
  106. package/dist/{index-n2gre124.js → index-fa4wg312.js} +4 -4
  107. package/dist/{index-zp4jpkp0.js → index-fk18k56k.js} +2 -2
  108. package/dist/{index-afjvjyck.js → index-g2j7pnak.js} +2 -134
  109. package/dist/index-g95fk660.js +116 -0
  110. package/dist/{index-r5c4fedv.js → index-h2fhjqy7.js} +2 -1
  111. package/dist/{index-sybedc8b.js → index-hbd32c6a.js} +23 -94
  112. package/dist/{index-fyphpknh.js → index-hp9d77wk.js} +1 -1
  113. package/dist/index-jd470k6q.js +109 -0
  114. package/dist/{index-b2bz0kdm.js → index-kb8styz3.js} +4 -3
  115. package/dist/{index-0c419yx7.js → index-kemm0ej5.js} +12 -9
  116. package/dist/{index-db2spkv1.js → index-ptn0g0gj.js} +3 -3
  117. package/dist/{index-w575evhq.js → index-r4r70zmh.js} +1 -1
  118. package/dist/{index-12m2v2a9.js → index-s4evrmp5.js} +1 -1
  119. package/dist/{index-1khy8y7n.js → index-t1sr4aks.js} +3 -3
  120. package/dist/{index-45tdvqa3.js → index-wh0ecvyk.js} +1 -1
  121. package/dist/{index-n53mswt3.js → index-x928baz2.js} +8 -1
  122. package/dist/index-yk4g8805.js +133 -0
  123. package/dist/{index-ygkka6zn.js → index-ywppsaby.js} +28 -5
  124. package/dist/{index-9853ymwb.js → index-za6j7nwy.js} +18 -4
  125. package/dist/internal/bounded-file-read.d.ts +41 -0
  126. package/dist/internal/bounded-file-read.d.ts.map +1 -0
  127. package/dist/internal/exclusive-lock.d.ts +2 -0
  128. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  129. package/dist/internal/with-exclusive-lock.d.ts +4 -2
  130. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  131. package/dist/telegram/broadcast-delivery.d.ts +23 -0
  132. package/dist/telegram/broadcast-delivery.d.ts.map +1 -0
  133. package/dist/telegram/broadcast-failure.d.ts +22 -0
  134. package/dist/telegram/broadcast-failure.d.ts.map +1 -0
  135. package/dist/telegram/broadcast-state.d.ts +6 -3
  136. package/dist/telegram/broadcast-state.d.ts.map +1 -1
  137. package/dist/telegram/broadcast.d.ts +10 -5
  138. package/dist/telegram/broadcast.d.ts.map +1 -1
  139. package/dist/tools/cli/format.d.ts.map +1 -1
  140. package/dist/tools/cli/invoke.d.ts +2 -2
  141. package/dist/tools/cli/invoke.d.ts.map +1 -1
  142. package/dist/tools/cli/publication-assets.d.ts +10 -0
  143. package/dist/tools/cli/publication-assets.d.ts.map +1 -0
  144. package/dist/tools/cli/publication-contract.d.ts +75 -0
  145. package/dist/tools/cli/publication-contract.d.ts.map +1 -0
  146. package/dist/tools/cli/publication-control.d.ts +4 -0
  147. package/dist/tools/cli/publication-control.d.ts.map +1 -0
  148. package/dist/tools/cli/publication-storage.d.ts +32 -0
  149. package/dist/tools/cli/publication-storage.d.ts.map +1 -0
  150. package/dist/tools/cli/publication.d.ts +35 -0
  151. package/dist/tools/cli/publication.d.ts.map +1 -0
  152. package/dist/tools/cli/update.d.ts.map +1 -1
  153. package/dist/tools/connections/define.d.ts.map +1 -1
  154. package/dist/tools/connections/error-projection.d.ts +4 -0
  155. package/dist/tools/connections/error-projection.d.ts.map +1 -0
  156. package/dist/tools/connections/errors.d.ts +24 -8
  157. package/dist/tools/connections/errors.d.ts.map +1 -1
  158. package/dist/tools/connections/limits.d.ts +11 -31
  159. package/dist/tools/connections/limits.d.ts.map +1 -1
  160. package/dist/tools/connections/mcp-client.d.ts +6 -4
  161. package/dist/tools/connections/mcp-client.d.ts.map +1 -1
  162. package/dist/tools/connections/mcp.d.ts.map +1 -1
  163. package/dist/tools/connections/openapi.d.ts.map +1 -1
  164. package/dist/tools/connections/operation-limits.d.ts +25 -0
  165. package/dist/tools/connections/operation-limits.d.ts.map +1 -0
  166. package/dist/tools/connections/sse-frames.d.ts +11 -2
  167. package/dist/tools/connections/sse-frames.d.ts.map +1 -1
  168. package/dist/tools/connections/sse-session.d.ts +15 -2
  169. package/dist/tools/connections/sse-session.d.ts.map +1 -1
  170. package/dist/tools/connections/types.d.ts +19 -1
  171. package/dist/tools/connections/types.d.ts.map +1 -1
  172. package/dist/tools/execute-result.d.ts.map +1 -1
  173. package/dist/tools/execute.d.ts.map +1 -1
  174. package/dist/tools/internal/observe-hook.d.ts +3 -0
  175. package/dist/tools/internal/observe-hook.d.ts.map +1 -0
  176. package/dist/tools/internal/surface-projector.d.ts +2 -1
  177. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  178. package/dist/tools/mcp/mount.d.ts +2 -2
  179. package/dist/tools/mcp/mount.d.ts.map +1 -1
  180. package/dist/tools/mcp/prepare.d.ts +4 -5
  181. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  182. package/dist/tools/mcp/register.d.ts +4 -1
  183. package/dist/tools/mcp/register.d.ts.map +1 -1
  184. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  185. package/dist/tools/remote.d.ts.map +1 -1
  186. package/dist/tools/runtime-tool-execution.d.ts +65 -0
  187. package/dist/tools/runtime-tool-execution.d.ts.map +1 -0
  188. package/dist/tools/runtime-tool-mcp.d.ts +27 -0
  189. package/dist/tools/runtime-tool-mcp.d.ts.map +1 -0
  190. package/dist/tools/runtime-tool.d.ts +9 -60
  191. package/dist/tools/runtime-tool.d.ts.map +1 -1
  192. package/dist/tools/surface.d.ts +12 -14
  193. package/dist/tools/surface.d.ts.map +1 -1
  194. package/llms/application.2.txt +221 -44
  195. package/llms/application.3.txt +3 -1
  196. package/llms/application.txt +1 -1
  197. package/llms/cli.2.txt +144 -1
  198. package/llms/cli.txt +123 -104
  199. package/llms/contract.txt +1 -1
  200. package/llms/files-packaging.txt +27 -0
  201. package/llms/process.txt +63 -1
  202. package/llms/server.4.txt +4 -1
  203. package/llms/server.5.txt +1 -0
  204. package/llms/stitchkit.2.txt +14 -0
  205. package/llms/stitchkit.txt +6 -4
  206. package/llms/telegram.txt +64 -2
  207. package/llms/tools-connections.txt +3 -0
  208. package/llms/tools-mcp.txt +29 -0
  209. package/llms/tools.2.txt +59 -0
  210. package/llms/tools.3.txt +1 -0
  211. package/llms/tools.txt +11 -52
  212. package/llms/upgrading-0.37.0-0.44.0.txt +444 -0
  213. package/llms/{upgrading-0.44.0-0.60.0.txt → upgrading-0.44.0-0.61.0.txt} +140 -271
  214. package/llms/{upgrading-0.61.0-0.74.0.txt → upgrading-0.62.0-0.80.0.txt} +217 -140
  215. package/llms/{upgrading-0.75.0-0.103.0.txt → upgrading-0.81.0-0.104.0.txt} +154 -217
  216. package/llms/upgrading.txt +4 -4
  217. package/llms-full.txt +745 -60
  218. package/llms.txt +14 -12
  219. package/native-assets.json +8 -0
  220. package/package.json +12 -3
  221. package/dist/index-wykebpn9.js +0 -221
  222. package/llms/upgrading-0.37.0.txt +0 -176
  223. package/dist/{index-69nvze1q.js → index-pptyv13k.js} +3 -3
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  projectRuntimeTool
3
- } from "./index-x87j7csh.js";
3
+ } from "./index-77nxk6ay.js";
4
4
 
5
5
  // src/tools/runtime-tool.ts
6
6
  function defineRuntimeTool2(definition) {
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  AppError2
3
- } from "./index-n53mswt3.js";
3
+ } from "./index-x928baz2.js";
4
4
  import {
5
5
  toolErrorFromResult
6
- } from "./index-m2xqkv55.js";
6
+ } from "./index-2vnh05w4.js";
7
7
  import {
8
8
  assertUniqueToolName
9
- } from "./index-x87j7csh.js";
9
+ } from "./index-77nxk6ay.js";
10
10
  import {
11
11
  collectTools2,
12
12
  createToolRunner
13
- } from "./index-r956rndn.js";
13
+ } from "./index-2hyavjjj.js";
14
14
 
15
15
  // src/tools/invoker.ts
16
16
  function createToolInvoker2(services, config) {
@@ -14,13 +14,13 @@ import {
14
14
  import {
15
15
  ToolExecutionControlError2,
16
16
  isToolExecutionControlError2
17
- } from "./index-m2xqkv55.js";
17
+ } from "./index-2vnh05w4.js";
18
18
  import {
19
19
  agentDurableEventId2
20
20
  } from "./index-mnkk1ffz.js";
21
21
  import {
22
22
  createLocalStepDurability2
23
- } from "./index-69nvze1q.js";
23
+ } from "./index-pptyv13k.js";
24
24
  import {
25
25
  isAgentToolError2,
26
26
  createToolDurabilityContext
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AppError2
3
- } from "./index-n53mswt3.js";
3
+ } from "./index-x928baz2.js";
4
4
  import {
5
5
  contractMethodFields
6
6
  } from "./index-1bx1xv1k.js";
@@ -9,109 +9,6 @@ import {
9
9
  callRuntimeHandler
10
10
  } from "./index-9jfdm5tg.js";
11
11
 
12
- // src/server/middleware/cors.ts
13
- var DEFAULT_CORS_ALLOW_HEADERS2 = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
14
- var DEFAULT_CORS_EXPOSE_HEADERS2 = "Content-Disposition, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified, X-Request-Id, X-Build-Id";
15
- function assertCorsConfig(config) {
16
- if (config.credentials && (config.origin === undefined || config.origin === "*")) {
17
- throw new Error("[stitchkit] cors: `credentials: true` cannot be combined with a wildcard origin. " + "Set `origin` to an explicit string or list.");
18
- }
19
- if (config.origin === undefined) {
20
- throw new Error("[stitchkit] cors: `origin` is required. Pass an explicit origin (or list), or '*' to deliberately allow every origin — omit `cors` entirely to emit no CORS headers.");
21
- }
22
- if (Array.isArray(config.origin) && config.origin.length === 0) {
23
- throw new Error("[stitchkit] cors: `origin` cannot be an empty list. Pass explicit origins, or '*' to deliberately allow every origin.");
24
- }
25
- }
26
- function resolveOrigin(config, requestOrigin) {
27
- if (config.origin === undefined)
28
- return;
29
- if (config.origin === "*") {
30
- return "*";
31
- }
32
- if (Array.isArray(config.origin)) {
33
- if (!requestOrigin)
34
- return;
35
- const lower = requestOrigin.toLowerCase();
36
- return config.origin.some((o) => o.toLowerCase() === lower) ? requestOrigin : undefined;
37
- }
38
- return config.origin;
39
- }
40
- function isOriginAllowed(config, requestOrigin) {
41
- if (!config || config.origin === undefined || config.origin === "*")
42
- return false;
43
- if (!requestOrigin || requestOrigin === "null")
44
- return false;
45
- const lower = requestOrigin.toLowerCase();
46
- const allowed = Array.isArray(config.origin) ? config.origin : [config.origin];
47
- return allowed.some((origin) => origin.toLowerCase() === lower);
48
- }
49
- function corsHeaders2(config, requestOrigin) {
50
- const allowOrigin = resolveOrigin(config, requestOrigin);
51
- const headers = {
52
- "Access-Control-Allow-Methods": config.methods ?? "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS",
53
- "Access-Control-Allow-Headers": config.headers ?? DEFAULT_CORS_ALLOW_HEADERS2
54
- };
55
- const expose = Array.isArray(config.exposeHeaders) ? config.exposeHeaders.join(", ") : config.exposeHeaders ?? DEFAULT_CORS_EXPOSE_HEADERS2;
56
- if (expose !== "") {
57
- headers["Access-Control-Expose-Headers"] = expose;
58
- }
59
- if (allowOrigin !== undefined) {
60
- headers["Access-Control-Allow-Origin"] = allowOrigin;
61
- if (config.credentials) {
62
- headers["Access-Control-Allow-Credentials"] = "true";
63
- }
64
- }
65
- if (Array.isArray(config.origin)) {
66
- headers.Vary = "Origin";
67
- }
68
- return headers;
69
- }
70
- function corsPreflightResponse2(config, req) {
71
- return new Response(null, {
72
- status: 204,
73
- headers: corsHeaders2(config, req.headers.get("origin"))
74
- });
75
- }
76
- function requestCorsHeaders(cors, req) {
77
- if (!cors)
78
- return {};
79
- return corsHeaders2(cors, req.headers.get("origin"));
80
- }
81
- function applyCors(res, cors, req) {
82
- const extra = requestCorsHeaders(cors, req);
83
- if (Object.keys(extra).length === 0)
84
- return res;
85
- try {
86
- for (const [key, value] of Object.entries(extra))
87
- setCorsHeader(res.headers, key, value);
88
- return res;
89
- } catch {
90
- const headers = new Headers(res.headers);
91
- for (const [key, value] of Object.entries(extra))
92
- setCorsHeader(headers, key, value);
93
- return new Response(res.body, {
94
- status: res.status,
95
- statusText: res.statusText,
96
- headers
97
- });
98
- }
99
- }
100
- function setCorsHeader(headers, key, value) {
101
- if (key !== "Vary") {
102
- headers.set(key, value);
103
- return;
104
- }
105
- const existing = headers.get("Vary");
106
- if (existing === null || existing.trim() === "") {
107
- headers.set("Vary", value);
108
- return;
109
- }
110
- const present = existing.split(",").some((field) => field.trim().toLowerCase() === "origin");
111
- if (!present)
112
- headers.set("Vary", `${existing}, ${value}`);
113
- }
114
-
115
12
  // src/server/implement.ts
116
13
  function isStreamingImplementation(value) {
117
14
  return typeof value === "object" && value !== null && "kind" in value && value.kind === "stitchkit.multipart.stream";
@@ -229,38 +126,9 @@ function createScopedImplement2() {
229
126
  return Object.assign(implementScoped, { stream, declare });
230
127
  }
231
128
 
232
- // src/server/process-signal-common.ts
233
- var DEFAULT_PROCESS_SIGNALS = ["SIGINT", "SIGTERM"];
234
- var defaultSignalSource = {
235
- on: (signal, handler) => {
236
- process.on(signal, handler);
237
- },
238
- off: (signal, handler) => {
239
- process.off(signal, handler);
240
- },
241
- raiseDefault: (signal) => {
242
- if (process.listenerCount(signal) > 0)
243
- return false;
244
- process.kill(process.pid, signal);
245
- return true;
246
- }
247
- };
248
- function reportSignalError(phase, error, onError) {
249
- try {
250
- onError?.(phase, error);
251
- } catch {}
252
- }
253
- function guardSignalCallback(run, phase, onError) {
254
- try {
255
- run();
256
- } catch (error) {
257
- reportSignalError(phase, error, onError);
258
- }
259
- }
260
-
261
129
  // src/internal/media-type.ts
262
130
  function mediaTypeEssence(contentType) {
263
131
  return (contentType ?? "").split(";", 1)[0]?.trim().toLowerCase() ?? "";
264
132
  }
265
133
 
266
- export { DEFAULT_CORS_ALLOW_HEADERS2, DEFAULT_CORS_EXPOSE_HEADERS2, assertCorsConfig, isOriginAllowed, corsHeaders2, corsPreflightResponse2, requestCorsHeaders, applyCors, defineMultipartStream2, createMultipartStream2, contractOnlyService, bindContract, implement2, createImplement2, createScopedImplement2, DEFAULT_PROCESS_SIGNALS, defaultSignalSource, reportSignalError, guardSignalCallback, mediaTypeEssence };
134
+ export { defineMultipartStream2, createMultipartStream2, contractOnlyService, bindContract, implement2, createImplement2, createScopedImplement2, mediaTypeEssence };
@@ -0,0 +1,116 @@
1
+ import {
2
+ attemptExclusiveLock
3
+ } from "./index-za6j7nwy.js";
4
+
5
+ // src/internal/with-exclusive-lock.ts
6
+ class ExclusiveLockError2 extends Error {
7
+ code;
8
+ label;
9
+ holder;
10
+ name = "ExclusiveLockError";
11
+ constructor(code, label, holder, message, options) {
12
+ super(message, options);
13
+ this.code = code;
14
+ this.label = label;
15
+ this.holder = holder;
16
+ }
17
+ }
18
+ var DEFAULT_TIMEOUT_MS = 1e4;
19
+ var DEFAULT_OWNERLESS_GRACE_MS = 5000;
20
+ var FIRST_RETRY_MS = 10;
21
+ var MAX_RETRY_MS = 100;
22
+ function nonNegative(name, value, fallback) {
23
+ if (value === undefined)
24
+ return fallback;
25
+ if (!Number.isFinite(value) || value < 0) {
26
+ throw new RangeError(`[stitchkit] withExclusiveLock: ${name} must be a finite number ≥ 0`);
27
+ }
28
+ return value;
29
+ }
30
+ function describeHolder(holder) {
31
+ if (!holder)
32
+ return "a holder that recorded no owner";
33
+ const machine = holder.machine === undefined ? "" : `, machine ${holder.machine}`;
34
+ return `pid ${holder.pid} on ${holder.host}${machine} since ${holder.acquiredAt}`;
35
+ }
36
+ function describeEvidence(diagnosis) {
37
+ if (!diagnosis)
38
+ return "";
39
+ const identity = diagnosis.identity === undefined ? "" : `, identity ${diagnosis.identity}`;
40
+ return ` (${diagnosis.attribution}, liveness ${diagnosis.liveness}${identity})`;
41
+ }
42
+ function pause(ms, signal) {
43
+ return new Promise((resolve) => {
44
+ const done = () => {
45
+ clearTimeout(timer);
46
+ signal?.removeEventListener("abort", done);
47
+ resolve();
48
+ };
49
+ const timer = setTimeout(done, ms);
50
+ signal?.addEventListener("abort", done, { once: true });
51
+ });
52
+ }
53
+ async function withExclusiveLock2(path, run, options = {}) {
54
+ const label = options.label ?? path;
55
+ const timeoutMs = nonNegative("timeoutMs", options.timeoutMs, DEFAULT_TIMEOUT_MS);
56
+ const ownerlessGraceMs = options.ownerlessGraceMs === null ? null : nonNegative("ownerlessGraceMs", options.ownerlessGraceMs, DEFAULT_OWNERLESS_GRACE_MS);
57
+ const mode = options.mode ?? 384;
58
+ if (!Number.isInteger(mode) || mode < 0 || mode > 511)
59
+ throw new RangeError("[stitchkit] withExclusiveLock: mode must be permission bits from 0000 to 0777");
60
+ const { signal } = options;
61
+ const deadline = performance.now() + timeoutMs;
62
+ let delay = FIRST_RETRY_MS;
63
+ for (;; ) {
64
+ if (signal?.aborted) {
65
+ throw new ExclusiveLockError2("LOCK_ABORTED", label, null, `[stitchkit] waiting for the lock on "${label}" was cancelled`, { cause: signal.reason });
66
+ }
67
+ const attempt = await attemptExclusiveLock(path, {
68
+ mode,
69
+ reclaim: true,
70
+ signal,
71
+ ownerlessGraceMs,
72
+ ...options.machineIdentity !== undefined && {
73
+ machineIdentity: options.machineIdentity
74
+ }
75
+ });
76
+ if ("held" in attempt) {
77
+ const { held } = attempt;
78
+ let result;
79
+ try {
80
+ if (signal?.aborted) {
81
+ throw new ExclusiveLockError2("LOCK_ABORTED", label, null, `[stitchkit] waiting for the lock on "${label}" was cancelled`, { cause: signal.reason });
82
+ }
83
+ result = await run({
84
+ path: held.path,
85
+ owner: held.owner,
86
+ reclaimed: held.reclaimed,
87
+ async assertHeld() {
88
+ try {
89
+ await held.assertHeld();
90
+ } catch (cause) {
91
+ throw new ExclusiveLockError2("LOCK_LOST", label, held.owner, `[stitchkit] the held lock on "${label}" changed or was released`, { cause });
92
+ }
93
+ }
94
+ });
95
+ } catch (error) {
96
+ await held.release().catch(() => {
97
+ return;
98
+ });
99
+ throw error;
100
+ }
101
+ await held.release();
102
+ return result;
103
+ }
104
+ if (signal?.aborted)
105
+ continue;
106
+ const remaining = deadline - performance.now();
107
+ if (remaining <= 0) {
108
+ const holder = attempt.diagnosis?.owner ?? null;
109
+ throw new ExclusiveLockError2("LOCK_TIMEOUT", label, holder, `[stitchkit] the lock on "${label}" is held by ${describeHolder(holder)}${describeEvidence(attempt.diagnosis)}; gave up after ${timeoutMs} ms`, { cause: attempt.diagnosis?.cause ?? attempt.error });
110
+ }
111
+ await pause(Math.min(delay * (0.5 + Math.random() / 2), remaining), signal);
112
+ delay = Math.min(delay * 2, MAX_RETRY_MS);
113
+ }
114
+ }
115
+
116
+ export { ExclusiveLockError2, withExclusiveLock2 };
@@ -9,7 +9,8 @@ var ContractStreamFrameSchema2 = z.discriminatedUnion("type", [
9
9
  code: z.string(),
10
10
  message: z.string().optional(),
11
11
  details: z.unknown().optional(),
12
- hint: z.string().optional()
12
+ hint: z.string().optional(),
13
+ retryable: z.boolean().optional()
13
14
  }).strict()
14
15
  }).strict(),
15
16
  z.object({ type: z.literal("end") }).strict()
@@ -3,16 +3,20 @@ import {
3
3
  ManagedFileRefSchema2
4
4
  } from "./index-xqhede6x.js";
5
5
  import {
6
- AtomicFilePublicationError2,
7
- publishAtomicFile
8
- } from "./index-8a9ksm91.js";
6
+ BoundedFileReadError,
7
+ readBoundedFile
8
+ } from "./index-jd470k6q.js";
9
9
  import {
10
10
  isWithinDir2
11
11
  } from "./index-5cc6r990.js";
12
+ import {
13
+ AtomicFilePublicationError2,
14
+ publishAtomicFile
15
+ } from "./index-8a9ksm91.js";
12
16
 
13
17
  // src/files/boundary.ts
14
18
  import { randomUUID } from "node:crypto";
15
- import { constants as constants2 } from "node:fs";
19
+ import { constants } from "node:fs";
16
20
  import { mkdir, open as open2, realpath, stat, unlink } from "node:fs/promises";
17
21
  import { basename as basename2, dirname, resolve } from "node:path";
18
22
 
@@ -71,40 +75,6 @@ function inspectedRef(path, size, inspection, fallback = {}) {
71
75
  }
72
76
  return parsed.data;
73
77
  }
74
- async function readHandle(handle, maxBytes, signal) {
75
- const chunks = [];
76
- let total = 0;
77
- let ended = false;
78
- while (!ended) {
79
- const capacity = Math.min(64 * 1024, maxBytes + 1 - total);
80
- if (capacity <= 0)
81
- throw new ManagedFileError2("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
82
- const chunk = new Uint8Array(capacity);
83
- let filled = 0;
84
- while (filled < capacity) {
85
- signal?.throwIfAborted();
86
- const { bytesRead } = await handle.read(chunk, filled, capacity - filled);
87
- if (bytesRead === 0) {
88
- ended = true;
89
- break;
90
- }
91
- filled += bytesRead;
92
- total += bytesRead;
93
- if (total > maxBytes)
94
- throw new ManagedFileError2("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
95
- }
96
- if (filled > 0)
97
- chunks.push(chunk.subarray(0, filled));
98
- }
99
- signal?.throwIfAborted();
100
- const bytes = new Uint8Array(total);
101
- let offset = 0;
102
- for (const chunk of chunks) {
103
- bytes.set(chunk, offset);
104
- offset += chunk.byteLength;
105
- }
106
- return bytes;
107
- }
108
78
  async function writeChunk(handle, chunk) {
109
79
  let offset = 0;
110
80
  while (offset < chunk.byteLength) {
@@ -161,67 +131,26 @@ async function writeSource(handle, source, maxBytes, inspectionBytes, signal) {
161
131
  }
162
132
 
163
133
  // src/files/read.ts
164
- import { constants } from "node:fs";
165
134
  import { open } from "node:fs/promises";
166
135
  import { basename } from "node:path";
167
136
  async function readManagedDescriptor(target, path, maxBytes, options, inspection, openDescriptor = open) {
168
- if (options.rejectSymlinks && !constants.O_NOFOLLOW)
169
- throw new ManagedFileError2("FILE_UNSUPPORTED", "strict leaf nofollow is unavailable");
170
- const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
171
- const handle = await openDescriptor(target, flags);
172
- let failed = false;
173
- let failure;
174
137
  let source;
175
138
  try {
176
- options.signal?.throwIfAborted();
177
- const before = await handle.stat();
178
- if (!before.isFile())
179
- throw new ManagedFileError2("FILE_NOT_REGULAR", "managed path is not a regular file");
180
- if (options.singleLink && before.nlink !== 1)
181
- throw new ManagedFileError2("FILE_UNSAFE_LINK", "managed file has multiple links");
182
- if (before.size > maxBytes)
183
- throw new ManagedFileError2("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
184
- const bytes = await readHandle(handle, maxBytes, options.signal);
185
- const after = options.stable || options.observe ? await handle.stat() : before;
186
- if (options.stable && (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.nlink !== after.nlink || bytes.length !== after.size))
187
- throw new ManagedFileError2("FILE_CHANGED", "managed file changed during read");
188
- options.signal?.throwIfAborted();
189
- const inspected = await inspectFile(inspection.inspect, {
190
- prefix: bytes.slice(0, inspection.bytes),
191
- name: basename(path)
192
- }, inspection.timeoutMs, options.signal);
193
- source = {
194
- ref: inspectedRef(path, bytes.byteLength, inspected),
195
- bytes,
196
- ...options.observe ? {
197
- observation: {
198
- dev: after.dev,
199
- ino: after.ino,
200
- size: after.size,
201
- nlink: after.nlink,
202
- mtimeMs: after.mtimeMs,
203
- ctimeMs: after.ctimeMs
204
- }
205
- } : {}
206
- };
139
+ source = await readBoundedFile(target, maxBytes, options, openDescriptor);
207
140
  } catch (error) {
208
- failed = true;
209
- failure = error;
210
- } finally {
211
- try {
212
- await handle.close();
213
- } catch (error) {
214
- if (!failed) {
215
- failed = true;
216
- failure = error;
217
- }
218
- }
141
+ if (error instanceof BoundedFileReadError)
142
+ throw new ManagedFileError2(error.code, error.message, { cause: error });
143
+ throw error;
219
144
  }
220
- if (failed)
221
- throw failure;
222
- if (source === undefined)
223
- throw new Error("Read completed without a result");
224
- return source;
145
+ const inspected = await inspectFile(inspection.inspect, {
146
+ prefix: source.bytes.slice(0, inspection.bytes),
147
+ name: basename(path)
148
+ }, inspection.timeoutMs, options.signal);
149
+ return {
150
+ ref: inspectedRef(path, source.bytes.byteLength, inspected),
151
+ bytes: source.bytes,
152
+ ...options.observe && { observation: source.observation }
153
+ };
225
154
  }
226
155
 
227
156
  // src/files/boundary.ts
@@ -230,7 +159,7 @@ var DEFAULT_INSPECTION_BYTES = 64 * 1024;
230
159
  var DEFAULT_INSPECTION_TIMEOUT_MS = 15000;
231
160
  var nofollowFlag;
232
161
  var noFollow = () => {
233
- nofollowFlag ??= constants2.O_NOFOLLOW ?? 0;
162
+ nofollowFlag ??= constants.O_NOFOLLOW ?? 0;
234
163
  return nofollowFlag;
235
164
  };
236
165
 
@@ -387,7 +316,7 @@ async function createManagedFileBoundary2(config) {
387
316
  let committed = false;
388
317
  let size = 0;
389
318
  try {
390
- handle = await open2(temporary, constants2.O_CREAT | constants2.O_EXCL | constants2.O_WRONLY | noFollow(), 384);
319
+ handle = await open2(temporary, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | noFollow(), 384);
391
320
  const written = await writeSource(handle, source, maxBytes, inspectionBytes, options.signal);
392
321
  size = written.size;
393
322
  if (options.durable)
@@ -5,7 +5,7 @@ import {
5
5
  AppError2,
6
6
  STITCH_ERROR_STATUS2,
7
7
  isStitchErrorCode2
8
- } from "./index-n53mswt3.js";
8
+ } from "./index-x928baz2.js";
9
9
  import {
10
10
  bytesToBase64Url,
11
11
  base64UrlToBytes
@@ -0,0 +1,109 @@
1
+ // src/internal/bounded-file-read.ts
2
+ import { constants } from "node:fs";
3
+ import { open } from "node:fs/promises";
4
+
5
+ class BoundedFileReadError extends Error {
6
+ code;
7
+ observation;
8
+ constructor(code, message, observation) {
9
+ super(message);
10
+ this.code = code;
11
+ this.observation = observation;
12
+ this.name = "BoundedFileReadError";
13
+ }
14
+ }
15
+ var observationOf = (info) => ({
16
+ dev: info.dev,
17
+ ino: info.ino,
18
+ size: info.size,
19
+ nlink: info.nlink,
20
+ mtimeMs: info.mtimeMs,
21
+ ctimeMs: info.ctimeMs
22
+ });
23
+ async function readBoundedFile(target, maxBytes, options = {}, openDescriptor = open) {
24
+ if (options.rejectSymlinks && !constants.O_NOFOLLOW)
25
+ throw new BoundedFileReadError("FILE_UNSUPPORTED", "strict leaf nofollow is unavailable");
26
+ options.signal?.throwIfAborted();
27
+ const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
28
+ const handle = await openDescriptor(target, flags);
29
+ let failed = false;
30
+ let failure;
31
+ let before;
32
+ let source;
33
+ try {
34
+ options.signal?.throwIfAborted();
35
+ before = await handle.stat();
36
+ if (!before.isFile())
37
+ throw new BoundedFileReadError("FILE_NOT_REGULAR", "managed path is not a regular file");
38
+ if (options.singleLink && before.nlink !== 1)
39
+ throw new BoundedFileReadError("FILE_UNSAFE_LINK", "managed file has multiple links");
40
+ if (before.size > maxBytes)
41
+ throw new BoundedFileReadError("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
42
+ const bytes = await readHandle(handle, maxBytes, options.signal);
43
+ const after = await handle.stat();
44
+ if (options.stable && (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.nlink !== after.nlink || bytes.length !== after.size))
45
+ throw new BoundedFileReadError("FILE_CHANGED", "managed file changed during read");
46
+ options.signal?.throwIfAborted();
47
+ source = { bytes, observation: observationOf(after) };
48
+ } catch (error) {
49
+ failed = true;
50
+ failure = error;
51
+ if (error instanceof BoundedFileReadError && error.code === "FILE_TOO_LARGE" && before) {
52
+ const after = await handle.stat().catch(() => {
53
+ return;
54
+ });
55
+ if (after?.isFile() && after.dev === before.dev && after.ino === before.ino && after.nlink === 1)
56
+ failure = new BoundedFileReadError(error.code, error.message, observationOf(after));
57
+ }
58
+ } finally {
59
+ try {
60
+ await handle.close();
61
+ } catch (error) {
62
+ if (!failed) {
63
+ failed = true;
64
+ failure = error;
65
+ }
66
+ }
67
+ }
68
+ if (failed)
69
+ throw failure;
70
+ if (source === undefined)
71
+ throw new Error("Read completed without a result");
72
+ return source;
73
+ }
74
+ async function readHandle(handle, maxBytes, signal) {
75
+ const chunks = [];
76
+ let total = 0;
77
+ let ended = false;
78
+ while (!ended) {
79
+ const capacity = Math.min(64 * 1024, maxBytes + 1 - total);
80
+ if (capacity <= 0)
81
+ throw new BoundedFileReadError("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
82
+ const chunk = new Uint8Array(capacity);
83
+ let filled = 0;
84
+ while (filled < capacity) {
85
+ signal?.throwIfAborted();
86
+ const { bytesRead } = await handle.read(chunk, filled, capacity - filled);
87
+ if (bytesRead === 0) {
88
+ ended = true;
89
+ break;
90
+ }
91
+ filled += bytesRead;
92
+ total += bytesRead;
93
+ if (total > maxBytes)
94
+ throw new BoundedFileReadError("FILE_TOO_LARGE", `file exceeds the ${maxBytes}-byte cap`);
95
+ }
96
+ if (filled > 0)
97
+ chunks.push(chunk.subarray(0, filled));
98
+ }
99
+ signal?.throwIfAborted();
100
+ const bytes = new Uint8Array(total);
101
+ let offset = 0;
102
+ for (const chunk of chunks) {
103
+ bytes.set(chunk, offset);
104
+ offset += chunk.byteLength;
105
+ }
106
+ return bytes;
107
+ }
108
+
109
+ export { BoundedFileReadError, readBoundedFile };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AppError2
3
- } from "./index-n53mswt3.js";
3
+ } from "./index-x928baz2.js";
4
4
  import {
5
5
  zodIssues2,
6
6
  formatZodError2
@@ -28,7 +28,7 @@ function recordedErrorMessage(code, envelopeMessage, thrown) {
28
28
  }
29
29
  return envelopeMessage;
30
30
  }
31
- function normalizeError2(err) {
31
+ function normalizeError2(err, options = {}) {
32
32
  if (AppError2.is(err)) {
33
33
  if (err.code === "REALTIME_CONTRACT_VIOLATION") {
34
34
  return new AppError2("REALTIME_CONTRACT_VIOLATION", "Realtime contract violation", 500);
@@ -40,7 +40,8 @@ function normalizeError2(err) {
40
40
  issues: zodIssues2(err).slice(0, MAX_DETAIL_ISSUES)
41
41
  });
42
42
  }
43
- console.error("[stitchkit] unhandled error:", err);
43
+ if (options.logUnexpected !== false)
44
+ console.error("[stitchkit] unhandled error:", err);
44
45
  return new AppError2("INTERNAL_SERVER_ERROR", "Internal server error", 500);
45
46
  }
46
47
  function strippedPaths(before, after, prefix) {