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,24 +1,44 @@
1
1
  import {
2
2
  makeCache
3
- } from "./chunk-D47C7KG5.js";
3
+ } from "./chunk-AYM2FUI5.js";
4
+ import {
5
+ accountSecrets,
6
+ appInvocationFetch,
7
+ boundFailureMessage,
8
+ describeFailure,
9
+ failureDetail,
10
+ leavingProviderError,
11
+ parseMcpError,
12
+ readCatalog,
13
+ routerSkills
14
+ } from "./chunk-RULZPNGP.js";
4
15
  import {
5
16
  folderSkillsEffect
6
- } from "./chunk-FDNTX5QJ.js";
17
+ } from "./chunk-OX233L7N.js";
7
18
  import {
19
+ ResponseStatusError,
8
20
  authorDatabase,
9
21
  isApp,
10
22
  toEffectApp,
11
23
  unavailableStorage
12
- } from "./chunk-JN55AYQH.js";
24
+ } from "./chunk-FULRJSWU.js";
25
+ import {
26
+ parseDatabaseSchema
27
+ } from "./chunk-5JVNM3CQ.js";
13
28
  import {
29
+ declaredOperations,
14
30
  fromPromise,
31
+ locate,
15
32
  nativeOperation,
16
33
  toPromise
17
- } from "./chunk-PYUYJRSK.js";
34
+ } from "./chunk-5XJR4XGW.js";
18
35
  import {
36
+ accountProviderError,
37
+ httpProviderError,
19
38
  parseProviderError
20
- } from "./chunk-ZJWDMTE3.js";
39
+ } from "./chunk-4OKYLVU4.js";
21
40
  import {
41
+ AccountCheckResult,
22
42
  DeclaredProvider,
23
43
  DeclaredRequirements,
24
44
  ElicitationFailed,
@@ -29,6 +49,7 @@ import {
29
49
  HostError,
30
50
  HostEvaluationFailed,
31
51
  HostInputInvalid,
52
+ HostKindMismatch,
32
53
  HostOperationFailed,
33
54
  HostOperationNotFound,
34
55
  HostOutputInvalid,
@@ -38,6 +59,7 @@ import {
38
59
  HostToolBlocked,
39
60
  HostToolNotFound,
40
61
  HostToolPolicyFailed,
62
+ HostedRouter,
41
63
  HostedTool,
42
64
  HostedToolSummary,
43
65
  HostedWebhook,
@@ -45,9 +67,8 @@ import {
45
67
  InvocationDeadline,
46
68
  ManualWebhookSetup,
47
69
  ManyAccounts,
48
- McpError,
49
70
  NonRetryableError,
50
- OperationToolPrefixes,
71
+ OpenapiResponseError,
51
72
  ResolvedAccounts,
52
73
  ToolResultObservation,
53
74
  TrustedToolApproval,
@@ -62,31 +83,33 @@ import {
62
83
  defaultWebhookTransportLimits,
63
84
  maxInputProblems,
64
85
  workflowDurationMillis
65
- } from "./chunk-MYYEW3RA.js";
86
+ } from "./chunk-N72RKJ5E.js";
66
87
  import {
67
88
  CacheError
68
- } from "./chunk-LGIYBDWA.js";
89
+ } from "./chunk-5DLG2FVN.js";
69
90
  import {
70
91
  AppSkills,
71
92
  SkillFile,
72
93
  SkillLoadFailed
73
- } from "./chunk-YEJOQEII.js";
74
- import {
75
- OpenapiResponseError
76
- } from "./chunk-SWPD52J7.js";
94
+ } from "./chunk-HW3DPBZR.js";
77
95
  import {
78
- captureTelemetry,
79
- invocationFetch
80
- } from "./chunk-ZCAMUXSG.js";
96
+ captureTelemetry
97
+ } from "./chunk-ETLILMHY.js";
81
98
  import {
99
+ allowedValues,
82
100
  decoderOf,
101
+ echoableKey,
83
102
  importedJsonSchema,
84
- jsonSchemaDecoder
85
- } from "./chunk-WFSQXYUT.js";
103
+ jsonSchemaDecoder,
104
+ jsonSchemaDocument,
105
+ maxAlternativeKeys,
106
+ objectShape,
107
+ unionShape
108
+ } from "./chunk-NPGRURDG.js";
86
109
  import {
87
110
  JsonObject,
88
111
  JsonValue
89
- } from "./chunk-SATWJKN6.js";
112
+ } from "./chunk-FBBXFFFJ.js";
90
113
  import {
91
114
  Cause_exports,
92
115
  Clock_exports,
@@ -95,10 +118,11 @@ import {
95
118
  Match_exports,
96
119
  Option_exports,
97
120
  Redacted_exports,
121
+ SchemaAST_exports,
98
122
  SchemaIssue_exports,
99
123
  Schema_exports,
100
124
  Stream_exports
101
- } from "./chunk-FW5HBOIK.js";
125
+ } from "./chunk-EXGKN554.js";
102
126
 
103
127
  // src/implementation/elicitation.ts
104
128
  var prepareElicitation = (input) => Effect_exports.gen(function* () {
@@ -139,19 +163,29 @@ var makeElicit = (handler, signal) => toPromise(
139
163
  var ApprovalDecision = Schema_exports.Literals(["approved", "denied", "user-approval"]);
140
164
 
141
165
  // src/implementation/workflow-context.ts
142
- var workflowSafe = (work) => work.pipe(
166
+ var workflowSafe = (work, secrets) => work.pipe(
143
167
  Effect_exports.catchCause((cause) => {
144
168
  if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
145
169
  const error = Cause_exports.squash(cause);
146
170
  if (Schema_exports.is(WorkflowFailure)(error)) return Effect_exports.fail(error);
171
+ const { errorName, message } = failureDetail(error, secrets);
147
172
  return Effect_exports.fail(
148
173
  new WorkflowFailure({
149
174
  reason: "execution",
150
- retryable: !(error instanceof NonRetryableError)
175
+ retryable: !(error instanceof NonRetryableError),
176
+ ...errorName === void 0 ? {} : { errorName },
177
+ ...message === void 0 ? {} : { message }
151
178
  })
152
179
  );
153
180
  })
154
181
  );
182
+ var inStep = (step) => (failure) => failure.step === void 0 ? new WorkflowFailure({
183
+ reason: failure.reason,
184
+ retryable: failure.retryable,
185
+ step: step.slice(0, 200),
186
+ ...failure.errorName === void 0 ? {} : { errorName: failure.errorName },
187
+ ...failure.message.length === 0 ? {} : { message: failure.message }
188
+ }) : failure;
155
189
  var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_exports.gen(function* () {
156
190
  const services = yield* Effect_exports.context();
157
191
  const counts = /* @__PURE__ */ new Map();
@@ -206,25 +240,33 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
206
240
  Effect_exports.sync(() => new AbortController()),
207
241
  (controller2) => Effect_exports.sync(() => controller2.abort())
208
242
  );
209
- const ctx = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
243
+ const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
210
244
  const result = yield* workflowSafe(
211
- Effect_exports.tryPromise({ try: () => callback(ctx), catch: (error) => error })
245
+ Effect_exports.tryPromise({
246
+ try: () => callback(step2.context),
247
+ catch: (error) => error
248
+ }),
249
+ step2.secrets
212
250
  );
213
251
  return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
214
252
  Effect_exports.mapError(
215
- () => new WorkflowFailure({ reason: "output", retryable: false })
253
+ () => new WorkflowFailure({
254
+ reason: "output",
255
+ retryable: false,
256
+ message: "The step returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
257
+ })
216
258
  )
217
259
  );
218
260
  })
219
261
  ).pipe(Effect_exports.provideContext(services))
220
262
  )
221
- );
263
+ ).pipe(Effect_exports.mapError(inStep(name)));
222
264
  });
223
265
  const operationStep = (kind, name, operation, input, options) => Effect_exports.gen(function* () {
224
266
  const target = nativeOperation(operation);
225
- const catalog = kind === "query" ? definition.queries : definition.mutations;
226
- const match = Object.entries(catalog ?? {}).find(
227
- ([, value]) => value === target && value.kind === kind
267
+ const root = definition.tools?.kind === "router" ? definition.tools : void 0;
268
+ const match = declaredOperations(root).find(
269
+ (entry) => entry.operation === target && entry.operation.kind === kind
228
270
  );
229
271
  if (target === void 0 || match === void 0)
230
272
  return yield* new WorkflowFailure({ reason: "operation", retryable: false });
@@ -243,9 +285,9 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
243
285
  parsed,
244
286
  () => attempt(
245
287
  parsed,
246
- execution.invoke({ kind, name: match[0], input: args, stepId, timeout }).pipe(Effect_exports.provideContext(services))
288
+ execution.invoke({ kind, name: match.name, input: args, stepId, timeout }).pipe(Effect_exports.provideContext(services))
247
289
  )
248
- );
290
+ ).pipe(Effect_exports.mapError(inStep(name)));
249
291
  });
250
292
  const invoke = (effect) => toPromise(() => effect.pipe(Effect_exports.provideContext(services)), signal)();
251
293
  const step = {
@@ -284,14 +326,91 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
284
326
  });
285
327
 
286
328
  // src/implementation/input-problems.ts
287
- var leafHook = (issue) => SchemaIssue_exports.hasInput(issue) ? "Invalid value" : SchemaIssue_exports.defaultLeafHook(issue);
329
+ var nativeObjectShape = (ast, limit) => objectShape(
330
+ ast.propertySignatures.flatMap(
331
+ ({ name, type }) => typeof name === "string" ? [{ name, optional: SchemaAST_exports.isOptional(SchemaAST_exports.toEncoded(type)) }] : []
332
+ ),
333
+ ast.indexSignatures.length > 0,
334
+ limit
335
+ );
336
+ var unionMembers = (ast) => SchemaAST_exports.isUnion(ast) ? ast.types.flatMap(unionMembers) : SchemaAST_exports.isUndefined(ast) || SchemaAST_exports.isVoid(ast) ? [] : [ast];
337
+ var fixedValues = (ast) => {
338
+ if (SchemaAST_exports.isLiteral(ast)) return [ast.literal];
339
+ if (SchemaAST_exports.isEnum(ast)) return ast.enums.map(([, value]) => value);
340
+ if (!SchemaAST_exports.isUnion(ast)) return void 0;
341
+ const members = unionMembers(ast).map(fixedValues);
342
+ return members.length > 0 && members.every((values) => values !== void 0) ? members.flat() : void 0;
343
+ };
344
+ var describeMember = (ast) => Match_exports.value(ast).pipe(
345
+ Match_exports.when(
346
+ SchemaAST_exports.isObjects,
347
+ (objects) => objects.propertySignatures.length > 0 ? nativeObjectShape(objects, maxAlternativeKeys) : "object"
348
+ ),
349
+ Match_exports.when(SchemaAST_exports.isArrays, () => "array"),
350
+ Match_exports.when(SchemaAST_exports.isTemplateLiteral, () => "a string matching a template"),
351
+ Match_exports.when(SchemaAST_exports.isString, () => "string"),
352
+ Match_exports.when(SchemaAST_exports.isNumber, () => "number"),
353
+ Match_exports.when(SchemaAST_exports.isBoolean, () => "boolean"),
354
+ Match_exports.when(SchemaAST_exports.isNull, () => "null"),
355
+ Match_exports.orElse(() => "a value with other constraints")
356
+ );
357
+ var memberSelector = (members) => {
358
+ const [first] = members;
359
+ if (members.length < 2 || first === void 0 || !SchemaAST_exports.isObjects(first)) return void 0;
360
+ return first.propertySignatures.map(({ name }) => name).find(
361
+ (name) => typeof name === "string" && members.every(
362
+ (member) => SchemaAST_exports.isObjects(member) && member.propertySignatures.some(
363
+ (property) => property.name === name && fixedValues(SchemaAST_exports.toEncoded(property.type)) !== void 0
364
+ )
365
+ )
366
+ );
367
+ };
368
+ var expectedUnion = (ast) => {
369
+ const members = unionMembers(ast);
370
+ const fixed = members.map(fixedValues);
371
+ const values = fixed.flatMap((memberValues) => memberValues === void 0 ? [] : memberValues);
372
+ const others = members.filter((_, index) => fixed[index] === void 0);
373
+ if (others.length === 0) return `Expected ${allowedValues(values)}`;
374
+ return `Expected ${unionShape(
375
+ [
376
+ ...values.length === 0 ? [] : [allowedValues(values)],
377
+ ...new Set(others.map(describeMember))
378
+ ],
379
+ memberSelector(members)
380
+ )}`;
381
+ };
382
+ var leafHook = (issue) => SchemaIssue_exports.hasInput(issue) ? "Invalid value" : Match_exports.value(issue).pipe(
383
+ Match_exports.tag("InvalidType", ({ ast }) => {
384
+ const values = fixedValues(ast);
385
+ return values !== void 0 ? `Expected ${allowedValues(values)}` : SchemaAST_exports.isObjects(ast) && ast.propertySignatures.length > 0 ? `Expected ${nativeObjectShape(ast)}` : SchemaIssue_exports.defaultLeafHook(issue);
386
+ }),
387
+ Match_exports.orElse(SchemaIssue_exports.defaultLeafHook)
388
+ );
288
389
  var checkHook = (issue) => SchemaIssue_exports.hasInput(issue) || SchemaIssue_exports.hasInput(issue.issue) ? SchemaIssue_exports.defaultCheckHook(issue) ?? "Invalid value" : SchemaIssue_exports.defaultCheckHook(issue);
289
390
  var format = SchemaIssue_exports.makeFormatterStandardSchemaV1({ leafHook, checkHook });
290
- var segment = (key) => typeof key === "number" ? `[${key}]` : typeof key === "string" && /^[A-Za-z_$][\w$-]{0,63}$/.test(key) ? `.${key}` : "[key]";
391
+ var located = (issue, path) => Match_exports.value(issue).pipe(
392
+ Match_exports.tag("Pointer", (pointer) => located(pointer.issue, [...path, ...pointer.path])),
393
+ Match_exports.tag("Composite", ({ issues }) => issues.flatMap((issue2) => located(issue2, path))),
394
+ Match_exports.tag("Encoding", (encoding) => located(encoding.issue, path)),
395
+ Match_exports.tag(
396
+ "AnyOf",
397
+ ({ ast, issues }) => issues.length === 0 ? [{ path, message: expectedUnion(ast) }] : issues.flatMap((issue2) => located(issue2, path))
398
+ ),
399
+ Match_exports.orElse(
400
+ (issue2) => format(issue2).issues.map((problem) => ({
401
+ path: [
402
+ ...path,
403
+ ...(problem.path ?? []).map((key) => typeof key === "object" ? key.key : key)
404
+ ],
405
+ message: problem.message
406
+ }))
407
+ )
408
+ );
409
+ var segment = (key) => typeof key === "number" ? `[${key}]` : typeof key === "string" && echoableKey(key) ? `.${key}` : "[key]";
291
410
  var inputInvalid = (error) => {
292
411
  if (!Schema_exports.isSchemaError(error)) return new HostInputInvalid();
293
- const problems = format(error.issue).issues.slice(0, maxInputProblems).map(({ path, message }) => {
294
- const location = (path ?? []).map((key) => segment(typeof key === "object" ? key.key : key));
412
+ const problems = located(error.issue, []).slice(0, maxInputProblems).map(({ path, message }) => {
413
+ const location = path.map(segment);
295
414
  return `${location.length === 0 ? "input" : `input${location.join("")}`}: ${message}`.slice(
296
415
  0,
297
416
  512
@@ -469,7 +588,7 @@ var authorCache = (host, accounts, signal, deadline) => {
469
588
  ...options.staleFor === void 0 ? {} : { staleFor: options.staleFor },
470
589
  load: Effect_exports.acquireUseRelease(
471
590
  Effect_exports.sync(() => new AbortController()),
472
- (controller) => invocationFetch(controller.signal).pipe(
591
+ (controller) => appInvocationFetch(controller.signal).pipe(
473
592
  Effect_exports.flatMap(
474
593
  (fetch) => fromPromise(options.load)({
475
594
  fetch,
@@ -523,6 +642,10 @@ var authorCache = (host, accounts, signal, deadline) => {
523
642
  };
524
643
 
525
644
  // src/implementation/host.ts
645
+ var WireCatalog = Schema_exports.Struct({
646
+ tools: Schema_exports.Array(Schema_exports.Union([HostedTool, HostedToolSummary])),
647
+ routers: Schema_exports.Array(HostedRouter)
648
+ });
526
649
  function safe2(work, failure) {
527
650
  return Effect_exports.suspend(work).pipe(
528
651
  Effect_exports.catchCause(
@@ -530,30 +653,39 @@ function safe2(work, failure) {
530
653
  )
531
654
  );
532
655
  }
533
- var evaluationSafe = (work) => work.pipe(
656
+ var evaluationSafe = (work, secrets) => work.pipe(
534
657
  Effect_exports.catchCause((cause) => {
535
658
  if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
536
659
  const error = Cause_exports.squash(cause);
537
660
  const provider = parseProviderError(error);
538
661
  const skills = parseSkillLoadFailed(error);
539
- const mcp = parseMcpError(error);
662
+ const mcp = parseMcpError(error, secrets);
540
663
  return Effect_exports.fail(
541
- Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed()
664
+ Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "discover") : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed(failureDetail(error, secrets))
542
665
  );
543
666
  })
544
667
  );
545
- function jsonSchema(decoder) {
546
- const imported = importedJsonSchema(decoder);
547
- if (imported !== void 0) return Schema_exports.decodeUnknownEffect(JsonObject)(imported);
548
- const document = Schema_exports.toJsonSchemaDocument(decoder);
549
- return Schema_exports.decodeUnknownEffect(JsonObject)({
550
- ...document.schema,
551
- $defs: document.definitions,
552
- $schema: "https://json-schema.org/draft/2020-12/schema"
553
- });
668
+ var declarationInvalid = (summary, cause, secrets = []) => new HostDeclarationInvalid({
669
+ source: "app",
670
+ errorName: "HostDeclarationInvalid",
671
+ message: boundFailureMessage(
672
+ cause === void 0 ? summary : `${summary}: ${describeFailure(cause)}`,
673
+ secrets
674
+ )
675
+ });
676
+ var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
677
+ Effect_exports.catchCause(
678
+ (cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
679
+ )
680
+ );
681
+ function declaredExposure(exposure) {
682
+ const named = (kind) => Object.entries(exposure ?? {}).filter(([, value]) => value === kind).map(([field]) => field).sort();
683
+ const plain = named("plain");
684
+ const raw = named("raw");
685
+ return { ...plain.length === 0 ? {} : { plain }, ...raw.length === 0 ? {} : { raw } };
554
686
  }
555
687
  function providerDeclaration(provider) {
556
- return safe2(
688
+ return declarationSafe(
557
689
  () => Effect_exports.gen(function* () {
558
690
  const auth = /* @__PURE__ */ new Map();
559
691
  for (const [name, method] of Object.entries(provider.auth)) {
@@ -562,42 +694,50 @@ function providerDeclaration(provider) {
562
694
  auth.set(name, {
563
695
  type: "secrets",
564
696
  label: method.label,
565
- fields: yield* jsonSchema(method.fields)
697
+ fields: yield* jsonSchemaDocument(method.fields),
698
+ ...declaredExposure(method.exposure)
566
699
  });
567
700
  break;
568
701
  case "oauth2":
569
702
  auth.set(name, {
570
703
  type: "oauth2",
571
704
  ...method.config,
572
- response: yield* jsonSchema(method.response)
705
+ response: yield* jsonSchemaDocument(method.response),
706
+ ...declaredExposure(method.exposure)
573
707
  });
574
708
  break;
575
709
  }
576
710
  }
577
711
  return yield* Schema_exports.decodeUnknownEffect(DeclaredProvider)({
578
712
  name: provider.name,
579
- auth: Object.fromEntries(auth)
713
+ auth: Object.fromEntries(auth),
714
+ // Order and repetition carry no meaning, so neither changes the provider's identity.
715
+ ...provider.hosts === void 0 ? {} : { hosts: [...new Set(provider.hosts)].sort() }
580
716
  });
581
717
  }),
582
- new HostDeclarationInvalid()
718
+ `Account provider "${provider.name}" has an invalid declaration`
583
719
  );
584
720
  }
585
721
  function requirements(slots, database) {
586
722
  return Effect_exports.gen(function* () {
587
723
  const accounts = /* @__PURE__ */ new Map();
588
724
  for (const [slot, selection] of Object.entries(slots)) {
725
+ const provider = selection instanceof ManyAccounts ? selection.provider : selection;
589
726
  accounts.set(slot, {
590
727
  cardinality: selection instanceof ManyAccounts ? "many" : "one",
591
- definition: yield* providerDeclaration(
592
- selection instanceof ManyAccounts ? selection.provider : selection
593
- )
728
+ definition: yield* providerDeclaration(provider),
729
+ ...provider.health === void 0 ? {} : { health: true }
594
730
  });
595
731
  }
596
732
  return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
597
733
  accounts: Object.fromEntries(accounts),
598
734
  capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
599
735
  ...database === void 0 ? {} : { database }
600
- }).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
736
+ }).pipe(
737
+ Effect_exports.mapError(
738
+ (cause) => declarationInvalid("The app's account or database declarations are invalid", cause)
739
+ )
740
+ );
601
741
  });
602
742
  }
603
743
  function canonical(value) {
@@ -607,6 +747,9 @@ function canonical(value) {
607
747
  }
608
748
  return JSON.stringify(value);
609
749
  }
750
+ function withoutHosts({ hosts: _hosts, ...provider }) {
751
+ return provider;
752
+ }
610
753
  function bindAccounts(slots, declarations, context) {
611
754
  return safe2(
612
755
  () => Effect_exports.gen(function* () {
@@ -632,7 +775,7 @@ function bindAccounts(slots, declarations, context) {
632
775
  for (const account of accounts) {
633
776
  if (ids.has(account.id)) return yield* Effect_exports.fail(new HostAccountsInvalid());
634
777
  ids.add(account.id);
635
- if (canonical(account.provider) !== canonical(requirement.definition) || !Object.hasOwn(provider.auth, account.method))
778
+ if (canonical(withoutHosts(account.provider)) !== canonical(withoutHosts(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
636
779
  return yield* Effect_exports.fail(new HostAccountsInvalid());
637
780
  const method = provider.auth[account.method];
638
781
  if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
@@ -653,17 +796,67 @@ function bindAccounts(slots, declarations, context) {
653
796
  new HostAccountsInvalid()
654
797
  );
655
798
  }
799
+ var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
800
+ Effect_exports.sync(() => {
801
+ const controller = new AbortController();
802
+ let refreshes = 0;
803
+ let ended = false;
804
+ const settle = () => {
805
+ if (ended && refreshes === 0) controller.abort();
806
+ };
807
+ const end = () => {
808
+ ended = true;
809
+ settle();
810
+ };
811
+ signal.addEventListener("abort", end, { once: true });
812
+ if (signal.aborted) end();
813
+ const settled = Effect_exports.sync(() => {
814
+ refreshes -= 1;
815
+ settle();
816
+ });
817
+ return {
818
+ signal: controller.signal,
819
+ close: () => {
820
+ signal.removeEventListener("abort", end);
821
+ end();
822
+ },
823
+ /** Counted from the hand-off, so a refresh that has not started yet keeps the fetch. */
824
+ background: (task) => Effect_exports.suspend(() => {
825
+ refreshes += 1;
826
+ return background(task.pipe(Effect_exports.ensuring(settled))).pipe(
827
+ Effect_exports.onError(() => settled)
828
+ );
829
+ })
830
+ };
831
+ }),
832
+ (lifetime) => Effect_exports.sync(lifetime.close)
833
+ );
656
834
  function dispatch(app, request, context, signal) {
657
835
  return Effect_exports.scoped(
658
836
  Effect_exports.gen(function* () {
659
- if (!isApp(app)) return yield* Effect_exports.fail(new HostDeclarationInvalid());
837
+ if (!isApp(app))
838
+ return yield* Effect_exports.fail(
839
+ declarationInvalid("The app module's default export is not an app created by defineApp")
840
+ );
660
841
  const native = toEffectApp(app);
842
+ const secrets = accountSecrets(context.accounts);
843
+ const storageFailure = (error) => Effect_exports.fail(new HostOperationFailed(failureDetail(error, secrets)));
661
844
  const declared = yield* requirements(native.accounts, native.database?.schema);
662
- if (request.operation === "requirements")
845
+ if (request.operation === "requirements") {
846
+ if (native.database !== void 0)
847
+ yield* parseDatabaseSchema(native.database.schema).pipe(
848
+ Effect_exports.catchTag(
849
+ "AppDatabaseError",
850
+ (cause) => Effect_exports.fail(
851
+ declarationInvalid("The app's account or database declarations are invalid", cause)
852
+ )
853
+ )
854
+ );
663
855
  return yield* safe2(
664
856
  () => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
665
857
  new HostDeclarationInvalid()
666
858
  );
859
+ }
667
860
  const lifetime = yield* Effect_exports.acquireRelease(
668
861
  Effect_exports.sync(() => new AbortController()),
669
862
  (controller) => Effect_exports.sync(() => controller.abort())
@@ -689,6 +882,15 @@ function dispatch(app, request, context, signal) {
689
882
  return yield* new WorkflowFailure({ reason: "engine", retryable: true });
690
883
  return result;
691
884
  });
885
+ if (request.operation === "account-check")
886
+ return yield* checkAccount(
887
+ native.accounts,
888
+ declared,
889
+ request.requirement,
890
+ context,
891
+ invocationSignal,
892
+ deadline
893
+ ).pipe(withinDeadline);
692
894
  let running;
693
895
  let transactionOpen = false;
694
896
  const delivery = (request2, signal2) => Effect_exports.suspend(
@@ -723,9 +925,19 @@ function dispatch(app, request, context, signal) {
723
925
  const files = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Array(SkillFile))(
724
926
  context.files ?? []
725
927
  ).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
928
+ let cacheCommands = 0;
929
+ const hostCache = context.cache ?? unavailableCache;
930
+ const fetching = yield* fetchLifetime(signal, hostCache.background);
726
931
  const bound = {
727
932
  cache: authorCache(
728
- context.cache ?? unavailableCache,
933
+ {
934
+ ...hostCache,
935
+ transport: (command) => {
936
+ cacheCommands += 1;
937
+ return hostCache.transport(command);
938
+ },
939
+ background: fetching.background
940
+ },
729
941
  Redacted_exports.value(context.accounts),
730
942
  invocationSignal,
731
943
  deadline
@@ -736,35 +948,43 @@ function dispatch(app, request, context, signal) {
736
948
  ),
737
949
  workflows: workflowReads,
738
950
  signal: invocationSignal,
739
- fetch: yield* invocationFetch(invocationSignal),
951
+ fetch: yield* appInvocationFetch(fetching.signal),
740
952
  elicit: makeElicit(delivery, invocationSignal)
741
953
  };
742
- const definition = yield* evaluationSafe(native.evaluate(bound)).pipe(
954
+ const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
743
955
  Effect_exports.withSpan("app.evaluate")
744
956
  );
745
957
  if (request.operation === "skills") {
746
958
  const declared2 = definition.skills ?? (yield* folderSkillsEffect({ files }).pipe(
747
959
  Effect_exports.mapError(() => new HostDeclarationInvalid())
748
960
  ));
749
- const source2 = definition.dynamicSkills;
750
- const dynamic = source2 === void 0 ? [] : yield* evaluationSafe(Effect_exports.suspend(source2.list)).pipe(
961
+ const source = definition.dynamicSkills;
962
+ const before = cacheCommands;
963
+ const dynamic = source === void 0 ? [] : yield* evaluationSafe(Effect_exports.suspend(source.list), secrets).pipe(
751
964
  Effect_exports.withSpan("app.skills.load")
752
965
  );
753
- const skills = yield* Schema_exports.decodeUnknownEffect(AppSkills)([...declared2, ...dynamic]).pipe(
754
- Effect_exports.mapError(() => new HostDeclarationInvalid())
755
- );
756
- return request.sources === true ? { skills, dynamic: source2 !== void 0 } : skills;
966
+ const cached = source !== void 0 && cacheCommands > before;
967
+ const authored = new Set([...declared2, ...dynamic].map((skill) => skill.name));
968
+ const routed = (yield* routerSkills(definition.tools).pipe(
969
+ Effect_exports.withSpan("app.skills.routers")
970
+ )).filter((skill) => !authored.has(skill.name));
971
+ const skills = yield* Schema_exports.decodeUnknownEffect(AppSkills)([
972
+ ...declared2,
973
+ ...dynamic,
974
+ ...routed
975
+ ]).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
976
+ return request.sources === true ? { skills, dynamic: source !== void 0, cached } : skills;
757
977
  }
758
978
  if (request.operation === "workflows") {
759
979
  return yield* Effect_exports.forEach(
760
980
  Object.entries(definition.workflows ?? {}),
761
- ([name2, entry]) => safe2(
981
+ ([name, entry]) => safe2(
762
982
  () => Effect_exports.gen(function* () {
763
983
  return yield* Schema_exports.decodeUnknownEffect(HostedWorkflow)({
764
- name: name2,
984
+ name,
765
985
  ...entry.description === void 0 ? {} : { description: entry.description },
766
- inputSchema: yield* jsonSchema(entry.input),
767
- ...entry.output === void 0 ? {} : { outputSchema: yield* jsonSchema(entry.output) }
986
+ inputSchema: yield* jsonSchemaDocument(entry.input),
987
+ ...entry.output === void 0 ? {} : { outputSchema: yield* jsonSchemaDocument(entry.output) }
768
988
  });
769
989
  }),
770
990
  new HostDeclarationInvalid()
@@ -797,108 +1017,60 @@ function dispatch(app, request, context, signal) {
797
1017
  new WorkflowFailure({ reason: "credentials", retryable: false })
798
1018
  );
799
1019
  return {
800
- ...accounts,
801
- cache: authorCache(
802
- context.cache ?? unavailableCache,
803
- Redacted_exports.value(current.accounts),
804
- signal2
805
- ),
806
- files,
807
- fetch: yield* invocationFetch(signal2),
808
- signal: signal2,
809
- runId: execution.runId,
810
- stepId,
811
- idempotencyKey: stepId
1020
+ context: {
1021
+ ...accounts,
1022
+ cache: authorCache(
1023
+ context.cache ?? unavailableCache,
1024
+ Redacted_exports.value(current.accounts),
1025
+ signal2
1026
+ ),
1027
+ files,
1028
+ fetch: yield* appInvocationFetch(signal2),
1029
+ signal: signal2,
1030
+ runId: execution.runId,
1031
+ stepId,
1032
+ idempotencyKey: stepId
1033
+ },
1034
+ // The resolved values, not the app's decoded fields, which may be `Redacted`.
1035
+ secrets: accountSecrets(current.accounts)
812
1036
  };
813
1037
  }),
814
1038
  invocationSignal
815
1039
  );
816
- const output = yield* workflowSafe(entry.run(workflowContext, input2));
1040
+ const output = yield* workflowSafe(entry.run(workflowContext, input2), secrets);
817
1041
  const outputSchema = entry.output;
818
1042
  const decoded = outputSchema === void 0 ? output : yield* safe2(
819
1043
  () => Schema_exports.decodeUnknownEffect(outputSchema)(output),
820
- new WorkflowFailure({ reason: "output", retryable: false })
1044
+ new WorkflowFailure({
1045
+ reason: "output",
1046
+ retryable: false,
1047
+ message: "The workflow's result does not match its declared output schema."
1048
+ })
821
1049
  );
822
1050
  return yield* safe2(
823
1051
  () => Schema_exports.decodeUnknownEffect(WorkflowValue)(decoded),
824
- new WorkflowFailure({ reason: "output", retryable: false })
1052
+ new WorkflowFailure({
1053
+ reason: "output",
1054
+ retryable: false,
1055
+ message: "The workflow returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
1056
+ })
825
1057
  );
826
1058
  }
827
1059
  if (request.operation === "inspect") {
828
1060
  const summary = request.detail === "summary";
829
- const wanted = request.tools === void 0 ? void 0 : new Set(request.tools);
830
- const metadata = [];
831
- for (const [prefix, readOnly, catalog2] of [
832
- [OperationToolPrefixes.query, true, definition.queries],
833
- [OperationToolPrefixes.mutate, false, definition.mutations]
834
- ]) {
835
- for (const [name2, operation] of Object.entries(catalog2 ?? {})) {
836
- if (wanted !== void 0 && !wanted.has(`${prefix}${name2}`)) continue;
837
- const schedules = Object.entries(definition.schedules ?? {}).filter(([, schedule]) => schedule.tool === `${prefix}${name2}`).map(([name3, { tool: _tool, ...schedule }]) => ({ name: name3, ...schedule }));
838
- if (request.scheduled === true && schedules.length === 0) continue;
839
- metadata.push(
840
- yield* safe2(
841
- () => Effect_exports.gen(function* () {
842
- const fields = {
843
- name: `${prefix}${name2}`,
844
- schedules,
845
- description: operation.description ?? `${readOnly ? "Query" : "Mutate"} ${name2}`,
846
- ...operation.title === void 0 ? {} : { title: operation.title },
847
- readOnly,
848
- annotations: { ...operation.annotations, readOnlyHint: readOnly }
849
- };
850
- if (summary)
851
- return yield* Schema_exports.decodeUnknownEffect(HostedToolSummary)(fields);
852
- return yield* Schema_exports.decodeUnknownEffect(HostedTool)({
853
- ...fields,
854
- inputSchema: yield* jsonSchema(operation.input),
855
- ...operation.output === void 0 ? operation.outputSchema === void 0 ? {} : { outputSchema: operation.outputSchema } : { outputSchema: yield* jsonSchema(operation.output) },
856
- ...operation._meta === void 0 ? {} : { _meta: operation._meta }
857
- });
858
- }),
859
- new HostDeclarationInvalid()
860
- )
861
- );
862
- }
863
- }
864
- const dynamic = request.scheduled === true ? void 0 : definition.dynamicTools;
865
- if (dynamic !== void 0 && (wanted === void 0 || metadata.length < wanted.size)) {
866
- const declared2 = new Set(metadata.map((tool2) => tool2.name));
867
- const discover = () => {
868
- if (summary && dynamic.summaries !== void 0) return dynamic.summaries();
869
- if (wanted !== void 0 && dynamic.describe !== void 0) {
870
- const describe = dynamic.describe;
871
- return Effect_exports.forEach(
872
- [...wanted].filter((name2) => !declared2.has(name2)),
873
- (name2) => describe(name2),
874
- { concurrency: "unbounded" }
875
- ).pipe(Effect_exports.map((tools) => tools.filter((tool2) => tool2 !== void 0)));
876
- }
877
- return dynamic.list();
878
- };
879
- const discovered = yield* evaluationSafe(discover()).pipe(
880
- Effect_exports.flatMap(
881
- (value) => safe2(
882
- () => summary ? Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedToolSummary))(value) : Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedTool))(value),
883
- new HostDeclarationInvalid()
884
- )
885
- )
886
- );
887
- const names = new Set(declared2);
888
- for (const tool2 of discovered) {
889
- const readOnly = tool2.name.startsWith(OperationToolPrefixes.query);
890
- if (!readOnly && !tool2.name.startsWith(OperationToolPrefixes.mutate) || tool2.name === OperationToolPrefixes.query || tool2.name === OperationToolPrefixes.mutate || names.has(tool2.name))
891
- return yield* new HostDeclarationInvalid();
892
- names.add(tool2.name);
893
- if (wanted !== void 0 && !wanted.has(tool2.name)) continue;
894
- metadata.push({
895
- ...tool2,
896
- readOnly,
897
- annotations: { ...tool2.annotations, readOnlyHint: readOnly }
898
- });
899
- }
900
- }
901
- return metadata;
1061
+ const catalog = yield* readCatalog(definition.tools, {
1062
+ summary,
1063
+ secrets,
1064
+ ...request.tools === void 0 ? {} : { wanted: new Set(request.tools) },
1065
+ ...request.scheduled === true ? { scheduled: true } : {},
1066
+ schedules: (name) => Object.entries(definition.schedules ?? {}).filter(([, schedule]) => schedule.tool === name).map(([name2, { tool: _tool, ...schedule }]) => ({ name: name2, ...schedule }))
1067
+ }).pipe(Effect_exports.withSpan("app.catalog.read"));
1068
+ return yield* safe2(
1069
+ () => Schema_exports.encodeEffect(WireCatalog)(catalog).pipe(
1070
+ Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
1071
+ ),
1072
+ new HostDeclarationInvalid()
1073
+ );
902
1074
  }
903
1075
  if (request.operation === "webhook-complete" || request.operation === "webhook-validate" || request.operation === "webhooks" || request.operation === "webhook-register" || request.operation === "webhook-handle" || request.operation === "webhook-unregister") {
904
1076
  const executeWebhook = (db) => dispatchWebhook(
@@ -922,25 +1094,22 @@ function dispatch(app, request, context, signal) {
922
1094
  const storage2 = context.storage ?? unavailableStorage;
923
1095
  return yield* storage2.mutate(native.database.schema, executeWebhook).pipe(
924
1096
  Effect_exports.catchTags({
925
- AppDatabaseError: () => Effect_exports.fail(new HostOperationFailed()),
926
- AppStorageUnavailable: () => Effect_exports.fail(new HostOperationFailed()),
927
- AppStorageError: () => Effect_exports.fail(new HostOperationFailed())
1097
+ AppDatabaseError: storageFailure,
1098
+ DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
1099
+ AppStorageUnavailable: storageFailure,
1100
+ AppStorageError: storageFailure
928
1101
  })
929
1102
  );
930
1103
  }
931
- const kind = request.operation === "call" ? request.tool.startsWith(OperationToolPrefixes.query) ? "query" : request.tool.startsWith(OperationToolPrefixes.mutate) ? "mutate" : void 0 : request.operation;
932
- if (kind === void 0) return yield* new HostToolNotFound();
933
- const name = request.operation === "call" ? request.tool.slice(OperationToolPrefixes[kind].length) : request.name;
934
- const toolName = `${OperationToolPrefixes[kind]}${name}`;
935
- const catalog = kind === "query" ? definition.queries : definition.mutations;
936
- const declaredTool = catalog !== void 0 && Object.hasOwn(catalog, name) ? catalog[name] : void 0;
937
- const source = definition.dynamicTools;
938
- const resolvedTool = source === void 0 || declaredTool !== void 0 ? void 0 : yield* evaluationSafe(source.resolve(toolName));
939
- const tool = declaredTool ?? resolvedTool;
940
- if (tool !== void 0 && tool.kind !== (kind === "query" ? "query" : "mutation"))
941
- return yield* new HostDeclarationInvalid();
1104
+ const toolName = request.operation === "call" ? request.tool : request.name;
1105
+ const location = locate(definition.tools, toolName);
1106
+ const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets);
942
1107
  if (tool === void 0)
943
1108
  return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
1109
+ const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
1110
+ if (requested !== void 0 && tool.kind !== requested)
1111
+ return yield* new HostKindMismatch({ tool: toolName, requested, actual: tool.kind });
1112
+ const kind = tool.kind === "query" ? "query" : "mutate";
944
1113
  const input = yield* Effect_exports.suspend(
945
1114
  () => Schema_exports.decodeUnknownEffect(tool.input)(request.input)
946
1115
  ).pipe(
@@ -994,7 +1163,7 @@ function dispatch(app, request, context, signal) {
994
1163
  transactionOpen = db !== void 0;
995
1164
  const output = yield* Effect_exports.gen(function* () {
996
1165
  running = yield* captureTelemetry;
997
- const fetch = yield* invocationFetch(invocationSignal);
1166
+ const fetch = yield* appInvocationFetch(fetching.signal);
998
1167
  return yield* tool.run(
999
1168
  {
1000
1169
  ...bound,
@@ -1022,14 +1191,15 @@ function dispatch(app, request, context, signal) {
1022
1191
  const error = Cause_exports.squash(cause);
1023
1192
  const provider = parseProviderError(error);
1024
1193
  const response = Schema_exports.decodeUnknownOption(OpenapiResponseError)(error);
1194
+ const mcp = parseMcpError(error, secrets);
1025
1195
  const failure = Schema_exports.decodeUnknownOption(ElicitationFailed)(error);
1026
1196
  return Effect_exports.fail(
1027
- Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(response) ? new OpenapiResponseError({
1197
+ Option_exports.isSome(provider) ? leavingProviderError(provider.value, secrets, "call") : Option_exports.isSome(response) ? new OpenapiResponseError({
1028
1198
  code: response.value.code,
1029
1199
  status: response.value.status,
1030
1200
  message: response.value.message,
1031
1201
  ...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
1032
- }) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed()
1202
+ }) : Option_exports.isSome(mcp) ? mcp.value : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
1033
1203
  );
1034
1204
  }),
1035
1205
  Effect_exports.withSpan("app.operation.execute", {
@@ -1060,14 +1230,61 @@ function dispatch(app, request, context, signal) {
1060
1230
  )
1061
1231
  ).pipe(
1062
1232
  Effect_exports.catchTags({
1063
- AppDatabaseError: () => Effect_exports.fail(new HostOperationFailed()),
1064
- AppStorageUnavailable: () => Effect_exports.fail(new HostOperationFailed()),
1065
- AppStorageError: () => Effect_exports.fail(new HostOperationFailed())
1233
+ AppDatabaseError: storageFailure,
1234
+ DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
1235
+ AppStorageUnavailable: storageFailure,
1236
+ AppStorageError: storageFailure
1066
1237
  })
1067
1238
  );
1068
1239
  })
1069
1240
  );
1070
1241
  }
1242
+ function checkAccount(slots, declared, requirement, context, signal, deadline) {
1243
+ return Effect_exports.gen(function* () {
1244
+ const selection = Object.hasOwn(slots, requirement) ? slots[requirement] : void 0;
1245
+ const slot = Object.hasOwn(declared.accounts, requirement) ? declared.accounts[requirement] : void 0;
1246
+ if (selection === void 0 || slot === void 0) return yield* new HostAccountsInvalid();
1247
+ const provider = selection instanceof ManyAccounts ? selection.provider : selection;
1248
+ const health = provider.health;
1249
+ if (health === void 0) return yield* new HostOperationNotFound();
1250
+ const { accounts } = yield* bindAccounts(
1251
+ { [requirement]: provider },
1252
+ { accounts: { [requirement]: { ...slot, cardinality: "one" } } },
1253
+ context
1254
+ ).pipe(Effect_exports.withSpan("app.accounts.bind"));
1255
+ const account = accounts[requirement];
1256
+ if (account === void 0 || !("id" in account)) return yield* new HostAccountsInvalid();
1257
+ const result = yield* Effect_exports.suspend(
1258
+ () => Effect_exports.gen(function* () {
1259
+ return yield* health.run({
1260
+ account,
1261
+ fetch: yield* appInvocationFetch(signal),
1262
+ signal,
1263
+ ...deadline === void 0 ? {} : { deadline }
1264
+ });
1265
+ })
1266
+ ).pipe(
1267
+ Effect_exports.catchCause((cause) => {
1268
+ if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
1269
+ const error = Cause_exports.squash(cause);
1270
+ const status = Schema_exports.decodeUnknownOption(ResponseStatusError)(error);
1271
+ const classified = Option_exports.isSome(status) ? Option_exports.fromNullishOr(httpProviderError(status.value.status)) : parseProviderError(error);
1272
+ const secrets = accountSecrets(context.accounts);
1273
+ return Effect_exports.fail(
1274
+ Option_exports.isSome(classified) ? leavingProviderError(accountProviderError(classified.value, account.id), secrets) : new HostOperationFailed(failureDetail(error, secrets))
1275
+ );
1276
+ }),
1277
+ Effect_exports.withSpan("app.account.check")
1278
+ );
1279
+ return yield* safe2(
1280
+ () => Schema_exports.decodeUnknownEffect(AccountCheckResult)(result ?? {}).pipe(
1281
+ Effect_exports.flatMap(Schema_exports.encodeEffect(AccountCheckResult)),
1282
+ Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(JsonValue))
1283
+ ),
1284
+ new HostOutputInvalid()
1285
+ );
1286
+ });
1287
+ }
1071
1288
  var parseSkillLoadFailed = (error) => Schema_exports.decodeUnknownOption(SkillLoadFailed)(error).pipe(
1072
1289
  Option_exports.map(
1073
1290
  ({ reason, message, status }) => new SkillLoadFailed({
@@ -1077,11 +1294,6 @@ var parseSkillLoadFailed = (error) => Schema_exports.decodeUnknownOption(SkillLo
1077
1294
  })
1078
1295
  )
1079
1296
  );
1080
- var parseMcpError = (error) => Schema_exports.decodeUnknownOption(McpError)(error).pipe(
1081
- Option_exports.map(
1082
- ({ phase, reason, status }) => new McpError({ phase, reason, ...status === void 0 ? {} : { status } })
1083
- )
1084
- );
1085
1297
  var errorStatus = Match_exports.type().pipe(
1086
1298
  Match_exports.tagsExhaustive({
1087
1299
  ProviderError: () => 502,
@@ -1093,11 +1305,14 @@ var errorStatus = Match_exports.type().pipe(
1093
1305
  HostAccountsInvalid: () => 422,
1094
1306
  HostInputInvalid: () => 422,
1095
1307
  HostOperationNotFound: () => 404,
1308
+ HostKindMismatch: () => 409,
1096
1309
  HostToolNotFound: () => 404,
1097
1310
  HostToolBlocked: () => 403,
1098
1311
  HostToolApprovalRequired: () => 409,
1099
1312
  HostToolPolicyFailed: () => 500,
1100
1313
  HostOperationFailed: () => 500,
1314
+ DatabaseLimitExceeded: () => 422,
1315
+ DatabaseFieldReserved: () => 422,
1101
1316
  HostDeclarationInvalid: () => 500,
1102
1317
  HostEvaluationFailed: () => 500,
1103
1318
  HostOutputInvalid: () => 500,
@@ -1124,6 +1339,14 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
1124
1339
  toolError = true;
1125
1340
  }
1126
1341
  }),
1342
+ // Name what failed on the span; the bounded message stays in the reply only.
1343
+ Effect_exports.tapError(
1344
+ (error) => (error._tag === "HostEvaluationFailed" || error._tag === "HostOperationFailed" || error._tag === "HostDeclarationInvalid") && error.errorName !== void 0 ? Effect_exports.annotateCurrentSpan({
1345
+ "error.type": error.errorName,
1346
+ ...error.source === void 0 ? {} : { "executor.failure.source": error.source },
1347
+ ...error.code === void 0 ? {} : { "executor.failure.code": error.code }
1348
+ }) : Effect_exports.void
1349
+ ),
1127
1350
  Effect_exports.withSpan(`app.${command.operation}`)
1128
1351
  );
1129
1352
  if (toolError)
@@ -1143,12 +1366,17 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
1143
1366
  ),
1144
1367
  Effect_exports.catchCause(
1145
1368
  (cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.logError(cause).pipe(
1146
- Effect_exports.as(
1147
- Response.json(
1148
- { ok: false, error: { _tag: "HostDeclarationInvalid" } },
1149
- { status: 500 }
1369
+ Effect_exports.andThen(
1370
+ Schema_exports.encodeEffect(HostError)(
1371
+ declarationInvalid(
1372
+ "The app failed while it was loaded",
1373
+ Cause_exports.squash(cause),
1374
+ accountSecrets(context.accounts)
1375
+ )
1150
1376
  )
1151
- )
1377
+ ),
1378
+ Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
1379
+ Effect_exports.orDie
1152
1380
  )
1153
1381
  )
1154
1382
  );