apps 0.0.1-beta.44 → 0.0.1-beta.47

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 (55) hide show
  1. package/framework-reference.json +1 -1
  2. package/js/{chunk-DZQYE626.js → chunk-7UUHJR2Q.js} +1 -1
  3. package/js/{chunk-4ZTVLEN6.js → chunk-CDXQDN7W.js} +1 -1
  4. package/js/{chunk-V3RS2BK6.js → chunk-D45JTD6N.js} +39 -29
  5. package/js/chunk-GDYPM7RS.js +266 -0
  6. package/js/{chunk-CZGWW4NQ.js → chunk-JM7LOD2W.js} +187 -9
  7. package/js/{chunk-ELO5PRCO.js → chunk-JY56GVSV.js} +95 -4
  8. package/js/{chunk-EJUK2NK5.js → chunk-KLYSEHUD.js} +1 -1
  9. package/js/{chunk-EMHFXFTJ.js → chunk-LTDHQJ2Z.js} +53 -0
  10. package/js/{chunk-MZH4J2PO.js → chunk-PD6I2SDG.js} +1 -1
  11. package/js/{chunk-DRJRCHHO.js → chunk-PO5NPRFT.js} +204 -73
  12. package/js/{chunk-MGGMEGB2.js → chunk-QKHTRD6G.js} +2 -2
  13. package/js/{chunk-5SHUB37R.js → chunk-SVHI6AKV.js} +3 -3
  14. package/js/{chunk-KSGYJV46.js → chunk-TUMGL2OC.js} +1 -1
  15. package/js/{chunk-5GLC42LK.js → chunk-UM62MBJQ.js} +42 -24
  16. package/js/{chunk-OTGUPKKK.js → chunk-X5U5KIWQ.js} +12 -46
  17. package/js/{chunk-7EBODVQJ.js → chunk-YQD2MLFY.js} +14 -13
  18. package/js/client.js +8 -8
  19. package/js/contracts.js +25 -3
  20. package/js/effect.js +11 -11
  21. package/js/graphql.js +20 -18
  22. package/js/host.js +76 -51
  23. package/js/index.js +23 -16
  24. package/js/mcp/effect.js +13 -13
  25. package/js/mcp/stdio.js +27 -22
  26. package/js/mcp.js +20 -18
  27. package/js/openapi.js +103 -77
  28. package/js/skills/effect.js +2 -2
  29. package/js/skills.js +50 -33
  30. package/js/ui/auth.js +3 -3
  31. package/js/ui/contracts.js +3 -3
  32. package/js/ui/serving.js +6 -6
  33. package/package.json +1 -1
  34. package/runtime.json +1 -1
  35. package/types/apps/src/contracts/app.d.ts +2 -0
  36. package/types/apps/src/contracts/context.d.ts +8 -1
  37. package/types/apps/src/contracts/events.d.ts +93 -0
  38. package/types/apps/src/contracts/host.d.ts +21 -4
  39. package/types/apps/src/contracts/protocol-version.d.ts +2 -2
  40. package/types/apps/src/contracts/protocols/11.d.ts +1098 -0
  41. package/types/apps/src/host.d.ts +5 -0
  42. package/types/apps/src/implementation/authoring.d.ts +25 -5
  43. package/types/apps/src/implementation/cache.d.ts +4 -0
  44. package/types/apps/src/implementation/elicitation.d.ts +6 -3
  45. package/types/apps/src/implementation/events.d.ts +59 -0
  46. package/types/apps/src/implementation/invocation-timing.d.ts +16 -0
  47. package/types/apps/src/implementation/operations.d.ts +2 -2
  48. package/types/apps/src/implementation/router-catalog.d.ts +4 -4
  49. package/types/apps/src/implementation/sql.d.ts +5 -0
  50. package/types/apps/src/implementation/workflows.d.ts +1 -1
  51. package/types/apps/src/index.d.ts +2 -0
  52. package/types/telemetry/src/index.d.ts +1 -0
  53. package/types/telemetry/src/ownership.d.ts +56 -0
  54. package/js/chunk-646JVUH4.js +0 -156
  55. package/js/{chunk-LNSVJS2Q.js → chunk-EOPQ727L.js} +2 -2
@@ -11,30 +11,34 @@ import {
11
11
  parseSkillLoadFailed,
12
12
  readCatalog,
13
13
  routerSkills
14
- } from "./chunk-5SHUB37R.js";
14
+ } from "./chunk-SVHI6AKV.js";
15
15
  import {
16
16
  appInvocationFetch
17
- } from "./chunk-DZQYE626.js";
17
+ } from "./chunk-7UUHJR2Q.js";
18
18
  import {
19
19
  folderSkillsEffect
20
20
  } from "./chunk-XBG7HHXC.js";
21
21
  import {
22
22
  ResponseStatusError,
23
+ declaredEvents,
23
24
  isApp,
25
+ makeEmitter,
24
26
  toEffectApp
25
- } from "./chunk-646JVUH4.js";
27
+ } from "./chunk-GDYPM7RS.js";
26
28
  import {
27
29
  declaredOperations,
28
- fromPromise,
29
30
  locate,
30
- nativeOperation,
31
- toPromise
32
- } from "./chunk-OTGUPKKK.js";
31
+ nativeOperation
32
+ } from "./chunk-X5U5KIWQ.js";
33
33
  import {
34
34
  accountProviderError,
35
+ appCode,
36
+ fromPromise,
35
37
  httpProviderError,
36
- parseProviderError
37
- } from "./chunk-EMHFXFTJ.js";
38
+ method,
39
+ parseProviderError,
40
+ toPromise
41
+ } from "./chunk-LTDHQJ2Z.js";
38
42
  import {
39
43
  AccountCheckResult,
40
44
  DeclaredProvider,
@@ -63,6 +67,7 @@ import {
63
67
  HostedWebhook,
64
68
  HostedWorkflow,
65
69
  InvocationDeadline,
70
+ InvocationTimingSink,
66
71
  ManualWebhookSetup,
67
72
  ManyAccounts,
68
73
  NonRetryableError,
@@ -83,7 +88,7 @@ import {
83
88
  migrationsDirectory,
84
89
  reservedTablePrefix,
85
90
  workflowDurationMillis
86
- } from "./chunk-ELO5PRCO.js";
91
+ } from "./chunk-JY56GVSV.js";
87
92
  import {
88
93
  CacheError
89
94
  } from "./chunk-MWKHKOTL.js";
@@ -91,9 +96,6 @@ import {
91
96
  AppSkills,
92
97
  SkillFile
93
98
  } from "./chunk-H72MEDMN.js";
94
- import {
95
- captureTelemetry
96
- } from "./chunk-CZGWW4NQ.js";
97
99
  import {
98
100
  allowedValues,
99
101
  decoderOf,
@@ -108,6 +110,12 @@ import {
108
110
  objectShape,
109
111
  unionShape
110
112
  } from "./chunk-KGCTYL2S.js";
113
+ import {
114
+ captureTelemetry,
115
+ makeOwnershipAccounting,
116
+ measuredSpan,
117
+ owned
118
+ } from "./chunk-JM7LOD2W.js";
111
119
  import {
112
120
  JsonObject,
113
121
  JsonValue
@@ -126,6 +134,34 @@ import {
126
134
  Stream_exports
127
135
  } from "./chunk-IFJU5SYQ.js";
128
136
 
137
+ // src/implementation/invocation-timing.ts
138
+ var elicitationWaitSpan = "app.elicitation.wait";
139
+ var workflowControlSpan = "app.workflow.control";
140
+ var timedInvocation = (operation) => (effect) => Effect_exports.gen(function* () {
141
+ const report = yield* InvocationTimingSink;
142
+ return yield* effect.pipe(
143
+ measuredSpan(`app.${operation}`, {}, (start) => {
144
+ const accounting = makeOwnershipAccounting(start, "executor");
145
+ return {
146
+ around: accounting.observe,
147
+ end: (end, span) => {
148
+ const spent = accounting.read(end);
149
+ report({
150
+ elapsedMs: Number(end - start) / 1e6,
151
+ upstreamMs: spent.upstream,
152
+ elicitationMs: spent.person,
153
+ authoredMs: spent.app
154
+ });
155
+ span.attribute("executor.upstream.wait_ms", spent.upstream);
156
+ span.attribute("executor.elicitation.wait_ms", spent.person);
157
+ span.attribute("executor.authored_ms", spent.app);
158
+ span.attribute("executor.overhead_ms", spent.executor);
159
+ }
160
+ };
161
+ })
162
+ );
163
+ });
164
+
129
165
  // src/implementation/elicitation.ts
130
166
  var prepareElicitation = (input) => Effect_exports.gen(function* () {
131
167
  const request = yield* Schema_exports.decodeUnknownEffect(FormElicitation)(input, {
@@ -152,13 +188,17 @@ var prepareElicitation = (input) => Effect_exports.gen(function* () {
152
188
  });
153
189
  return { request, respond };
154
190
  });
155
- var makeElicit = (handler, signal) => toPromise(
191
+ var makeElicit = (handler, signal, telemetry) => toPromise(
156
192
  (input) => Effect_exports.gen(function* () {
157
193
  if (handler === void 0) return yield* new ElicitationFailed({ reason: "unavailable" });
158
194
  const form = yield* prepareElicitation(input);
159
- return yield* handler(form.request, signal).pipe(Effect_exports.flatMap(form.respond));
195
+ return yield* handler(form.request, signal).pipe(
196
+ owned("person", elicitationWaitSpan),
197
+ Effect_exports.flatMap(form.respond)
198
+ );
160
199
  }),
161
- signal
200
+ signal,
201
+ telemetry
162
202
  );
163
203
 
164
204
  // src/contracts/approval.ts
@@ -244,10 +284,7 @@ var makeWorkflowContext = (execution, definition, fresh, signal) => Effect_expor
244
284
  );
245
285
  const step2 = yield* fresh(stepId, AbortSignal.any([signal, controller.signal]));
246
286
  const result = yield* workflowSafe(
247
- Effect_exports.tryPromise({
248
- try: () => callback(step2.context),
249
- catch: (error) => error
250
- }),
287
+ fromPromise(callback, "step")(step2.context),
251
288
  step2.secrets
252
289
  );
253
290
  return yield* Schema_exports.decodeUnknownEffect(WorkflowValue)(result).pipe(
@@ -605,7 +642,8 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
605
642
  return yield* new HostOutputInvalid();
606
643
  chunks.push(chunk);
607
644
  })
608
- )
645
+ ),
646
+ appCode("webhook")
609
647
  );
610
648
  const bytes = new Uint8Array(size);
611
649
  let offset = 0;
@@ -629,6 +667,7 @@ var dispatchWebhook = (definition, command, context, accounts) => Effect_exports
629
667
 
630
668
  // src/implementation/sql.ts
631
669
  var receipts = `${reservedTablePrefix}step_receipts`;
670
+ var stepEvents = `${reservedTablePrefix}step_events`;
632
671
  var migrationsTable = `${reservedTablePrefix}migrations`;
633
672
  var legacyRows = `${reservedTablePrefix}legacy_rows`;
634
673
  var materialize = (cursor) => {
@@ -775,7 +814,12 @@ var authorSql = (storage, options) => {
775
814
  transactions += 1;
776
815
  violation = void 0;
777
816
  const handle = transactionHandle();
778
- return storage.transactionSync(() => {
817
+ const emittedBefore = options.emitted?.length;
818
+ const discardEmitted = () => {
819
+ if (options.emitted !== void 0 && emittedBefore !== void 0)
820
+ options.emitted.length = emittedBefore;
821
+ };
822
+ const body = () => {
779
823
  open = true;
780
824
  try {
781
825
  const complete = () => {
@@ -792,12 +836,25 @@ var authorSql = (storage, options) => {
792
836
  `CREATE TABLE IF NOT EXISTS ${receipts} (id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL, result TEXT NOT NULL) WITHOUT ROWID`
793
837
  );
794
838
  const saved = storage.sql.exec(`SELECT fingerprint, result FROM ${receipts} WHERE id = ?`, step.key).toArray()[0];
839
+ storage.sql.exec(
840
+ `CREATE TABLE IF NOT EXISTS ${stepEvents} (id TEXT PRIMARY KEY, events TEXT NOT NULL) WITHOUT ROWID`
841
+ );
795
842
  if (saved !== void 0) {
796
843
  if (saved.fingerprint !== step.fingerprint)
797
844
  throw new Error("This workflow step already ran with different input.");
845
+ const replayed = storage.sql.exec(`SELECT events FROM ${stepEvents} WHERE id = ?`, step.key).toArray()[0];
846
+ if (replayed !== void 0 && options.emitted !== void 0)
847
+ options.emitted.push(...JSON.parse(String(replayed.events)));
798
848
  return JSON.parse(String(saved.result));
799
849
  }
800
850
  const encoded = JSON.stringify(complete() ?? null);
851
+ const emitted = options.emitted?.slice(emittedBefore ?? 0) ?? [];
852
+ if (emitted.length > 0)
853
+ storage.sql.exec(
854
+ `INSERT INTO ${stepEvents} (id, events) VALUES (?, ?)`,
855
+ step.key,
856
+ JSON.stringify(emitted)
857
+ );
801
858
  storage.sql.exec(
802
859
  `INSERT INTO ${receipts} (id, fingerprint, result) VALUES (?, ?, ?)`,
803
860
  step.key,
@@ -809,7 +866,13 @@ var authorSql = (storage, options) => {
809
866
  open = false;
810
867
  handle.end();
811
868
  }
812
- });
869
+ };
870
+ try {
871
+ return storage.transactionSync(body);
872
+ } catch (error) {
873
+ discardEmitted();
874
+ throw error;
875
+ }
813
876
  };
814
877
  const writer = {
815
878
  // A step's writes go through its one transaction, which also records its receipt.
@@ -849,9 +912,12 @@ var MigrationFailed = class extends Schema_exports.TaggedError()("MigrationFaile
849
912
  }
850
913
  };
851
914
  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("")
915
+ var sha256 = (text) => (
916
+ // oxlint-disable-next-line executor/authored-code-through-adapter -- Web Crypto
917
+ Effect_exports.promise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(text))).pipe(
918
+ Effect_exports.map(
919
+ (digest) => Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
920
+ )
855
921
  )
856
922
  );
857
923
  var hasMigrations = (files) => files.some(
@@ -959,10 +1025,10 @@ var unavailableCache = {
959
1025
  transport: () => Effect_exports.fail(new CacheError({ reason: "unavailable" })),
960
1026
  background: () => Effect_exports.die(new Error("Cache background runner is unavailable"))
961
1027
  };
962
- var authorCache = (host, accounts, signal, deadline) => {
1028
+ var authorCache = (host, accounts, signal, telemetry, deadline) => {
963
1029
  const scoped = (scope, callerSignal = signal) => {
964
1030
  const cache = makeCache(host.transport, host.background, scope, deadline);
965
- const load = (method, options) => cache[method]({
1031
+ const load = (read, options) => cache[read]({
966
1032
  key: options.key,
967
1033
  schema: decoderOf(options.schema),
968
1034
  freshFor: options.freshFor,
@@ -972,7 +1038,10 @@ var authorCache = (host, accounts, signal, deadline) => {
972
1038
  Effect_exports.sync(() => new AbortController()),
973
1039
  (controller) => appInvocationFetch(controller.signal).pipe(
974
1040
  Effect_exports.flatMap(
975
- (fetch) => fromPromise(options.load)({
1041
+ (fetch) => fromPromise(
1042
+ method(options, "load"),
1043
+ "loader"
1044
+ )({
976
1045
  fetch,
977
1046
  signal: controller.signal,
978
1047
  cache: scoped(scope, controller.signal)
@@ -982,22 +1051,30 @@ var authorCache = (host, accounts, signal, deadline) => {
982
1051
  (controller) => Effect_exports.sync(() => controller.abort())
983
1052
  )
984
1053
  });
1054
+ const service = (method2, operation) => toPromise(
1055
+ (...args) => operation(...args).pipe(
1056
+ owned("executor", "app.cache.call", { attributes: { "cache.method": method2 } })
1057
+ ),
1058
+ callerSignal,
1059
+ telemetry
1060
+ );
985
1061
  return {
986
- get: toPromise((options) => load("get", options), callerSignal),
987
- revalidate: toPromise(
988
- (options) => load("revalidate", options),
989
- callerSignal
1062
+ get: service("get", (options) => load("get", options)),
1063
+ revalidate: service(
1064
+ "revalidate",
1065
+ (options) => load("revalidate", options)
990
1066
  ),
991
- read: toPromise(
1067
+ read: service(
1068
+ "read",
992
1069
  (key, schema) => cache.read([key]).pipe(
993
1070
  Effect_exports.flatMap((entries) => {
994
1071
  const entry = entries[0];
995
1072
  return entry === void 0 || entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value);
996
1073
  })
997
- ),
998
- callerSignal
1074
+ )
999
1075
  ),
1000
- readMany: toPromise(
1076
+ readMany: service(
1077
+ "readMany",
1001
1078
  (keys, schema) => cache.read(keys).pipe(
1002
1079
  Effect_exports.flatMap(
1003
1080
  (entries) => Effect_exports.forEach(
@@ -1005,11 +1082,10 @@ var authorCache = (host, accounts, signal, deadline) => {
1005
1082
  (entry) => entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value)
1006
1083
  )
1007
1084
  )
1008
- ),
1009
- callerSignal
1085
+ )
1010
1086
  ),
1011
- write: toPromise(cache.write, callerSignal),
1012
- invalidate: toPromise(cache.invalidate, callerSignal),
1087
+ write: service("write", cache.write),
1088
+ invalidate: service("invalidate", cache.invalidate),
1013
1089
  forAccount: (account) => {
1014
1090
  const bound = Object.values(accounts).flatMap((value) => Array.isArray(value) ? value : [value]).find((value) => value.id === account.id);
1015
1091
  if (bound === void 0) throw new CacheError({ reason: "invalid" });
@@ -1070,22 +1146,22 @@ function providerDeclaration(provider) {
1070
1146
  return declarationSafe(
1071
1147
  () => Effect_exports.gen(function* () {
1072
1148
  const auth = /* @__PURE__ */ new Map();
1073
- for (const [name, method] of Object.entries(provider.auth)) {
1074
- switch (method._tag) {
1149
+ for (const [name, method2] of Object.entries(provider.auth)) {
1150
+ switch (method2._tag) {
1075
1151
  case "secrets":
1076
1152
  auth.set(name, {
1077
1153
  type: "secrets",
1078
- label: method.label,
1079
- fields: yield* jsonSchemaDocument(method.fields),
1080
- ...declaredExposure(method.exposure)
1154
+ label: method2.label,
1155
+ fields: yield* jsonSchemaDocument(method2.fields),
1156
+ ...declaredExposure(method2.exposure)
1081
1157
  });
1082
1158
  break;
1083
1159
  case "oauth2":
1084
1160
  auth.set(name, {
1085
1161
  type: "oauth2",
1086
- ...method.config,
1087
- response: yield* jsonSchemaDocument(method.response),
1088
- ...declaredExposure(method.exposure)
1162
+ ...method2.config,
1163
+ response: yield* jsonSchemaDocument(method2.response),
1164
+ ...declaredExposure(method2.exposure)
1089
1165
  });
1090
1166
  break;
1091
1167
  }
@@ -1100,7 +1176,7 @@ function providerDeclaration(provider) {
1100
1176
  `Account provider "${provider.name}" has an invalid declaration`
1101
1177
  );
1102
1178
  }
1103
- function requirements(slots, sql) {
1179
+ function requirements(slots, sql, events) {
1104
1180
  return Effect_exports.gen(function* () {
1105
1181
  const accounts = /* @__PURE__ */ new Map();
1106
1182
  for (const [slot, selection] of Object.entries(slots)) {
@@ -1114,7 +1190,13 @@ function requirements(slots, sql) {
1114
1190
  return yield* Schema_exports.decodeUnknownEffect(DeclaredRequirements)({
1115
1191
  accounts: Object.fromEntries(accounts),
1116
1192
  capabilities: { skills: true, toolIndex: true, skillSources: true, scheduledTools: true },
1117
- ...sql ? { sql: true } : {}
1193
+ ...sql ? { sql: true } : {},
1194
+ ...events === void 0 || Object.keys(events).length === 0 ? {} : {
1195
+ events: yield* declarationSafe(
1196
+ () => declaredEvents(events),
1197
+ "The app's event declarations are invalid"
1198
+ )
1199
+ }
1118
1200
  }).pipe(
1119
1201
  Effect_exports.mapError(
1120
1202
  (cause) => declarationInvalid("The app's account declarations are invalid", cause)
@@ -1159,10 +1241,10 @@ function bindAccounts(slots, declarations, context) {
1159
1241
  ids.add(account.id);
1160
1242
  if (canonical(withoutHosts(account.provider)) !== canonical(withoutHosts(requirement.definition)) || !Object.hasOwn(provider.auth, account.method))
1161
1243
  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());
1244
+ const method2 = provider.auth[account.method];
1245
+ if (method2 === void 0) return yield* Effect_exports.fail(new HostAccountsInvalid());
1164
1246
  const fields = yield* Schema_exports.decodeUnknownEffect(
1165
- method._tag === "secrets" ? method.fields : method.response
1247
+ method2._tag === "secrets" ? method2.fields : method2.response
1166
1248
  )(account.fields);
1167
1249
  values.push({ id: account.id, method: account.method, fields });
1168
1250
  }
@@ -1213,7 +1295,7 @@ var fetchLifetime = (signal, background) => Effect_exports.acquireRelease(
1213
1295
  }),
1214
1296
  (lifetime) => Effect_exports.sync(lifetime.close)
1215
1297
  );
1216
- function dispatch(app, request, context, signal) {
1298
+ function dispatch(app, request, context, signal, emitted) {
1217
1299
  return Effect_exports.scoped(
1218
1300
  Effect_exports.gen(function* () {
1219
1301
  if (!isApp(app))
@@ -1223,7 +1305,7 @@ function dispatch(app, request, context, signal) {
1223
1305
  const native = toEffectApp(app);
1224
1306
  const secrets = accountSecrets(context.accounts);
1225
1307
  const ownsSql = hasMigrations(context.files ?? []);
1226
- const declared = yield* requirements(native.accounts, ownsSql);
1308
+ const declared = yield* requirements(native.accounts, ownsSql, native.events);
1227
1309
  if (request.operation === "requirements")
1228
1310
  return yield* safe2(
1229
1311
  () => Schema_exports.decodeUnknownEffect(JsonValue)(declared),
@@ -1262,6 +1344,7 @@ function dispatch(app, request, context, signal) {
1262
1344
  Effect_exports.sync(
1263
1345
  () => authorSql(storage, {
1264
1346
  signal: invocationSignal,
1347
+ emitted,
1265
1348
  ...step === void 0 ? {} : { step }
1266
1349
  })
1267
1350
  ),
@@ -1299,27 +1382,50 @@ function dispatch(app, request, context, signal) {
1299
1382
  let running;
1300
1383
  const delivery = (request2, signal2) => Effect_exports.suspend(
1301
1384
  () => running !== void 0 && context.elicitation !== void 0 ? context.elicitation(request2, signal2).pipe(
1302
- Effect_exports.withSpan("app.tool.elicitation"),
1385
+ // Delivering the question and waiting for its answer is the person's time.
1386
+ owned("person", "app.tool.elicitation"),
1303
1387
  Effect_exports.provideContext(running.context)
1304
1388
  ) : Effect_exports.fail(new ElicitationFailed({ reason: "unavailable" }))
1305
1389
  );
1306
1390
  const unavailableWorkflow = () => Effect_exports.fail(new WorkflowFailure({ reason: "unavailable", retryable: false }));
1391
+ const telemetry = yield* captureTelemetry;
1392
+ const control = (operation, work) => work.pipe(
1393
+ owned("executor", workflowControlSpan, {
1394
+ attributes: { "executor.workflow.operation": operation }
1395
+ })
1396
+ );
1307
1397
  const workflowControls = {
1308
1398
  start: toPromise(
1309
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2),
1310
- invocationSignal
1399
+ (input2) => control(
1400
+ "start",
1401
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.start(input2)
1402
+ ),
1403
+ invocationSignal,
1404
+ telemetry.context
1311
1405
  ),
1312
1406
  get: toPromise(
1313
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2),
1314
- invocationSignal
1407
+ (input2) => control(
1408
+ "get",
1409
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.get(input2)
1410
+ ),
1411
+ invocationSignal,
1412
+ telemetry.context
1315
1413
  ),
1316
1414
  list: toPromise(
1317
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2),
1318
- invocationSignal
1415
+ (input2) => control(
1416
+ "list",
1417
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.list(input2)
1418
+ ),
1419
+ invocationSignal,
1420
+ telemetry.context
1319
1421
  ),
1320
1422
  terminate: toPromise(
1321
- (input2) => context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2),
1322
- invocationSignal
1423
+ (input2) => control(
1424
+ "terminate",
1425
+ context.workflowControls === void 0 ? unavailableWorkflow() : context.workflowControls.terminate(input2)
1426
+ ),
1427
+ invocationSignal,
1428
+ telemetry.context
1323
1429
  )
1324
1430
  };
1325
1431
  const workflowReads = {
@@ -1344,6 +1450,7 @@ function dispatch(app, request, context, signal) {
1344
1450
  },
1345
1451
  Redacted_exports.value(context.accounts),
1346
1452
  invocationSignal,
1453
+ telemetry.context,
1347
1454
  deadline
1348
1455
  ),
1349
1456
  files,
@@ -1353,8 +1460,19 @@ function dispatch(app, request, context, signal) {
1353
1460
  workflows: workflowReads,
1354
1461
  signal: invocationSignal,
1355
1462
  fetch: yield* appInvocationFetch(fetching.signal),
1356
- elicit: makeElicit(delivery, invocationSignal)
1463
+ elicit: makeElicit(delivery, invocationSignal, telemetry.context)
1357
1464
  };
1465
+ const accountIds = Object.values(bound.accounts).flatMap(
1466
+ (selected) => (Array.isArray(selected) ? selected : [selected]).map(
1467
+ (account) => account.id
1468
+ )
1469
+ );
1470
+ const emitter = (sourceAccount) => makeEmitter({
1471
+ events: native.events ?? {},
1472
+ accounts: accountIds,
1473
+ ...sourceAccount === void 0 ? {} : { sourceAccount },
1474
+ emitted
1475
+ });
1358
1476
  const definition = yield* evaluationSafe(native.evaluate(bound), secrets).pipe(
1359
1477
  Effect_exports.withSpan("app.evaluate")
1360
1478
  );
@@ -1426,7 +1544,8 @@ function dispatch(app, request, context, signal) {
1426
1544
  cache: authorCache(
1427
1545
  context.cache ?? unavailableCache,
1428
1546
  Redacted_exports.value(current.accounts),
1429
- signal2
1547
+ signal2,
1548
+ (yield* captureTelemetry).context
1430
1549
  ),
1431
1550
  files,
1432
1551
  fetch: yield* appInvocationFetch(signal2),
@@ -1488,14 +1607,17 @@ function dispatch(app, request, context, signal) {
1488
1607
  workflows: workflowControls,
1489
1608
  signal: bound.signal,
1490
1609
  fetch: bound.fetch,
1491
- sql: session2.writer
1610
+ sql: session2.writer,
1611
+ events: emitter("sourceAccount" in request ? request.sourceAccount : void 0)
1492
1612
  },
1493
1613
  Redacted_exports.value(context.accounts)
1494
1614
  );
1495
1615
  }
1496
1616
  const toolName = request.operation === "call" ? request.tool : request.name;
1497
1617
  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);
1618
+ const tool = location === void 0 ? void 0 : location.kind === "operation" ? location.operation : yield* evaluationSafe(location.source.resolve(location.name), secrets).pipe(
1619
+ Effect_exports.withSpan("app.tool.resolve")
1620
+ );
1499
1621
  if (tool === void 0)
1500
1622
  return yield* request.operation === "call" ? new HostToolNotFound() : new HostOperationNotFound();
1501
1623
  const requested = request.operation === "call" ? request.kind : request.operation === "query" ? "query" : "mutation";
@@ -1566,7 +1688,8 @@ function dispatch(app, request, context, signal) {
1566
1688
  ...bound,
1567
1689
  fetch,
1568
1690
  workflows: kind === "mutate" ? workflowControls : workflowReads,
1569
- sql: kind === "mutate" ? session.writer : session.reader
1691
+ sql: kind === "mutate" ? session.writer : session.reader,
1692
+ ...kind === "mutate" ? { events: emitter() } : {}
1570
1693
  },
1571
1694
  input
1572
1695
  );
@@ -1695,7 +1818,8 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
1695
1818
  ...command.operation === "call" ? { "executor.tool.name": command.tool } : {}
1696
1819
  });
1697
1820
  let toolError = false;
1698
- const value = yield* dispatch(app, command, context, request.signal).pipe(
1821
+ const emitted = [];
1822
+ const value = yield* dispatch(app, command, context, request.signal, emitted).pipe(
1699
1823
  Effect_exports.provideService(ToolResultObservation, {
1700
1824
  failed: () => {
1701
1825
  toolError = true;
@@ -1710,14 +1834,21 @@ var createAppHandler = (app) => (request, context) => Effect_exports.gen(functio
1710
1834
  ...error.code === void 0 ? {} : { "executor.failure.code": error.code }
1711
1835
  }) : Effect_exports.void
1712
1836
  ),
1713
- Effect_exports.withSpan(`app.${command.operation}`)
1837
+ // Tool operations time themselves, dividing their time by who owned the work in progress.
1838
+ // Other operations do not.
1839
+ command.operation === "call" || command.operation === "query" || command.operation === "mutate" ? timedInvocation(command.operation) : Effect_exports.withSpan(`app.${command.operation}`)
1714
1840
  );
1715
1841
  if (toolError)
1716
1842
  yield* Effect_exports.annotateCurrentSpan({
1717
1843
  "executor.outcome": "failed",
1718
1844
  "error.type": "McpToolError"
1719
1845
  });
1720
- return Response.json({ ok: true, value, ...toolError ? { toolError: true } : {} });
1846
+ return Response.json({
1847
+ ok: true,
1848
+ value,
1849
+ ...toolError ? { toolError: true } : {},
1850
+ ...emitted.length === 0 ? {} : { events: emitted }
1851
+ });
1721
1852
  }).pipe(
1722
1853
  Effect_exports.catch(
1723
1854
  (error) => Schema_exports.encodeEffect(HostError)(error).pipe(
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  fixedRouter
3
- } from "./chunk-5SHUB37R.js";
3
+ } from "./chunk-SVHI6AKV.js";
4
4
  import {
5
5
  nativeOperation,
6
6
  operationDeclaration,
7
7
  routerDeclaration
8
- } from "./chunk-OTGUPKKK.js";
8
+ } from "./chunk-X5U5KIWQ.js";
9
9
 
10
10
  // src/implementation/protocol-operations.ts
11
11
  var protocolOperations = (operations, kinds = {}) => {
@@ -4,12 +4,12 @@ import {
4
4
  import {
5
5
  joinPath,
6
6
  mergeMeta
7
- } from "./chunk-OTGUPKKK.js";
7
+ } from "./chunk-X5U5KIWQ.js";
8
8
  import {
9
9
  isShortenedUpstream,
10
10
  parseProviderError,
11
11
  providerError
12
- } from "./chunk-EMHFXFTJ.js";
12
+ } from "./chunk-LTDHQJ2Z.js";
13
13
  import {
14
14
  ApiErrorResponse,
15
15
  HostDeclarationInvalid,
@@ -21,7 +21,7 @@ import {
21
21
  McpError,
22
22
  McpError2,
23
23
  SkillLoadFailed as SkillLoadFailed2
24
- } from "./chunk-ELO5PRCO.js";
24
+ } from "./chunk-JY56GVSV.js";
25
25
  import {
26
26
  CacheError,
27
27
  FailureCode,
@@ -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,