stitchkit 0.91.0 → 0.91.2

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,48 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.91.2] — 2026-09-22
19
+
20
+ ### Fixed
21
+
22
+ - **A refused union now presents the field it already collected.** 0.90.8 made
23
+ the real path available — and then `formatZodError` printed the first five
24
+ entries of a tree walk, which for a union over primitives (`z.json()`, or any
25
+ recursive schema) are the branches that failed on the type of the whole value:
26
+ all at the union's own path, all saying the same thing. A consuming session
27
+ read `(root)` five times and `...and 14 more issues` while the line naming
28
+ `nodes.0.streams` sat eighteenth of nineteen, and spent an hour on it. Three
29
+ changes, each measured on that payload: a branch is described by the **deepest
30
+ named field it reached** rather than by its first issue (which for a nested
31
+ union is that nested `invalid_union` at the parent's own path, saying nothing
32
+ new); a truncated summary keeps the branches that got **furthest** rather than
33
+ the first few; and the text projection prints one line per path, since the
34
+ union's own line already quotes the repeats and each one spends a slot. The
35
+ depth limit now bounds how many *issues* a nested union contributes and no
36
+ longer silences its own line, which used to read `nodes.0.streams: Invalid
37
+ input` on exactly the line that mattered. `zodIssues` and `details.issues` are
38
+ unchanged in shape and still carry every branch, repeats included — a machine
39
+ addresses them by branch number. An error with no unions prints exactly what
40
+ it printed before. → ADR 0188
41
+
42
+ ## [0.91.1] — 2026-09-22
43
+
44
+ ### Fixed
45
+
46
+ - **A refusal relayed from a discovered MCP tool no longer says "retryable" for
47
+ everything.** `mcpToolFailure` rebuilt the remote's refusal with a constant
48
+ 502 and read neither `retryable` nor `_hint` off the envelope it had just
49
+ parsed. 502 is a retryable class, so the status-derived answer was `true` for
50
+ every relayed failure there has ever been — `NOT_FOUND` included, and a model
51
+ reading it calls the missing thing again. That is the exact opposite of what
52
+ the field was added for in 0.91.0. Both fields are now carried as the remote
53
+ sent them: `retryable` only when it is a boolean, `_hint` only when it is a
54
+ string, so `0` or `'false'` stays undeclared rather than being coerced into a
55
+ decision. The status stays 502 in both branches — the failure did happen
56
+ upstream, and a declared `retryable` wins over it anyway. A remote that
57
+ declares nothing is unchanged, and the unstructured branch
58
+ (`UPSTREAM_TOOL_ERROR`) has nothing to declare and keeps the 502 default.
59
+
18
60
  ## [0.91.0] — 2026-09-22
19
61
 
20
62
  ### ⚠️ Breaking changes
@@ -6,7 +6,7 @@ import {
6
6
  composeAgentPrompt,
7
7
  createAgentRuntime,
8
8
  createAgentRuntimeEventSink
9
- } from "./index-bx6yq2m4.js";
9
+ } from "./index-7hz88dy8.js";
10
10
  import"./index-p13mwz16.js";
11
11
  import"./index-y64k3s0h.js";
12
12
  import {
@@ -19,10 +19,10 @@ import {
19
19
  walkContainedFiles
20
20
  } from "./index-bn2cjajt.js";
21
21
  import"./index-kw9t5ayn.js";
22
- import"./index-mqhjmadk.js";
22
+ import"./index-s3dssqxp.js";
23
23
  import"./index-vsbzgd7b.js";
24
24
  import"./index-f9mb610r.js";
25
- import"./index-13cjtmrw.js";
25
+ import"./index-e0znv5gn.js";
26
26
  import"./index-0a349c33.js";
27
27
  import"./index-rxfy4cq7.js";
28
28
  import"./index-6k1937bx.js";
@@ -24,7 +24,7 @@ import {
24
24
  renderAgentStateSlots,
25
25
  repairedSearchCall,
26
26
  selectAgentHistory
27
- } from "./index-bx6yq2m4.js";
27
+ } from "./index-7hz88dy8.js";
28
28
  import"./index-p13mwz16.js";
29
29
  import {
30
30
  AgentAdmissionEventSchema,
@@ -162,7 +162,7 @@ import {
162
162
  import {
163
163
  buildToolManifest,
164
164
  mountAgent
165
- } from "./index-f4p4b8f6.js";
165
+ } from "./index-pena034b.js";
166
166
  import {
167
167
  DURABILITY_STEP_EVENT_KIND,
168
168
  ParkAbortedError,
@@ -172,12 +172,12 @@ import {
172
172
  StepResultNotSerializableError,
173
173
  createLocalStepDurability
174
174
  } from "./index-kw9t5ayn.js";
175
- import"./index-qrbdq8jk.js";
176
- import"./index-1qvdwnp2.js";
177
- import"./index-mqhjmadk.js";
175
+ import"./index-a2nzz56k.js";
176
+ import"./index-4x809vqd.js";
177
+ import"./index-s3dssqxp.js";
178
178
  import"./index-vsbzgd7b.js";
179
179
  import"./index-f9mb610r.js";
180
- import"./index-13cjtmrw.js";
180
+ import"./index-e0znv5gn.js";
181
181
  import"./index-0a349c33.js";
182
182
  import"./index-rxfy4cq7.js";
183
183
  import"./index-6k1937bx.js";
package/dist/cli.js CHANGED
@@ -11,14 +11,14 @@ import {
11
11
  readCapped,
12
12
  renderCliView,
13
13
  routeCliArgv
14
- } from "./index-ya611vx3.js";
14
+ } from "./index-seyy8dvn.js";
15
15
  import"./index-sbdmyz75.js";
16
- import"./index-qrbdq8jk.js";
17
- import"./index-1qvdwnp2.js";
18
- import"./index-mqhjmadk.js";
16
+ import"./index-a2nzz56k.js";
17
+ import"./index-4x809vqd.js";
18
+ import"./index-s3dssqxp.js";
19
19
  import"./index-vsbzgd7b.js";
20
20
  import"./index-f9mb610r.js";
21
- import"./index-13cjtmrw.js";
21
+ import"./index-e0znv5gn.js";
22
22
  import"./index-0a349c33.js";
23
23
  import"./index-rxfy4cq7.js";
24
24
  import"./index-6k1937bx.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeToolMethod,
3
3
  toolErrorFromResult
4
- } from "./index-mqhjmadk.js";
4
+ } from "./index-s3dssqxp.js";
5
5
  import {
6
6
  assertToolExtensionCompatible,
7
7
  mergeSchemas,
@@ -37,7 +37,7 @@ import {
37
37
  import {
38
38
  ToolExecutionControlError,
39
39
  isToolExecutionControlError
40
- } from "./index-mqhjmadk.js";
40
+ } from "./index-s3dssqxp.js";
41
41
  import {
42
42
  isRecord,
43
43
  transportResult
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  contractToolMountable
3
- } from "./index-1qvdwnp2.js";
3
+ } from "./index-4x809vqd.js";
4
4
  import {
5
5
  runtimeToolMountable
6
6
  } from "./index-8z9we758.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  collectTools,
3
3
  createToolRunner
4
- } from "./index-1qvdwnp2.js";
4
+ } from "./index-4x809vqd.js";
5
5
  import {
6
6
  toolErrorFromResult
7
- } from "./index-mqhjmadk.js";
7
+ } from "./index-s3dssqxp.js";
8
8
  import {
9
9
  assertUniqueToolName
10
10
  } from "./index-fenaekmk.js";
@@ -20,12 +20,29 @@ function unionBranches(issue) {
20
20
  return;
21
21
  return errors;
22
22
  }
23
+ function deepestBranchReason(issues, prefix, budget) {
24
+ let deepest;
25
+ for (const issue of issues) {
26
+ const path = [...prefix, ...issue.path];
27
+ const nested = budget > 0 ? unionBranches(issue) : undefined;
28
+ const candidates = nested ? nested.map((branch) => deepestBranchReason(branch, path, budget - 1)).filter((reason) => reason !== undefined) : [{ path, message: issue.message }];
29
+ for (const candidate of candidates) {
30
+ if (!deepest || candidate.path.length > deepest.path.length)
31
+ deepest = candidate;
32
+ }
33
+ }
34
+ return deepest;
35
+ }
23
36
  function unionSummary(branches, prefix) {
24
- const described = branches.slice(0, MAX_DESCRIBED_BRANCHES).map((issues, index) => {
25
- const first = issues[0];
26
- if (!first)
27
- return `branch ${index + 1} reported no reason`;
28
- return `branch ${index + 1} at ${issuePath([...prefix, ...first.path])}: ${first.message}`;
37
+ const reasons = branches.map((issues, index) => ({
38
+ branch: index + 1,
39
+ reason: deepestBranchReason(issues, prefix, MAX_UNION_DEPTH)
40
+ }));
41
+ const ranked = [...reasons].sort((a, b) => (b.reason?.path.length ?? -1) - (a.reason?.path.length ?? -1));
42
+ const described = ranked.slice(0, MAX_DESCRIBED_BRANCHES).map(({ branch, reason }) => {
43
+ if (!reason)
44
+ return `branch ${branch} reported no reason`;
45
+ return `branch ${branch} at ${issuePath(reason.path)}: ${reason.message}`;
29
46
  });
30
47
  const rest = branches.length - described.length;
31
48
  const suffix = rest > 0 ? `; ...and ${rest} more branches` : "";
@@ -34,14 +51,14 @@ function unionSummary(branches, prefix) {
34
51
  function collectIssues(issues, prefix, branch, depth, into) {
35
52
  for (const issue of issues) {
36
53
  const path = [...prefix, ...issue.path];
37
- const branches = depth < MAX_UNION_DEPTH ? unionBranches(issue) : undefined;
54
+ const branches = unionBranches(issue);
38
55
  into.push({
39
56
  path: issuePath(path),
40
57
  code: issue.code,
41
58
  message: branches ? unionSummary(branches, path) : issue.message,
42
59
  ...branch !== undefined && { branch }
43
60
  });
44
- if (!branches)
61
+ if (!branches || depth >= MAX_UNION_DEPTH)
45
62
  continue;
46
63
  branches.forEach((branchIssues, index) => {
47
64
  collectIssues(branchIssues, path, index + 1, depth + 1, into);
@@ -55,7 +72,13 @@ function zodIssues(error) {
55
72
  }
56
73
  var MAX_FORMATTED_ISSUES = 5;
57
74
  function formatZodError(error) {
58
- const all = zodIssues(error);
75
+ const seen = new Set;
76
+ const all = zodIssues(error).filter((issue) => {
77
+ if (seen.has(issue.path))
78
+ return false;
79
+ seen.add(issue.path);
80
+ return true;
81
+ });
59
82
  const shown = all.slice(0, MAX_FORMATTED_ISSUES);
60
83
  const lines = shown.map((issue) => {
61
84
  const where = issue.branch === undefined ? issue.path : `${issue.path} (branch ${issue.branch})`;
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-2qzskm8h.js";
5
5
  import {
6
6
  zodIssues
7
- } from "./index-13cjtmrw.js";
7
+ } from "./index-e0znv5gn.js";
8
8
  import {
9
9
  AppError
10
10
  } from "./index-2vtcmrj9.js";
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  createValidatedRealtimeSocket,
12
12
  isModuleNotFound
13
- } from "./index-13e1k7v9.js";
13
+ } from "./index-f477k430.js";
14
14
  import {
15
15
  DEFAULT_PROCESS_SIGNALS,
16
16
  RUNTIME_CONTEXT_RESERVED_KEYS,
@@ -41,7 +41,7 @@ import {
41
41
  normalizeError,
42
42
  recordedErrorMessage,
43
43
  validateDeclaredOutput
44
- } from "./index-13cjtmrw.js";
44
+ } from "./index-e0znv5gn.js";
45
45
  import {
46
46
  DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
47
47
  joinRoutePath,
@@ -4,16 +4,16 @@ import {
4
4
  } from "./index-kw9t5ayn.js";
5
5
  import {
6
6
  collectToolSurface
7
- } from "./index-qrbdq8jk.js";
7
+ } from "./index-a2nzz56k.js";
8
8
  import {
9
9
  createToolRunner,
10
10
  formatToolError
11
- } from "./index-1qvdwnp2.js";
11
+ } from "./index-4x809vqd.js";
12
12
  import {
13
13
  isToolExecutionControlError,
14
14
  toolCauseFromResult,
15
15
  toolResultFromError
16
- } from "./index-mqhjmadk.js";
16
+ } from "./index-s3dssqxp.js";
17
17
  import {
18
18
  isRecord
19
19
  } from "./index-77fekveh.js";
@@ -6,7 +6,7 @@ import {
6
6
  formatZodError,
7
7
  normalizeError,
8
8
  validateDeclaredOutput
9
- } from "./index-13cjtmrw.js";
9
+ } from "./index-e0znv5gn.js";
10
10
  import {
11
11
  coerceJsonArgs
12
12
  } from "./index-7zbps32p.js";
@@ -3,19 +3,19 @@ import {
3
3
  } from "./index-sbdmyz75.js";
4
4
  import {
5
5
  collectToolSurface
6
- } from "./index-qrbdq8jk.js";
6
+ } from "./index-a2nzz56k.js";
7
7
  import {
8
8
  createToolRunner,
9
9
  formatToolError
10
- } from "./index-1qvdwnp2.js";
10
+ } from "./index-4x809vqd.js";
11
11
  import {
12
12
  toolErrorFromResult,
13
13
  toolResultFromError
14
- } from "./index-mqhjmadk.js";
14
+ } from "./index-s3dssqxp.js";
15
15
  import {
16
16
  formatZodError,
17
17
  validateDeclaredOutput
18
- } from "./index-13cjtmrw.js";
18
+ } from "./index-e0znv5gn.js";
19
19
  import {
20
20
  coerceJsonArgs
21
21
  } from "./index-7zbps32p.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  normalizeError
3
- } from "./index-13cjtmrw.js";
3
+ } from "./index-e0znv5gn.js";
4
4
 
5
5
  // src/internal/bounded-lines.ts
6
6
  var DEFAULT_STREAM_LINE_BYTES = 1024 * 1024;
@@ -3,7 +3,7 @@ import {
3
3
  inputIsQuery,
4
4
  parseSSE,
5
5
  readBoundedUtf8Lines
6
- } from "./index-b971qjes.js";
6
+ } from "./index-v5573g1k.js";
7
7
  import {
8
8
  ApiError,
9
9
  RequestCancellationError,
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  createUrlBuilder,
16
16
  createUrlBuilders,
17
17
  parseNDJSON
18
- } from "./index-137jjs4v.js";
18
+ } from "./index-yewwh1w4.js";
19
19
  import {
20
20
  REALTIME_REJECTION_KEY,
21
21
  asRealtimeRejection,
@@ -23,7 +23,7 @@ import {
23
23
  isModuleNotFound,
24
24
  parseRealtimeRequestAcknowledgement,
25
25
  parseRealtimeRequestArguments
26
- } from "./index-13e1k7v9.js";
26
+ } from "./index-f477k430.js";
27
27
  import {
28
28
  RealtimeRequestDisconnectedError,
29
29
  RealtimeRequestInvalidAcknowledgementError,
@@ -34,7 +34,7 @@ import {
34
34
  } from "./index-2qzskm8h.js";
35
35
  import {
36
36
  parseSSE
37
- } from "./index-b971qjes.js";
37
+ } from "./index-v5573g1k.js";
38
38
  import {
39
39
  LiveStateControllerStatusSchema,
40
40
  LiveStatePhaseSchema,
@@ -49,7 +49,7 @@ import {
49
49
  import {
50
50
  formatZodError,
51
51
  zodIssues
52
- } from "./index-13cjtmrw.js";
52
+ } from "./index-e0znv5gn.js";
53
53
  import {
54
54
  ALL_TRANSPORTS,
55
55
  ContractStreamFrameSchema,
@@ -25,6 +25,16 @@ export interface ZodIssueSummary {
25
25
  * the refusal names the branch and the path instead of only `(root)`.
26
26
  */
27
27
  export declare function zodIssues(error: z.ZodError): ZodIssueSummary[];
28
+ /**
29
+ * The text a person reads, which is a different job from the structured list.
30
+ *
31
+ * `zodIssues` keeps every branch failure, including the several that sit at the
32
+ * union's own path — a machine addresses them by branch number and wants them
33
+ * all. A reader gains nothing from the same path twice: the union's own line
34
+ * already quotes those reasons, and each repeat costs one of the few lines the
35
+ * cap allows. So the text keeps the first issue at each path and drops the
36
+ * rest, which is what leaves room for the line naming the field.
37
+ */
28
38
  export declare function formatZodError(error: z.ZodError): string;
29
39
  /**
30
40
  * The stable error code for a thrown value — `AppError.code`, `VALIDATION_ERROR`
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQvC,qFAAqF;AACrF,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAyED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,eAAe,EAAE,CAI9D;AAKD,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAWxD;AAKD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,MAAM,EAAE,OAAO,GACd,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAyBrD;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,EACb,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GACrC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAe9D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,IAAI,EAAE,OAAO,EACb,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GACrC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAe9D"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQvC,qFAAqF;AACrF,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwID;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,eAAe,EAAE,CAI9D;AAKD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAgBxD;AAKD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,MAAM,EAAE,OAAO,GACd,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAyBrD;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,EACb,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GACrC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAe9D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,IAAI,EAAE,OAAO,EACb,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GACrC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAe9D"}
package/dist/node.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  createHandler,
6
6
  createSocketIOServer,
7
7
  createUnixClientTransport
8
- } from "./index-zsqy3xfn.js";
8
+ } from "./index-jpfqfg5c.js";
9
9
  import"./index-y91ry9h2.js";
10
10
  import {
11
11
  ShutdownOptionsSchema,
@@ -14,7 +14,7 @@ import {
14
14
  ShutdownStatusSchema,
15
15
  createServerLifecycle
16
16
  } from "./index-3z73fh2c.js";
17
- import"./index-13e1k7v9.js";
17
+ import"./index-f477k430.js";
18
18
  import"./index-2qzskm8h.js";
19
19
  import {
20
20
  createImplement,
@@ -27,7 +27,7 @@ import {
27
27
  } from "./index-709nh7z7.js";
28
28
  import"./index-vsbzgd7b.js";
29
29
  import"./index-f9mb610r.js";
30
- import"./index-13cjtmrw.js";
30
+ import"./index-e0znv5gn.js";
31
31
  import"./index-0a349c33.js";
32
32
  import"./index-rxfy4cq7.js";
33
33
  import"./index-6k1937bx.js";
@@ -27,7 +27,7 @@ import {
27
27
  import"../index-f9mb610r.js";
28
28
  import {
29
29
  recordedErrorMessage
30
- } from "../index-13cjtmrw.js";
30
+ } from "../index-e0znv5gn.js";
31
31
  import"../index-0a349c33.js";
32
32
  import"../index-rxfy4cq7.js";
33
33
  import"../index-6k1937bx.js";
package/dist/remote.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createClient
3
- } from "./index-137jjs4v.js";
4
- import"./index-b971qjes.js";
3
+ } from "./index-yewwh1w4.js";
4
+ import"./index-v5573g1k.js";
5
5
  import {
6
6
  ApiError
7
7
  } from "./index-3xwxfj4z.js";
8
- import"./index-13cjtmrw.js";
8
+ import"./index-e0znv5gn.js";
9
9
  import {
10
10
  mergeMeta,
11
11
  resolveRouteParamsSchema
@@ -13,7 +13,7 @@ import {
13
13
  sseRoute,
14
14
  streamingRoute,
15
15
  webSocketLane
16
- } from "../index-zsqy3xfn.js";
16
+ } from "../index-jpfqfg5c.js";
17
17
  import"../index-y91ry9h2.js";
18
18
  import {
19
19
  withDeadline
@@ -25,13 +25,13 @@ import {
25
25
  ShutdownStatusSchema,
26
26
  createServerLifecycle
27
27
  } from "../index-3z73fh2c.js";
28
- import"../index-13e1k7v9.js";
28
+ import"../index-f477k430.js";
29
29
  import"../index-2qzskm8h.js";
30
30
  import {
31
31
  inputIsQuery,
32
32
  parseSSE,
33
33
  streamSSE
34
- } from "../index-b971qjes.js";
34
+ } from "../index-v5573g1k.js";
35
35
  import {
36
36
  composeAuthHooks,
37
37
  createAuthHook,
@@ -82,7 +82,7 @@ import {
82
82
  formatZodError,
83
83
  normalizeError,
84
84
  zodIssues
85
- } from "../index-13cjtmrw.js";
85
+ } from "../index-e0znv5gn.js";
86
86
  import {
87
87
  DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
88
88
  joinRoutePath,
package/dist/testing.js CHANGED
@@ -28,19 +28,19 @@ import {
28
28
  import {
29
29
  createClient,
30
30
  createClients
31
- } from "./index-137jjs4v.js";
31
+ } from "./index-yewwh1w4.js";
32
32
  import {
33
33
  RealtimeRequestDisconnectedError,
34
34
  RealtimeRequestInvalidAcknowledgementError,
35
35
  RealtimeRequestTimeoutError
36
36
  } from "./index-2qzskm8h.js";
37
- import"./index-b971qjes.js";
37
+ import"./index-v5573g1k.js";
38
38
  import"./index-3xwxfj4z.js";
39
39
  import {
40
40
  compareCodepoints,
41
41
  serializeCanonicalJson
42
42
  } from "./index-0j3vcp5m.js";
43
- import"./index-13cjtmrw.js";
43
+ import"./index-e0znv5gn.js";
44
44
  import {
45
45
  joinRoutePath
46
46
  } from "./index-0a349c33.js";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createToolInvoker
3
- } from "./index-bh70rk41.js";
4
- import"./index-1qvdwnp2.js";
5
- import"./index-mqhjmadk.js";
3
+ } from "./index-axvavfr4.js";
4
+ import"./index-4x809vqd.js";
5
+ import"./index-s3dssqxp.js";
6
6
  import"./index-vsbzgd7b.js";
7
7
  import"./index-f9mb610r.js";
8
- import"./index-13cjtmrw.js";
8
+ import"./index-e0znv5gn.js";
9
9
  import"./index-0a349c33.js";
10
10
  import"./index-rxfy4cq7.js";
11
11
  import"./index-6k1937bx.js";
@@ -543,7 +543,7 @@ function mcpToolFailure(toolName, result) {
543
543
  if (isRecord(payload) && typeof payload.error === "string") {
544
544
  const details = isRecord(payload.details) ? payload.details : undefined;
545
545
  const message = typeof details?.message === "string" ? details.message : payload.error;
546
- return new AppError(payload.error, message, 502, details);
546
+ return new AppError(payload.error, message, 502, details, typeof payload._hint === "string" ? payload._hint : undefined, undefined, typeof payload.retryable === "boolean" ? payload.retryable : undefined);
547
547
  }
548
548
  return new AppError(UPSTREAM_TOOL_ERROR, `External MCP tool "${toolName}" returned an error`, 502, payload === undefined ? undefined : { upstream: payload });
549
549
  }
@@ -34,11 +34,21 @@ export declare const UPSTREAM_TOOL_ERROR = "UPSTREAM_TOOL_ERROR";
34
34
  * it printed a code frame of the framework bundle before the JSON failure and
35
35
  * was then scrubbed to a bare `INTERNAL_SERVER_ERROR`.
36
36
  *
37
- * A structured `{ error, details }` body is the remote contract's own refusal
38
- * and is relayed as one. Anything else keeps the framework's sentence and
39
- * carries what the server did send — reporting less than we have is not caution.
37
+ * A structured `{ error, retryable, details, _hint }` body is the remote
38
+ * contract's own refusal and is relayed as one — every field of it. Anything
39
+ * else keeps the framework's sentence and carries what the server did send —
40
+ * reporting less than we have is not caution.
41
+ *
40
42
  * The status is 502 either way: whatever the code says, the failure happened
41
- * upstream, and a consumer re-serving it over HTTP should say so.
43
+ * upstream, and a consumer re-serving it over HTTP should say so. That constant
44
+ * is exactly why `retryable` has to be carried rather than re-derived. 502 is a
45
+ * retryable class, so a status-derived answer says `true` for every relayed
46
+ * refusal there has ever been — `NOT_FOUND` included, and a model reading it
47
+ * calls the missing thing again. The remote already decided, declared or
48
+ * derived from its own status, and its answer is the one that means something:
49
+ * it is the only side that knows whether repeating the call could work. `_hint`
50
+ * rides along for the same reason — it is the remote's instruction for what to
51
+ * do instead, and dropping it leaves the model with a refusal and no next move.
42
52
  */
43
53
  export declare function mcpToolFailure(toolName: string, result: unknown): AppError;
44
54
  //# sourceMappingURL=mcp-envelope.d.ts.map
@@ -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;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,QAAQ,CAa1E"}
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"}
package/dist/tools.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  buildToolManifest,
27
27
  describeToolCatalog,
28
28
  mountAgent
29
- } from "./index-f4p4b8f6.js";
29
+ } from "./index-pena034b.js";
30
30
  import {
31
31
  AgentToolError,
32
32
  createLocalStepDurability,
@@ -46,7 +46,7 @@ import {
46
46
  } from "./index-4fpa9dy2.js";
47
47
  import {
48
48
  createToolInvoker
49
- } from "./index-bh70rk41.js";
49
+ } from "./index-axvavfr4.js";
50
50
  import {
51
51
  WaitTimeoutError,
52
52
  createCli,
@@ -55,22 +55,22 @@ import {
55
55
  fetchPinnedDocument,
56
56
  readCapped,
57
57
  runWaitOperation
58
- } from "./index-ya611vx3.js";
58
+ } from "./index-seyy8dvn.js";
59
59
  import"./index-sbdmyz75.js";
60
60
  import {
61
61
  collectToolSurface
62
- } from "./index-qrbdq8jk.js";
62
+ } from "./index-a2nzz56k.js";
63
63
  import {
64
64
  collectTools,
65
65
  createToolRunner,
66
66
  formatToolError
67
- } from "./index-1qvdwnp2.js";
67
+ } from "./index-4x809vqd.js";
68
68
  import {
69
69
  ToolExecutionControlError,
70
70
  executeToolMethod,
71
71
  isToolExecutionControlError,
72
72
  toolResultFromError
73
- } from "./index-mqhjmadk.js";
73
+ } from "./index-s3dssqxp.js";
74
74
  import {
75
75
  getRequestContext,
76
76
  getTraceId,
@@ -79,7 +79,7 @@ import {
79
79
  import"./index-f9mb610r.js";
80
80
  import {
81
81
  normalizeError
82
- } from "./index-13cjtmrw.js";
82
+ } from "./index-e0znv5gn.js";
83
83
  import {
84
84
  defineContract
85
85
  } from "./index-0a349c33.js";
package/llms-full.txt CHANGED
@@ -6110,6 +6110,15 @@ const signals = bindProcessSignals(app, {
6110
6110
  await app.start()
6111
6111
  ```
6112
6112
 
6113
+ **Bind before you start, and the order is load-bearing.** Reading it the other way
6114
+ round — start serving, then arrange for shutdown — leaves a window between the
6115
+ first accepted request and the first listener, and a supervisor that sends
6116
+ `SIGTERM` inside that window kills the process outright: exit 143, no shutdown
6117
+ chain, no `onComplete`, nothing drained. The window is small and opens exactly
6118
+ when the machine is busiest, which is when a supervisor is most likely to be
6119
+ restarting something. `bindProcessSignals` does not start anything, so there is
6120
+ no cost to binding first.
6121
+
6113
6122
  The exact resource callbacks are typed by their public configuration. The
6114
6123
  important ownership rule is stable: the application decides what the
6115
6124
  database/server/provider objects are and how they are configured; Stitchkit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.91.0",
3
+ "version": "0.91.2",
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",