apps 0.0.1-beta.43 → 0.0.1-beta.46

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 (54) hide show
  1. package/framework-reference.json +1 -1
  2. package/js/{chunk-XSD3RZFX.js → chunk-3B2JAOSE.js} +23 -12
  3. package/js/{chunk-KTPKTBKZ.js → chunk-3UGDI2UI.js} +5 -5
  4. package/js/chunk-5FHWNLCI.js +88 -0
  5. package/js/{chunk-MSDGZ7FA.js → chunk-6QXPBJ5T.js} +14 -13
  6. package/js/{chunk-Z3S2IVI3.js → chunk-7LGRK7TP.js} +2 -2
  7. package/js/{chunk-T65AFHU3.js → chunk-7UUHJR2Q.js} +1 -1
  8. package/js/{chunk-4ZTVLEN6.js → chunk-CDXQDN7W.js} +1 -1
  9. package/js/{chunk-OBXHQNWC.js → chunk-CVAJ4F6O.js} +16 -3
  10. package/js/{chunk-KBIKBWSS.js → chunk-H72MEDMN.js} +4 -3
  11. package/js/{chunk-VU6GQ2SH.js → chunk-JM7LOD2W.js} +212 -22
  12. package/js/{chunk-EJUK2NK5.js → chunk-KLYSEHUD.js} +1 -1
  13. package/js/{chunk-ILYK7BQG.js → chunk-LHCGND3R.js} +12 -46
  14. package/js/{chunk-EMHFXFTJ.js → chunk-LTDHQJ2Z.js} +53 -0
  15. package/js/{chunk-47BLLMRQ.js → chunk-OJ47HQVJ.js} +143 -65
  16. package/js/{chunk-MZH4J2PO.js → chunk-PD6I2SDG.js} +1 -1
  17. package/js/{chunk-KSGYJV46.js → chunk-TUMGL2OC.js} +1 -1
  18. package/js/{chunk-5GLC42LK.js → chunk-UM62MBJQ.js} +42 -24
  19. package/js/{chunk-IN2WIN7I.js → chunk-XBG7HHXC.js} +1 -1
  20. package/js/{chunk-RIKH5H2X.js → chunk-XK5I2XOI.js} +39 -29
  21. package/js/client.js +9 -9
  22. package/js/contracts.js +9 -5
  23. package/js/effect.js +14 -14
  24. package/js/graphql.js +23 -21
  25. package/js/host.js +79 -54
  26. package/js/index.js +23 -18
  27. package/js/mcp/effect.js +16 -16
  28. package/js/mcp/stdio.js +30 -25
  29. package/js/mcp.js +23 -21
  30. package/js/openapi.js +106 -80
  31. package/js/skills/effect.js +5 -5
  32. package/js/skills.js +53 -36
  33. package/js/ui/auth.js +3 -3
  34. package/js/ui/contracts.js +3 -3
  35. package/js/ui/serving.js +7 -7
  36. package/package.json +1 -1
  37. package/runtime.json +1 -1
  38. package/types/apps/src/contracts/host.d.ts +15 -0
  39. package/types/apps/src/host.d.ts +5 -0
  40. package/types/apps/src/implementation/authoring.d.ts +25 -5
  41. package/types/apps/src/implementation/cache.d.ts +4 -0
  42. package/types/apps/src/implementation/elicitation.d.ts +6 -3
  43. package/types/apps/src/implementation/invocation-timing.d.ts +16 -0
  44. package/types/apps/src/implementation/operations.d.ts +2 -2
  45. package/types/apps/src/implementation/router-catalog.d.ts +4 -4
  46. package/types/apps/src/implementation/workflows.d.ts +1 -1
  47. package/types/telemetry/src/index.d.ts +1 -0
  48. package/types/telemetry/src/ownership.d.ts +56 -0
  49. package/types/telemetry/src/recorded-failure.d.ts +20 -11
  50. package/types/utils/src/api-error.d.ts +4 -2
  51. package/types/utils/src/recorded-message.d.ts +7 -4
  52. package/types/utils/src/user-facing-error.d.ts +4 -2
  53. package/js/chunk-EG72MSVK.js +0 -16
  54. package/js/{chunk-LNSVJS2Q.js → chunk-EOPQ727L.js} +2 -2
@@ -11,30 +11,32 @@ import {
11
11
  parseSkillLoadFailed,
12
12
  readCatalog,
13
13
  routerSkills
14
- } from "./chunk-KTPKTBKZ.js";
14
+ } from "./chunk-3UGDI2UI.js";
15
15
  import {
16
16
  appInvocationFetch
17
- } from "./chunk-T65AFHU3.js";
17
+ } from "./chunk-7UUHJR2Q.js";
18
18
  import {
19
19
  folderSkillsEffect
20
- } from "./chunk-IN2WIN7I.js";
20
+ } from "./chunk-XBG7HHXC.js";
21
21
  import {
22
22
  ResponseStatusError,
23
23
  isApp,
24
24
  toEffectApp
25
- } from "./chunk-XSD3RZFX.js";
25
+ } from "./chunk-3B2JAOSE.js";
26
26
  import {
27
27
  declaredOperations,
28
- fromPromise,
29
28
  locate,
30
- nativeOperation,
31
- toPromise
32
- } from "./chunk-ILYK7BQG.js";
29
+ nativeOperation
30
+ } from "./chunk-LHCGND3R.js";
33
31
  import {
34
32
  accountProviderError,
33
+ appCode,
34
+ fromPromise,
35
35
  httpProviderError,
36
- parseProviderError
37
- } from "./chunk-EMHFXFTJ.js";
36
+ method,
37
+ parseProviderError,
38
+ toPromise
39
+ } from "./chunk-LTDHQJ2Z.js";
38
40
  import {
39
41
  AccountCheckResult,
40
42
  DeclaredProvider,
@@ -63,6 +65,7 @@ import {
63
65
  HostedWebhook,
64
66
  HostedWorkflow,
65
67
  InvocationDeadline,
68
+ InvocationTimingSink,
66
69
  ManualWebhookSetup,
67
70
  ManyAccounts,
68
71
  NonRetryableError,
@@ -83,17 +86,14 @@ import {
83
86
  migrationsDirectory,
84
87
  reservedTablePrefix,
85
88
  workflowDurationMillis
86
- } from "./chunk-OBXHQNWC.js";
89
+ } from "./chunk-CVAJ4F6O.js";
87
90
  import {
88
91
  CacheError
89
92
  } from "./chunk-MWKHKOTL.js";
90
93
  import {
91
94
  AppSkills,
92
95
  SkillFile
93
- } from "./chunk-KBIKBWSS.js";
94
- import {
95
- captureTelemetry
96
- } from "./chunk-VU6GQ2SH.js";
96
+ } from "./chunk-H72MEDMN.js";
97
97
  import {
98
98
  allowedValues,
99
99
  decoderOf,
@@ -108,6 +108,12 @@ import {
108
108
  objectShape,
109
109
  unionShape
110
110
  } from "./chunk-KGCTYL2S.js";
111
+ import {
112
+ captureTelemetry,
113
+ makeOwnershipAccounting,
114
+ measuredSpan,
115
+ owned
116
+ } from "./chunk-JM7LOD2W.js";
111
117
  import {
112
118
  JsonObject,
113
119
  JsonValue
@@ -126,6 +132,34 @@ import {
126
132
  Stream_exports
127
133
  } from "./chunk-IFJU5SYQ.js";
128
134
 
135
+ // src/implementation/invocation-timing.ts
136
+ var elicitationWaitSpan = "app.elicitation.wait";
137
+ var workflowControlSpan = "app.workflow.control";
138
+ var timedInvocation = (operation) => (effect) => Effect_exports.gen(function* () {
139
+ const report = yield* InvocationTimingSink;
140
+ return yield* effect.pipe(
141
+ measuredSpan(`app.${operation}`, {}, (start) => {
142
+ const accounting = makeOwnershipAccounting(start, "executor");
143
+ return {
144
+ around: accounting.observe,
145
+ end: (end, span) => {
146
+ const spent = accounting.read(end);
147
+ report({
148
+ elapsedMs: Number(end - start) / 1e6,
149
+ upstreamMs: spent.upstream,
150
+ elicitationMs: spent.person,
151
+ authoredMs: spent.app
152
+ });
153
+ span.attribute("executor.upstream.wait_ms", spent.upstream);
154
+ span.attribute("executor.elicitation.wait_ms", spent.person);
155
+ span.attribute("executor.authored_ms", spent.app);
156
+ span.attribute("executor.overhead_ms", spent.executor);
157
+ }
158
+ };
159
+ })
160
+ );
161
+ });
162
+
129
163
  // src/implementation/elicitation.ts
130
164
  var prepareElicitation = (input) => Effect_exports.gen(function* () {
131
165
  const request = yield* Schema_exports.decodeUnknownEffect(FormElicitation)(input, {
@@ -152,13 +186,17 @@ var prepareElicitation = (input) => Effect_exports.gen(function* () {
152
186
  });
153
187
  return { request, respond };
154
188
  });
155
- var makeElicit = (handler, signal) => toPromise(
189
+ var makeElicit = (handler, signal, telemetry) => toPromise(
156
190
  (input) => Effect_exports.gen(function* () {
157
191
  if (handler === void 0) return yield* new ElicitationFailed({ reason: "unavailable" });
158
192
  const form = yield* prepareElicitation(input);
159
- return yield* handler(form.request, signal).pipe(Effect_exports.flatMap(form.respond));
193
+ return yield* handler(form.request, signal).pipe(
194
+ owned("person", elicitationWaitSpan),
195
+ Effect_exports.flatMap(form.respond)
196
+ );
160
197
  }),
161
- signal
198
+ signal,
199
+ telemetry
162
200
  );
163
201
 
164
202
  // src/contracts/approval.ts
@@ -244,10 +282,7 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
244
282
  );
245
283
  const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
246
284
  const result = yield* workflowSafe(
247
- Effect_exports.tryPromise({
248
- try: () => callback(step2.context),
249
- catch: (error) => error
250
- }),
285
+ fromPromise(callback, "step")(step2.context),
251
286
  step2.secrets
252
287
  );
253
288
  return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
@@ -605,7 +640,8 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
605
640
  return yield* new HostOutputInvalid();
606
641
  chunks.push(chunk);
607
642
  })
608
- )
643
+ ),
644
+ appCode("webhook")
609
645
  );
610
646
  const bytes = new Uint8Array(size);
611
647
  let offset = 0;
@@ -849,9 +885,12 @@ var MigrationFailed = class extends Schema_exports.TaggedError()("MigrationFaile
849
885
  }
850
886
  };
851
887
  var migrationName = /^(\d+)_[A-Za-z0-9_-]+\.sql$/;
852
- var sha256 = (text) => Effect_exports.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))).pipe(
853
- Effect_exports.map(
854
- (digest) => Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
888
+ var sha256 = (text) => (
889
+ // oxlint-disable-next-line executor/authored-code-through-adapter -- Web Crypto
890
+ Effect_exports.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))).pipe(
891
+ Effect_exports.map(
892
+ (digest) => Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
893
+ )
855
894
  )
856
895
  );
857
896
  var hasMigrations = (files) => files.some(
@@ -959,10 +998,10 @@ var unavailableCache = {
959
998
  transport: () => Effect_exports.fail(new CacheError({ reason: "unavailable" })),
960
999
  background: () => Effect_exports.die(new Error("Cache background runner is unavailable"))
961
1000
  };
962
- var authorCache = (host, accounts, signal, deadline) => {
1001
+ var authorCache = (host, accounts, signal, telemetry, deadline) => {
963
1002
  const scoped = (scope, callerSignal = signal) => {
964
1003
  const cache = makeCache(host.transport, host.background, scope, deadline);
965
- const load = (method, options) => cache[method]({
1004
+ const load = (read, options) => cache[read]({
966
1005
  key: options.key,
967
1006
  schema: decoderOf(options.schema),
968
1007
  freshFor: options.freshFor,
@@ -972,7 +1011,10 @@ var authorCache = (host, accounts, signal, deadline) => {
972
1011
  Effect_exports.sync(() => new AbortController()),
973
1012
  (controller) => appInvocationFetch(controller.signal).pipe(
974
1013
  Effect_exports.flatMap(
975
- (fetch) => fromPromise(options.load)({
1014
+ (fetch) => fromPromise(
1015
+ method(options, "load"),
1016
+ "loader"
1017
+ )({
976
1018
  fetch,
977
1019
  signal: controller.signal,
978
1020
  cache: scoped(scope, controller.signal)
@@ -982,22 +1024,30 @@ var authorCache = (host, accounts, signal, deadline) => {
982
1024
  (controller) => Effect_exports.sync(() => controller.abort())
983
1025
  )
984
1026
  });
1027
+ const service = (method2, operation) => toPromise(
1028
+ (...args) => operation(...args).pipe(
1029
+ owned("executor", "app.cache.call", { attributes: { "cache.method": method2 } })
1030
+ ),
1031
+ callerSignal,
1032
+ telemetry
1033
+ );
985
1034
  return {
986
- get: toPromise((options) => load("get", options), callerSignal),
987
- revalidate: toPromise(
988
- (options) => load("revalidate", options),
989
- callerSignal
1035
+ get: service("get", (options) => load("get", options)),
1036
+ revalidate: service(
1037
+ "revalidate",
1038
+ (options) => load("revalidate", options)
990
1039
  ),
991
- read: toPromise(
1040
+ read: service(
1041
+ "read",
992
1042
  (key, schema) => cache.read([key]).pipe(
993
1043
  Effect_exports.flatMap((entries) => {
994
1044
  const entry = entries[0];
995
1045
  return entry === void 0 || entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value);
996
1046
  })
997
- ),
998
- callerSignal
1047
+ )
999
1048
  ),
1000
- readMany: toPromise(
1049
+ readMany: service(
1050
+ "readMany",
1001
1051
  (keys, schema) => cache.read(keys).pipe(
1002
1052
  Effect_exports.flatMap(
1003
1053
  (entries) => Effect_exports.forEach(
@@ -1005,11 +1055,10 @@ var authorCache = (host, accounts, signal, deadline) => {
1005
1055
  (entry) => entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value)
1006
1056
  )
1007
1057
  )
1008
- ),
1009
- callerSignal
1058
+ )
1010
1059
  ),
1011
- write: toPromise(cache.write, callerSignal),
1012
- invalidate: toPromise(cache.invalidate, callerSignal),
1060
+ write: service("write", cache.write),
1061
+ invalidate: service("invalidate", cache.invalidate),
1013
1062
  forAccount: (account) => {
1014
1063
  const bound = Object.values(accounts).flatMap((value) => Array.isArray(value) ? value : [value]).find((value) => value.id === account.id);
1015
1064
  if (bound === void 0) throw new CacheError({ reason: "invalid" });
@@ -1070,22 +1119,22 @@ function providerDeclaration(provider) {
1070
1119
  return declarationSafe(
1071
1120
  () => Effect_exports.gen(function* () {
1072
1121
  const auth = /* @__PURE__ */ new Map();
1073
- for (const [name, method] of Object.entries(provider.auth)) {
1074
- switch (method._tag) {
1122
+ for (const [name, method2] of Object.entries(provider.auth)) {
1123
+ switch (method2._tag) {
1075
1124
  case "secrets":
1076
1125
  auth.set(name, {
1077
1126
  type: "secrets",
1078
- label: method.label,
1079
- fields: yield* jsonSchemaDocument(method.fields),
1080
- ...declaredExposure(method.exposure)
1127
+ label: method2.label,
1128
+ fields: yield* jsonSchemaDocument(method2.fields),
1129
+ ...declaredExposure(method2.exposure)
1081
1130
  });
1082
1131
  break;
1083
1132
  case "oauth2":
1084
1133
  auth.set(name, {
1085
1134
  type: "oauth2",
1086
- ...method.config,
1087
- response: yield* jsonSchemaDocument(method.response),
1088
- ...declaredExposure(method.exposure)
1135
+ ...method2.config,
1136
+ response: yield* jsonSchemaDocument(method2.response),
1137
+ ...declaredExposure(method2.exposure)
1089
1138
  });
1090
1139
  break;
1091
1140
  }
@@ -1159,10 +1208,10 @@ function bindAccounts(slots, declarations, context) {
1159
1208
  ids.add(account.id);
1160
1209
  if (canonical(withoutHosts(account.provider)) !== canonical(withoutHosts(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
1161
1210
  return yield* Effect_exports.fail(new HostAccountsInvalid());
1162
- const method = provider.auth[account.method];
1163
- if (method === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1211
+ const method2 = provider.auth[account.method];
1212
+ if (method2 === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1164
1213
  const fields = yield* Schema_exports.decodeUnknownEffect(
1165
- method._tag === "secrets" ? method.fields : method.response
1214
+ method2._tag === "secrets" ? method2.fields : method2.response
1166
1215
  )(account.fields);
1167
1216
  values.push({ id: account.id, method: account.method, fields });
1168
1217
  }
@@ -1299,27 +1348,50 @@ function dispatch(app, request, context, signal) {
1299
1348
  let running;
1300
1349
  const delivery = (request2, signal2) => Effect_exports.suspend(
1301
1350
  () => running !== void 0 && context.elicitation !== void 0 ? context.elicitation(request2, signal2).pipe(
1302
- Effect_exports.withSpan("app.tool.elicitation"),
1351
+ // Delivering the question and waiting for its answer is the person's time.
1352
+ owned("person", "app.tool.elicitation"),
1303
1353
  Effect_exports.provideContext(running.context)
1304
1354
  ) : Effect_exports.fail(new ElicitationFailed({ reason: "unavailable" }))
1305
1355
  );
1306
1356
  const unavailableWorkflow = () => Effect_exports.fail(new WorkflowFailure({ reason: "unavailable", retryable: false }));
1357
+ const telemetry = yield* captureTelemetry;
1358
+ const control = (operation, work) => work.pipe(
1359
+ owned("executor", workflowControlSpan, {
1360
+ attributes: { "executor.workflow.operation": operation }
1361
+ })
1362
+ );
1307
1363
  const workflowControls = {
1308
1364
  start: toPromise(
1309
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2),
1310
- invocationSignal
1365
+ (input2) => control(
1366
+ "start",
1367
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2)
1368
+ ),
1369
+ invocationSignal,
1370
+ telemetry.context
1311
1371
  ),
1312
1372
  get: toPromise(
1313
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2),
1314
- invocationSignal
1373
+ (input2) => control(
1374
+ "get",
1375
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2)
1376
+ ),
1377
+ invocationSignal,
1378
+ telemetry.context
1315
1379
  ),
1316
1380
  list: toPromise(
1317
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2),
1318
- invocationSignal
1381
+ (input2) => control(
1382
+ "list",
1383
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2)
1384
+ ),
1385
+ invocationSignal,
1386
+ telemetry.context
1319
1387
  ),
1320
1388
  terminate: toPromise(
1321
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2),
1322
- invocationSignal
1389
+ (input2) => control(
1390
+ "terminate",
1391
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2)
1392
+ ),
1393
+ invocationSignal,
1394
+ telemetry.context
1323
1395
  )
1324
1396
  };
1325
1397
  const workflowReads = {
@@ -1344,6 +1416,7 @@ function dispatch(app, request, context, signal) {
1344
1416
  },
1345
1417
  Redacted_exports.value(context.accounts),
1346
1418
  invocationSignal,
1419
+ telemetry.context,
1347
1420
  deadline
1348
1421
  ),
1349
1422
  files,
@@ -1353,7 +1426,7 @@ function dispatch(app, request, context, signal) {
1353
1426
  workflows: workflowReads,
1354
1427
  signal: invocationSignal,
1355
1428
  fetch: yield* appInvocationFetch(fetching.signal),
1356
- elicit: makeElicit(delivery, invocationSignal)
1429
+ elicit: makeElicit(delivery, invocationSignal, telemetry.context)
1357
1430
  };
1358
1431
  const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
1359
1432
  Effect_exports.withSpan("app.evaluate")
@@ -1426,7 +1499,8 @@ function dispatch(app, request, context, signal) {
1426
1499
  cache: authorCache(
1427
1500
  context.cache ?? unavailableCache,
1428
1501
  Redacted_exports.value(current.accounts),
1429
- signal2
1502
+ signal2,
1503
+ (yield* captureTelemetry).context
1430
1504
  ),
1431
1505
  files,
1432
1506
  fetch: yield* appInvocationFetch(signal2),
@@ -1495,7 +1569,9 @@ function dispatch(app, request, context, signal) {
1495
1569
  }
1496
1570
  const toolName = request.operation === "call" ? request.tool : request.name;
1497
1571
  const location = locate(definition.tools, toolName);
1498
- const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets);
1572
+ const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets).pipe(
1573
+ Effect_exports.withSpan("app.tool.resolve")
1574
+ );
1499
1575
  if (tool === void 0)
1500
1576
  return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
1501
1577
  const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
@@ -1710,7 +1786,9 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
1710
1786
  ...error.code === void 0 ? {} : { "executor.failure.code": error.code }
1711
1787
  }) : Effect_exports.void
1712
1788
  ),
1713
- Effect_exports.withSpan(`app.${command.operation}`)
1789
+ // Tool operations time themselves, dividing their time by who owned the work in progress.
1790
+ // Other operations do not.
1791
+ command.operation === "call" || command.operation === "query" || command.operation === "mutate" ? timedInvocation(command.operation) : Effect_exports.withSpan(`app.${command.operation}`)
1714
1792
  );
1715
1793
  if (toolError)
1716
1794
  yield* Effect_exports.annotateCurrentSpan({
@@ -4,7 +4,7 @@ import {
4
4
  fromWeb,
5
5
  layerMergedContext,
6
6
  make2 as make
7
- } from "./chunk-LNSVJS2Q.js";
7
+ } from "./chunk-EOPQ727L.js";
8
8
  import {
9
9
  Reference,
10
10
  Service,
@@ -19,7 +19,7 @@ import {
19
19
  text,
20
20
  uint8Array,
21
21
  urlParams
22
- } from "./chunk-LNSVJS2Q.js";
22
+ } from "./chunk-EOPQ727L.js";
23
23
  import {
24
24
  Cause,
25
25
  Defect,
@@ -1,3 +1,8 @@
1
+ import {
2
+ fromPromise,
3
+ method,
4
+ toPromise
5
+ } from "./chunk-LTDHQJ2Z.js";
1
6
  import {
2
7
  CacheError
3
8
  } from "./chunk-MWKHKOTL.js";
@@ -8,6 +13,7 @@ import {
8
13
  JsonObject
9
14
  } from "./chunk-H2CJWXA3.js";
10
15
  import {
16
+ Deferred_exports,
11
17
  Duration_exports,
12
18
  Effect_exports,
13
19
  Schema_exports
@@ -31,7 +37,6 @@ var Manifest = Schema_exports.Struct({
31
37
  summaries: Schema_exports.Int,
32
38
  header: Schema_exports.optionalKey(JsonObject)
33
39
  });
34
- var invoke = (work) => Effect_exports.tryPromise({ try: work, catch: (error) => error });
35
40
  var catalogCache = (options) => Effect_exports.gen(function* () {
36
41
  const cache = options.cache;
37
42
  const key = [...options.prefix, "current"];
@@ -48,14 +53,12 @@ var catalogCache = (options) => Effect_exports.gen(function* () {
48
53
  const pages = (cache2, revision, kind, count, decoder) => Effect_exports.gen(function* () {
49
54
  const batches = yield* Effect_exports.forEach(
50
55
  Array.from({ length: Math.ceil(count / 4) }, (_, batch) => batch * 4),
51
- (offset) => invoke(
52
- () => cache2.readMany(
53
- Array.from(
54
- { length: Math.min(4, count - offset) },
55
- (_, index) => part(revision, kind, offset + index)
56
- ),
57
- schema(Schema_exports.Array(decoder))
58
- )
56
+ (offset) => fromPromise(method(cache2, "readMany"), "cache")(
57
+ Array.from(
58
+ { length: Math.min(4, count - offset) },
59
+ (_, index) => part(revision, kind, offset + index)
60
+ ),
61
+ schema(Schema_exports.Array(decoder))
59
62
  ),
60
63
  { concurrency: "unbounded" }
61
64
  );
@@ -66,7 +69,7 @@ var catalogCache = (options) => Effect_exports.gen(function* () {
66
69
  }
67
70
  return values;
68
71
  });
69
- const kept = (cache2) => invoke(() => cache2.read(key, schema(Manifest))).pipe(
72
+ const kept = (cache2) => fromPromise(method(cache2, "read"), "cache")(key, schema(Manifest)).pipe(
70
73
  Effect_exports.map(
71
74
  (manifest) => manifest === void 0 ? void 0 : {
72
75
  header: manifest.header,
@@ -76,12 +79,13 @@ var catalogCache = (options) => Effect_exports.gen(function* () {
76
79
  );
77
80
  const refresh = (context) => Effect_exports.gen(function* () {
78
81
  const { tools, header } = yield* options.load(context, kept(context.cache));
79
- const digest = yield* invoke(
80
- () => crypto.subtle.digest(
82
+ const digest = yield* Effect_exports.tryPromise({
83
+ try: () => crypto.subtle.digest(
81
84
  "SHA-256",
82
85
  new TextEncoder().encode(JSON.stringify({ tools, header: header ?? null }))
83
- )
84
- );
86
+ ),
87
+ catch: (error) => error
88
+ });
85
89
  const revision = Array.from(
86
90
  new Uint8Array(digest),
87
91
  (byte) => byte.toString(16).padStart(2, "0")
@@ -101,7 +105,7 @@ var catalogCache = (options) => Effect_exports.gen(function* () {
101
105
  batch = [];
102
106
  batchBytes = 0;
103
107
  if (!entries.length) return Effect_exports.void;
104
- return invoke(() => context.cache.write(entries, retention)).pipe(
108
+ return fromPromise(method(context.cache, "write"), "cache")(entries, retention).pipe(
105
109
  Effect_exports.withSpan("app.cache.flush", {
106
110
  attributes: {
107
111
  "cache.flush.index": flushes++,
@@ -160,17 +164,30 @@ var catalogCache = (options) => Effect_exports.gen(function* () {
160
164
  freshFor,
161
165
  staleFor,
162
166
  ...options.stale === void 0 ? {} : { stale: options.stale },
163
- load: (context) => Effect_exports.runPromise(refresh(context), { signal: context.signal })
167
+ // A cache may call the loader as a Promise; its own signal cancels that load.
168
+ load: toPromise(refresh, (context) => context.signal)
164
169
  };
165
170
  let reading;
166
- const current = () => cache === void 0 ? Effect_exports.fail(new CacheError({ reason: "unavailable" })) : invoke(
167
- () => reading ??= cache.get(getOptions).finally(() => {
168
- reading = void 0;
169
- })
170
- );
171
+ const current = () => Effect_exports.suspend(() => {
172
+ if (cache === void 0) return Effect_exports.fail(new CacheError({ reason: "unavailable" }));
173
+ const shared = reading;
174
+ if (shared !== void 0) return Deferred_exports.await(shared);
175
+ const deferred = Deferred_exports.makeUnsafe();
176
+ reading = deferred;
177
+ return fromPromise(
178
+ method(cache, "get"),
179
+ "cache"
180
+ )(getOptions).pipe(
181
+ Effect_exports.onExit(
182
+ (exit) => Effect_exports.sync(() => {
183
+ if (reading === deferred) reading = void 0;
184
+ }).pipe(Effect_exports.andThen(Deferred_exports.done(deferred, exit)))
185
+ )
186
+ );
187
+ });
171
188
  if (options.revalidate) {
172
189
  if (cache === void 0) yield* local;
173
- else yield* invoke(() => cache.revalidate(getOptions));
190
+ else yield* fromPromise(method(cache, "revalidate"), "cache")(getOptions);
174
191
  }
175
192
  const metadata = () => Effect_exports.gen(function* () {
176
193
  if (cache === void 0) return (yield* local).tools;
@@ -195,8 +212,9 @@ var catalogCache = (options) => Effect_exports.gen(function* () {
195
212
  }),
196
213
  resolve: (name) => cache === void 0 ? local.pipe(Effect_exports.map(({ tools }) => tools.find((tool) => tool.name === name))) : current().pipe(
197
214
  Effect_exports.flatMap(
198
- (manifest) => invoke(
199
- () => cache.read(part(manifest.revision, "tool", name), schema(options.schema))
215
+ (manifest) => fromPromise(method(cache, "read"), "cache")(
216
+ part(manifest.revision, "tool", name),
217
+ schema(options.schema)
200
218
  )
201
219
  )
202
220
  )
@@ -5,7 +5,7 @@ import {
5
5
  SkillDefinitionInvalid,
6
6
  SkillFile,
7
7
  SkillFilePath
8
- } from "./chunk-KBIKBWSS.js";
8
+ } from "./chunk-H72MEDMN.js";
9
9
  import {
10
10
  Effect_exports,
11
11
  Schema_exports