apps 0.0.1-beta.3 → 0.0.1-beta.31

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 (140) hide show
  1. package/README.md +68 -44
  2. package/framework-reference.json +1 -1
  3. package/js/{chunk-RN2MXB4R.js → chunk-3FJYVAE4.js} +128 -24
  4. package/js/chunk-4OKYLVU4.js +118 -0
  5. package/js/{chunk-LGIYBDWA.js → chunk-5DLG2FVN.js} +65 -1
  6. package/js/{chunk-PLCMJREA.js → chunk-5JVNM3CQ.js} +60 -20
  7. package/js/chunk-5XJR4XGW.js +254 -0
  8. package/js/{chunk-FZJOYIZO.js → chunk-6KG4DZD7.js} +1 -1
  9. package/js/{chunk-EVJUVWN2.js → chunk-6ZJ2H6P4.js} +2 -2
  10. package/js/{chunk-NQ3OMCA5.js → chunk-AUFVX4KM.js} +2 -2
  11. package/js/{chunk-D47C7KG5.js → chunk-AYM2FUI5.js} +2 -2
  12. package/js/{chunk-5MQZEB6Y.js → chunk-BGALSHLT.js} +37 -12
  13. package/js/{chunk-QKHR7BMF.js → chunk-CJY5X26R.js} +3 -3
  14. package/js/{chunk-M6ZRRIBI.js → chunk-DASNNAP4.js} +1 -1
  15. package/js/{chunk-ZCAMUXSG.js → chunk-ETLILMHY.js} +3 -4
  16. package/js/{chunk-FW5HBOIK.js → chunk-EXGKN554.js} +2005 -1710
  17. package/js/{chunk-SATWJKN6.js → chunk-FBBXFFFJ.js} +1 -1
  18. package/js/{chunk-JN55AYQH.js → chunk-FULRJSWU.js} +61 -32
  19. package/js/{chunk-HDTGZWP2.js → chunk-GG566OOE.js} +139 -32
  20. package/js/chunk-GZ4UHXRT.js +92 -0
  21. package/js/{chunk-YEJOQEII.js → chunk-HW3DPBZR.js} +45 -7
  22. package/js/{chunk-HDJH3RPR.js → chunk-MFHUR5SB.js} +2 -2
  23. package/js/{chunk-MYYEW3RA.js → chunk-N72RKJ5E.js} +984 -61
  24. package/js/{chunk-WFSQXYUT.js → chunk-NPGRURDG.js} +390 -18
  25. package/js/chunk-OD3KFKZD.js +1617 -0
  26. package/js/{chunk-FDNTX5QJ.js → chunk-OX233L7N.js} +2 -2
  27. package/js/{chunk-G7ZIRKMK.js → chunk-QYM4STZW.js} +118 -197
  28. package/js/chunk-RULZPNGP.js +801 -0
  29. package/js/{chunk-BMOIAIVR.js → chunk-UMCMZFXW.js} +49 -1
  30. package/js/{chunk-J7O55ZV7.js → chunk-W7F23NQ2.js} +419 -191
  31. package/js/chunk-WG5DFZFT.js +42 -0
  32. package/js/{chunk-T2LAZCAD.js → chunk-ZOY7PDMI.js} +1 -1
  33. package/js/client.js +120 -84
  34. package/js/contracts.js +110 -16
  35. package/js/effect.js +20 -20
  36. package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
  37. package/js/graphql.js +58 -54
  38. package/js/host.js +20 -20
  39. package/js/index.js +247 -204
  40. package/js/mcp/effect.js +24 -22
  41. package/js/mcp/stdio.js +35 -30
  42. package/js/mcp.js +105 -68
  43. package/js/openapi.js +4087 -1503
  44. package/js/react.js +3 -3
  45. package/js/skills/effect.js +5 -3
  46. package/js/skills.js +15 -15
  47. package/js/storage/facet.js +4 -4
  48. package/js/ui/auth/contracts.js +2 -2
  49. package/js/ui/auth.js +5 -5
  50. package/js/ui/contracts.js +5 -4
  51. package/js/ui/serving.js +8516 -214
  52. package/package.json +1 -1
  53. package/runtime.json +1 -1
  54. package/types/app-data/src/contracts/database.d.ts +33 -6
  55. package/types/app-data/src/implementation/schema.d.ts +2 -17
  56. package/types/apps/src/contracts/api-response-error.d.ts +4 -0
  57. package/types/apps/src/contracts/app.d.ts +7 -6
  58. package/types/apps/src/contracts/failure.d.ts +54 -0
  59. package/types/apps/src/contracts/graphql.d.ts +2 -1
  60. package/types/apps/src/contracts/host.d.ts +34 -11
  61. package/types/apps/src/contracts/mcp.d.ts +91 -10
  62. package/types/apps/src/contracts/network.d.ts +84 -0
  63. package/types/apps/src/contracts/openapi-compile.d.ts +31 -3
  64. package/types/apps/src/contracts/openapi.d.ts +45 -9
  65. package/types/apps/src/contracts/operations.d.ts +5 -6
  66. package/types/apps/src/contracts/protocol-version.d.ts +2 -2
  67. package/types/apps/src/contracts/protocols/1.d.ts +251 -69
  68. package/types/apps/src/contracts/protocols/2.d.ts +710 -0
  69. package/types/apps/src/contracts/protocols/3.d.ts +716 -0
  70. package/types/apps/src/contracts/protocols/4.d.ts +1298 -0
  71. package/types/apps/src/contracts/protocols/5.d.ts +1174 -0
  72. package/types/apps/src/contracts/protocols/6.d.ts +1620 -0
  73. package/types/apps/src/contracts/protocols/7.d.ts +1784 -0
  74. package/types/apps/src/contracts/protocols/8.d.ts +1119 -0
  75. package/types/apps/src/contracts/protocols/oauth.d.ts +89 -0
  76. package/types/apps/src/contracts/provider-error.d.ts +9 -0
  77. package/types/apps/src/contracts/provider.d.ts +115 -10
  78. package/types/apps/src/contracts/router.d.ts +59 -0
  79. package/types/apps/src/contracts/skills.d.ts +18 -5
  80. package/types/apps/src/contracts/storage.d.ts +3 -3
  81. package/types/apps/src/contracts/ui.d.ts +18 -0
  82. package/types/apps/src/contracts/workflows.d.ts +34 -3
  83. package/types/apps/src/graphql.d.ts +1 -3
  84. package/types/apps/src/implementation/account-router.d.ts +12 -0
  85. package/types/apps/src/implementation/app.d.ts +5 -4
  86. package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
  87. package/types/apps/src/implementation/catalog-cache.d.ts +34 -4
  88. package/types/apps/src/implementation/elicitation.d.ts +9 -9
  89. package/types/apps/src/implementation/failure-detail.d.ts +46 -0
  90. package/types/apps/src/implementation/graphql-catalog.d.ts +4 -7
  91. package/types/apps/src/implementation/graphql.d.ts +4 -3
  92. package/types/apps/src/implementation/input-problems.d.ts +4 -1
  93. package/types/apps/src/implementation/mcp-call.d.ts +6 -5
  94. package/types/apps/src/implementation/mcp-catalog.d.ts +7 -8
  95. package/types/apps/src/implementation/mcp-client.d.ts +49 -25
  96. package/types/apps/src/implementation/mcp-stdio.d.ts +1 -1
  97. package/types/apps/src/implementation/mcp-tools.d.ts +2 -1
  98. package/types/apps/src/implementation/mcp.d.ts +52 -25
  99. package/types/apps/src/implementation/network.d.ts +16 -0
  100. package/types/apps/src/implementation/openapi-compile.d.ts +27 -6
  101. package/types/apps/src/implementation/openapi-document.d.ts +46 -19
  102. package/types/apps/src/implementation/openapi-names.d.ts +9 -4
  103. package/types/apps/src/implementation/openapi-request.d.ts +10 -2
  104. package/types/apps/src/implementation/openapi-source.d.ts +8 -6
  105. package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
  106. package/types/apps/src/implementation/operations.d.ts +36 -3
  107. package/types/apps/src/implementation/protocol-operations.d.ts +6 -4
  108. package/types/apps/src/implementation/provider-error.d.ts +28 -1
  109. package/types/apps/src/implementation/provider.d.ts +19 -5
  110. package/types/apps/src/implementation/router-catalog.d.ts +224 -0
  111. package/types/apps/src/implementation/router.d.ts +68 -0
  112. package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
  113. package/types/apps/src/implementation/schema.d.ts +80 -1
  114. package/types/apps/src/implementation/skills.d.ts +2 -2
  115. package/types/apps/src/implementation/storage.d.ts +5 -3
  116. package/types/apps/src/implementation/ui-account-notice.d.ts +9 -0
  117. package/types/apps/src/implementation/ui-client.d.ts +2 -2
  118. package/types/apps/src/implementation/ui-document.d.ts +5 -0
  119. package/types/apps/src/implementation/ui-errors.d.ts +1 -1
  120. package/types/apps/src/implementation/ui-serving.d.ts +10 -4
  121. package/types/apps/src/implementation/ui-watch.d.ts +1 -1
  122. package/types/apps/src/implementation/upstream-error.d.ts +7 -0
  123. package/types/apps/src/implementation/webhooks.d.ts +1 -1
  124. package/types/apps/src/implementation/workflow-context.d.ts +11 -3
  125. package/types/apps/src/index.d.ts +29 -11
  126. package/types/apps/src/mcp-stdio.d.ts +2 -5
  127. package/types/apps/src/mcp.d.ts +25 -5
  128. package/types/apps/src/openapi.d.ts +6 -6
  129. package/types/apps/src/skills.d.ts +4 -4
  130. package/types/telemetry/src/browser-operations.d.ts +5 -2
  131. package/types/telemetry/src/config.d.ts +2 -2
  132. package/types/utils/src/api-error.d.ts +48 -0
  133. package/js/chunk-PYUYJRSK.js +0 -93
  134. package/js/chunk-SWPD52J7.js +0 -35
  135. package/js/chunk-W7D7WVSY.js +0 -18
  136. package/js/chunk-Z5NMEGJN.js +0 -29
  137. package/js/chunk-ZJWDMTE3.js +0 -63
  138. package/types/apps/src/contracts/dynamic-tools.d.ts +0 -13
  139. package/types/apps/src/implementation/account-operations.d.ts +0 -151
  140. package/types/apps/src/implementation/dynamic-tools.d.ts +0 -8
@@ -1,26 +1,32 @@
1
1
  import {
2
2
  prepareElicitation
3
- } from "./chunk-J7O55ZV7.js";
3
+ } from "./chunk-W7F23NQ2.js";
4
4
  import {
5
5
  fromPromise
6
- } from "./chunk-PYUYJRSK.js";
6
+ } from "./chunk-5XJR4XGW.js";
7
+ import {
8
+ bodyUpstreamError
9
+ } from "./chunk-4OKYLVU4.js";
7
10
  import {
8
11
  ElicitationFailed,
9
12
  McpError,
13
+ McpServerHeader,
10
14
  McpToolMetadata,
11
15
  McpToolResult,
16
+ RouterIcon,
12
17
  ToolResultObservation,
13
18
  defaultElicitationLimits,
14
19
  defaultMcpClientLimits,
15
20
  mcpSdkTimerCeilingMs
16
- } from "./chunk-MYYEW3RA.js";
21
+ } from "./chunk-N72RKJ5E.js";
17
22
  import {
18
- compileJsonSchemaDecoder,
19
- jsonSchemaDecoder
20
- } from "./chunk-WFSQXYUT.js";
23
+ jsonSchemaDecoder,
24
+ nestJsonSchema,
25
+ preparedJsonSchemaDecoder
26
+ } from "./chunk-NPGRURDG.js";
21
27
  import {
22
28
  JsonObject
23
- } from "./chunk-SATWJKN6.js";
29
+ } from "./chunk-FBBXFFFJ.js";
24
30
  import {
25
31
  Clock_exports,
26
32
  Deferred_exports,
@@ -29,29 +35,79 @@ import {
29
35
  Option_exports,
30
36
  Queue_exports,
31
37
  Schema_exports
32
- } from "./chunk-FW5HBOIK.js";
38
+ } from "./chunk-EXGKN554.js";
33
39
 
34
40
  // src/implementation/mcp-tools.ts
41
+ var resultFields = {
42
+ content: { type: "array", items: { type: "object" } },
43
+ structuredContent: { type: "object" },
44
+ isError: { type: "boolean" },
45
+ _meta: { type: "object" }
46
+ };
47
+ var definitionReference = /^#\/(?:\$defs|definitions)\/[^/]+$/;
48
+ var locating = /* @__PURE__ */ new Set(["$id", "$anchor", "$dynamicAnchor", "$recursiveAnchor"]);
49
+ var onlyDefinitionReferences = (value) => Array.isArray(value) ? value.every(onlyDefinitionReferences) : value === null || typeof value !== "object" ? true : Object.entries(value).every(
50
+ ([key, item]) => locating.has(key) || key === "$dynamicRef" || key === "$recursiveRef" ? false : key === "$ref" ? typeof item === "string" && definitionReference.test(item) : onlyDefinitionReferences(item)
51
+ );
52
+ var placed = (structuredContent, pointer) => {
53
+ if (onlyDefinitionReferences(structuredContent)) {
54
+ const { $defs, definitions, $schema: _draft, ...schema } = structuredContent;
55
+ return {
56
+ schema,
57
+ root: {
58
+ ...$defs === void 0 ? {} : { $defs },
59
+ ...definitions === void 0 ? {} : { definitions }
60
+ }
61
+ };
62
+ }
63
+ try {
64
+ return { schema: nestJsonSchema(structuredContent, pointer), root: {} };
65
+ } catch {
66
+ return { schema: structuredContent, root: {} };
67
+ }
68
+ };
69
+ var resultSchema = (structuredContent) => {
70
+ if (structuredContent === void 0)
71
+ return { type: "object", properties: resultFields, required: ["content"] };
72
+ const { schema, root } = placed(structuredContent, "#/anyOf/0/properties/structuredContent");
73
+ return {
74
+ // The envelope's keywords mean the same in every draft, so the server's draft applies.
75
+ ...structuredContent.$schema === void 0 ? {} : { $schema: structuredContent.$schema },
76
+ ...root,
77
+ anyOf: [
78
+ {
79
+ type: "object",
80
+ properties: { ...resultFields, structuredContent: schema, isError: { const: false } },
81
+ required: ["content", "structuredContent"]
82
+ },
83
+ {
84
+ type: "object",
85
+ properties: { ...resultFields, isError: { const: true } },
86
+ required: ["content", "isError"]
87
+ }
88
+ ]
89
+ };
90
+ };
35
91
  var adaptMcpTool = (client, tool) => Effect_exports.gen(function* () {
36
92
  const decoder = yield* jsonSchemaDecoder(tool.inputSchema).pipe(
37
93
  Effect_exports.mapError(() => new McpError({ phase: "schema", reason: "invalid_response" }))
38
94
  );
39
- const output = tool.outputSchema === void 0 ? void 0 : yield* Effect_exports.cached(
40
- compileJsonSchemaDecoder(tool.outputSchema).pipe(
41
- Effect_exports.mapError(() => new McpError({ phase: "schema", reason: "invalid_response" }))
42
- )
43
- );
95
+ const output = preparedJsonSchemaDecoder(resultSchema(tool.outputSchema));
96
+ const { outputSchema: _upstream, ...metadata } = tool;
44
97
  const adapted = {
45
- ...tool,
98
+ ...metadata,
46
99
  description: tool.description ?? tool.title ?? tool.name,
47
100
  input: decoder,
101
+ output: output.decoder,
48
102
  ...tool.annotations?.readOnlyHint === void 0 ? {} : { readOnly: tool.annotations.readOnlyHint },
49
103
  run: (context, input) => Effect_exports.gen(function* () {
50
104
  const arguments_ = yield* Schema_exports.decodeUnknownEffect(decoder)(input).pipe(
51
105
  Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonObject)),
52
106
  Effect_exports.mapError(() => new McpError({ phase: "call", reason: "invalid_input" }))
53
107
  );
54
- const outputDecoder = output === void 0 ? void 0 : yield* output;
108
+ yield* output.compile.pipe(
109
+ Effect_exports.mapError(() => new McpError({ phase: "schema", reason: "invalid_response" }))
110
+ );
55
111
  const result = yield* client.call(tool.name, arguments_, context);
56
112
  if (result.isError === true) {
57
113
  (yield* ToolResultObservation).failed();
@@ -60,17 +116,13 @@ var adaptMcpTool = (client, tool) => Effect_exports.gen(function* () {
60
116
  "error.type": "McpToolError"
61
117
  });
62
118
  }
63
- if (outputDecoder !== void 0 && !result.isError)
64
- yield* Schema_exports.decodeUnknownEffect(outputDecoder)(result.structuredContent).pipe(
65
- Effect_exports.mapError(() => new McpError({ phase: "call", reason: "invalid_response" }))
66
- );
67
119
  return result;
68
120
  })
69
121
  };
70
122
  return adapted;
71
123
  });
72
124
  var adaptMcpTools = (client) => Effect_exports.gen(function* () {
73
- const metadata = yield* client.list;
125
+ const { tools: metadata } = yield* client.list;
74
126
  const entries = yield* Effect_exports.forEach(
75
127
  metadata,
76
128
  (tool) => adaptMcpTool(client, tool).pipe(Effect_exports.map((adapted) => [tool.name, adapted]))
@@ -79,7 +131,11 @@ var adaptMcpTools = (client) => Effect_exports.gen(function* () {
79
131
  });
80
132
 
81
133
  // src/implementation/mcp-client.ts
82
- import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
134
+ import {
135
+ ErrorCode as ErrorCode2,
136
+ ListToolsResultSchema,
137
+ McpError as ProtocolError2
138
+ } from "@modelcontextprotocol/sdk/types.js";
83
139
 
84
140
  // src/implementation/mcp-call.ts
85
141
  import {
@@ -208,6 +264,20 @@ var mcpCall = (client, name, input, context, timeoutMs, failure) => Effect_expor
208
264
  );
209
265
 
210
266
  // src/implementation/mcp-client.ts
267
+ var clientCodes = /* @__PURE__ */ new Set([
268
+ ErrorCode2.RequestTimeout,
269
+ ErrorCode2.ConnectionClosed
270
+ ]);
271
+ var answeredError = (error) => {
272
+ if (!(error instanceof ProtocolError2) || clientCodes.has(error.code)) return void 0;
273
+ const prefix = `MCP error ${error.code}: `;
274
+ return bodyUpstreamError({
275
+ error: {
276
+ code: error.code,
277
+ message: error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message
278
+ }
279
+ });
280
+ };
211
281
  var mcpJsonSchemaValidator = {
212
282
  getValidator(document) {
213
283
  const decoder = Effect_exports.runSync(jsonSchemaDecoder(document));
@@ -233,7 +303,7 @@ function mcpClient(withClient, timeoutMs, failure) {
233
303
  do {
234
304
  const page = yield* Effect_exports.tryPromise({
235
305
  // This session only reads metadata. listTools() also eagerly compiles
236
- // every output validator; mcpOperations validates the selected tool on call.
306
+ // every output validator; mcpRouter validates the selected tool on call.
237
307
  try: (signal) => client.request(
238
308
  { method: "tools/list", params: cursor === void 0 ? {} : { cursor } },
239
309
  ListToolsResultSchema,
@@ -263,18 +333,52 @@ function mcpClient(withClient, timeoutMs, failure) {
263
333
  cursors.add(cursor);
264
334
  }
265
335
  } while (cursor !== void 0);
266
- return [...tools.values()];
336
+ const info = client.getServerVersion();
337
+ const instructions = client.getInstructions();
338
+ const icons = info?.icons?.flatMap(
339
+ (icon) => Option_exports.toArray(Schema_exports.decodeUnknownOption(RouterIcon)(icon))
340
+ );
341
+ const server = Schema_exports.decodeUnknownOption(McpServerHeader)({
342
+ ...info?.name === void 0 ? {} : { name: info.name },
343
+ ...info?.title === void 0 ? {} : { title: info.title },
344
+ ...info?.version === void 0 ? {} : { version: info.version },
345
+ ...info?.description === void 0 ? {} : { description: info.description },
346
+ ...info?.websiteUrl === void 0 ? {} : { websiteUrl: info.websiteUrl },
347
+ ...icons === void 0 ? {} : { icons },
348
+ ...instructions === void 0 ? {} : { instructions }
349
+ });
350
+ return {
351
+ tools: [...tools.values()],
352
+ server: Option_exports.getOrElse(server, () => ({}))
353
+ };
267
354
  })
268
355
  ).pipe(Effect_exports.withSpan("provider.mcp.discover"));
356
+ const check = withClient(
357
+ "discover",
358
+ (client) => Effect_exports.tryPromise({
359
+ try: (signal) => client.request({ method: "tools/list", params: {} }, ListToolsResultSchema, {
360
+ signal,
361
+ timeout: timeoutMs
362
+ }),
363
+ catch: (error) => failure("discover", error)
364
+ }).pipe(
365
+ Effect_exports.asVoid,
366
+ Effect_exports.withSpan("provider.mcp.request", {
367
+ kind: "client",
368
+ attributes: { "rpc.system.name": "jsonrpc", "rpc.method": "tools/list" }
369
+ })
370
+ )
371
+ ).pipe(Effect_exports.withSpan("provider.mcp.check"));
269
372
  const call = (name, input, context) => withClient("call", (client) => mcpCall(client, name, input, context, timeoutMs, failure)).pipe(
270
373
  Effect_exports.withSpan("provider.mcp.call", { attributes: { "mcp.tool.name": name } })
271
374
  );
272
- return { list, call };
375
+ return { list, check, call };
273
376
  }
274
377
 
275
378
  export {
276
379
  adaptMcpTool,
277
380
  adaptMcpTools,
381
+ answeredError,
278
382
  mcpJsonSchemaValidator,
279
383
  mcpClient
280
384
  };
@@ -0,0 +1,118 @@
1
+ import {
2
+ ProviderError,
3
+ maxUpstreamMessageLength
4
+ } from "./chunk-5DLG2FVN.js";
5
+ import {
6
+ AccountId
7
+ } from "./chunk-FBBXFFFJ.js";
8
+ import {
9
+ Option_exports,
10
+ Schema_exports
11
+ } from "./chunk-EXGKN554.js";
12
+
13
+ // src/implementation/upstream-error.ts
14
+ var ErrorToken = Schema_exports.String.check(Schema_exports.isPattern(/^[A-Za-z0-9._-]{1,128}$/));
15
+ var JsonRpcError = Schema_exports.Struct({
16
+ error: Schema_exports.Struct({ code: Schema_exports.Int, message: Schema_exports.String })
17
+ });
18
+ var OAuthError = Schema_exports.Struct({
19
+ error: ErrorToken,
20
+ error_description: Schema_exports.optional(Schema_exports.String)
21
+ });
22
+ var bounded = (message) => message.length <= maxUpstreamMessageLength ? message : `${message.slice(0, maxUpstreamMessageLength - 1)}\u2026`;
23
+ var isShortenedUpstream = (message) => message.length === maxUpstreamMessageLength && message.endsWith("\u2026");
24
+ var stated = (code, message) => ({
25
+ code,
26
+ ...message === void 0 || message === "" ? {} : { message: bounded(message) }
27
+ });
28
+ var bodyUpstreamError = (json) => {
29
+ const rpc = Schema_exports.decodeUnknownOption(JsonRpcError)(json);
30
+ if (Option_exports.isSome(rpc)) return stated(rpc.value.error.code, rpc.value.error.message);
31
+ const oauth = Schema_exports.decodeUnknownOption(OAuthError)(json);
32
+ if (Option_exports.isSome(oauth)) return stated(oauth.value.error, oauth.value.error_description);
33
+ return void 0;
34
+ };
35
+ var authParam = /([A-Za-z][A-Za-z0-9_-]*)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,"]+))/g;
36
+ var challengeUpstreamError = (header) => {
37
+ const bearer = header === void 0 ? -1 : header.search(/\bBearer\b/i);
38
+ if (header === void 0 || bearer === -1) return void 0;
39
+ const params = /* @__PURE__ */ new Map();
40
+ for (const [, name, quoted, token] of header.slice(bearer + "Bearer".length).matchAll(authParam))
41
+ if (name !== void 0 && !params.has(name.toLowerCase()))
42
+ params.set(name.toLowerCase(), quoted?.replace(/\\(.)/g, "$1") ?? token ?? "");
43
+ const code = Schema_exports.decodeUnknownOption(ErrorToken)(params.get("error"));
44
+ return Option_exports.isNone(code) ? void 0 : stated(code.value, params.get("error_description"));
45
+ };
46
+
47
+ // src/implementation/provider-error.ts
48
+ var providerError = ({
49
+ reason,
50
+ status,
51
+ accountId,
52
+ phase,
53
+ upstream
54
+ }) => new ProviderError({
55
+ reason,
56
+ ...status === void 0 ? {} : { status },
57
+ ...accountId === void 0 ? {} : { accountId },
58
+ ...phase === void 0 ? {} : { phase },
59
+ ...upstream === void 0 ? {} : { upstream }
60
+ });
61
+ function parseProviderError(error) {
62
+ return Schema_exports.decodeUnknownOption(ProviderError)(error).pipe(Option_exports.map(providerError));
63
+ }
64
+ function providerErrorDetail(error, detail) {
65
+ return providerError({
66
+ ...error,
67
+ phase: error.phase ?? detail.phase,
68
+ upstream: error.upstream ?? detail.upstream
69
+ });
70
+ }
71
+ function httpProviderError(status, headers = {}) {
72
+ const upstream = challengeUpstreamError(headers["www-authenticate"]);
73
+ if (status >= 500 && status <= 599)
74
+ return providerError({ reason: "unavailable", status, upstream });
75
+ if (status === 401) return providerError({ reason: "unauthorized", status, upstream });
76
+ if (status === 429) return providerError({ reason: "rate_limited", status, upstream });
77
+ if (status !== 403) return void 0;
78
+ const retry = headers["retry-after"];
79
+ if (headers["x-ratelimit-remaining"] === "0" || retry !== void 0 && (/^\d+$/.test(retry) || Number.isFinite(Date.parse(retry))))
80
+ return providerError({ reason: "rate_limited", status, upstream });
81
+ if (typeof upstream?.code === "string" && upstream.code.toLowerCase() === "insufficient_scope")
82
+ return providerError({ reason: "forbidden", status, upstream });
83
+ return providerError({ reason: "rejected", status, upstream });
84
+ }
85
+ function accountProviderError(error, accountId) {
86
+ const parsed = parseProviderError(error);
87
+ const account = Schema_exports.decodeUnknownOption(AccountId)(accountId);
88
+ if (Option_exports.isNone(parsed) || Option_exports.isNone(account)) return error;
89
+ return providerError({ ...parsed.value, accountId: account.value });
90
+ }
91
+ function graphqlProviderError(errors, status) {
92
+ const codes = errors.flatMap((error) => {
93
+ const parsed = Schema_exports.decodeUnknownOption(
94
+ Schema_exports.Struct({
95
+ type: Schema_exports.optional(Schema_exports.String),
96
+ extensions: Schema_exports.optional(Schema_exports.Struct({ code: Schema_exports.optional(Schema_exports.String) }))
97
+ })
98
+ )(error);
99
+ return Option_exports.isSome(parsed) ? [parsed.value.type, parsed.value.extensions?.code] : [];
100
+ });
101
+ if (codes.includes("RATE_LIMITED") || codes.includes("TOO_MANY_REQUESTS"))
102
+ return new ProviderError({ reason: "rate_limited", status });
103
+ if (codes.includes("UNAUTHENTICATED"))
104
+ return new ProviderError({ reason: "unauthorized", status });
105
+ if (codes.includes("FORBIDDEN")) return new ProviderError({ reason: "forbidden", status });
106
+ return void 0;
107
+ }
108
+
109
+ export {
110
+ isShortenedUpstream,
111
+ bodyUpstreamError,
112
+ providerError,
113
+ parseProviderError,
114
+ providerErrorDetail,
115
+ httpProviderError,
116
+ accountProviderError,
117
+ graphqlProviderError
118
+ };
@@ -1,6 +1,55 @@
1
+ import {
2
+ AccountId
3
+ } from "./chunk-FBBXFFFJ.js";
1
4
  import {
2
5
  Schema_exports
3
- } from "./chunk-FW5HBOIK.js";
6
+ } from "./chunk-EXGKN554.js";
7
+
8
+ // src/contracts/failure.ts
9
+ var maxFailureMessageLength = 2048;
10
+ var FailureSource = Schema_exports.Literals(["app", "storage", "service"]);
11
+ var FailureName = Schema_exports.String.check(Schema_exports.isMaxLength(128));
12
+ var FailureCode = Schema_exports.String.check(Schema_exports.isMaxLength(128));
13
+ var FailureMessage = Schema_exports.String.check(Schema_exports.isMaxLength(maxFailureMessageLength));
14
+ var maxFailureFields = 8;
15
+ var maxFailureFieldLength = 256;
16
+ var FailureFieldName = Schema_exports.String.check(
17
+ Schema_exports.isPattern(/^[A-Za-z_$][A-Za-z0-9_$]{0,63}$/)
18
+ );
19
+ var FailureFieldValue = Schema_exports.Union([
20
+ Schema_exports.String.check(Schema_exports.isMaxLength(maxFailureFieldLength)),
21
+ Schema_exports.Finite,
22
+ Schema_exports.Boolean
23
+ ]);
24
+ var FailureFields = Schema_exports.Record(FailureFieldName, FailureFieldValue).check(
25
+ Schema_exports.isMaxProperties(maxFailureFields)
26
+ );
27
+ var FailureDetail = {
28
+ source: Schema_exports.optionalKey(FailureSource),
29
+ errorName: Schema_exports.optionalKey(FailureName),
30
+ code: Schema_exports.optionalKey(FailureCode),
31
+ message: Schema_exports.optionalKey(FailureMessage),
32
+ fields: Schema_exports.optionalKey(FailureFields)
33
+ };
34
+ var maxUpstreamMessageLength = 1024;
35
+ var UpstreamError = Schema_exports.Struct({
36
+ code: Schema_exports.Union([
37
+ Schema_exports.Int,
38
+ Schema_exports.String.check(Schema_exports.isMinLength(1), Schema_exports.isMaxLength(128))
39
+ ]),
40
+ message: Schema_exports.optionalKey(Schema_exports.String.check(Schema_exports.isMaxLength(maxUpstreamMessageLength)))
41
+ });
42
+ var FailurePhase = Schema_exports.Literals(["connect", "discover", "call"]);
43
+
44
+ // src/contracts/provider-error.ts
45
+ var ProviderError = class extends Schema_exports.TaggedError()("ProviderError", {
46
+ reason: Schema_exports.Literals(["unauthorized", "forbidden", "rate_limited", "unavailable", "rejected"]),
47
+ status: Schema_exports.optional(Schema_exports.Int.check(Schema_exports.isBetween({ minimum: 100, maximum: 599 }))),
48
+ accountId: Schema_exports.optional(AccountId),
49
+ phase: Schema_exports.optional(FailurePhase),
50
+ upstream: Schema_exports.optional(UpstreamError)
51
+ }) {
52
+ };
4
53
 
5
54
  // ../app-cache/src/contracts/cache.ts
6
55
  var CacheError = class extends Schema_exports.TaggedError()("CacheError", {
@@ -76,6 +125,21 @@ var CacheReply = Schema_exports.Union([
76
125
  ]);
77
126
 
78
127
  export {
128
+ maxFailureMessageLength,
129
+ FailureSource,
130
+ FailureName,
131
+ FailureCode,
132
+ FailureMessage,
133
+ maxFailureFields,
134
+ maxFailureFieldLength,
135
+ FailureFieldName,
136
+ FailureFieldValue,
137
+ FailureFields,
138
+ FailureDetail,
139
+ maxUpstreamMessageLength,
140
+ UpstreamError,
141
+ FailurePhase,
142
+ ProviderError,
79
143
  CacheError,
80
144
  cacheLimits,
81
145
  CacheEntry,
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  AppDatabaseError,
3
+ DatabaseFieldReserved,
4
+ DatabaseLimitExceeded,
3
5
  DatabaseLimits,
4
6
  DatabaseOperation,
5
7
  DatabaseSchema,
@@ -8,18 +10,21 @@ import {
8
10
  Row,
9
11
  RowMetadata,
10
12
  defaultDatabaseLimits,
11
- defaultDatabaseRuntimeLimits
12
- } from "./chunk-BMOIAIVR.js";
13
+ defaultDatabaseRuntimeLimits,
14
+ reservedFieldNames
15
+ } from "./chunk-UMCMZFXW.js";
13
16
  import {
17
+ Cause_exports,
14
18
  Clock_exports,
15
19
  Effect_exports,
16
20
  Encoding_exports,
17
21
  Schema_exports,
18
22
  Semaphore_exports
19
- } from "./chunk-FW5HBOIK.js";
23
+ } from "./chunk-EXGKN554.js";
20
24
 
21
25
  // ../app-data/src/implementation/schema.ts
22
- var metadata = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt"]);
26
+ var metadata = new Set(reservedFieldNames);
27
+ var reserved = (name) => metadata.has(name);
23
28
  var indexesFor = (table) => [{ name: "by_creation", fields: [] }, ...table.indexes].map((index) => ({
24
29
  name: index.name,
25
30
  fields: [
@@ -33,23 +38,25 @@ var validScalar = (field, value) => field.kind === "number" ? typeof value === "
33
38
  return point !== void 0 && point >= 55296 && point <= 57343;
34
39
  });
35
40
  var parseDatabaseSchema = (input) => Schema_exports.decodeUnknownEffect(DatabaseSchema)(input).pipe(
41
+ Effect_exports.mapError(() => new AppDatabaseError({ reason: "schema" })),
36
42
  Effect_exports.flatMap(
37
43
  (schema) => Effect_exports.gen(function* () {
38
- for (const table of Object.values(schema)) {
39
- if (Object.keys(table.fields).some((name) => metadata.has(name)) || new Set(table.indexes.map((index) => index.name)).size !== table.indexes.length)
44
+ for (const [name, table] of Object.entries(schema)) {
45
+ const field = Object.keys(table.fields).find(reserved);
46
+ if (field !== void 0) return yield* new DatabaseFieldReserved({ table: name, field });
47
+ if (new Set(table.indexes.map((index) => index.name)).size !== table.indexes.length)
40
48
  return yield* new AppDatabaseError({ reason: "schema" });
41
- for (const field of Object.values(table.fields)) {
42
- if ((field.kind === "id" ? field.references === void 0 : field.references !== void 0) || field.default !== void 0 && !validScalar(field, field.default) || field.references !== void 0 && !Object.hasOwn(schema, field.references))
49
+ for (const field2 of Object.values(table.fields)) {
50
+ if ((field2.kind === "id" ? field2.references === void 0 : field2.references !== void 0) || field2.default !== void 0 && !validScalar(field2, field2.default) || field2.references !== void 0 && !Object.hasOwn(schema, field2.references))
43
51
  return yield* new AppDatabaseError({ reason: "schema" });
44
52
  }
45
53
  for (const index of table.indexes)
46
- if (index.name === "by_creation" || new Set(index.fields).size !== index.fields.length || index.fields.some((name) => fieldFor(table, name) === void 0))
54
+ if (index.name === "by_creation" || new Set(index.fields).size !== index.fields.length || index.fields.some((name2) => fieldFor(table, name2) === void 0))
47
55
  return yield* new AppDatabaseError({ reason: "schema" });
48
56
  }
49
57
  return schema;
50
58
  })
51
- ),
52
- Effect_exports.mapError(() => new AppDatabaseError({ reason: "schema" }))
59
+ )
53
60
  );
54
61
  var canonicalSchema = (schema) => JSON.stringify(
55
62
  Object.fromEntries(
@@ -248,7 +255,12 @@ var decodeBody = Schema_exports.decodeUnknownEffect(Schema_exports.fromJsonStrin
248
255
  var storageError = () => new AppDatabaseError({ reason: "storage" });
249
256
  var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
250
257
  const { sql, crypto } = options;
251
- const schema = yield* parseDatabaseSchema(options.schema);
258
+ const schema = yield* parseDatabaseSchema(options.schema).pipe(
259
+ Effect_exports.catchTag(
260
+ "DatabaseFieldReserved",
261
+ () => Effect_exports.fail(new AppDatabaseError({ reason: "schema" }))
262
+ )
263
+ );
252
264
  const limits = yield* Schema_exports.decodeUnknownEffect(DatabaseLimits)(
253
265
  options.limits ?? defaultDatabaseLimits
254
266
  ).pipe(Effect_exports.mapError(() => new AppDatabaseError({ reason: "limit" })));
@@ -295,7 +307,13 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
295
307
  };
296
308
  const charge = (name, amount) => Effect_exports.suspend(() => {
297
309
  used[name] += amount;
298
- return used[name] > limits[name] ? Effect_exports.fail(new AppDatabaseError({ reason: "limit" })) : Effect_exports.void;
310
+ return used[name] > limits[name] ? Effect_exports.fail(
311
+ new DatabaseLimitExceeded({
312
+ limit: name,
313
+ maximum: limits[name],
314
+ requested: used[name]
315
+ })
316
+ ) : Effect_exports.void;
299
317
  });
300
318
  const get = (table, id) => Effect_exports.gen(function* () {
301
319
  yield* charge("directGets", 1);
@@ -312,8 +330,13 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
312
330
  const store = (tableName, table, row) => Effect_exports.gen(function* () {
313
331
  const meta = yield* Schema_exports.decodeUnknownEffect(RowMetadata)(row);
314
332
  const body = JSON.stringify(row);
315
- if (new TextEncoder().encode(body).length > limits.valueBytes)
316
- return yield* new AppDatabaseError({ reason: "limit" });
333
+ const bytes = new TextEncoder().encode(body).length;
334
+ if (bytes > limits.valueBytes)
335
+ return yield* new DatabaseLimitExceeded({
336
+ limit: "valueBytes",
337
+ maximum: limits.valueBytes,
338
+ requested: bytes
339
+ });
317
340
  const keys = yield* Effect_exports.forEach(
318
341
  indexesFor(table),
319
342
  (index) => encodeIndexKey(
@@ -384,9 +407,14 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
384
407
  const bounds = yield* queryBounds(table, plan, limits.indexBytes);
385
408
  reads.add(tableName);
386
409
  yield* charge("scanCalls", 1);
387
- const maximum = terminal.kind === "count" ? limits.rowsRead - used.rowsRead : limits.rowsReturned - used.rowsReturned;
388
- const count = terminal.kind === "first" ? 1 : terminal.kind === "take" ? terminal.count : terminal.kind === "paginate" ? terminal.numItems : maximum;
389
- if (count > maximum) return yield* new AppDatabaseError({ reason: "limit" });
410
+ const remaining = terminal.kind === "count" ? limits.rowsRead - used.rowsRead : limits.rowsReturned - used.rowsReturned;
411
+ const count = terminal.kind === "first" ? 1 : terminal.kind === "take" ? terminal.count : terminal.kind === "paginate" ? terminal.numItems : remaining;
412
+ if ((terminal.kind === "take" || terminal.kind === "paginate") && count > limits.rowsReturned)
413
+ return yield* new DatabaseLimitExceeded({
414
+ limit: "pageSize",
415
+ maximum: limits.rowsReturned,
416
+ requested: count
417
+ });
390
418
  if (count === 0 && terminal.kind === "take") return [];
391
419
  const query = yield* fingerprint(
392
420
  crypto,
@@ -412,7 +440,10 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
412
440
  plan.order === "asc" ? sql`i.sort_key > ${position}` : sql`i.sort_key < ${position}`
413
441
  );
414
442
  const direction = plan.order === "asc" ? sql.literal("ASC") : sql.literal("DESC");
415
- const limit = terminal.kind === "first" || terminal.kind === "take" ? count : count + 1;
443
+ const limit = Math.min(
444
+ terminal.kind === "first" || terminal.kind === "take" ? count : count + 1,
445
+ remaining + 1
446
+ );
416
447
  if (terminal.kind === "count") {
417
448
  const rows2 = yield* sql`SELECT i.sort_key FROM app_indexes i WHERE ${sql.and(predicates)} ORDER BY i.sort_key ${direction} LIMIT ${limit}`.pipe(
418
449
  Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(Schema_exports.Array(CountRow)))
@@ -436,7 +467,11 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
436
467
  )
437
468
  );
438
469
  if (terminal.kind === "collect" && rows.length > count)
439
- return yield* new AppDatabaseError({ reason: "limit" });
470
+ return yield* new DatabaseLimitExceeded({
471
+ limit: "rowsReturned",
472
+ maximum: limits.rowsReturned,
473
+ requested: used.rowsReturned + rows.length
474
+ });
440
475
  const page = rows.slice(0, count);
441
476
  yield* charge("rowsReturned", page.length);
442
477
  const values = yield* Effect_exports.forEach(page, (row) => decodeBody(row.body));
@@ -502,6 +537,11 @@ var makeSqliteDatabase = (options) => Effect_exports.gen(function* () {
502
537
  })
503
538
  };
504
539
  return yield* Effect_exports.suspend(() => work(session)).pipe(
540
+ // A failed database call poisons the session. Report that failure even when
541
+ // authored code caught it or threw something else in its place.
542
+ Effect_exports.catchCause(
543
+ (cause) => failed === void 0 || Cause_exports.hasInterrupts(cause) ? Effect_exports.failCause(cause) : Effect_exports.fail(failed)
544
+ ),
505
545
  Effect_exports.tap(
506
546
  () => gate.withPermits(1)(
507
547
  Effect_exports.suspend(() => failed === void 0 ? Effect_exports.void : Effect_exports.fail(failed))