apps 0.0.1-beta.4 → 0.0.1-beta.5

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 (67) hide show
  1. package/framework-reference.json +1 -1
  2. package/js/{chunk-SATWJKN6.js → chunk-27F7W2LG.js} +1 -1
  3. package/js/{chunk-PYUYJRSK.js → chunk-3XKZDQLM.js} +2 -2
  4. package/js/chunk-4M277YTM.js +136 -0
  5. package/js/{chunk-HDJH3RPR.js → chunk-57RKNWL2.js} +2 -2
  6. package/js/{chunk-EQB7JMAL.js → chunk-67EVWIGJ.js} +8 -8
  7. package/js/{chunk-DHUDODG5.js → chunk-C3VAOK5B.js} +11 -9
  8. package/js/{chunk-FW5HBOIK.js → chunk-CDL5PM2Q.js} +307 -169
  9. package/js/{chunk-D47C7KG5.js → chunk-CYYBFC2K.js} +2 -2
  10. package/js/{chunk-3M2MEDNL.js → chunk-DQAZTA4I.js} +145 -20
  11. package/js/{chunk-WFSQXYUT.js → chunk-FWQC6I3C.js} +2 -2
  12. package/js/{chunk-ZJWDMTE3.js → chunk-G7T27IWB.js} +3 -3
  13. package/js/{chunk-G7ZIRKMK.js → chunk-IJX4CYZO.js} +3 -3
  14. package/js/{chunk-FDNTX5QJ.js → chunk-IPI4MFSN.js} +2 -2
  15. package/js/{chunk-YEJOQEII.js → chunk-JU7VHODU.js} +1 -1
  16. package/js/{chunk-NQ3OMCA5.js → chunk-KUMBKVJD.js} +2 -2
  17. package/js/{chunk-6VRYO2BG.js → chunk-LUVSFETN.js} +235 -58
  18. package/js/{chunk-EVJUVWN2.js → chunk-M3B3DE4K.js} +2 -2
  19. package/js/{chunk-BMOIAIVR.js → chunk-N7YDVXYJ.js} +49 -1
  20. package/js/{chunk-M6ZRRIBI.js → chunk-PJJ24GU7.js} +1 -1
  21. package/js/{chunk-FZJOYIZO.js → chunk-PZB6T6KU.js} +1 -1
  22. package/js/{chunk-ZCAMUXSG.js → chunk-RJDDBDSN.js} +3 -3
  23. package/js/{chunk-W7D7WVSY.js → chunk-SB3V4YVR.js} +2 -2
  24. package/js/{chunk-Z5NMEGJN.js → chunk-TDNYXSIX.js} +1 -1
  25. package/js/{chunk-2VPJHFOU.js → chunk-UDDE5KOR.js} +6 -6
  26. package/js/{chunk-QKHR7BMF.js → chunk-UK573G7W.js} +1 -1
  27. package/js/{chunk-T2LAZCAD.js → chunk-VFZKSM3T.js} +1 -1
  28. package/js/{chunk-SWPD52J7.js → chunk-W4DMKWAB.js} +1 -1
  29. package/js/{chunk-5MQZEB6Y.js → chunk-XHO2ZX6W.js} +4 -4
  30. package/js/{chunk-LGIYBDWA.js → chunk-YEPYT6SD.js} +1 -1
  31. package/js/{chunk-PLCMJREA.js → chunk-ZQINWV4W.js} +60 -20
  32. package/js/client.js +10 -10
  33. package/js/contracts.js +32 -9
  34. package/js/effect.js +21 -20
  35. package/js/graphql.js +23 -22
  36. package/js/host.js +21 -20
  37. package/js/index.js +14 -14
  38. package/js/mcp/effect.js +23 -22
  39. package/js/mcp/stdio.js +23 -22
  40. package/js/mcp.js +25 -24
  41. package/js/openapi.js +23 -123
  42. package/js/react.js +3 -3
  43. package/js/skills/effect.js +3 -3
  44. package/js/skills.js +12 -12
  45. package/js/storage/facet.js +4 -4
  46. package/js/ui/auth/contracts.js +2 -2
  47. package/js/ui/auth.js +5 -5
  48. package/js/ui/contracts.js +4 -4
  49. package/js/ui/serving.js +8 -8
  50. package/package.json +1 -1
  51. package/runtime.json +1 -1
  52. package/types/app-data/src/contracts/database.d.ts +33 -6
  53. package/types/app-data/src/implementation/schema.d.ts +2 -17
  54. package/types/apps/src/contracts/failure.d.ts +25 -0
  55. package/types/apps/src/contracts/host.d.ts +11 -6
  56. package/types/apps/src/contracts/openapi.d.ts +1 -1
  57. package/types/apps/src/contracts/protocol-version.d.ts +2 -2
  58. package/types/apps/src/contracts/protocols/1.d.ts +15 -1
  59. package/types/apps/src/contracts/protocols/2.d.ts +2 -2
  60. package/types/apps/src/contracts/protocols/3.d.ts +676 -0
  61. package/types/apps/src/contracts/storage.d.ts +3 -3
  62. package/types/apps/src/contracts/workflows.d.ts +34 -3
  63. package/types/apps/src/implementation/elicitation.d.ts +1 -1
  64. package/types/apps/src/implementation/failure-detail.d.ts +25 -0
  65. package/types/apps/src/implementation/storage.d.ts +5 -3
  66. package/types/apps/src/implementation/webhooks.d.ts +1 -1
  67. package/types/apps/src/implementation/workflow-context.d.ts +11 -3
@@ -1,23 +1,29 @@
1
1
  import {
2
2
  makeCache
3
- } from "./chunk-D47C7KG5.js";
3
+ } from "./chunk-CYYBFC2K.js";
4
4
  import {
5
5
  folderSkillsEffect
6
- } from "./chunk-FDNTX5QJ.js";
6
+ } from "./chunk-IPI4MFSN.js";
7
+ import {
8
+ OpenapiError
9
+ } from "./chunk-4M277YTM.js";
7
10
  import {
8
11
  authorDatabase,
9
12
  isApp,
10
13
  toEffectApp,
11
14
  unavailableStorage
12
- } from "./chunk-DHUDODG5.js";
15
+ } from "./chunk-C3VAOK5B.js";
16
+ import {
17
+ parseDatabaseSchema
18
+ } from "./chunk-ZQINWV4W.js";
13
19
  import {
14
20
  fromPromise,
15
21
  nativeOperation,
16
22
  toPromise
17
- } from "./chunk-PYUYJRSK.js";
23
+ } from "./chunk-3XKZDQLM.js";
18
24
  import {
19
25
  parseProviderError
20
- } from "./chunk-ZJWDMTE3.js";
26
+ } from "./chunk-G7T27IWB.js";
21
27
  import {
22
28
  DeclaredProvider,
23
29
  DeclaredRequirements,
@@ -60,33 +66,41 @@ import {
60
66
  WorkflowValue,
61
67
  approvalElicitation,
62
68
  defaultWebhookTransportLimits,
69
+ maxFailureMessageLength,
63
70
  maxInputProblems,
64
71
  workflowDurationMillis
65
- } from "./chunk-3M2MEDNL.js";
72
+ } from "./chunk-DQAZTA4I.js";
73
+ import {
74
+ AppDatabaseError
75
+ } from "./chunk-N7YDVXYJ.js";
66
76
  import {
67
77
  CacheError
68
- } from "./chunk-LGIYBDWA.js";
78
+ } from "./chunk-YEPYT6SD.js";
69
79
  import {
70
80
  AppSkills,
71
81
  SkillFile,
72
82
  SkillLoadFailed
73
- } from "./chunk-YEJOQEII.js";
83
+ } from "./chunk-JU7VHODU.js";
74
84
  import {
75
85
  OpenapiResponseError
76
- } from "./chunk-SWPD52J7.js";
86
+ } from "./chunk-W4DMKWAB.js";
77
87
  import {
78
88
  captureTelemetry,
79
89
  invocationFetch
80
- } from "./chunk-ZCAMUXSG.js";
90
+ } from "./chunk-RJDDBDSN.js";
81
91
  import {
82
92
  decoderOf,
83
93
  importedJsonSchema,
84
94
  jsonSchemaDecoder
85
- } from "./chunk-WFSQXYUT.js";
95
+ } from "./chunk-FWQC6I3C.js";
96
+ import {
97
+ AppStorageError,
98
+ AppStorageUnavailable
99
+ } from "./chunk-PZB6T6KU.js";
86
100
  import {
87
101
  JsonObject,
88
102
  JsonValue
89
- } from "./chunk-SATWJKN6.js";
103
+ } from "./chunk-27F7W2LG.js";
90
104
  import {
91
105
  Cause_exports,
92
106
  Clock_exports,
@@ -94,11 +108,12 @@ import {
94
108
  Encoding_exports,
95
109
  Match_exports,
96
110
  Option_exports,
111
+ Predicate_exports,
97
112
  Redacted_exports,
98
113
  SchemaIssue_exports,
99
114
  Schema_exports,
100
115
  Stream_exports
101
- } from "./chunk-FW5HBOIK.js";
116
+ } from "./chunk-CDL5PM2Q.js";
102
117
 
103
118
  // src/implementation/elicitation.ts
104
119
  var prepareElicitation = (input) => Effect_exports.gen(function* () {
@@ -138,20 +153,121 @@ var makeElicit = (handler, signal) => toPromise(
138
153
  // src/contracts/approval.ts
139
154
  var ApprovalDecision = Schema_exports.Literals(["approved", "denied", "user-approval"]);
140
155
 
156
+ // src/implementation/failure-detail.ts
157
+ var storageMessages = {
158
+ schema: "The app's database schema is invalid.",
159
+ schema_changed: "The app's database schema changed during this operation. Retry it.",
160
+ table: "The operation used a table the app's database schema does not declare.",
161
+ index: "The operation used an index the table does not declare, or used it incorrectly.",
162
+ range: "The index range is invalid for the declared index.",
163
+ value: "A value does not match the table's declared field schema.",
164
+ readonly: "Queries cannot write. Move writes into a mutation.",
165
+ cursor: "The pagination cursor is invalid or belongs to a different query.",
166
+ limit: "The operation exceeded a per-invocation app data limit.",
167
+ closed: "The database session closed before this operation finished.",
168
+ storage: "App storage failed to complete the operation.",
169
+ replay: "A workflow step replayed with different input than its first run."
170
+ };
171
+ var minimumSecretLength = 6;
172
+ var secretValues = (value, found) => {
173
+ if (typeof value === "string") {
174
+ if (value.length >= minimumSecretLength) found.add(value);
175
+ } else if (Array.isArray(value)) for (const item of value) secretValues(item, found);
176
+ else if (Predicate_exports.isObject(value))
177
+ for (const item of Object.values(value)) secretValues(item, found);
178
+ return found;
179
+ };
180
+ var accountFieldSecrets = (accounts) => {
181
+ const found = /* @__PURE__ */ new Set();
182
+ if (Predicate_exports.isObject(accounts)) {
183
+ for (const slot of Object.values(accounts))
184
+ for (const account of Array.isArray(slot) ? slot : [slot])
185
+ if (Predicate_exports.hasProperty(account, "fields")) secretValues(account.fields, found);
186
+ }
187
+ return [...found].sort((a, b) => b.length - a.length);
188
+ };
189
+ var accountSecrets = (accounts) => accountFieldSecrets(Redacted_exports.value(accounts));
190
+ var boundFailureMessage = (message, secrets) => {
191
+ let redacted = message;
192
+ for (const secret of secrets) redacted = redacted.split(secret).join("[redacted]");
193
+ return redacted.length <= maxFailureMessageLength ? redacted : `${redacted.slice(0, maxFailureMessageLength - 1)}\u2026`;
194
+ };
195
+ var errorName = (error) => (error.name.length > 0 ? error.name : "Error").slice(0, 128);
196
+ var ownMessage = (error) => {
197
+ const cause = error.cause;
198
+ const suffix = cause instanceof Error && cause.message.length > 0 ? ` (caused by ${errorName(cause)}: ${cause.message})` : "";
199
+ return error.message.length > 0 ? `${error.message}${suffix}` : void 0;
200
+ };
201
+ var describeFailure = (error) => error instanceof Error ? `${errorName(error)}: ${ownMessage(error) ?? "(no message)"}` : typeof error === "string" ? error : `A non-Error ${error === null ? "null" : typeof error} value was thrown`;
202
+ var failureDetail = (error, secrets) => {
203
+ if (Schema_exports.is(AppDatabaseError)(error))
204
+ return {
205
+ source: "storage",
206
+ errorName: "AppDatabaseError",
207
+ code: error.reason,
208
+ message: boundFailureMessage(ownMessage(error) ?? storageMessages[error.reason], secrets)
209
+ };
210
+ if (Schema_exports.is(AppStorageUnavailable)(error))
211
+ return {
212
+ source: "storage",
213
+ errorName: "AppStorageUnavailable",
214
+ message: "App storage is not available on this host."
215
+ };
216
+ if (Schema_exports.is(AppStorageError)(error))
217
+ return {
218
+ source: "storage",
219
+ errorName: "AppStorageError",
220
+ message: "App storage failed to complete the operation."
221
+ };
222
+ if (Schema_exports.is(OpenapiError)(error))
223
+ return {
224
+ source: "service",
225
+ errorName: "OpenapiError",
226
+ code: error.reason,
227
+ message: error.reason === "request" ? error.status === void 0 ? "The API request failed before a response arrived." : `The API responded with HTTP ${error.status}, which its OpenAPI document does not declare as an error with a message.` : error.reason === "invalid_input" ? "The input could not be encoded as a request for this API operation." : "The API's OpenAPI definition for this operation is invalid."
228
+ };
229
+ if (error instanceof Error)
230
+ return {
231
+ source: "app",
232
+ errorName: errorName(error),
233
+ message: boundFailureMessage(
234
+ ownMessage(error) ?? `${errorName(error)} was thrown without a message.`,
235
+ secrets
236
+ )
237
+ };
238
+ if (typeof error === "string")
239
+ return { source: "app", errorName: "string", message: boundFailureMessage(error, secrets) };
240
+ return {
241
+ source: "app",
242
+ errorName: typeof error,
243
+ message: `A non-Error ${error === null ? "null" : typeof error} value was thrown.`
244
+ };
245
+ };
246
+
141
247
  // src/implementation/workflow-context.ts
142
- var workflowSafe = (work) => work.pipe(
248
+ var workflowSafe = (work, secrets) => work.pipe(
143
249
  Effect_exports.catchCause((cause) => {
144
250
  if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
145
251
  const error = Cause_exports.squash(cause);
146
252
  if (Schema_exports.is(WorkflowFailure)(error)) return Effect_exports.fail(error);
253
+ const { errorName: errorName2, message } = failureDetail(error, secrets);
147
254
  return Effect_exports.fail(
148
255
  new WorkflowFailure({
149
256
  reason: "execution",
150
- retryable: !(error instanceof NonRetryableError)
257
+ retryable: !(error instanceof NonRetryableError),
258
+ ...errorName2 === void 0 ? {} : { errorName: errorName2 },
259
+ ...message === void 0 ? {} : { message }
151
260
  })
152
261
  );
153
262
  })
154
263
  );
264
+ var inStep = (step) => (failure) => failure.step === void 0 ? new WorkflowFailure({
265
+ reason: failure.reason,
266
+ retryable: failure.retryable,
267
+ step: step.slice(0, 200),
268
+ ...failure.errorName === void 0 ? {} : { errorName: failure.errorName },
269
+ ...failure.message.length === 0 ? {} : { message: failure.message }
270
+ }) : failure;
155
271
  var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_exports.gen(function* () {
156
272
  const services = yield* Effect_exports.context();
157
273
  const counts = /* @__PURE__ */ new Map();
@@ -206,19 +322,27 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
206
322
  Effect_exports.sync(() => new AbortController()),
207
323
  (controller2) => Effect_exports.sync(() => controller2.abort())
208
324
  );
209
- const ctx = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
325
+ const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
210
326
  const result = yield* workflowSafe(
211
- Effect_exports.tryPromise({ try: () => callback(ctx), catch: (error) => error })
327
+ Effect_exports.tryPromise({
328
+ try: () => callback(step2.context),
329
+ catch: (error) => error
330
+ }),
331
+ step2.secrets
212
332
  );
213
333
  return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
214
334
  Effect_exports.mapError(
215
- () => new WorkflowFailure({ reason: "output", retryable: false })
335
+ () => new WorkflowFailure({
336
+ reason: "output",
337
+ retryable: false,
338
+ message: "The step returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
339
+ })
216
340
  )
217
341
  );
218
342
  })
219
343
  ).pipe(Effect_exports.provideContext(services))
220
344
  )
221
- );
345
+ ).pipe(Effect_exports.mapError(inStep(name)));
222
346
  });
223
347
  const operationStep = (kind, name, operation, input, options) => Effect_exports.gen(function* () {
224
348
  const target = nativeOperation(operation);
@@ -245,7 +369,7 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
245
369
  parsed,
246
370
  execution.invoke({ kind, name: match[0], input: args, stepId, timeout }).pipe(Effect_exports.provideContext(services))
247
371
  )
248
- );
372
+ ).pipe(Effect_exports.mapError(inStep(name)));
249
373
  });
250
374
  const invoke = (effect) => toPromise(() => effect.pipe(Effect_exports.provideContext(services)), signal)();
251
375
  const step = {
@@ -530,7 +654,7 @@ function safe2(work, failure) {
530
654
  )
531
655
  );
532
656
  }
533
- var evaluationSafe = (work) => work.pipe(
657
+ var evaluationSafe = (work, secrets) => work.pipe(
534
658
  Effect_exports.catchCause((cause) => {
535
659
  if (Cause_exports.hasInterrupts(cause)) return Effect_exports.interrupt;
536
660
  const error = Cause_exports.squash(cause);
@@ -538,7 +662,7 @@ var evaluationSafe = (work) => work.pipe(
538
662
  const skills = parseSkillLoadFailed(error);
539
663
  const mcp = parseMcpError(error);
540
664
  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()
665
+ Option_exports.isSome(provider) ? provider.value : Option_exports.isSome(skills) ? skills.value : Option_exports.isSome(mcp) ? mcp.value : new HostEvaluationFailed(failureDetail(error, secrets))
542
666
  );
543
667
  })
544
668
  );
@@ -552,8 +676,21 @@ function jsonSchema(decoder) {
552
676
  $schema: "https://json-schema.org/draft/2020-12/schema"
553
677
  });
554
678
  }
679
+ var declarationInvalid = (summary, cause, secrets = []) => new HostDeclarationInvalid({
680
+ source: "app",
681
+ errorName: "HostDeclarationInvalid",
682
+ message: boundFailureMessage(
683
+ cause === void 0 ? summary : `${summary}: ${describeFailure(cause)}`,
684
+ secrets
685
+ )
686
+ });
687
+ var declarationSafe = (work, summary) => Effect_exports.suspend(work).pipe(
688
+ Effect_exports.catchCause(
689
+ (cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.fail(declarationInvalid(summary, Cause_exports.squash(cause)))
690
+ )
691
+ );
555
692
  function providerDeclaration(provider) {
556
- return safe2(
693
+ return declarationSafe(
557
694
  () => Effect_exports.gen(function* () {
558
695
  const auth = /* @__PURE__ */ new Map();
559
696
  for (const [name, method] of Object.entries(provider.auth)) {
@@ -579,7 +716,7 @@ function providerDeclaration(provider) {
579
716
  auth: Object.fromEntries(auth)
580
717
  });
581
718
  }),
582
- new HostDeclarationInvalid()
719
+ `Account provider "${provider.name}" has an invalid declaration`
583
720
  );
584
721
  }
585
722
  function requirements(slots, database) {
@@ -597,7 +734,11 @@ function requirements(slots, database) {
597
734
  accounts: Object.fromEntries(accounts),
598
735
  capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
599
736
  ...database === void 0 ? {} : { database }
600
- }).pipe(Effect_exports.mapError(() => new HostDeclarationInvalid()));
737
+ }).pipe(
738
+ Effect_exports.mapError(
739
+ (cause) => declarationInvalid("The app's account or database declarations are invalid", cause)
740
+ )
741
+ );
601
742
  });
602
743
  }
603
744
  function canonical(value) {
@@ -656,14 +797,29 @@ function bindAccounts(slots, declarations, context) {
656
797
  function dispatch(app, request, context, signal) {
657
798
  return Effect_exports.scoped(
658
799
  Effect_exports.gen(function* () {
659
- if (!isApp(app)) return yield* Effect_exports.fail(new HostDeclarationInvalid());
800
+ if (!isApp(app))
801
+ return yield* Effect_exports.fail(
802
+ declarationInvalid("The app module's default export is not an app created by defineApp")
803
+ );
660
804
  const native = toEffectApp(app);
805
+ const secrets = accountSecrets(context.accounts);
806
+ const storageFailure = (error) => Effect_exports.fail(new HostOperationFailed(failureDetail(error, secrets)));
661
807
  const declared = yield* requirements(native.accounts, native.database?.schema);
662
- if (request.operation === "requirements")
808
+ if (request.operation === "requirements") {
809
+ if (native.database !== void 0)
810
+ yield* parseDatabaseSchema(native.database.schema).pipe(
811
+ Effect_exports.catchTag(
812
+ "AppDatabaseError",
813
+ (cause) => Effect_exports.fail(
814
+ declarationInvalid("The app's account or database declarations are invalid", cause)
815
+ )
816
+ )
817
+ );
663
818
  return yield* safe2(
664
819
  () => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
665
820
  new HostDeclarationInvalid()
666
821
  );
822
+ }
667
823
  const lifetime = yield* Effect_exports.acquireRelease(
668
824
  Effect_exports.sync(() => new AbortController()),
669
825
  (controller) => Effect_exports.sync(() => controller.abort())
@@ -747,7 +903,7 @@ function dispatch(app, request, context, signal) {
747
903
  fetch: yield* invocationFetch(invocationSignal),
748
904
  elicit: makeElicit(delivery, invocationSignal)
749
905
  };
750
- const definition = yield* evaluationSafe(native.evaluate(bound)).pipe(
906
+ const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
751
907
  Effect_exports.withSpan("app.evaluate")
752
908
  );
753
909
  if (request.operation === "skills") {
@@ -756,7 +912,7 @@ function dispatch(app, request, context, signal) {
756
912
  ));
757
913
  const source2 = definition.dynamicSkills;
758
914
  const before = cacheCommands;
759
- const dynamic = source2 === void 0 ? [] : yield* evaluationSafe(Effect_exports.suspend(source2.list)).pipe(
915
+ const dynamic = source2 === void 0 ? [] : yield* evaluationSafe(Effect_exports.suspend(source2.list), secrets).pipe(
760
916
  Effect_exports.withSpan("app.skills.load")
761
917
  );
762
918
  const cached = source2 !== void 0 && cacheCommands > before;
@@ -807,31 +963,43 @@ function dispatch(app, request, context, signal) {
807
963
  new WorkflowFailure({ reason: "credentials", retryable: false })
808
964
  );
809
965
  return {
810
- ...accounts,
811
- cache: authorCache(
812
- context.cache ?? unavailableCache,
813
- Redacted_exports.value(current.accounts),
814
- signal2
815
- ),
816
- files,
817
- fetch: yield* invocationFetch(signal2),
818
- signal: signal2,
819
- runId: execution.runId,
820
- stepId,
821
- idempotencyKey: stepId
966
+ context: {
967
+ ...accounts,
968
+ cache: authorCache(
969
+ context.cache ?? unavailableCache,
970
+ Redacted_exports.value(current.accounts),
971
+ signal2
972
+ ),
973
+ files,
974
+ fetch: yield* invocationFetch(signal2),
975
+ signal: signal2,
976
+ runId: execution.runId,
977
+ stepId,
978
+ idempotencyKey: stepId
979
+ },
980
+ // The resolved values, not the app's decoded fields, which may be `Redacted`.
981
+ secrets: accountSecrets(current.accounts)
822
982
  };
823
983
  }),
824
984
  invocationSignal
825
985
  );
826
- const output = yield* workflowSafe(entry.run(workflowContext, input2));
986
+ const output = yield* workflowSafe(entry.run(workflowContext, input2), secrets);
827
987
  const outputSchema = entry.output;
828
988
  const decoded = outputSchema === void 0 ? output : yield* safe2(
829
989
  () => Schema_exports.decodeUnknownEffect(outputSchema)(output),
830
- new WorkflowFailure({ reason: "output", retryable: false })
990
+ new WorkflowFailure({
991
+ reason: "output",
992
+ retryable: false,
993
+ message: "The workflow's result does not match its declared output schema."
994
+ })
831
995
  );
832
996
  return yield* safe2(
833
997
  () => Schema_exports.decodeUnknownEffect(WorkflowValue)(decoded),
834
- new WorkflowFailure({ reason: "output", retryable: false })
998
+ new WorkflowFailure({
999
+ reason: "output",
1000
+ retryable: false,
1001
+ message: "The workflow returned a value that is not JSON, such as undefined, or is larger than 1 MiB. Return null for no result."
1002
+ })
835
1003
  );
836
1004
  }
837
1005
  if (request.operation === "inspect") {
@@ -886,7 +1054,7 @@ function dispatch(app, request, context, signal) {
886
1054
  }
887
1055
  return dynamic.list();
888
1056
  };
889
- const discovered = yield* evaluationSafe(discover()).pipe(
1057
+ const discovered = yield* evaluationSafe(discover(), secrets).pipe(
890
1058
  Effect_exports.flatMap(
891
1059
  (value) => safe2(
892
1060
  () => summary ? Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedToolSummary))(value) : Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedTool))(value),
@@ -932,9 +1100,10 @@ function dispatch(app, request, context, signal) {
932
1100
  const storage2 = context.storage ?? unavailableStorage;
933
1101
  return yield* storage2.mutate(native.database.schema, executeWebhook).pipe(
934
1102
  Effect_exports.catchTags({
935
- AppDatabaseError: () => Effect_exports.fail(new HostOperationFailed()),
936
- AppStorageUnavailable: () => Effect_exports.fail(new HostOperationFailed()),
937
- AppStorageError: () => Effect_exports.fail(new HostOperationFailed())
1103
+ AppDatabaseError: storageFailure,
1104
+ DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
1105
+ AppStorageUnavailable: storageFailure,
1106
+ AppStorageError: storageFailure
938
1107
  })
939
1108
  );
940
1109
  }
@@ -945,7 +1114,7 @@ function dispatch(app, request, context, signal) {
945
1114
  const catalog = kind === "query" ? definition.queries : definition.mutations;
946
1115
  const declaredTool = catalog !== void 0 && Object.hasOwn(catalog, name) ? catalog[name] : void 0;
947
1116
  const source = definition.dynamicTools;
948
- const resolvedTool = source === void 0 || declaredTool !== void 0 ? void 0 : yield* evaluationSafe(source.resolve(toolName));
1117
+ const resolvedTool = source === void 0 || declaredTool !== void 0 ? void 0 : yield* evaluationSafe(source.resolve(toolName), secrets);
949
1118
  const tool = declaredTool ?? resolvedTool;
950
1119
  if (tool !== void 0 && tool.kind !== (kind === "query" ? "query" : "mutation"))
951
1120
  return yield* new HostDeclarationInvalid();
@@ -1039,7 +1208,7 @@ function dispatch(app, request, context, signal) {
1039
1208
  status: response.value.status,
1040
1209
  message: response.value.message,
1041
1210
  ...response.value.recovery === void 0 ? {} : { recovery: response.value.recovery }
1042
- }) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed()
1211
+ }) : Option_exports.isSome(failure) ? failure.value : new HostOperationFailed(failureDetail(error, secrets))
1043
1212
  );
1044
1213
  }),
1045
1214
  Effect_exports.withSpan("app.operation.execute", {
@@ -1070,9 +1239,10 @@ function dispatch(app, request, context, signal) {
1070
1239
  )
1071
1240
  ).pipe(
1072
1241
  Effect_exports.catchTags({
1073
- AppDatabaseError: () => Effect_exports.fail(new HostOperationFailed()),
1074
- AppStorageUnavailable: () => Effect_exports.fail(new HostOperationFailed()),
1075
- AppStorageError: () => Effect_exports.fail(new HostOperationFailed())
1242
+ AppDatabaseError: storageFailure,
1243
+ DatabaseLimitExceeded: (error) => Effect_exports.fail(error),
1244
+ AppStorageUnavailable: storageFailure,
1245
+ AppStorageError: storageFailure
1076
1246
  })
1077
1247
  );
1078
1248
  })
@@ -1108,6 +1278,8 @@ var errorStatus = Match_exports.type().pipe(
1108
1278
  HostToolApprovalRequired: () => 409,
1109
1279
  HostToolPolicyFailed: () => 500,
1110
1280
  HostOperationFailed: () => 500,
1281
+ DatabaseLimitExceeded: () => 422,
1282
+ DatabaseFieldReserved: () => 422,
1111
1283
  HostDeclarationInvalid: () => 500,
1112
1284
  HostEvaluationFailed: () => 500,
1113
1285
  HostOutputInvalid: () => 500,
@@ -1153,12 +1325,17 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
1153
1325
  ),
1154
1326
  Effect_exports.catchCause(
1155
1327
  (cause) => Cause_exports.hasInterrupts(cause) ? Effect_exports.interrupt : Effect_exports.logError(cause).pipe(
1156
- Effect_exports.as(
1157
- Response.json(
1158
- { ok: false, error: { _tag: "HostDeclarationInvalid" } },
1159
- { status: 500 }
1328
+ Effect_exports.andThen(
1329
+ Schema_exports.encodeEffect(HostError)(
1330
+ declarationInvalid(
1331
+ "The app failed while it was loaded",
1332
+ Cause_exports.squash(cause),
1333
+ accountSecrets(context.accounts)
1334
+ )
1160
1335
  )
1161
- )
1336
+ ),
1337
+ Effect_exports.map((error) => Response.json({ ok: false, error }, { status: 500 })),
1338
+ Effect_exports.orDie
1162
1339
  )
1163
1340
  )
1164
1341
  );
@@ -3,7 +3,7 @@ import {
3
3
  invalidate,
4
4
  layer,
5
5
  mutation
6
- } from "./chunk-M6ZRRIBI.js";
6
+ } from "./chunk-PJJ24GU7.js";
7
7
  import {
8
8
  Boolean,
9
9
  Cause,
@@ -158,7 +158,7 @@ import {
158
158
  void_2,
159
159
  whileLoop,
160
160
  zipRight
161
- } from "./chunk-FW5HBOIK.js";
161
+ } from "./chunk-CDL5PM2Q.js";
162
162
  import {
163
163
  __export
164
164
  } from "./chunk-CZ7CSFO4.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Schema_exports
3
- } from "./chunk-FW5HBOIK.js";
3
+ } from "./chunk-CDL5PM2Q.js";
4
4
 
5
5
  // ../app-data/src/contracts/database.ts
6
6
  var DataName = Schema_exports.String.check(
@@ -113,6 +113,51 @@ var defaultDatabaseLimits = {
113
113
  valueBytes: 64 * 1024,
114
114
  indexBytes: 2048
115
115
  };
116
+ var DatabaseLimit = Schema_exports.Literals([
117
+ "scanCalls",
118
+ "directGets",
119
+ "rowsRead",
120
+ "rowsReturned",
121
+ "pageSize",
122
+ "bytesRead",
123
+ "writes",
124
+ "valueBytes"
125
+ ]);
126
+ var count = (value) => value.toLocaleString("en-US");
127
+ var limitMessages = {
128
+ scanCalls: (maximum, requested) => `This invocation made ${count(requested)} index queries; the limit is ${count(maximum)}. Each first(), take(), collect(), count() or paginate() call on withIndex(...) counts once. Read related rows with one take() or paginate() over a shared index prefix instead of one first() per item, use get(id) for known IDs, or split the work across workflow steps.`,
129
+ directGets: (maximum, requested) => `This invocation made ${count(requested)} get(id) calls, including those made by update and delete; the limit is ${count(maximum)}. Split the work across workflow steps or mutations.`,
130
+ rowsRead: (maximum, requested) => `This invocation scanned ${count(requested)} rows; the limit is ${count(maximum)}. Narrow the index range, or page with paginate() across calls or workflow steps.`,
131
+ rowsReturned: (maximum, requested) => `This invocation returned ${count(requested)} rows; the limit is ${count(maximum)}. collect() fails rather than truncating. Page with paginate() across calls or workflow steps.`,
132
+ pageSize: (maximum, requested) => `One call asked for ${count(requested)} rows; take(n) and paginate({ numItems }) accept at most ${count(maximum)}. Page with paginate() across calls or workflow steps.`,
133
+ bytesRead: (maximum, requested) => `This invocation read ${count(requested)} bytes; the limit is ${count(maximum)}. Read fewer or smaller rows per call, or page with paginate() across calls or workflow steps.`,
134
+ writes: (maximum, requested) => `This mutation made ${count(requested)} writes; the limit is ${count(maximum)}. Split large ingests into batches, one batch per mutation or workflow step.`,
135
+ valueBytes: (maximum, requested) => `A row encodes to ${count(requested)} bytes; each row may use at most ${count(maximum)}. Store large content outside the row or split it across rows.`
136
+ };
137
+ var DatabaseLimitExceeded = class extends Schema_exports.TaggedError()(
138
+ "DatabaseLimitExceeded",
139
+ {
140
+ limit: DatabaseLimit,
141
+ maximum: Schema_exports.Int,
142
+ requested: Schema_exports.Int
143
+ }
144
+ ) {
145
+ get message() {
146
+ return limitMessages[this.limit](this.maximum, this.requested);
147
+ }
148
+ };
149
+ var reservedFieldNames = ["id", "createdAt", "updatedAt"];
150
+ var DatabaseFieldReserved = class extends Schema_exports.TaggedError()(
151
+ "DatabaseFieldReserved",
152
+ {
153
+ table: Schema_exports.String,
154
+ field: Schema_exports.Literals(reservedFieldNames)
155
+ }
156
+ ) {
157
+ get message() {
158
+ return `Table "${this.table}" declares "${this.field}", which is reserved: the host adds id, createdAt and updatedAt to every row. Rename the field, or use the row's own ${this.field}.`;
159
+ }
160
+ };
116
161
  var DatabaseRuntimeLimits = Schema_exports.Struct({
117
162
  maxCursorChars: Schema_exports.Int.check(Schema_exports.isGreaterThan(0)),
118
163
  connectionCacheCapacity: Schema_exports.Int.check(Schema_exports.isGreaterThan(0)),
@@ -134,5 +179,8 @@ export {
134
179
  AppDatabaseError,
135
180
  DatabaseLimits,
136
181
  defaultDatabaseLimits,
182
+ DatabaseLimitExceeded,
183
+ reservedFieldNames,
184
+ DatabaseFieldReserved,
137
185
  defaultDatabaseRuntimeLimits
138
186
  };
@@ -58,7 +58,7 @@ import {
58
58
  useSpan,
59
59
  void_2 as void_,
60
60
  withFiber
61
- } from "./chunk-FW5HBOIK.js";
61
+ } from "./chunk-CDL5PM2Q.js";
62
62
 
63
63
  // ../../node_modules/.bun/effect@https+++pkg.pr.new+Effect-TS+effect+effect@c7d1ffff31a3e2ae0b0b+a654a55b752bdb24/node_modules/effect/dist/unstable/reactivity/Reactivity.js
64
64
  var TypeId = "~effect/reactivity/Reactivity";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Schema_exports
3
- } from "./chunk-FW5HBOIK.js";
3
+ } from "./chunk-CDL5PM2Q.js";
4
4
 
5
5
  // src/contracts/storage.ts
6
6
  var StorageName = Schema_exports.NonEmptyString.check(Schema_exports.isMaxLength(200));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FetchHttpClient_exports
3
- } from "./chunk-HDJH3RPR.js";
3
+ } from "./chunk-57RKNWL2.js";
4
4
  import {
5
5
  HttpBody_exports,
6
6
  HttpClient,
@@ -18,7 +18,7 @@ import {
18
18
  setBody,
19
19
  transformResponse,
20
20
  uint8Array
21
- } from "./chunk-QKHR7BMF.js";
21
+ } from "./chunk-UK573G7W.js";
22
22
  import {
23
23
  Array as Array2,
24
24
  Boolean2 as Boolean,
@@ -125,7 +125,7 @@ import {
125
125
  withDefault2 as withDefault,
126
126
  withTracerEnabled,
127
127
  zero
128
- } from "./chunk-FW5HBOIK.js";
128
+ } from "./chunk-CDL5PM2Q.js";
129
129
  import {
130
130
  __export
131
131
  } from "./chunk-CZ7CSFO4.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  AccountId
3
- } from "./chunk-SATWJKN6.js";
3
+ } from "./chunk-27F7W2LG.js";
4
4
  import {
5
5
  Schema_exports
6
- } from "./chunk-FW5HBOIK.js";
6
+ } from "./chunk-CDL5PM2Q.js";
7
7
 
8
8
  // src/contracts/provider-error.ts
9
9
  var ProviderError = class extends Schema_exports.TaggedError()("ProviderError", {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  operationDeclaration
3
- } from "./chunk-PYUYJRSK.js";
3
+ } from "./chunk-3XKZDQLM.js";
4
4
 
5
5
  // src/implementation/protocol-operations.ts
6
6
  var protocolOperations = (operations, kinds = {}) => {