stitchkit 0.60.0 → 0.60.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/agent-runtime/coordinator.d.ts +10 -0
  2. package/dist/agent-runtime/coordinator.d.ts.map +1 -1
  3. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  4. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  5. package/dist/agent-runtime/schemas.d.ts.map +1 -1
  6. package/dist/agent-runtime/store-driver.d.ts.map +1 -1
  7. package/dist/agent-runtime.js +97 -12
  8. package/dist/application/grammy.d.ts +12 -6
  9. package/dist/application/grammy.d.ts.map +1 -1
  10. package/dist/application/kernel.d.ts +12 -2
  11. package/dist/application/kernel.d.ts.map +1 -1
  12. package/dist/application-grammy.js +5 -3
  13. package/dist/application.js +2 -1
  14. package/dist/cli.js +5 -4
  15. package/dist/contract/errors.d.ts +1 -0
  16. package/dist/contract/errors.d.ts.map +1 -1
  17. package/dist/contract/index.js +1 -1
  18. package/dist/{index-8pc5s3pz.js → index-1pgeyyee.js} +3 -3
  19. package/dist/{index-f7521k0x.js → index-2cgbdckv.js} +7 -5
  20. package/dist/{index-8es1hrv4.js → index-6taryy00.js} +1 -1
  21. package/dist/{index-1zencgcb.js → index-82e74yfx.js} +5 -3
  22. package/dist/{index-3w74r08v.js → index-mfw1pec7.js} +7 -5
  23. package/dist/{index-9h1vba8n.js → index-t8xrqc9g.js} +1 -0
  24. package/dist/{index-6fbp58g8.js → index-tvwcrx2d.js} +4 -2
  25. package/dist/{index-v6e8hnkx.js → index-wd8g8z6e.js} +1 -84
  26. package/dist/{index-2akar0rq.js → index-wrhf06ak.js} +7 -5
  27. package/dist/index-xxye8j3k.js +85 -0
  28. package/dist/{index-3hn10n4c.js → index-y91zd0ch.js} +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/node.js +8 -7
  31. package/dist/observability/index.js +4 -3
  32. package/dist/remote.js +4 -2
  33. package/dist/server/index.js +14 -13
  34. package/dist/testing.js +2 -1
  35. package/dist/tools.js +11 -9
  36. package/llms-full.txt +58 -56
  37. package/package.json +5 -5
@@ -1,13 +1,15 @@
1
1
  import {
2
- AppError,
3
2
  isUnsafeKey
4
- } from "./index-v6e8hnkx.js";
3
+ } from "./index-wd8g8z6e.js";
5
4
  import {
6
5
  resolveTraceContext
7
6
  } from "./index-pzyt11ch.js";
8
7
  import {
9
8
  isRecord
10
9
  } from "./index-smpbdg6k.js";
10
+ import {
11
+ AppError
12
+ } from "./index-xxye8j3k.js";
11
13
 
12
14
  // src/internal/errors.ts
13
15
  import { z } from "zod";
@@ -2,89 +2,6 @@ import {
2
2
  parseTrailingWildcard
3
3
  } from "./index-pzyt11ch.js";
4
4
 
5
- // src/contract/errors.ts
6
- var APP_ERROR_BRAND = Symbol.for("stitchkit.AppError");
7
-
8
- class AppError extends Error {
9
- code;
10
- status;
11
- details;
12
- hint;
13
- traceId;
14
- constructor(code, message, status = 500, details, hint, traceId) {
15
- super(message ?? code);
16
- this.code = code;
17
- this.status = status;
18
- this.details = details;
19
- this.hint = hint;
20
- this.traceId = traceId;
21
- this.name = "AppError";
22
- Object.defineProperty(this, APP_ERROR_BRAND, { value: true });
23
- }
24
- static is(err) {
25
- return typeof err === "object" && err !== null && APP_ERROR_BRAND in err;
26
- }
27
- toJSON() {
28
- return {
29
- error: {
30
- code: this.code,
31
- message: this.message,
32
- ...this.details && { details: this.details },
33
- ...this.hint && { hint: this.hint }
34
- }
35
- };
36
- }
37
- }
38
- function notFound(message = "Not found") {
39
- throw new AppError("NOT_FOUND", message, 404);
40
- }
41
- function badRequest(message, details) {
42
- throw new AppError("BAD_REQUEST", message, 400, details);
43
- }
44
- function unauthorized(message = "Unauthorized") {
45
- throw new AppError("UNAUTHORIZED", message, 401);
46
- }
47
- function forbidden(message = "Forbidden") {
48
- throw new AppError("FORBIDDEN", message, 403);
49
- }
50
- function conflict(message = "Conflict", details) {
51
- throw new AppError("CONFLICT", message, 409, details);
52
- }
53
- function rateLimited(message = "Too many requests") {
54
- throw new AppError("RATE_LIMITED", message, 429);
55
- }
56
- var STITCH_ERROR_STATUS = {
57
- BAD_REQUEST: 400,
58
- UNAUTHORIZED: 401,
59
- FORBIDDEN: 403,
60
- NOT_FOUND: 404,
61
- METHOD_NOT_ALLOWED: 405,
62
- CONFLICT: 409,
63
- RATE_LIMITED: 429,
64
- VALIDATION_ERROR: 400,
65
- FILE_INVALID_PATH: 400,
66
- FILE_OUTSIDE_ROOT: 400,
67
- FILE_NOT_FOUND: 404,
68
- FILE_NOT_REGULAR: 422,
69
- FILE_INSPECTION_REJECTED: 422,
70
- FILE_TOO_LARGE: 413,
71
- FILE_EXISTS: 409,
72
- REALTIME_CONTRACT_VIOLATION: 500,
73
- APPLICATION_NOT_ACCEPTING: 503,
74
- WAIT_TIMEOUT: 408,
75
- WAIT_FAILED: 409,
76
- DOWNLOAD_NOT_FOUND: 404,
77
- VIEW_HTTP_ERROR: 502,
78
- OPERATION_NOT_SUCCEEDED: 409,
79
- INTERNAL_SERVER_ERROR: 500
80
- };
81
- function isStitchErrorCode(code) {
82
- return Object.hasOwn(STITCH_ERROR_STATUS, code);
83
- }
84
- function appError(code, message, details) {
85
- throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
86
- }
87
-
88
5
  // src/contract/define.ts
89
6
  import { z } from "zod";
90
7
 
@@ -286,4 +203,4 @@ function base64UrlToBytes(segment) {
286
203
  const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, "=");
287
204
  return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
288
205
  }
289
- export { isUnsafeKey, safeJsonParse, defineContract, mergeMeta, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, bytesToBase64Url, base64UrlToBytes };
206
+ export { isUnsafeKey, safeJsonParse, defineContract, mergeMeta, bytesToBase64Url, base64UrlToBytes };
@@ -7,17 +7,19 @@ import {
7
7
  normalizeError,
8
8
  runWithRequestContext,
9
9
  validateDeclaredOutput
10
- } from "./index-6fbp58g8.js";
10
+ } from "./index-tvwcrx2d.js";
11
11
  import {
12
- AppError,
13
- STITCH_ERROR_STATUS,
14
- isStitchErrorCode,
15
12
  isUnsafeKey,
16
13
  safeJsonParse
17
- } from "./index-v6e8hnkx.js";
14
+ } from "./index-wd8g8z6e.js";
18
15
  import {
19
16
  isRecord
20
17
  } from "./index-smpbdg6k.js";
18
+ import {
19
+ AppError,
20
+ STITCH_ERROR_STATUS,
21
+ isStitchErrorCode
22
+ } from "./index-xxye8j3k.js";
21
23
 
22
24
  // src/tools/coerce.ts
23
25
  import { z } from "zod";
@@ -0,0 +1,85 @@
1
+ // src/contract/errors.ts
2
+ var APP_ERROR_BRAND = Symbol.for("stitchkit.AppError");
3
+
4
+ class AppError extends Error {
5
+ code;
6
+ status;
7
+ details;
8
+ hint;
9
+ traceId;
10
+ constructor(code, message, status = 500, details, hint, traceId) {
11
+ super(message ?? code);
12
+ this.code = code;
13
+ this.status = status;
14
+ this.details = details;
15
+ this.hint = hint;
16
+ this.traceId = traceId;
17
+ this.name = "AppError";
18
+ Object.defineProperty(this, APP_ERROR_BRAND, { value: true });
19
+ }
20
+ static is(err) {
21
+ return typeof err === "object" && err !== null && APP_ERROR_BRAND in err;
22
+ }
23
+ toJSON() {
24
+ return {
25
+ error: {
26
+ code: this.code,
27
+ message: this.message,
28
+ ...this.details && { details: this.details },
29
+ ...this.hint && { hint: this.hint }
30
+ }
31
+ };
32
+ }
33
+ }
34
+ function notFound(message = "Not found") {
35
+ throw new AppError("NOT_FOUND", message, 404);
36
+ }
37
+ function badRequest(message, details) {
38
+ throw new AppError("BAD_REQUEST", message, 400, details);
39
+ }
40
+ function unauthorized(message = "Unauthorized") {
41
+ throw new AppError("UNAUTHORIZED", message, 401);
42
+ }
43
+ function forbidden(message = "Forbidden") {
44
+ throw new AppError("FORBIDDEN", message, 403);
45
+ }
46
+ function conflict(message = "Conflict", details) {
47
+ throw new AppError("CONFLICT", message, 409, details);
48
+ }
49
+ function rateLimited(message = "Too many requests") {
50
+ throw new AppError("RATE_LIMITED", message, 429);
51
+ }
52
+ var STITCH_ERROR_STATUS = {
53
+ BAD_REQUEST: 400,
54
+ UNAUTHORIZED: 401,
55
+ FORBIDDEN: 403,
56
+ NOT_FOUND: 404,
57
+ METHOD_NOT_ALLOWED: 405,
58
+ CONFLICT: 409,
59
+ RATE_LIMITED: 429,
60
+ VALIDATION_ERROR: 400,
61
+ FILE_INVALID_PATH: 400,
62
+ FILE_OUTSIDE_ROOT: 400,
63
+ FILE_NOT_FOUND: 404,
64
+ FILE_NOT_REGULAR: 422,
65
+ FILE_INSPECTION_REJECTED: 422,
66
+ FILE_TOO_LARGE: 413,
67
+ FILE_EXISTS: 409,
68
+ REALTIME_CONTRACT_VIOLATION: 500,
69
+ APPLICATION_NOT_ACCEPTING: 503,
70
+ GRAMMY_WEBHOOK_NOT_ACCEPTING: 503,
71
+ WAIT_TIMEOUT: 408,
72
+ WAIT_FAILED: 409,
73
+ DOWNLOAD_NOT_FOUND: 404,
74
+ VIEW_HTTP_ERROR: 502,
75
+ OPERATION_NOT_SUCCEEDED: 409,
76
+ INTERNAL_SERVER_ERROR: 500
77
+ };
78
+ function isStitchErrorCode(code) {
79
+ return Object.hasOwn(STITCH_ERROR_STATUS, code);
80
+ }
81
+ function appError(code, message, details) {
82
+ throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
83
+ }
84
+
85
+ export { AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  isUnsafeKey,
3
3
  mergeMeta
4
- } from "./index-v6e8hnkx.js";
4
+ } from "./index-wd8g8z6e.js";
5
5
  import {
6
6
  callRuntimeHandler,
7
7
  isRecord,
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  parseTrailingWildcard,
20
20
  rateLimited,
21
21
  unauthorized
22
- } from "./index-9h1vba8n.js";
22
+ } from "./index-t8xrqc9g.js";
23
23
  import {
24
24
  isRecord,
25
25
  mapObject,
package/dist/node.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  bindRealtimeServer,
4
4
  createHandler,
5
5
  createSocketIOServer
6
- } from "./index-f7521k0x.js";
6
+ } from "./index-2cgbdckv.js";
7
7
  import {
8
8
  createImplement,
9
9
  createImplementRegistry,
@@ -12,7 +12,7 @@ import {
12
12
  createScopedImplementRegistry,
13
13
  implement,
14
14
  implementRegistry
15
- } from "./index-3hn10n4c.js";
15
+ } from "./index-y91zd0ch.js";
16
16
  import"./index-557by2db.js";
17
17
  import {
18
18
  ShutdownOptionsSchema,
@@ -21,7 +21,11 @@ import {
21
21
  ShutdownStatusSchema,
22
22
  createServerLifecycle
23
23
  } from "./index-dk6e56g0.js";
24
- import"./index-6fbp58g8.js";
24
+ import"./index-tvwcrx2d.js";
25
+ import"./index-wd8g8z6e.js";
26
+ import"./index-6k1937bx.js";
27
+ import"./index-pzyt11ch.js";
28
+ import"./index-smpbdg6k.js";
25
29
  import {
26
30
  AppError,
27
31
  appError,
@@ -31,10 +35,7 @@ import {
31
35
  notFound,
32
36
  rateLimited,
33
37
  unauthorized
34
- } from "./index-v6e8hnkx.js";
35
- import"./index-6k1937bx.js";
36
- import"./index-pzyt11ch.js";
37
- import"./index-smpbdg6k.js";
38
+ } from "./index-xxye8j3k.js";
38
39
  // src/server/node.ts
39
40
  import { serve } from "srvx/node";
40
41
 
@@ -10,7 +10,7 @@ import {
10
10
  redact,
11
11
  sanitizePayload,
12
12
  truncatePreview
13
- } from "../index-8es1hrv4.js";
13
+ } from "../index-6taryy00.js";
14
14
  import {
15
15
  getRequestContext,
16
16
  getTraceId,
@@ -22,8 +22,8 @@ import {
22
22
  setRequestError,
23
23
  setRequestUser,
24
24
  wrapInRequestContext
25
- } from "../index-6fbp58g8.js";
26
- import"../index-v6e8hnkx.js";
25
+ } from "../index-tvwcrx2d.js";
26
+ import"../index-wd8g8z6e.js";
27
27
  import"../index-6k1937bx.js";
28
28
  import {
29
29
  childSpan,
@@ -36,6 +36,7 @@ import {
36
36
  import {
37
37
  isRecord
38
38
  } from "../index-smpbdg6k.js";
39
+ import"../index-xxye8j3k.js";
39
40
 
40
41
  // src/observability/audit.ts
41
42
  function toolErrorMessage(result) {
package/dist/remote.js CHANGED
@@ -4,14 +4,16 @@ import {
4
4
  } from "./index-svqhcrrj.js";
5
5
  import"./index-48ffdxgk.js";
6
6
  import {
7
- AppError,
8
7
  mergeMeta
9
- } from "./index-v6e8hnkx.js";
8
+ } from "./index-wd8g8z6e.js";
10
9
  import"./index-6k1937bx.js";
11
10
  import"./index-pzyt11ch.js";
12
11
  import {
13
12
  isRecord
14
13
  } from "./index-smpbdg6k.js";
14
+ import {
15
+ AppError
16
+ } from "./index-xxye8j3k.js";
15
17
 
16
18
  // src/tools/remote.ts
17
19
  var HTTP_ONLY = Object.freeze(["HTTP"]);
@@ -7,7 +7,7 @@ import {
7
7
  parseMultipart,
8
8
  socketIoLane,
9
9
  webSocketLane
10
- } from "../index-f7521k0x.js";
10
+ } from "../index-2cgbdckv.js";
11
11
  import {
12
12
  composeAuthHooks,
13
13
  createAuthHook,
@@ -20,7 +20,7 @@ import {
20
20
  signJwt,
21
21
  verifyJwt,
22
22
  verifyPkce
23
- } from "../index-3w74r08v.js";
23
+ } from "../index-mfw1pec7.js";
24
24
  import {
25
25
  DEFAULT_CORS_ALLOW_HEADERS,
26
26
  DEFAULT_CORS_EXPOSE_HEADERS,
@@ -34,7 +34,7 @@ import {
34
34
  defineMultipartStream,
35
35
  implement,
36
36
  implementRegistry
37
- } from "../index-3hn10n4c.js";
37
+ } from "../index-y91zd0ch.js";
38
38
  import {
39
39
  isWithinDir,
40
40
  realPathWithinDir
@@ -65,7 +65,16 @@ import {
65
65
  resolveSocketIp,
66
66
  resolveTraceId,
67
67
  zodIssues
68
- } from "../index-6fbp58g8.js";
68
+ } from "../index-tvwcrx2d.js";
69
+ import"../index-wd8g8z6e.js";
70
+ import"../index-6k1937bx.js";
71
+ import {
72
+ joinRoutePath,
73
+ parseTrailingWildcard
74
+ } from "../index-pzyt11ch.js";
75
+ import {
76
+ isRecord
77
+ } from "../index-smpbdg6k.js";
69
78
  import {
70
79
  AppError,
71
80
  STITCH_ERROR_STATUS,
@@ -77,15 +86,7 @@ import {
77
86
  notFound,
78
87
  rateLimited,
79
88
  unauthorized
80
- } from "../index-v6e8hnkx.js";
81
- import"../index-6k1937bx.js";
82
- import {
83
- joinRoutePath,
84
- parseTrailingWildcard
85
- } from "../index-pzyt11ch.js";
86
- import {
87
- isRecord
88
- } from "../index-smpbdg6k.js";
89
+ } from "../index-xxye8j3k.js";
89
90
  // src/server/bun.ts
90
91
  import { chmodSync, statSync, unlinkSync } from "node:fs";
91
92
  function reclaimStaleUnixSocket(path) {
package/dist/testing.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-vtjgx3vv.js";
5
5
  import {
6
6
  createApplication
7
- } from "./index-1zencgcb.js";
7
+ } from "./index-82e74yfx.js";
8
8
  import"./index-8eywc9zv.js";
9
9
  import {
10
10
  RealtimeRequestDisconnectedError,
@@ -32,6 +32,7 @@ import {
32
32
  import {
33
33
  isRecord
34
34
  } from "./index-smpbdg6k.js";
35
+ import"./index-xxye8j3k.js";
35
36
 
36
37
  // src/agent-runtime/testing.ts
37
38
  function createAgentRaceBarrier(timeoutMs = 5000) {
package/dist/tools.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  signJwt,
3
3
  verifyPkce
4
- } from "./index-3w74r08v.js";
4
+ } from "./index-mfw1pec7.js";
5
5
  import {
6
6
  DEFAULT_CORS_ALLOW_HEADERS,
7
7
  DEFAULT_PROCESS_SIGNALS,
@@ -9,7 +9,7 @@ import {
9
9
  defaultSignalSource,
10
10
  guardSignalCallback,
11
11
  reportSignalError
12
- } from "./index-3hn10n4c.js";
12
+ } from "./index-y91zd0ch.js";
13
13
  import {
14
14
  WaitTimeoutError,
15
15
  collectToolSurface,
@@ -24,7 +24,7 @@ import {
24
24
  formatToolError,
25
25
  readCapped,
26
26
  runWaitOperation
27
- } from "./index-8pc5s3pz.js";
27
+ } from "./index-1pgeyyee.js";
28
28
  import {
29
29
  ToolExecutionControlError,
30
30
  coerceJsonArgs,
@@ -32,7 +32,7 @@ import {
32
32
  isToolExecutionControlError,
33
33
  toolErrorFromResult,
34
34
  toolResultFromError
35
- } from "./index-2akar0rq.js";
35
+ } from "./index-wrhf06ak.js";
36
36
  import {
37
37
  ManagedFileError
38
38
  } from "./index-bfcpjw20.js";
@@ -52,18 +52,16 @@ import"./index-6djpbnda.js";
52
52
  import"./index-cby4ar3v.js";
53
53
  import {
54
54
  redact
55
- } from "./index-8es1hrv4.js";
55
+ } from "./index-6taryy00.js";
56
56
  import {
57
57
  getRequestContext,
58
58
  getTraceId,
59
59
  normalizeError,
60
60
  runWithRequestContext
61
- } from "./index-6fbp58g8.js";
61
+ } from "./index-tvwcrx2d.js";
62
62
  import {
63
- AppError,
64
- STITCH_ERROR_STATUS,
65
63
  defineContract
66
- } from "./index-v6e8hnkx.js";
64
+ } from "./index-wd8g8z6e.js";
67
65
  import {
68
66
  ManagedFilePathSchema,
69
67
  ManagedFileRefSchema
@@ -74,6 +72,10 @@ import {
74
72
  import {
75
73
  isRecord
76
74
  } from "./index-smpbdg6k.js";
75
+ import {
76
+ AppError,
77
+ STITCH_ERROR_STATUS
78
+ } from "./index-xxye8j3k.js";
77
79
 
78
80
  // src/tools/agent.ts
79
81
  import { jsonSchema, tool } from "ai";
package/llms-full.txt CHANGED
@@ -7496,10 +7496,12 @@ if (error instanceof AgentRuntimeConflictError) …
7496
7496
  `ActivityTokenBrand` is exported, so `ActivityProjection` can be implemented by
7497
7497
  a test double. `STITCH_ERROR_STATUS` gained `APPLICATION_NOT_ACCEPTING` (503) —
7498
7498
  only an exhaustive `satisfies Record<StitchErrorCode, …>` map stops compiling,
7499
- and the fix is one line. `GRAMMY_WEBHOOK_NOT_ACCEPTING` is deliberately *not*
7500
- registered: the registry belongs to the generic core, and a provider name has no
7501
- place in a union every consumer imports. It travels as itself through a partial
7502
- `codeMap`.
7499
+ and the fix is one line. (`GRAMMY_WEBHOOK_NOT_ACCEPTING` joined it in 0.60.1,
7500
+ under the same rule see ADR 0105. This section briefly said the opposite: that
7501
+ an adapter's code stays out of the registry. It does not, and leaving it out was
7502
+ the worse of the two, because `isStitchErrorCode` then answered `false` and the
7503
+ code reached the wire spelled stitchkit's way, past both `codeMap` and
7504
+ `unmappedCode`.)
7503
7505
 
7504
7506
  `application.shutdown()` no longer accepts `retryAfterSeconds`. Delete it from
7505
7507
  the call — the kernel never read it. If you meant the HTTP `Retry-After` a
@@ -7995,58 +7997,6 @@ The Node-shaped callback is gone, and the policy is now composed with shutdown
7995
7997
  admission on both runtimes: a handshake arriving during drain is refused for
7996
7998
  you.
7997
7999
 
7998
- ## Released migration: 0.46.0
7999
-
8000
- ### `REALTIME_CONTRACT_VIOLATION` joined the error registry
8001
-
8002
- Realtime contract failures use the framework error model instead of a bare
8003
- `ZodError`, so an exhaustive map stops compiling until the code is added:
8004
-
8005
- ```ts
8006
- // before
8007
- { …, INTERNAL_SERVER_ERROR: 'internal' } satisfies Record<StitchErrorCode, string>
8008
- // after
8009
- { …, INTERNAL_SERVER_ERROR: 'internal', REALTIME_CONTRACT_VIOLATION: 'internal' } satisfies Record<StitchErrorCode, string>
8010
- ```
8011
-
8012
- Only an exhaustive map breaks. Since 0.56.1 `codeMap` itself is partial, so a
8013
- map without the `satisfies` keeps compiling and lets the code travel as itself.
8014
-
8015
- ### `RealtimeRejectedEvent.error` is an `AppError`
8016
-
8017
- ```ts
8018
- // before
8019
- onRejected: ({ error }) => error.issues
8020
- // after
8021
- onRejected: ({ error }) => error.details?.issues // the ZodError moves to error.cause
8022
- ```
8023
-
8024
- The envelope gained `reason` and `fault`. The consequence worth checking: code
8025
- reading `.issues` directly does not fail to compile if the handler is loosely
8026
- typed — it silently reads `undefined`. Grep for `.issues` on rejection handlers.
8027
-
8028
- ### CLI construction refuses reserved names
8029
-
8030
- A contract field or tool named `json`, `wait`, `quiet`, `dry-run`, `help`,
8031
- `version`, `wait-timeout` or `output-dir` now **throws while the CLI is built**,
8032
- instead of being silently shadowed:
8033
-
8034
- ```ts
8035
- // before: app schedule_job --wait 2h → {"path":"2h"}, exit 0
8036
- // after: building a CLI over a contract with a "wait" field throws
8037
- ```
8038
-
8039
- This one fires at startup, not at call time, so an application shipping such a
8040
- field crashes on boot after the upgrade. That is deliberate — the old behaviour
8041
- corrupted arguments silently — but it means the upgrade is not safe to deploy
8042
- without building the CLI once locally.
8043
-
8044
- ### `createToolLogger` writes to stderr
8045
-
8046
- stdout is the JSON-RPC channel of a stdio MCP server, and the previous
8047
- `console.info` default corrupted it. Pass `log` to redirect if your process
8048
- collected tool logs from stdout.
8049
-
8050
8000
  ## Released migration: 0.48.0
8051
8001
 
8052
8002
  ### Typed-client request options move to `.withOptions`
@@ -8172,6 +8122,58 @@ contract shape.
8172
8122
  (`STITCH_ERROR_STATUS`, `serveFile`, `scopePrefixes`, `afterToolCall`'s
8173
8123
  `MethodDef`, `maxUploadBytes`) are available to adopt, not required.
8174
8124
 
8125
+ ## Released migration: 0.46.0
8126
+
8127
+ ### `REALTIME_CONTRACT_VIOLATION` joined the error registry
8128
+
8129
+ Realtime contract failures use the framework error model instead of a bare
8130
+ `ZodError`, so an exhaustive map stops compiling until the code is added:
8131
+
8132
+ ```ts
8133
+ // before
8134
+ { …, INTERNAL_SERVER_ERROR: 'internal' } satisfies Record<StitchErrorCode, string>
8135
+ // after
8136
+ { …, INTERNAL_SERVER_ERROR: 'internal', REALTIME_CONTRACT_VIOLATION: 'internal' } satisfies Record<StitchErrorCode, string>
8137
+ ```
8138
+
8139
+ Only an exhaustive map breaks. Since 0.56.1 `codeMap` itself is partial, so a
8140
+ map without the `satisfies` keeps compiling and lets the code travel as itself.
8141
+
8142
+ ### `RealtimeRejectedEvent.error` is an `AppError`
8143
+
8144
+ ```ts
8145
+ // before
8146
+ onRejected: ({ error }) => error.issues
8147
+ // after
8148
+ onRejected: ({ error }) => error.details?.issues // the ZodError moves to error.cause
8149
+ ```
8150
+
8151
+ The envelope gained `reason` and `fault`. The consequence worth checking: code
8152
+ reading `.issues` directly does not fail to compile if the handler is loosely
8153
+ typed — it silently reads `undefined`. Grep for `.issues` on rejection handlers.
8154
+
8155
+ ### CLI construction refuses reserved names
8156
+
8157
+ A contract field or tool named `json`, `wait`, `quiet`, `dry-run`, `help`,
8158
+ `version`, `wait-timeout` or `output-dir` now **throws while the CLI is built**,
8159
+ instead of being silently shadowed:
8160
+
8161
+ ```ts
8162
+ // before: app schedule_job --wait 2h → {"path":"2h"}, exit 0
8163
+ // after: building a CLI over a contract with a "wait" field throws
8164
+ ```
8165
+
8166
+ This one fires at startup, not at call time, so an application shipping such a
8167
+ field crashes on boot after the upgrade. That is deliberate — the old behaviour
8168
+ corrupted arguments silently — but it means the upgrade is not safe to deploy
8169
+ without building the CLI once locally.
8170
+
8171
+ ### `createToolLogger` writes to stderr
8172
+
8173
+ stdout is the JSON-RPC channel of a stdio MCP server, and the previous
8174
+ `console.info` default corrupted it. Pass `log` to redirect if your process
8175
+ collected tool logs from stdout.
8176
+
8175
8177
  ## Released migration: 0.44.0
8176
8178
 
8177
8179
  ### MCP TypeScript SDK v2 and protocol `2026-07-28`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.60.0",
3
+ "version": "0.60.1",
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",
@@ -207,18 +207,18 @@
207
207
  "@openrouter/ai-sdk-provider": "^3.0.0",
208
208
  "@socket.io/bun-engine": "^0.1.1",
209
209
  "@socket.io/component-emitter": "^3.1.2",
210
- "@tanstack/react-query": "5.101.4",
211
- "@types/bun": "^1.3.14",
210
+ "@tanstack/react-query": "5.102.3",
211
+ "@types/bun": "^1.4.0",
212
212
  "@types/json-schema": "^7.0.15",
213
213
  "@types/react": "^19.2.18",
214
214
  "@typescript/typescript6": "^6.0.2",
215
- "ai": "^7.0.65",
215
+ "ai": "^7.0.78",
216
216
  "grammy": "^1.45.1",
217
217
  "react": "^19.2.8",
218
218
  "react-query-kit": "^3.3.4",
219
219
  "socket.io": "^4.8.3",
220
220
  "socket.io-client": "^4.8.3",
221
- "srvx": "^0.12.5",
221
+ "srvx": "^0.12.7",
222
222
  "typescript": "^7.0.2",
223
223
  "zod": "^4.4.3"
224
224
  }