stitchkit 0.101.1 → 0.101.3

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.
package/CHANGELOG.md CHANGED
@@ -15,6 +15,39 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.101.3] — 2026-09-29
19
+
20
+ ### Fixed
21
+
22
+ - **`stitchkit/tools/connections`** — a discovered MCP command whose tool
23
+ answers with no content parts (a tool without an output contract) prints
24
+ `null` on the CLI and exits `0`. It printed the whole envelope — the
25
+ server's `_meta` and an empty `content` — as if that were the answer; a
26
+ failed call with no parts now fails as `UPSTREAM_TOOL_ERROR` without
27
+ relaying that envelope either.
28
+
29
+ ## [0.101.2] — 2026-09-29
30
+
31
+ ### Added
32
+
33
+ - **`stitchkit`** — `onUploadProgress` in React Native and Expo: the body goes
34
+ to the platform's `XMLHttpRequest` as the client built it — the `FormData`
35
+ itself, so a `{ uri, name, type }` file still streams from disk — and its
36
+ upload events are the count. An injected `fetch` there is refused with a
37
+ `TypeError` at the call. → ADR 0217.
38
+ - **`stitchkit`** — `uploadInChunks` takes any `ChunkSource` (`size` and
39
+ `slice(start, end)`), not only a DOM `Blob`: an Expo `File` passes without a
40
+ cast, and a part's `bytes` is what its `slice` returns. New type
41
+ `ChunkSource`. → ADR 0217.
42
+ - **`stitchkit/files`** — `CHUNK_SPOOL_ERROR_CODES` and
43
+ `isChunkSpoolErrorCode`, so an application that maps error codes onto its
44
+ own recognises a spool refusal without its own list.
45
+
46
+ ### Changed
47
+
48
+ - **`stitchkit/files`** — `ChunkSpoolAssembly.chunkPaths` is a `string[]`, a
49
+ fresh array per `assemble`, so it passes to an API that takes one.
50
+
18
51
  ## [0.101.1] — 2026-09-29
19
52
 
20
53
  ### Added
@@ -35,16 +35,29 @@ export interface ChunkedUploadStart {
35
35
  readonly chunkBytes: number;
36
36
  readonly chunkCount: number;
37
37
  }
38
- export interface ChunkedUploadPart {
38
+ /**
39
+ * What the driver reads a file through: its size and a slice per part. A `Blob`
40
+ * is one; so is a platform file that is not a DOM `Blob` — an Expo `File`, a
41
+ * handle over a file on disk — and the part is whatever its `slice` returns.
42
+ */
43
+ export interface ChunkSource<TPart = Blob> {
44
+ readonly size: number;
45
+ slice(start: number, end: number): TPart;
46
+ }
47
+ export interface ChunkedUploadPart<TPart = Blob> {
39
48
  readonly uploadId: string;
40
49
  readonly index: number;
41
- readonly bytes: Blob;
50
+ /** The file's `slice(start, end)` for this part. */
51
+ readonly bytes: TPart;
42
52
  }
43
- export interface ChunkedUploadConfig<TResult> {
44
- readonly file: Blob;
53
+ export interface ChunkedUploadConfig<TResult, TPart = Blob> {
54
+ readonly file: ChunkSource<TPart>;
45
55
  /** Bytes per part; every part but the last is exactly this long. */
46
56
  readonly chunkBytes: number;
47
- /** Default `crypto.randomUUID()`. Pass one to resume the same upload. */
57
+ /**
58
+ * Default `crypto.randomUUID()`, fresh per call. Pass a stable one — the id
59
+ * of the app's own job — to resume after a restart instead of sending again.
60
+ */
48
61
  readonly uploadId?: string;
49
62
  readonly signal?: AbortSignal;
50
63
  /** Repeats of one part (and of `init`) on a failure that may pass. Default 3. */
@@ -63,7 +76,7 @@ export interface ChunkedUploadConfig<TResult> {
63
76
  readonly finished: TResult;
64
77
  }>;
65
78
  /** Send one part; pass `options` on to the client call as they are. */
66
- readonly chunk: (part: ChunkedUploadPart, options: ClientRequestOptions) => Promise<unknown>;
79
+ readonly chunk: (part: ChunkedUploadPart<TPart>, options: ClientRequestOptions) => Promise<unknown>;
67
80
  readonly finalize: (upload: {
68
81
  readonly uploadId: string;
69
82
  }, options: {
@@ -76,5 +89,5 @@ export interface ChunkedUploadConfig<TResult> {
76
89
  * A caller's abort, a refusal and a conflict are final.
77
90
  */
78
91
  export declare function isRetryableUploadFailure(error: unknown): boolean;
79
- export declare function uploadInChunks<TResult>(config: ChunkedUploadConfig<TResult>): Promise<TResult>;
92
+ export declare function uploadInChunks<TResult, TPart = Blob>(config: ChunkedUploadConfig<TResult, TPart>): Promise<TResult>;
80
93
  //# sourceMappingURL=chunked-upload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chunked-upload.d.ts","sourceRoot":"","sources":["../../src/browser/chunked-upload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAkB,MAAM,0BAA0B,CAAC;AAGrF,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB,CAAC,OAAO;IAC1C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,iFAAiF;IACjF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAChE;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,CACb,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC9B,OAAO,CAAC,SAAS,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7F,QAAQ,CAAC,QAAQ,EAAE,CACjB,MAAM,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EACrC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC9B,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQhE;AAED,wBAAsB,cAAc,CAAC,OAAO,EAC1C,MAAM,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC,CAoDlB"}
1
+ {"version":3,"file":"chunked-upload.d.ts","sourceRoot":"","sources":["../../src/browser/chunked-upload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAkB,MAAM,0BAA0B,CAAC;AAGrF,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,IAAI;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1C;AAED,MAAM,WAAW,iBAAiB,CAAC,KAAK,GAAG,IAAI;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI;IACxD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,iFAAiF;IACjF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAChE;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,CACb,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC9B,OAAO,CAAC,SAAS,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,CACd,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC,EAC9B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,CACjB,MAAM,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EACrC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC9B,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQhE;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,EACxD,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAyDlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"client-executors.d.ts","sourceRoot":"","sources":["../../src/browser/client-executors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAInE,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;AAkEhB,MAAM,MAAM,qBAAqB,GAAG,CAClC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,oBAAoB,KAC3B,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,qBAAqB,CA+DvB;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,EACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GACvC,qBAAqB,CAsHvB"}
1
+ {"version":3,"file":"client-executors.d.ts","sourceRoot":"","sources":["../../src/browser/client-executors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAInE,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;AAkEhB,MAAM,MAAM,qBAAqB,GAAG,CAClC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,oBAAoB,KAC3B,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,qBAAqB,CA+DvB;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,EACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GACvC,qBAAqB,CAyHvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/browser/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/browser/http.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,23 @@
1
1
  /**
2
- * Upload progress for one client call: a delivery wrapper that encodes the
3
- * request body once and reports how much of it has gone out.
2
+ * Upload progress for one client call: a delivery wrapper that reports how
3
+ * much of the request body has gone out.
4
4
  *
5
- * Fetch has no upload event, so the count comes from one of two places:
5
+ * Fetch has no upload event, so the count comes from one of three places:
6
6
  *
7
- * - **stream** (Bun, Node, an injected fetch, a unix socket): the encoded
8
- * body leaves as a `ReadableStream` the transport pulls in 64 KiB pieces,
9
- * with an exact `content-length`. A piece counts when the transport takes it.
10
- * - **xhr** (a browser on its own fetch): `XMLHttpRequest.upload` events, the
11
- * only upload signal every browser has — a streaming request body needs
12
- * HTTP/2 in Chromium and does not exist in Safari.
7
+ * - **stream** (Bun, Node, an injected fetch, a unix socket): the body is
8
+ * encoded once and leaves as a `ReadableStream` the transport pulls in
9
+ * 64 KiB pieces, with an exact `content-length`. A piece counts when the
10
+ * transport takes it.
11
+ * - **xhr** (a browser on its own fetch): the encoded body goes through
12
+ * `XMLHttpRequest`, whose upload events are the only upload signal every
13
+ * browser has — a streaming request body needs HTTP/2 in Chromium and does
14
+ * not exist in Safari.
15
+ * - **native-xhr** (React Native, Expo): the body goes to the platform's
16
+ * `XMLHttpRequest` as the client built it — a `FormData` whose
17
+ * `{ uri, name, type }` file the platform streams from disk, or a JSON
18
+ * string — and its upload events are the count. React Native has neither a
19
+ * streaming request body nor a way to read such a `FormData` back into
20
+ * bytes, and must not load the file into memory to count it.
13
21
  *
14
22
  * Every call of the wrapper is one attempt, so a transport retry starts the
15
23
  * count again under the next attempt number.
@@ -18,9 +26,18 @@ import type { UploadProgress } from '../contract/client-types.js';
18
26
  import type { ClientFetch } from './transport.js';
19
27
  type UploadProgressListener = (progress: UploadProgress) => void;
20
28
  /** Where upload bytes are counted. */
21
- export type UploadProgressRoute = 'stream' | 'xhr';
22
- /** A browser's own fetch counts through XHR; anything injected or non-browser streams. */
29
+ export type UploadProgressRoute = 'stream' | 'xhr' | 'native-xhr';
30
+ /**
31
+ * A browser's own fetch counts through XHR, React Native's through its native
32
+ * XHR; anything else streams. React Native cannot stream a request body, so an
33
+ * injected fetch there is refused rather than reporting a buffered body at once.
34
+ */
23
35
  export declare function uploadProgressRoute(injectedTransport: boolean): UploadProgressRoute;
24
- export declare function withUploadProgress(transport: ClientFetch, listener: UploadProgressListener, route: UploadProgressRoute): ClientFetch;
36
+ /** The route, and for `native-xhr` the body as the caller built it when the transport receives it inside a `Request`. */
37
+ export interface UploadProgressDelivery {
38
+ readonly route: UploadProgressRoute;
39
+ readonly nativeBody?: XMLHttpRequestBodyInit | null;
40
+ }
41
+ export declare function withUploadProgress(transport: ClientFetch, listener: UploadProgressListener, delivery: UploadProgressDelivery): ClientFetch;
25
42
  export {};
26
43
  //# sourceMappingURL=upload-progress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload-progress.d.ts","sourceRoot":"","sources":["../../src/browser/upload-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,KAAK,sBAAsB,GAAG,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;AAEjE,sCAAsC;AACtC,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAInD,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,iBAAiB,EAAE,OAAO,GAAG,mBAAmB,CAInF;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,sBAAsB,EAChC,KAAK,EAAE,mBAAmB,GACzB,WAAW,CAyCb"}
1
+ {"version":3,"file":"upload-progress.d.ts","sourceRoot":"","sources":["../../src/browser/upload-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,KAAK,sBAAsB,GAAG,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;AAEjE,sCAAsC;AACtC,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,KAAK,GAAG,YAAY,CAAC;AASlE;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,iBAAiB,EAAE,OAAO,GAAG,mBAAmB,CAYnF;AAED,yHAAyH;AACzH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CACrD;AAuBD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,sBAAsB,EAChC,QAAQ,EAAE,sBAAsB,GAC/B,WAAW,CAuDb"}
@@ -97,8 +97,9 @@ export interface ClientRequestOptions {
97
97
  /**
98
98
  * Hear the request body leave: first `sentBytes: 0`, then growing values,
99
99
  * last equal to `totalBytes`. Bun and Node stream the encoded body through
100
- * the configured fetch; a browser without an injected fetch sends through
101
- * `XMLHttpRequest`, the one portable source of upload events. Body methods
100
+ * the configured fetch; a browser or React Native without an injected fetch
101
+ * sends through `XMLHttpRequest`, the one portable source of upload events
102
+ * (React Native refuses an injected fetch here). Body methods
102
103
  * only — a `GET`, `HEAD`, `DELETE` or streaming endpoint refuses it.
103
104
  */
104
105
  onUploadProgress?: (progress: UploadProgress) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"client-types.d.ts","sourceRoot":"","sources":["../../src/contract/client-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client-types.d.ts","sourceRoot":"","sources":["../../src/contract/client-types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export { type ManagedFilePath, ManagedFilePathSchema, type ManagedFileRef, ManagedFileRefSchema, } from '../contract/file-ref.js';
2
2
  export { createManagedFileBoundary, type ManagedFileBoundary, type ManagedFileBoundaryConfig, ManagedFileError, type ManagedFileErrorCode, type ManagedFileInspection, type ManagedFileInspectionInput, type ManagedFileInspector, type ManagedFileReadOptions, type ManagedFileSource, type ManagedFileWriteOptions, } from '../files/boundary.js';
3
- export { type ChunkSpool, type ChunkSpoolAssembly, type ChunkSpoolConfig, type ChunkSpoolErrorCode, type ChunkSpoolKey, type ChunkSpoolOpen, type ChunkSpoolPart, createChunkSpool, } from '../files/chunk-spool.js';
3
+ export { CHUNK_SPOOL_ERROR_CODES, type ChunkSpool, type ChunkSpoolAssembly, type ChunkSpoolConfig, type ChunkSpoolErrorCode, type ChunkSpoolKey, type ChunkSpoolOpen, type ChunkSpoolPart, createChunkSpool, isChunkSpoolErrorCode, } from '../files/chunk-spool.js';
4
4
  export { type WriteFileAtomicOptions, writeFileAtomic, writeFileAtomicSync, } from '../internal/atomic-file.js';
5
5
  export { type ExclusiveLock, ExclusiveLockError, type ExclusiveLockOptions, type ExclusiveLockOwner, withExclusiveLock, } from '../internal/with-exclusive-lock.js';
6
6
  //# sourceMappingURL=files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/entrypoints/files.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,cAAc,EACnB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,sBAAsB,EAC3B,eAAe,EACf,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,aAAa,EAClB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/entrypoints/files.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,cAAc,EACnB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,uBAAuB,EACvB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,sBAAsB,EAC3B,eAAe,EACf,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,aAAa,EAClB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,iCAAiC,CAAC"}
@@ -40,6 +40,10 @@ var STATUS = {
40
40
  UPLOAD_CHUNK_SIZE: 400,
41
41
  UPLOAD_INCOMPLETE: 409
42
42
  };
43
+ function isChunkSpoolErrorCode(code) {
44
+ return Object.hasOwn(STATUS, code);
45
+ }
46
+ var CHUNK_SPOOL_ERROR_CODES = Object.freeze(Object.keys(STATUS).filter(isChunkSpoolErrorCode));
43
47
  function refuse(code, message, details) {
44
48
  return new AppError2(code, message, STATUS[code], details);
45
49
  }
@@ -333,12 +337,14 @@ async function withExclusiveLock(path, run, options = {}) {
333
337
  }
334
338
  }
335
339
  export {
340
+ CHUNK_SPOOL_ERROR_CODES,
336
341
  ExclusiveLockError,
337
342
  ManagedFileError2 as ManagedFileError,
338
343
  ManagedFilePathSchema2 as ManagedFilePathSchema,
339
344
  ManagedFileRefSchema2 as ManagedFileRefSchema,
340
345
  createChunkSpool,
341
346
  createManagedFileBoundary2 as createManagedFileBoundary,
347
+ isChunkSpoolErrorCode,
342
348
  withExclusiveLock,
343
349
  writeFileAtomic2 as writeFileAtomic,
344
350
  writeFileAtomicSync2 as writeFileAtomicSync
@@ -1,4 +1,4 @@
1
- export { type ChunkedUploadConfig, type ChunkedUploadPart, type ChunkedUploadProgress, type ChunkedUploadStart, uploadInChunks, } from '../browser/chunked-upload.js';
1
+ export { type ChunkedUploadConfig, type ChunkedUploadPart, type ChunkedUploadProgress, type ChunkedUploadStart, type ChunkSource, uploadInChunks, } from '../browser/chunked-upload.js';
2
2
  export { type ClientConfig, type ClientContract, type ClientFetch, type ClientRegistryValue, type ContractClientConfig, contractEndpointMatchers, createClient, createClients, createScopedClients, createScopedUrlBuilders, createUrlBuilder, createUrlBuilders, type PathPrefixArgs, type RegistryScope, type ScopeClientConfigs, type ScopedClientRegistry, type ScopedUrlBuilderRegistry, type UrlBuilderConfig, } from '../browser/client.js';
3
3
  export { ApiError, type ApiEvent, type ApiEventListener, type ConfiguredHttpClient, createHttpClient, type HeaderProvider, type HttpClient, type HttpClientConfig, type RequestOptions, type UnauthorizedMatcher, } from '../browser/http.js';
4
4
  export { createLiveStateController, type LiveStateController, type LiveStateControllerConfig, type LiveStateControllerError, type LiveStateControllerSnapshot, type LiveStateControllerStatus, LiveStateControllerStatusSchema, type LiveStateEventDecision, type LiveStatePhase, LiveStatePhaseSchema, type LiveStateSource, type LiveStateSourceOpenInput, type LiveStateSourceOpenResult, type LiveStateStopReason, LiveStateStopReasonSchema, type LiveStateSubscriberError, } from '../browser/live-state.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entrypoints/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,+BAA+B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,wBAAwB,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,WAAW,EACX,QAAQ,GACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGzF,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entrypoints/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,+BAA+B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,wBAAwB,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,WAAW,EACX,QAAQ,GACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGzF,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  ApiError2,
10
10
  createHttpClient2
11
- } from "../index-h43cepag.js";
11
+ } from "../index-1h6gtdrj.js";
12
12
  import"../index-m38ej7e5.js";
13
13
  import {
14
14
  DEFAULT_CONTRACT_STREAM_FRAME_BYTES2,
@@ -24,7 +24,7 @@ import {
24
24
  createUrlBuilder2,
25
25
  createUrlBuilders2,
26
26
  createScopedUrlBuilders2
27
- } from "../index-65jwqhcf.js";
27
+ } from "../index-d82d3xg4.js";
28
28
  import"../index-w0eqdhyd.js";
29
29
  import {
30
30
  LiveStatePhaseSchema2,
@@ -110,6 +110,9 @@ async function uploadInChunks(config) {
110
110
  if (!Number.isSafeInteger(chunkBytes) || chunkBytes <= 0) {
111
111
  throw new TypeError("uploadInChunks: chunkBytes must be a positive integer");
112
112
  }
113
+ if (!Number.isSafeInteger(file.size) || file.size < 0) {
114
+ throw new TypeError("uploadInChunks: the file size must be a whole number of bytes");
115
+ }
113
116
  if (file.size === 0)
114
117
  throw new TypeError("uploadInChunks: the file is empty");
115
118
  const totalBytes = file.size;
@@ -134,12 +137,14 @@ async function uploadInChunks(config) {
134
137
  for (let index = 0;index < chunkCount; index += 1) {
135
138
  throwIfAborted(signal);
136
139
  const start = index * chunkBytes;
137
- const bytes = file.slice(start, Math.min(totalBytes, start + chunkBytes));
140
+ const end = Math.min(totalBytes, start + chunkBytes);
141
+ const partBytes = end - start;
142
+ const bytes = file.slice(start, end);
138
143
  await repeating((attempt) => config.chunk({ uploadId, index, bytes }, {
139
144
  ...signal && { signal },
140
- onUploadProgress: (progress) => report(start + fileShare(progress, bytes.size), index, attempt)
145
+ onUploadProgress: (progress) => report(start + fileShare(progress, partBytes), index, attempt)
141
146
  }), { retries, retryDelayMs, signal });
142
- report(start + bytes.size, index + 1, 1);
147
+ report(end, index + 1, 1);
143
148
  }
144
149
  throwIfAborted(signal);
145
150
  return config.finalize({ uploadId }, { signal });
@@ -2,7 +2,7 @@ import"../index-hby4qhax.js";
2
2
  import {
3
3
  ApiError2,
4
4
  isAbortLikeError
5
- } from "../index-h43cepag.js";
5
+ } from "../index-1h6gtdrj.js";
6
6
  import {
7
7
  isRecord
8
8
  } from "../index-9jfdm5tg.js";
@@ -1,12 +1,12 @@
1
1
  import"../index-hby4qhax.js";
2
2
  import {
3
3
  ApiError2
4
- } from "../index-h43cepag.js";
4
+ } from "../index-1h6gtdrj.js";
5
5
  import"../index-m38ej7e5.js";
6
6
  import"../index-r5c4fedv.js";
7
7
  import {
8
8
  createClient2
9
- } from "../index-65jwqhcf.js";
9
+ } from "../index-d82d3xg4.js";
10
10
  import {
11
11
  AppError2
12
12
  } from "../index-n53mswt3.js";
@@ -1,5 +1,5 @@
1
1
  import"../index-hby4qhax.js";
2
- import"../index-h43cepag.js";
2
+ import"../index-1h6gtdrj.js";
3
3
  import {
4
4
  joinRoutePath
5
5
  } from "../index-m38ej7e5.js";
@@ -7,7 +7,7 @@ import"../index-r5c4fedv.js";
7
7
  import {
8
8
  createClient2,
9
9
  createClients2
10
- } from "../index-65jwqhcf.js";
10
+ } from "../index-d82d3xg4.js";
11
11
  import"../index-n53mswt3.js";
12
12
  import"../index-q0th8q0z.js";
13
13
  import {
@@ -529,6 +529,8 @@ function unwrapMcpResult(result) {
529
529
  return result.structuredContent;
530
530
  if (!Array.isArray(result.content))
531
531
  return result;
532
+ if (result.content.length === 0)
533
+ return null;
532
534
  const only = result.content.length === 1 ? result.content[0] : undefined;
533
535
  if (!isRecord(only) || only.type !== "text" || typeof only.text !== "string")
534
536
  return result;
@@ -1,7 +1,7 @@
1
1
  import"../index-hby4qhax.js";
2
2
  import {
3
3
  ApiError2
4
- } from "../index-h43cepag.js";
4
+ } from "../index-1h6gtdrj.js";
5
5
  import"../index-m38ej7e5.js";
6
6
  import {
7
7
  defineContract2
@@ -21,6 +21,14 @@
21
21
  */
22
22
  import type { ZodType } from 'zod';
23
23
  export type ChunkSpoolErrorCode = 'UPLOAD_INVALID' | 'UPLOAD_TOO_LARGE' | 'UPLOAD_NOT_FOUND' | 'UPLOAD_CONFLICT' | 'UPLOAD_CHUNK_OUT_OF_RANGE' | 'UPLOAD_CHUNK_SIZE' | 'UPLOAD_INCOMPLETE';
24
+ /**
25
+ * Whether an error code is one the spool refuses with. An application that
26
+ * maps error codes onto its own must map these too — an unmapped one would
27
+ * reach its client as an unknown 500 instead of the spool's 4xx.
28
+ */
29
+ export declare function isChunkSpoolErrorCode(code: string): code is ChunkSpoolErrorCode;
30
+ /** Every code the spool refuses with. */
31
+ export declare const CHUNK_SPOOL_ERROR_CODES: readonly ChunkSpoolErrorCode[];
24
32
  export interface ChunkSpoolConfig<TMeta> {
25
33
  /** Where uploads in progress live; one directory per upload. */
26
34
  readonly directory: string;
@@ -49,7 +57,7 @@ export interface ChunkSpoolAssembly<TMeta> {
49
57
  readonly meta: TMeta;
50
58
  readonly totalBytes: number;
51
59
  /** The parts on disk, in order; valid until `discard`. */
52
- readonly chunkPaths: readonly string[];
60
+ readonly chunkPaths: string[];
53
61
  /** The whole file, part after part. */
54
62
  stream(): ReadableStream<Uint8Array>;
55
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chunk-spool.d.ts","sourceRoot":"","sources":["../../src/files/chunk-spool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,MAAM,MAAM,mBAAmB,GAC3B,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,2BAA2B,GAC3B,mBAAmB,GACnB,mBAAmB,CAAC;AAoBxB,MAAM,WAAW,gBAAgB,CAAC,KAAK;IACrC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,KAAK,CAAE,SAAQ,aAAa;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,uCAAuC;IACvC,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,UAAU,CAAC,KAAK;IAC/B,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IAC1D,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,2EAA2E;IAC3E,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAkED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CA4J1F"}
1
+ {"version":3,"file":"chunk-spool.d.ts","sourceRoot":"","sources":["../../src/files/chunk-spool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,MAAM,MAAM,mBAAmB,GAC3B,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,2BAA2B,GAC3B,mBAAmB,GACnB,mBAAmB,CAAC;AAYxB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,mBAAmB,CAE/E;AAED,yCAAyC;AACzC,eAAO,MAAM,uBAAuB,EAAE,SAAS,mBAAmB,EAEjE,CAAC;AAUF,MAAM,WAAW,gBAAgB,CAAC,KAAK;IACrC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,KAAK,CAAE,SAAQ,aAAa;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAC9B,uCAAuC;IACvC,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,UAAU,CAAC,KAAK;IAC/B,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IAC1D,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,2EAA2E;IAC3E,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAkED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CA4J1F"}
@@ -146,34 +146,70 @@ function responseTraceId(response) {
146
146
 
147
147
  // src/browser/upload-progress.ts
148
148
  var PIECE_BYTES = 64 * 1024;
149
+ function isReactNative() {
150
+ return Reflect.get(globalThis.navigator ?? {}, "product") === "ReactNative";
151
+ }
149
152
  function uploadProgressRoute(injectedTransport) {
153
+ if (isReactNative()) {
154
+ if (injectedTransport) {
155
+ throw new TypeError("onUploadProgress in React Native counts through its XMLHttpRequest and cannot count an injected fetch — drop the custom fetch for this client");
156
+ }
157
+ return "native-xhr";
158
+ }
150
159
  return !injectedTransport && typeof globalThis.XMLHttpRequest === "function" ? "xhr" : "stream";
151
160
  }
152
- function withUploadProgress(transport, listener, route) {
161
+ function reporter(listener, attempt) {
162
+ let reported = -1;
163
+ const emit = (sentBytes, totalBytes) => {
164
+ reported = sentBytes;
165
+ try {
166
+ listener({ sentBytes, totalBytes, attempt });
167
+ } catch {}
168
+ };
169
+ return (sentBytes, totalBytes) => {
170
+ if (sentBytes <= reported)
171
+ return;
172
+ if (reported < 0 && sentBytes > 0)
173
+ emit(0, totalBytes);
174
+ emit(sentBytes, totalBytes);
175
+ };
176
+ }
177
+ function withUploadProgress(transport, listener, delivery) {
153
178
  let attempts = 0;
154
179
  return async (input, init) => {
155
180
  attempts += 1;
156
- const attempt = attempts;
181
+ const report = reporter(listener, attempts);
182
+ const signal = init?.signal ?? (input instanceof Request ? input.signal : undefined);
183
+ const credentials = init?.credentials ?? (input instanceof Request ? input.credentials : undefined);
184
+ if (delivery.route === "native-xhr") {
185
+ return sendNative(input, init, delivery.nativeBody ?? xhrBodyOf(init?.body), {
186
+ signal,
187
+ credentials,
188
+ report
189
+ });
190
+ }
157
191
  const request = new Request(input, init);
158
192
  const headers = new Headers(request.headers);
159
193
  const bytes = new Uint8Array(await request.arrayBuffer());
160
- let reported = -1;
161
- const report = (sentBytes) => {
162
- if (sentBytes <= reported)
163
- return;
164
- reported = sentBytes;
165
- try {
166
- listener({ sentBytes, totalBytes: bytes.byteLength, attempt });
167
- } catch {}
168
- };
169
- const signal = init?.signal ?? (input instanceof Request ? input.signal : undefined);
170
- const credentials = init?.credentials ?? (input instanceof Request ? input.credentials : undefined);
171
- report(0);
172
- if (route === "xhr") {
173
- return sendThroughXhr(request, headers, bytes, { signal, credentials, report });
194
+ const total = bytes.byteLength;
195
+ report(0, total);
196
+ if (delivery.route === "xhr") {
197
+ if (credentials === "omit") {
198
+ throw new TypeError("onUploadProgress sends through XMLHttpRequest, which cannot omit same-origin cookies — use credentials 'same-origin' or 'include'");
199
+ }
200
+ return sendThroughXhr({
201
+ method: request.method,
202
+ url: request.url,
203
+ headers,
204
+ body: total > 0 ? bytes : null,
205
+ totalBytes: total,
206
+ withCredentials: credentials === "include",
207
+ signal,
208
+ report
209
+ });
174
210
  }
175
- headers.set("content-length", String(bytes.byteLength));
176
- const counted = bytes.byteLength > 0 ? { body: countedBody(bytes, report), duplex: "half" } : {};
211
+ headers.set("content-length", String(total));
212
+ const counted = total > 0 ? { body: countedBody(bytes, (sent) => report(sent, total)), duplex: "half" } : {};
177
213
  const outgoing = {
178
214
  ...init,
179
215
  method: request.method,
@@ -201,37 +237,86 @@ function countedBody(bytes, report) {
201
237
  }
202
238
  }, { highWaterMark: 0 });
203
239
  }
240
+ function sendNative(input, init, body, { signal, credentials, report }) {
241
+ const request = input instanceof Request ? input : undefined;
242
+ const headers = new Headers(request?.headers);
243
+ new Headers(init?.headers).forEach((value, name) => {
244
+ headers.set(name, value);
245
+ });
246
+ if (body instanceof FormData)
247
+ headers.delete("content-type");
248
+ const totalBytes = knownLength(body);
249
+ if (totalBytes !== undefined)
250
+ report(0, totalBytes);
251
+ return sendThroughXhr({
252
+ method: init?.method ?? request?.method ?? "GET",
253
+ url: request?.url ?? String(input),
254
+ headers,
255
+ body,
256
+ totalBytes,
257
+ ...credentials === "include" && { withCredentials: true },
258
+ ...credentials === "omit" && { withCredentials: false },
259
+ signal,
260
+ report
261
+ });
262
+ }
263
+ function xhrBodyOf(body) {
264
+ if (body instanceof ReadableStream) {
265
+ throw new TypeError("onUploadProgress in React Native cannot send a streamed body");
266
+ }
267
+ return body ?? null;
268
+ }
269
+ function knownLength(body) {
270
+ if (body === null)
271
+ return 0;
272
+ if (typeof body === "string")
273
+ return new TextEncoder().encode(body).byteLength;
274
+ if (body instanceof Blob)
275
+ return body.size;
276
+ if (body instanceof ArrayBuffer || ArrayBuffer.isView(body))
277
+ return body.byteLength;
278
+ return;
279
+ }
204
280
  var BROWSER_OWNED_HEADERS = new Set(["content-length", "host", "connection"]);
205
- function sendThroughXhr(request, headers, bytes, { signal, credentials, report }) {
281
+ function sendThroughXhr(send) {
282
+ const { signal, report } = send;
283
+ let total = send.totalBytes;
284
+ const progress = (loaded, eventTotal) => {
285
+ if (total === undefined && eventTotal > 0)
286
+ total = eventTotal;
287
+ if (total !== undefined)
288
+ report(Math.min(loaded, total), total);
289
+ };
290
+ const finished = () => {
291
+ if (total !== undefined)
292
+ report(total, total);
293
+ };
206
294
  return new Promise((resolve, reject) => {
207
- if (credentials === "omit") {
208
- reject(new TypeError("onUploadProgress sends through XMLHttpRequest, which cannot omit same-origin cookies — use credentials 'same-origin' or 'include'"));
209
- return;
210
- }
211
295
  if (signal?.aborted) {
212
296
  reject(abortReason(signal));
213
297
  return;
214
298
  }
215
299
  const xhr = new XMLHttpRequest;
216
- xhr.open(request.method, request.url, true);
217
- headers.forEach((value, name) => {
300
+ xhr.open(send.method, send.url, true);
301
+ send.headers.forEach((value, name) => {
218
302
  if (!BROWSER_OWNED_HEADERS.has(name))
219
303
  xhr.setRequestHeader(name, value);
220
304
  });
221
- xhr.withCredentials = credentials === "include";
305
+ if (send.withCredentials !== undefined)
306
+ xhr.withCredentials = send.withCredentials;
222
307
  xhr.responseType = "arraybuffer";
223
308
  const abort = () => xhr.abort();
224
309
  signal?.addEventListener("abort", abort, { once: true });
225
310
  const settle = () => signal?.removeEventListener("abort", abort);
226
- xhr.upload.onprogress = (event) => report(Math.min(event.loaded, bytes.byteLength));
227
- xhr.upload.onload = () => report(bytes.byteLength);
311
+ xhr.upload.onprogress = (event) => progress(event.loaded, event.total);
312
+ xhr.upload.onload = finished;
228
313
  xhr.onload = () => {
229
314
  settle();
230
315
  if (xhr.status < 200 || xhr.status > 599) {
231
316
  reject(new TypeError("Network request failed"));
232
317
  return;
233
318
  }
234
- report(bytes.byteLength);
319
+ finished();
235
320
  resolve(responseOf(xhr));
236
321
  };
237
322
  xhr.onerror = () => {
@@ -242,7 +327,7 @@ function sendThroughXhr(request, headers, bytes, { signal, credentials, report }
242
327
  settle();
243
328
  reject(signal ? abortReason(signal) : new DOMException("Aborted", "AbortError"));
244
329
  };
245
- xhr.send(bytes.byteLength > 0 ? bytes : null);
330
+ xhr.send(send.body);
246
331
  });
247
332
  }
248
333
  function abortReason(signal) {
@@ -341,6 +426,9 @@ function requestFailure(error, emit) {
341
426
  const msg = error instanceof Error ? error.message : undefined;
342
427
  return new ApiError2("UNKNOWN_ERROR", status, msg ? { message: msg } : undefined, msg, undefined, responseTraceId(response), { cause: error });
343
428
  }
429
+ function jsonBodyOf(data) {
430
+ return data === undefined ? null : JSON.stringify(data);
431
+ }
344
432
  function errorBodyOf(data) {
345
433
  if (typeof data !== "string")
346
434
  return data ?? null;
@@ -424,7 +512,10 @@ function createHttpClient2(config) {
424
512
  const cancellation = createRequestCancellation(options.signal, options.timeout ?? config.timeout ?? 30000);
425
513
  const transport = config.fetch ?? globalThis.fetch.bind(globalThis);
426
514
  const kyOptions = {
427
- fetch: createRetryAwareFetch(options.onUploadProgress ? withUploadProgress(transport, options.onUploadProgress, uploadProgressRoute(config.fetch !== undefined || config.unix !== undefined)) : transport, config.unix),
515
+ fetch: createRetryAwareFetch(options.onUploadProgress ? withUploadProgress(transport, options.onUploadProgress, {
516
+ route: uploadProgressRoute(config.fetch !== undefined || config.unix !== undefined),
517
+ nativeBody: data instanceof FormData ? data : jsonBodyOf(data)
518
+ }) : transport, config.unix),
428
519
  timeout: false,
429
520
  signal: cancellation.signal
430
521
  };
@@ -7,7 +7,7 @@ import {
7
7
  ApiError2,
8
8
  refuseLocally,
9
9
  parseApiErrorBody
10
- } from "./index-h43cepag.js";
10
+ } from "./index-1h6gtdrj.js";
11
11
  import {
12
12
  parseTrailingWildcard
13
13
  } from "./index-m38ej7e5.js";
@@ -540,10 +540,13 @@ function createFetchExecutor(endpoint, prefix, config, contractConfig) {
540
540
  const hasBody = endpoint.method !== "GET" && endpoint.method !== "HEAD" && endpoint.method !== "DELETE" && !endpoint.multipart && endpoint.input && Object.keys(plan.remainingArgs).length > 0;
541
541
  if (hasBody)
542
542
  headers["Content-Type"] = "application/json";
543
+ const progressRoute = options?.onUploadProgress ? uploadProgressRoute(config.fetch !== undefined) : undefined;
543
544
  try {
544
545
  return await cancellation.run(async (signal) => {
545
546
  const body = endpoint.multipart ? buildMultipartForm(endpoint.multipart, plan.remainingArgs) : hasBody ? JSON.stringify(plan.remainingArgs) : undefined;
546
- const deliver = options?.onUploadProgress ? withUploadProgress(executeFetch, options.onUploadProgress, uploadProgressRoute(config.fetch !== undefined)) : executeFetch;
547
+ const deliver = options?.onUploadProgress && progressRoute ? withUploadProgress(executeFetch, options.onUploadProgress, {
548
+ route: progressRoute
549
+ }) : executeFetch;
547
550
  const res = await deliver(url, {
548
551
  method: endpoint.method,
549
552
  headers,
@@ -12,6 +12,10 @@
12
12
  * So the CLI unwraps, and only the CLI. The order is the server's own order of
13
13
  * preference: `structuredContent` is the answer when the server sent one; a lone
14
14
  * text part is the answer when it parses as JSON, and its text when it does not.
15
+ * No parts at all is no answer, and says so as JSON: `null`. The envelope around
16
+ * an empty `content` carries only protocol metadata, and `_meta` is never an
17
+ * answer. Not `undefined`: a discovered tool declares an output, and an absent
18
+ * value there is a broken handler, not an empty one.
15
19
  * Anything else — several parts, an image, audio — is passed through whole,
16
20
  * because picking one part out of many would be inventing an answer.
17
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-envelope.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAaxD;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,QAAQ,CAwB1E"}
1
+ {"version":3,"file":"mcp-envelope.d.ts","sourceRoot":"","sources":["../../../src/tools/connections/mcp-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAcxD;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,QAAQ,CAwB1E"}
package/llms/cli.txt CHANGED
@@ -912,9 +912,11 @@ kind, because the handler's value is what gets printed, piped and aggregated:
912
912
  handed the envelope, `--count-by status` groups the *content parts* and answers
913
913
  `no record carries the field "status" — available: text, type`. So the CLI
914
914
  transport unwraps, and only it: `structuredContent` when the server sent one, a
915
- lone text part when it parses as JSON, its text when it does not. Several parts,
916
- an image or audio pass through whole — picking one of many would be inventing an
917
- answer.
915
+ lone text part when it parses as JSON, its text when it does not, and `null` when
916
+ there are no parts at all — a tool without an output contract answers that way,
917
+ and the `_meta` beside an empty `content` is protocol metadata, never the answer.
918
+ Several parts, an image or audio pass through whole — picking one of many would
919
+ be inventing an answer.
918
920
 
919
921
 
920
922
  ## Auth parity
package/llms/files.txt CHANGED
@@ -32,5 +32,6 @@ available from `stitchkit/contract`.
32
32
  | `createChunkSpool` | function | the server half of a chunked upload: parts on disk under `owner` + client-minted `uploadId`, each with a size+sha256 receipt; idempotent `open` and `put`, the first writer of a part wins across processes, `assemble` in order once every part is in, `sweep` of untouched uploads — [guide](../guide/client.md#chunked-uploads) |
33
33
  | `ChunkSpool` / `ChunkSpoolConfig` / `ChunkSpoolKey` / `ChunkSpoolOpen` / `ChunkSpoolPart` / `ChunkSpoolAssembly` | _type_ | the spool, its directory, part size, file limit, meta schema and age; an upload's key; its declaration; one part; the assembled parts with a concatenating `stream()` |
34
34
  | `ChunkSpoolErrorCode` | _type_ | the `AppError` codes a spool refuses with, each with its 4xx status: `UPLOAD_INVALID`, `UPLOAD_TOO_LARGE`, `UPLOAD_NOT_FOUND`, `UPLOAD_CONFLICT`, `UPLOAD_CHUNK_OUT_OF_RANGE`, `UPLOAD_CHUNK_SIZE`, `UPLOAD_INCOMPLETE` |
35
+ | `CHUNK_SPOOL_ERROR_CODES` / `isChunkSpoolErrorCode` | const / function | every `ChunkSpoolErrorCode` as a frozen list, and the guard for one — map them onto the app's own error codes, or a spool refusal reaches its client as an unknown 500 |
35
36
 
36
37
  ---
@@ -372,6 +372,11 @@ await api.health.withOptions({ signal: controller.signal })
372
372
 
373
373
  A call with a body can report it leaving:
374
374
 
375
+ > **In a browser or React Native, do not give the client its own `fetch` for
376
+ > a call you want counted.** Without one the count comes from
377
+ > `XMLHttpRequest` upload events; with one the body is streamed to it, which a
378
+ > browser may buffer (and report at once) and React Native refuses.
379
+
375
380
  ```ts
376
381
  await api.recordings.upload.withOptions(
377
382
  { file, title: 'Take 3' },
@@ -395,13 +400,14 @@ await api.recordings.upload.withOptions(
395
400
  `TypeError` at the call — it has no body to count, or a live response the
396
401
  browser route would buffer. A listener that throws does not fail the upload.
397
402
 
398
- Fetch has no upload event, so the count comes from one of two routes, chosen
403
+ Fetch has no upload event, so the count comes from one of three routes, chosen
399
404
  per call:
400
405
 
401
406
  | Where the client runs | Route | What counts |
402
407
  |---|---|---|
403
408
  | Bun, Node, SSR, an injected `fetch`, a unix socket | the body is encoded once and sent as a stream of 64 KiB pieces with an exact `content-length` | a piece counts when the transport pulls it |
404
409
  | a browser on its own fetch | `XMLHttpRequest`, with the same headers, credentials, errors, cancellation and timeout | `xhr.upload` progress events |
410
+ | React Native / Expo on its own fetch | the platform's `XMLHttpRequest`, handed the body as the client built it — the `FormData` itself, so a `{ uri, name, type }` file streams from disk; the same errors, cancellation and timeout | `xhr.upload` progress events; a `FormData`'s `totalBytes` comes with the first one |
405
411
 
406
412
  The browser route exists because a streaming request body is not portable:
407
413
  Chromium sends one only over HTTP/2 and Safari not at all. Two consequences of
@@ -410,7 +416,13 @@ and the response is read whole before the call resolves. An injected `fetch`
410
416
  always takes the stream route — it owns the I/O, and a transport that buffers
411
417
  the stream before sending reports the whole body at once.
412
418
 
413
- A counted body is encoded in memory once. A file larger than one request
419
+ React Native is recognised by `navigator.product === 'ReactNative'`. Its
420
+ credentials follow its own fetch: `include` and `omit` set `withCredentials`,
421
+ anything else keeps the platform default. An injected `fetch` there is refused
422
+ with a `TypeError` at the call: React Native cannot stream a request body, so
423
+ there is nothing to count.
424
+
425
+ Off React Native a counted body is encoded in memory once. A file larger than one request
414
426
  belongs in [chunked uploads](#chunked-uploads), whose parts are sized for it.
415
427
 
416
428
  ### Injected delivery adapters
@@ -572,7 +584,7 @@ implement(contract, {
572
584
  ```
573
585
 
574
586
  ```ts
575
- // client — Bun, Node or a browser
587
+ // client — Bun, Node, a browser or React Native
576
588
  import { uploadInChunks } from 'stitchkit'
577
589
 
578
590
  const accepted = await uploadInChunks({
@@ -591,9 +603,15 @@ const accepted = await uploadInChunks({
591
603
 
592
604
  The rules the two halves share:
593
605
 
594
- - **The client mints the upload id** (default `crypto.randomUUID()`), so a
595
- repeated `init` is the same upload. The spool keys it by `owner` too — the
596
- same id from another owner is another upload.
606
+ - **The client mints the upload id** (default `crypto.randomUUID()`, fresh per
607
+ call), so a repeated `init` is the same upload. The spool keys it by `owner`
608
+ too — the same id from another owner is another upload. To resume after the
609
+ app restarts instead of sending the file again, pass a stable `uploadId` —
610
+ the id of the app's own job or attempt.
611
+ - **The file is anything with `size` and `slice(start, end)`** (`ChunkSource`).
612
+ A `Blob` is one; so is a platform file that is not a DOM `Blob`, such as an
613
+ Expo `File`, passed without a cast. A part's `bytes` is what `slice`
614
+ returns, so the part call hands it to the client as the multipart file.
597
615
  - **A part is idempotent.** The spool keeps a size+sha256 receipt per index:
598
616
  the same bytes again answer `'repeated'`, other bytes `UPLOAD_CONFLICT`
599
617
  (409). So the driver repeats `init` and a part on a failure that may pass — no
@@ -607,7 +625,9 @@ The rules the two halves share:
607
625
  - **Every part but the last is exactly `chunkBytes`** and `chunkCount` must add
608
626
  up; the spool refuses anything else with a 4xx `AppError`
609
627
  (`ChunkSpoolErrorCode`), which a handler can let through as the client's
610
- typed error.
628
+ typed error. An application that maps error codes onto its own must map
629
+ these too — `isChunkSpoolErrorCode` / `CHUNK_SPOOL_ERROR_CODES` from
630
+ `stitchkit/files` — or a refusal reaches its client as an unknown 500.
611
631
  - **Progress counts file bytes**, inside a part too — the driver passes
612
632
  `onUploadProgress` into the part call, so the [upload
613
633
  progress](#upload-progress) route of the client applies. A repeated part
@@ -45,6 +45,7 @@ The browser-and-server entrypoint. Re-exports everything from
45
45
  | `UploadProgress` | _type_ | `{ sentBytes, totalBytes, attempt }` heard by `onUploadProgress`: bytes of the encoded body handed to the network, first `0`, last `totalBytes`, counted again on each transport retry — [guide](../guide/client.md#upload-progress) |
46
46
  | `uploadInChunks` | function | send a file larger than one request as `init` → parts → `finalize` through three calls the app owns; client-minted id, repeats of a part on a failure that may pass, `finalize` never repeated, cancel checked between parts, progress in file bytes — [guide](../guide/client.md#chunked-uploads) |
47
47
  | `ChunkedUploadConfig` / `ChunkedUploadStart` / `ChunkedUploadPart` / `ChunkedUploadProgress` | _type_ | the driver's file, part size, retries and three calls; what `init` declares; one part; progress `{ sentBytes, totalBytes, index, chunkCount, attempt }` |
48
+ | `ChunkSource` | _type_ | what the driver reads a file through — `size` and `slice(start, end)`; a `Blob` is one, so is a platform file that is not (an Expo `File`), and a part's `bytes` is what its `slice` returns |
48
49
  | `ContractClientConfig` | _type_ | per-tenant / resource-scoped client config — dynamic `pathPrefix` + `stripPrefixKeys` ([guide](../guide/client.md#contractclientconfig--per-tenant--resource-scoped-clients)) |
49
50
  | `contractEndpointMatchers` | function | compile exact pathname matchers for selected HTTP contract operations and expected-401 policy |
50
51
  | `PathPrefixArgs` | _type_ | required string-valued keys exposed to a typed dynamic `pathPrefix` callback |
package/llms-full.txt CHANGED
@@ -2788,6 +2788,11 @@ await api.health.withOptions({ signal: controller.signal })
2788
2788
 
2789
2789
  A call with a body can report it leaving:
2790
2790
 
2791
+ > **In a browser or React Native, do not give the client its own `fetch` for
2792
+ > a call you want counted.** Without one the count comes from
2793
+ > `XMLHttpRequest` upload events; with one the body is streamed to it, which a
2794
+ > browser may buffer (and report at once) and React Native refuses.
2795
+
2791
2796
  ```ts
2792
2797
  await api.recordings.upload.withOptions(
2793
2798
  { file, title: 'Take 3' },
@@ -2811,13 +2816,14 @@ await api.recordings.upload.withOptions(
2811
2816
  `TypeError` at the call — it has no body to count, or a live response the
2812
2817
  browser route would buffer. A listener that throws does not fail the upload.
2813
2818
 
2814
- Fetch has no upload event, so the count comes from one of two routes, chosen
2819
+ Fetch has no upload event, so the count comes from one of three routes, chosen
2815
2820
  per call:
2816
2821
 
2817
2822
  | Where the client runs | Route | What counts |
2818
2823
  |---|---|---|
2819
2824
  | Bun, Node, SSR, an injected `fetch`, a unix socket | the body is encoded once and sent as a stream of 64 KiB pieces with an exact `content-length` | a piece counts when the transport pulls it |
2820
2825
  | a browser on its own fetch | `XMLHttpRequest`, with the same headers, credentials, errors, cancellation and timeout | `xhr.upload` progress events |
2826
+ | React Native / Expo on its own fetch | the platform's `XMLHttpRequest`, handed the body as the client built it — the `FormData` itself, so a `{ uri, name, type }` file streams from disk; the same errors, cancellation and timeout | `xhr.upload` progress events; a `FormData`'s `totalBytes` comes with the first one |
2821
2827
 
2822
2828
  The browser route exists because a streaming request body is not portable:
2823
2829
  Chromium sends one only over HTTP/2 and Safari not at all. Two consequences of
@@ -2826,7 +2832,13 @@ and the response is read whole before the call resolves. An injected `fetch`
2826
2832
  always takes the stream route — it owns the I/O, and a transport that buffers
2827
2833
  the stream before sending reports the whole body at once.
2828
2834
 
2829
- A counted body is encoded in memory once. A file larger than one request
2835
+ React Native is recognised by `navigator.product === 'ReactNative'`. Its
2836
+ credentials follow its own fetch: `include` and `omit` set `withCredentials`,
2837
+ anything else keeps the platform default. An injected `fetch` there is refused
2838
+ with a `TypeError` at the call: React Native cannot stream a request body, so
2839
+ there is nothing to count.
2840
+
2841
+ Off React Native a counted body is encoded in memory once. A file larger than one request
2830
2842
  belongs in [chunked uploads](#chunked-uploads), whose parts are sized for it.
2831
2843
 
2832
2844
  ### Injected delivery adapters
@@ -2988,7 +3000,7 @@ implement(contract, {
2988
3000
  ```
2989
3001
 
2990
3002
  ```ts
2991
- // client — Bun, Node or a browser
3003
+ // client — Bun, Node, a browser or React Native
2992
3004
  import { uploadInChunks } from 'stitchkit'
2993
3005
 
2994
3006
  const accepted = await uploadInChunks({
@@ -3007,9 +3019,15 @@ const accepted = await uploadInChunks({
3007
3019
 
3008
3020
  The rules the two halves share:
3009
3021
 
3010
- - **The client mints the upload id** (default `crypto.randomUUID()`), so a
3011
- repeated `init` is the same upload. The spool keys it by `owner` too — the
3012
- same id from another owner is another upload.
3022
+ - **The client mints the upload id** (default `crypto.randomUUID()`, fresh per
3023
+ call), so a repeated `init` is the same upload. The spool keys it by `owner`
3024
+ too — the same id from another owner is another upload. To resume after the
3025
+ app restarts instead of sending the file again, pass a stable `uploadId` —
3026
+ the id of the app's own job or attempt.
3027
+ - **The file is anything with `size` and `slice(start, end)`** (`ChunkSource`).
3028
+ A `Blob` is one; so is a platform file that is not a DOM `Blob`, such as an
3029
+ Expo `File`, passed without a cast. A part's `bytes` is what `slice`
3030
+ returns, so the part call hands it to the client as the multipart file.
3013
3031
  - **A part is idempotent.** The spool keeps a size+sha256 receipt per index:
3014
3032
  the same bytes again answer `'repeated'`, other bytes `UPLOAD_CONFLICT`
3015
3033
  (409). So the driver repeats `init` and a part on a failure that may pass — no
@@ -3023,7 +3041,9 @@ The rules the two halves share:
3023
3041
  - **Every part but the last is exactly `chunkBytes`** and `chunkCount` must add
3024
3042
  up; the spool refuses anything else with a 4xx `AppError`
3025
3043
  (`ChunkSpoolErrorCode`), which a handler can let through as the client's
3026
- typed error.
3044
+ typed error. An application that maps error codes onto its own must map
3045
+ these too — `isChunkSpoolErrorCode` / `CHUNK_SPOOL_ERROR_CODES` from
3046
+ `stitchkit/files` — or a refusal reaches its client as an unknown 500.
3027
3047
  - **Progress counts file bytes**, inside a part too — the driver passes
3028
3048
  `onUploadProgress` into the part call, so the [upload
3029
3049
  progress](#upload-progress) route of the client applies. A repeated part
@@ -9047,9 +9067,11 @@ kind, because the handler's value is what gets printed, piped and aggregated:
9047
9067
  handed the envelope, `--count-by status` groups the *content parts* and answers
9048
9068
  `no record carries the field "status" — available: text, type`. So the CLI
9049
9069
  transport unwraps, and only it: `structuredContent` when the server sent one, a
9050
- lone text part when it parses as JSON, its text when it does not. Several parts,
9051
- an image or audio pass through whole — picking one of many would be inventing an
9052
- answer.
9070
+ lone text part when it parses as JSON, its text when it does not, and `null` when
9071
+ there are no parts at all — a tool without an output contract answers that way,
9072
+ and the `_meta` beside an empty `content` is protocol metadata, never the answer.
9073
+ Several parts, an image or audio pass through whole — picking one of many would
9074
+ be inventing an answer.
9053
9075
 
9054
9076
 
9055
9077
  ## Auth parity
@@ -18183,6 +18205,7 @@ The browser-and-server entrypoint. Re-exports everything from
18183
18205
  | `UploadProgress` | _type_ | `{ sentBytes, totalBytes, attempt }` heard by `onUploadProgress`: bytes of the encoded body handed to the network, first `0`, last `totalBytes`, counted again on each transport retry — [guide](../guide/client.md#upload-progress) |
18184
18206
  | `uploadInChunks` | function | send a file larger than one request as `init` → parts → `finalize` through three calls the app owns; client-minted id, repeats of a part on a failure that may pass, `finalize` never repeated, cancel checked between parts, progress in file bytes — [guide](../guide/client.md#chunked-uploads) |
18185
18207
  | `ChunkedUploadConfig` / `ChunkedUploadStart` / `ChunkedUploadPart` / `ChunkedUploadProgress` | _type_ | the driver's file, part size, retries and three calls; what `init` declares; one part; progress `{ sentBytes, totalBytes, index, chunkCount, attempt }` |
18208
+ | `ChunkSource` | _type_ | what the driver reads a file through — `size` and `slice(start, end)`; a `Blob` is one, so is a platform file that is not (an Expo `File`), and a part's `bytes` is what its `slice` returns |
18186
18209
  | `ContractClientConfig` | _type_ | per-tenant / resource-scoped client config — dynamic `pathPrefix` + `stripPrefixKeys` ([guide](../guide/client.md#contractclientconfig--per-tenant--resource-scoped-clients)) |
18187
18210
  | `contractEndpointMatchers` | function | compile exact pathname matchers for selected HTTP contract operations and expected-401 policy |
18188
18211
  | `PathPrefixArgs` | _type_ | required string-valued keys exposed to a typed dynamic `pathPrefix` callback |
@@ -20042,6 +20065,7 @@ available from `stitchkit/contract`.
20042
20065
  | `createChunkSpool` | function | the server half of a chunked upload: parts on disk under `owner` + client-minted `uploadId`, each with a size+sha256 receipt; idempotent `open` and `put`, the first writer of a part wins across processes, `assemble` in order once every part is in, `sweep` of untouched uploads — [guide](../guide/client.md#chunked-uploads) |
20043
20066
  | `ChunkSpool` / `ChunkSpoolConfig` / `ChunkSpoolKey` / `ChunkSpoolOpen` / `ChunkSpoolPart` / `ChunkSpoolAssembly` | _type_ | the spool, its directory, part size, file limit, meta schema and age; an upload's key; its declaration; one part; the assembled parts with a concatenating `stream()` |
20044
20067
  | `ChunkSpoolErrorCode` | _type_ | the `AppError` codes a spool refuses with, each with its 4xx status: `UPLOAD_INVALID`, `UPLOAD_TOO_LARGE`, `UPLOAD_NOT_FOUND`, `UPLOAD_CONFLICT`, `UPLOAD_CHUNK_OUT_OF_RANGE`, `UPLOAD_CHUNK_SIZE`, `UPLOAD_INCOMPLETE` |
20068
+ | `CHUNK_SPOOL_ERROR_CODES` / `isChunkSpoolErrorCode` | const / function | every `ChunkSpoolErrorCode` as a frozen list, and the guard for one — map them onto the app's own error codes, or a spool refusal reaches its client as an unknown 500 |
20045
20069
 
20046
20070
  ---
20047
20071
 
package/llms.txt CHANGED
@@ -9,7 +9,7 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
9
9
  Load the slice for each entrypoint your code imports — `import … from 'stitchkit/server'` → `llms/server.txt`; the root `stitchkit` import → `llms/stitchkit.txt`. A slice holds that entrypoint's API reference section and the guide pages whose home it is; every guide lives in exactly one slice, and a slice that needs another's guide names it under "Also read". Each file is at most 50.0 KB; a longer one continues in numbered parts, each naming the next at its top. Moving across versions: load `llms/upgrading.txt` and the range slices it lists between your version and the target. `llms-full.txt` inlines everything; it is far larger than a context window, so do not read it whole.
10
10
 
11
11
  ## Entrypoint slices
12
- - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 16.5 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 43.6 KB → [llms/stitchkit.3.txt](llms/stitchkit.3.txt) 16.9 KB
12
+ - **stitchkit**: [llms/stitchkit.txt](llms/stitchkit.txt) 16.5 KB → [llms/stitchkit.2.txt](llms/stitchkit.2.txt) 45.2 KB → [llms/stitchkit.3.txt](llms/stitchkit.3.txt) 17.1 KB
13
13
  - **stitchkit/live**: [llms/live.txt](llms/live.txt) 21.6 KB
14
14
  - **stitchkit/react**: [llms/react.txt](llms/react.txt) 9.0 KB
15
15
  - **stitchkit/react/keyboard**: [llms/react-keyboard.txt](llms/react-keyboard.txt) 9.4 KB
@@ -17,7 +17,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
17
17
  - **stitchkit/tools/contract**: [llms/tools-contract.txt](llms/tools-contract.txt) 0.2 KB
18
18
  - **stitchkit/tools/invoker**: [llms/tools-invoker.txt](llms/tools-invoker.txt) 0.2 KB
19
19
  - **stitchkit/tools/connections**: [llms/tools-connections.txt](llms/tools-connections.txt) 3.1 KB
20
- - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 42.7 KB → [llms/cli.2.txt](llms/cli.2.txt) 8.1 KB
20
+ - **stitchkit/cli**: [llms/cli.txt](llms/cli.txt) 42.8 KB → [llms/cli.2.txt](llms/cli.2.txt) 8.1 KB
21
21
  - **stitchkit/remote**: [llms/remote.txt](llms/remote.txt) 1.0 KB
22
22
  - **stitchkit/contract**: [llms/contract.txt](llms/contract.txt) 31.9 KB
23
23
  - **stitchkit/primitives**: [llms/primitives.txt](llms/primitives.txt) 9.3 KB
@@ -39,7 +39,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
39
39
  - **stitchkit/application/schemas**: [llms/application-schemas.txt](llms/application-schemas.txt) 1.8 KB
40
40
  - **stitchkit/testing**: [llms/testing.txt](llms/testing.txt) 30.8 KB
41
41
  - **stitchkit/agent-runtime/sandbox**: [llms/agent-runtime-sandbox.txt](llms/agent-runtime-sandbox.txt) 8.1 KB
42
- - **stitchkit/files**: [llms/files.txt](llms/files.txt) 3.8 KB
42
+ - **stitchkit/files**: [llms/files.txt](llms/files.txt) 4.1 KB
43
43
  - **stitchkit/telegram**: [llms/telegram.txt](llms/telegram.txt) 26.9 KB
44
44
  - **stitchkit/telegram/html**: [llms/telegram-html.txt](llms/telegram-html.txt) 2.7 KB
45
45
  - **stitchkit/telegram/screens**: [llms/telegram-screens.txt](llms/telegram-screens.txt) 21.2 KB
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.101.1",
3
+ "version": "0.101.3",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",