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
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-MWKHKOTL.js";
9
9
  import {
10
10
  invocationFetch
11
- } from "./chunk-CZGWW4NQ.js";
11
+ } from "./chunk-JM7LOD2W.js";
12
12
  import {
13
13
  Effect_exports,
14
14
  Schema_exports
@@ -6,7 +6,7 @@ import {
6
6
  HttpApiGroup_exports,
7
7
  HttpApiSchema_exports,
8
8
  HttpApi_exports
9
- } from "./chunk-KSGYJV46.js";
9
+ } from "./chunk-TUMGL2OC.js";
10
10
  import {
11
11
  Schema_exports
12
12
  } from "./chunk-IFJU5SYQ.js";
@@ -1,12 +1,10 @@
1
1
  import {
2
2
  prepareElicitation
3
- } from "./chunk-DRJRCHHO.js";
3
+ } from "./chunk-PO5NPRFT.js";
4
4
  import {
5
+ bodyUpstreamError,
5
6
  fromPromise
6
- } from "./chunk-OTGUPKKK.js";
7
- import {
8
- bodyUpstreamError
9
- } from "./chunk-EMHFXFTJ.js";
7
+ } from "./chunk-LTDHQJ2Z.js";
10
8
  import {
11
9
  ElicitationFailed,
12
10
  McpError,
@@ -18,12 +16,15 @@ import {
18
16
  defaultElicitationLimits,
19
17
  defaultMcpClientLimits,
20
18
  mcpSdkTimerCeilingMs
21
- } from "./chunk-ELO5PRCO.js";
19
+ } from "./chunk-JY56GVSV.js";
22
20
  import {
23
21
  jsonSchemaDecoder,
24
22
  nestJsonSchema,
25
23
  preparedJsonSchemaDecoder
26
24
  } from "./chunk-KGCTYL2S.js";
25
+ import {
26
+ owned
27
+ } from "./chunk-JM7LOD2W.js";
27
28
  import {
28
29
  JsonObject
29
30
  } from "./chunk-H2CJWXA3.js";
@@ -187,11 +188,14 @@ var mcpCall = (client, name, input, context, timeoutMs, failure) => Effect_expor
187
188
  const callbacks = /* @__PURE__ */ new Set();
188
189
  const lifetime = yield* Effect_exports.acquireRelease(
189
190
  Effect_exports.sync(() => new AbortController()),
190
- (controller) => Effect_exports.promise(async () => {
191
- controller.abort();
192
- client.removeRequestHandler("elicitation/create");
193
- await Promise.allSettled(callbacks);
194
- })
191
+ (controller) => (
192
+ // oxlint-disable-next-line executor/authored-code-through-adapter -- the MCP SDK's elicitation callbacks
193
+ Effect_exports.promise(async () => {
194
+ controller.abort();
195
+ client.removeRequestHandler("elicitation/create");
196
+ await Promise.allSettled(callbacks);
197
+ })
198
+ )
195
199
  );
196
200
  client.setRequestHandler(ElicitRequestSchema, (request, extra) => {
197
201
  const signal = AbortSignal.any([lifetime.signal, extra.signal]);
@@ -203,7 +207,10 @@ var mcpCall = (client, name, input, context, timeoutMs, failure) => Effect_expor
203
207
  const deliver = context.elicit;
204
208
  if (deliver === void 0) return yield* new ElicitationFailed({ reason: "unavailable" });
205
209
  const answer = yield* budget.waitForInput(
206
- fromPromise(deliver)(form.request).pipe(
210
+ fromPromise(
211
+ deliver,
212
+ "elicitation"
213
+ )(form.request).pipe(
207
214
  Effect_exports.mapError(
208
215
  (error) => Option_exports.getOrElse(
209
216
  Schema_exports.decodeUnknownOption(ElicitationFailed)(error),
@@ -253,7 +260,7 @@ var mcpCall = (client, name, input, context, timeoutMs, failure) => Effect_expor
253
260
  );
254
261
  })
255
262
  ).pipe(
256
- Effect_exports.withSpan("provider.mcp.request", {
263
+ owned("upstream", "provider.mcp.request", {
257
264
  kind: "client",
258
265
  attributes: {
259
266
  "rpc.system.name": "jsonrpc",
@@ -311,7 +318,7 @@ function mcpClient(withClient, timeoutMs, failure) {
311
318
  ),
312
319
  catch: (error) => failure("discover", error)
313
320
  }).pipe(
314
- Effect_exports.withSpan("provider.mcp.request", {
321
+ owned("upstream", "provider.mcp.request", {
315
322
  kind: "client",
316
323
  attributes: { "rpc.system.name": "jsonrpc", "rpc.method": "tools/list" }
317
324
  })
@@ -352,25 +359,28 @@ function mcpClient(withClient, timeoutMs, failure) {
352
359
  server: Option_exports.getOrElse(server, () => ({}))
353
360
  };
354
361
  })
355
- ).pipe(Effect_exports.withSpan("provider.mcp.discover"));
362
+ ).pipe(owned("upstream", "provider.mcp.discover"));
356
363
  const check = withClient(
357
364
  "discover",
358
- (client) => Effect_exports.tryPromise({
359
- try: (signal) => client.request({ method: "tools/list", params: {} }, ListToolsResultSchema, {
360
- signal,
361
- timeout: timeoutMs
362
- }),
363
- catch: (error) => failure("discover", error)
364
- }).pipe(
365
- Effect_exports.asVoid,
366
- Effect_exports.withSpan("provider.mcp.request", {
367
- kind: "client",
368
- attributes: { "rpc.system.name": "jsonrpc", "rpc.method": "tools/list" }
369
- })
365
+ (client) => (
366
+ // oxlint-disable-next-line executor/authored-code-through-adapter -- MCP SDK
367
+ Effect_exports.tryPromise({
368
+ try: (signal) => client.request({ method: "tools/list", params: {} }, ListToolsResultSchema, {
369
+ signal,
370
+ timeout: timeoutMs
371
+ }),
372
+ catch: (error) => failure("discover", error)
373
+ }).pipe(
374
+ Effect_exports.asVoid,
375
+ owned("upstream", "provider.mcp.request", {
376
+ kind: "client",
377
+ attributes: { "rpc.system.name": "jsonrpc", "rpc.method": "tools/list" }
378
+ })
379
+ )
370
380
  )
371
- ).pipe(Effect_exports.withSpan("provider.mcp.check"));
381
+ ).pipe(owned("upstream", "provider.mcp.check"));
372
382
  const call = (name, input, context) => withClient("call", (client) => mcpCall(client, name, input, context, timeoutMs, failure)).pipe(
373
- Effect_exports.withSpan("provider.mcp.call", { attributes: { "mcp.tool.name": name } })
383
+ owned("upstream", "provider.mcp.call", { attributes: { "mcp.tool.name": name } })
374
384
  );
375
385
  return { list, check, call };
376
386
  }
@@ -0,0 +1,266 @@
1
+ import {
2
+ declaredOperations,
3
+ nativeOperation,
4
+ nativeRouter
5
+ } from "./chunk-X5U5KIWQ.js";
6
+ import {
7
+ fromPromise,
8
+ method
9
+ } from "./chunk-LTDHQJ2Z.js";
10
+ import {
11
+ EmittedEvent,
12
+ EventName,
13
+ ScheduleTiming,
14
+ defaultEventLimits
15
+ } from "./chunk-JY56GVSV.js";
16
+ import {
17
+ decoderOf,
18
+ isSchema,
19
+ jsonSchemaDocument,
20
+ schemaArgument
21
+ } from "./chunk-KGCTYL2S.js";
22
+ import {
23
+ JsonValue
24
+ } from "./chunk-H2CJWXA3.js";
25
+ import {
26
+ Effect_exports,
27
+ Schema_exports
28
+ } from "./chunk-IFJU5SYQ.js";
29
+
30
+ // src/contracts/http.ts
31
+ var ResponseStatusError = class extends Schema_exports.TaggedError()(
32
+ "ResponseStatusError",
33
+ { status: Schema_exports.Number }
34
+ ) {
35
+ get message() {
36
+ return `Request failed with status ${this.status}`;
37
+ }
38
+ };
39
+ var ResponseDecodeError = class extends Schema_exports.TaggedError()(
40
+ "ResponseDecodeError",
41
+ {}
42
+ ) {
43
+ get message() {
44
+ return "Response body did not match the expected schema";
45
+ }
46
+ };
47
+
48
+ // src/implementation/workflows.ts
49
+ var NativeWorkflow = /* @__PURE__ */ Symbol("apps.Workflow");
50
+ var workflow = (options, run) => ({
51
+ [NativeWorkflow]: {
52
+ input: decoderOf(schemaArgument(options.input, "The workflow input")),
53
+ ...options.output === void 0 ? {} : { output: decoderOf(schemaArgument(options.output, "The workflow output")) },
54
+ ...options.description === void 0 ? {} : { description: options.description },
55
+ // SAFETY: defineApp checks required context; the host supplies the pinned run's capabilities.
56
+ run: (context, input) => fromPromise(run, "workflow")(context, input)
57
+ }
58
+ });
59
+ var nativeWorkflow = (value) => {
60
+ if (typeof value !== "object" || value === null || !(NativeWorkflow in value)) return void 0;
61
+ return value[NativeWorkflow];
62
+ };
63
+
64
+ // src/implementation/events.ts
65
+ var Native = /* @__PURE__ */ Symbol("apps.Event");
66
+ var scalarTypes = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean"]);
67
+ var isScalarSchema = (document) => {
68
+ const type = document.type;
69
+ if (typeof type === "string") return scalarTypes.has(type);
70
+ const choices = Array.isArray(document.enum) ? document.enum : "const" in document ? [document.const] : void 0;
71
+ return choices !== void 0 && choices.length > 0 && choices.every((value) => ["string", "number", "boolean"].includes(typeof value));
72
+ };
73
+ var event = (options) => {
74
+ const filters = options.filters ?? {};
75
+ const fieldDecoders = Object.fromEntries(
76
+ Object.entries(filters).map(([key, field]) => [
77
+ key,
78
+ decoderOf(schemaArgument(field, `The event filter ${JSON.stringify(key)}`))
79
+ ])
80
+ );
81
+ for (const [key, decoder] of Object.entries(fieldDecoders)) {
82
+ const document = Effect_exports.runSync(jsonSchemaDocument(decoder));
83
+ if (!isScalarSchema(document))
84
+ throw new TypeError(
85
+ `The event filter ${JSON.stringify(key)} must be a string, number, boolean or literal`
86
+ );
87
+ }
88
+ return {
89
+ [Native]: {
90
+ description: options.description,
91
+ filters: fieldDecoders,
92
+ payload: decoderOf(schemaArgument(options.payload, "The event payload"))
93
+ },
94
+ description: options.description,
95
+ filters,
96
+ payload: options.payload
97
+ };
98
+ };
99
+ var nativeEvent = (declaration) => typeof declaration === "object" && declaration !== null && Native in declaration ? declaration[Native] : void 0;
100
+ var declaredEvents = (events) => Effect_exports.forEach(
101
+ Object.entries(events),
102
+ ([name, declared]) => Effect_exports.gen(function* () {
103
+ const filters = yield* jsonSchemaDocument(Schema_exports.Struct(declared.filters));
104
+ const payload = yield* jsonSchemaDocument(declared.payload);
105
+ return [name, { description: declared.description, filters, payload }];
106
+ })
107
+ ).pipe(Effect_exports.map((entries) => Object.fromEntries(entries)));
108
+ var makeEmitter = (input) => ({
109
+ emit: (name, data, ...rest) => {
110
+ const options = rest[0] ?? {};
111
+ const declared = Object.hasOwn(input.events, name) ? input.events[name] : void 0;
112
+ if (declared === void 0) throw new TypeError(`This app declares no event named "${name}"`);
113
+ if (input.emitted.length >= defaultEventLimits.maxEventsPerInvocation)
114
+ throw new RangeError(
115
+ `An invocation can emit at most ${defaultEventLimits.maxEventsPerInvocation} events`
116
+ );
117
+ const payload = Schema_exports.decodeUnknownSync(declared.payload)(data);
118
+ const filters = Schema_exports.decodeUnknownSync(Schema_exports.Struct(declared.filters))(
119
+ options.filters ?? {}
120
+ );
121
+ const account = options.account ?? input.sourceAccount ?? (input.accounts.length === 1 ? input.accounts[0] : void 0) ?? null;
122
+ if (account === null && input.accounts.length > 1)
123
+ throw new TypeError(
124
+ "This invocation has several accounts; name the one the event came from with { account }"
125
+ );
126
+ if (account !== null && !input.accounts.includes(account))
127
+ throw new TypeError("The event's account is not one of this invocation's accounts");
128
+ const occurredAt = options.occurredAt === void 0 ? Date.now() : options.occurredAt instanceof Date ? options.occurredAt.getTime() : options.occurredAt;
129
+ const occurrence = Schema_exports.decodeUnknownSync(EmittedEvent)({
130
+ name: Schema_exports.decodeUnknownSync(EventName)(name),
131
+ id: options.id ?? crypto.randomUUID(),
132
+ occurredAt,
133
+ data: payload,
134
+ filters,
135
+ account
136
+ });
137
+ if (new TextEncoder().encode(JSON.stringify(occurrence.data)).byteLength > defaultEventLimits.maxDataBytes)
138
+ throw new RangeError(
139
+ `An event's data can be at most ${defaultEventLimits.maxDataBytes} bytes of JSON; send a summary and a tool to read the rest`
140
+ );
141
+ input.emitted.push(occurrence);
142
+ }
143
+ });
144
+
145
+ // src/implementation/app.ts
146
+ var InternalApp = /* @__PURE__ */ Symbol("apps.App");
147
+ var isApp = (value) => typeof value === "object" && value !== null && InternalApp in value;
148
+ var toEffectApp = (app) => app[InternalApp];
149
+ function rejectCatalogs(definition) {
150
+ if ("queries" in definition || "mutations" in definition)
151
+ throw new Error("Put queries and mutations in a router under tools");
152
+ }
153
+ function adaptDefinition(definition) {
154
+ rejectCatalogs(definition);
155
+ const webhooks = definition.webhooks === void 0 ? {} : {
156
+ // SAFETY: `Required` only where the optional method was just checked to be present.
157
+ webhooks: Object.fromEntries(
158
+ Object.entries(definition.webhooks).map(([name, webhook]) => [
159
+ name,
160
+ {
161
+ ...webhook,
162
+ ...webhook.register === void 0 ? {} : {
163
+ register: fromPromise(
164
+ method(webhook, "register"),
165
+ "webhook"
166
+ )
167
+ },
168
+ handle: fromPromise(method(webhook, "handle"), "webhook"),
169
+ ...webhook.unregister === void 0 ? {} : {
170
+ unregister: fromPromise(
171
+ method(webhook, "unregister"),
172
+ "webhook"
173
+ )
174
+ },
175
+ ..."config" in webhook && isSchema(webhook.config) ? { config: decoderOf(webhook.config) } : {},
176
+ ..."state" in webhook && isSchema(webhook.state) ? { state: decoderOf(webhook.state) } : {}
177
+ }
178
+ ])
179
+ )
180
+ };
181
+ const workflows = definition.workflows === void 0 ? {} : {
182
+ workflows: Object.fromEntries(
183
+ Object.entries(definition.workflows).map(([name, value]) => {
184
+ const declared2 = nativeWorkflow(value);
185
+ if (declared2 === void 0) throw new Error("Invalid workflow declaration");
186
+ return [name, declared2];
187
+ })
188
+ )
189
+ };
190
+ const root = definition.tools === void 0 ? void 0 : nativeRouter(definition.tools);
191
+ if (definition.tools !== void 0 && root === void 0)
192
+ throw new Error("tools must be a router");
193
+ const data = root === void 0 ? {} : { tools: root };
194
+ const declared = root?.kind === "router" ? declaredOperations(root) : [];
195
+ const mutations = /* @__PURE__ */ new Set();
196
+ for (const { operation } of declared) {
197
+ if (operation.kind !== "mutation") continue;
198
+ if (mutations.has(operation))
199
+ throw new Error("A mutation can be mounted at only one path in tools");
200
+ mutations.add(operation);
201
+ }
202
+ const schedules = definition.schedules === void 0 ? {} : {
203
+ schedules: Object.fromEntries(
204
+ Object.entries(definition.schedules).map(([name, schedule]) => {
205
+ const target = nativeOperation(schedule.operation);
206
+ const match = declared.find(
207
+ ({ operation }) => operation === target && operation.kind === "mutation"
208
+ );
209
+ if (match === void 0)
210
+ throw new Error("A schedule must reference a mutation in this app's tools");
211
+ return [
212
+ name,
213
+ {
214
+ timing: Schema_exports.decodeUnknownSync(ScheduleTiming)(schedule.timing),
215
+ input: Schema_exports.decodeUnknownSync(JsonValue)(schedule.input),
216
+ tool: match.name
217
+ }
218
+ ];
219
+ })
220
+ )
221
+ };
222
+ return {
223
+ ...definition,
224
+ ...webhooks,
225
+ ...workflows,
226
+ ...data,
227
+ ...schedules
228
+ };
229
+ }
230
+ var defineApp = (requirements, definition) => {
231
+ if (typeof definition !== "function") rejectCatalogs(definition);
232
+ const evaluate = typeof definition === "function" ? definition : async () => definition;
233
+ const factory = fromPromise(evaluate, "factory");
234
+ const events = requirements.events === void 0 ? void 0 : Object.fromEntries(
235
+ Object.entries(requirements.events).map(([name, declared]) => {
236
+ const native2 = nativeEvent(declared);
237
+ if (native2 === void 0)
238
+ throw new TypeError(
239
+ `The event ${JSON.stringify(name)} must be declared with event()`
240
+ );
241
+ return [name, native2];
242
+ })
243
+ );
244
+ const native = {
245
+ accounts: requirements.accounts,
246
+ ...events === void 0 ? {} : { events },
247
+ evaluate: (context) => factory(context).pipe(Effect_exports.map((value) => adaptDefinition(value)))
248
+ };
249
+ return {
250
+ [InternalApp]: native,
251
+ accounts: native.accounts,
252
+ evaluate: (context) => Effect_exports.runPromise(factory(context))
253
+ };
254
+ };
255
+
256
+ export {
257
+ ResponseStatusError,
258
+ ResponseDecodeError,
259
+ workflow,
260
+ event,
261
+ declaredEvents,
262
+ makeEmitter,
263
+ isApp,
264
+ toEffectApp,
265
+ defineApp
266
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FetchHttpClient_exports
3
- } from "./chunk-MZH4J2PO.js";
3
+ } from "./chunk-PD6I2SDG.js";
4
4
  import {
5
5
  recordedMessage
6
6
  } from "./chunk-5FHWNLCI.js";
@@ -23,7 +23,7 @@ import {
23
23
  tapError,
24
24
  transformResponse,
25
25
  uint8Array
26
- } from "./chunk-LNSVJS2Q.js";
26
+ } from "./chunk-EOPQ727L.js";
27
27
  import {
28
28
  Array as Array2,
29
29
  Boolean2 as Boolean,
@@ -139,6 +139,145 @@ import {
139
139
  __export
140
140
  } from "./chunk-CZ7CSFO4.js";
141
141
 
142
+ // ../telemetry/src/ownership.ts
143
+ var ownerAttribute = "executor.owner";
144
+ var SpanOwner = Context_exports.Reference("@executor-js/telemetry/SpanOwner", {
145
+ defaultValue: () => void 0
146
+ });
147
+ var declaredOwner = (annotations) => Context_exports.get(annotations, SpanOwner);
148
+ var ownedBy = (owner, options = {}) => ({
149
+ ...options,
150
+ annotations: Context_exports.add(options.annotations ?? Context_exports.empty(), SpanOwner, owner)
151
+ });
152
+ var owned = (owner, name, options) => (effect2) => effect2.pipe(Effect_exports.withSpan(name, ownedBy(owner, options)));
153
+ var measuredSpan = (name, options, measure) => (effect2) => Effect_exports.useSpan(name, options, (span) => {
154
+ const inner = Effect_exports.withParentSpan(effect2, span);
155
+ if (span.status._tag === "Ended") return inner;
156
+ const { around, end } = measure(span.status.startTime);
157
+ return (around === void 0 ? inner : around(inner)).pipe(
158
+ Effect_exports.onExit(
159
+ (exit) => Effect_exports.flatMap(
160
+ Clock_exports.currentTimeNanos,
161
+ (now) => Effect_exports.sync(() => {
162
+ end(now, span);
163
+ span.end(now, exit);
164
+ })
165
+ )
166
+ )
167
+ );
168
+ });
169
+ var concurrent = ["executor", "person", "upstream", "app"];
170
+ var makeOwnershipAccounting = (origin, owner) => {
171
+ const totals = { executor: 0, app: 0, upstream: 0, person: 0 };
172
+ const innermost = { executor: 0, app: 0, upstream: 0, person: 0 };
173
+ const boundaries2 = /* @__PURE__ */ new WeakMap();
174
+ let reached = origin;
175
+ let done = false;
176
+ const advance = (time) => {
177
+ if (time <= reached) return;
178
+ const current = concurrent.find((candidate) => innermost[candidate] > 0) ?? owner;
179
+ totals[current] += Number(time - reached) / 1e6;
180
+ reached = time;
181
+ };
182
+ const enclosing = (boundary) => {
183
+ let found = boundary.parent;
184
+ while (found !== void 0 && !found.open) found = found.parent;
185
+ boundary.parent = found;
186
+ return found;
187
+ };
188
+ const opened = (boundary) => {
189
+ const parent = enclosing(boundary);
190
+ if (parent !== void 0 && parent.children++ === 0) innermost[parent.owner] -= 1;
191
+ innermost[boundary.owner] += 1;
192
+ };
193
+ const closed = (boundary) => {
194
+ boundary.open = false;
195
+ if (boundary.children === 0) innermost[boundary.owner] -= 1;
196
+ const parent = enclosing(boundary);
197
+ if (parent === void 0) return;
198
+ parent.children += boundary.children - 1;
199
+ if (parent.children === 0) innermost[parent.owner] += 1;
200
+ };
201
+ const observed = (tracer) => ({
202
+ ...tracer,
203
+ span: (options) => {
204
+ const span = tracer.span(options);
205
+ if (done) return span;
206
+ const parent = Option_exports.getOrUndefined(options.parent);
207
+ const enclosingBoundary = parent === void 0 ? void 0 : boundaries2.get(parent);
208
+ const boundary = {
209
+ owner: declaredOwner(options.annotations) ?? enclosingBoundary?.owner ?? owner,
210
+ parent: enclosingBoundary,
211
+ open: true,
212
+ children: 0
213
+ };
214
+ advance(options.startTime);
215
+ opened(boundary);
216
+ const tracked = {
217
+ _tag: "Span",
218
+ get name() {
219
+ return span.name;
220
+ },
221
+ get spanId() {
222
+ return span.spanId;
223
+ },
224
+ get traceId() {
225
+ return span.traceId;
226
+ },
227
+ get parent() {
228
+ return span.parent;
229
+ },
230
+ get annotations() {
231
+ return span.annotations;
232
+ },
233
+ get status() {
234
+ return span.status;
235
+ },
236
+ get attributes() {
237
+ return span.attributes;
238
+ },
239
+ get links() {
240
+ return span.links;
241
+ },
242
+ get sampled() {
243
+ return span.sampled;
244
+ },
245
+ get kind() {
246
+ return span.kind;
247
+ },
248
+ end: (endTime, exit) => {
249
+ if (boundary.open && !done) {
250
+ advance(endTime);
251
+ closed(boundary);
252
+ }
253
+ span.end(endTime, exit);
254
+ },
255
+ attribute: (key, value) => span.attribute(key, value),
256
+ event: (name, startTime, attributes2) => span.event(name, startTime, attributes2),
257
+ addLinks: (links) => span.addLinks(links)
258
+ };
259
+ boundaries2.set(tracked, boundary);
260
+ return tracked;
261
+ }
262
+ });
263
+ return {
264
+ /** Run `effect` with the spans it opens observed, including spans it hands to later work. */
265
+ observe: (effect2) => Effect_exports.gen(function* () {
266
+ const tracer = yield* Tracer_exports.Tracer;
267
+ return yield* effect2.pipe(Effect_exports.provideService(Tracer_exports.Tracer, observed(tracer)));
268
+ }),
269
+ /**
270
+ * Close the window at `end` and return its milliseconds by owner, each instant counted once.
271
+ * Spans still open count up to `end`; spans that open or end afterwards are ignored.
272
+ */
273
+ read: (end) => {
274
+ if (!done) advance(end);
275
+ done = true;
276
+ return totals;
277
+ }
278
+ };
279
+ };
280
+
142
281
  // ../telemetry/src/context.ts
143
282
  var captureTelemetry = Effect_exports.gen(function* () {
144
283
  let context2 = Context_exports.make(Tracer_exports.Tracer, yield* Tracer_exports.Tracer).pipe(
@@ -170,9 +309,10 @@ var invocationFetch = (signal) => Effect_exports.gen(function* () {
170
309
  const request = yield* Effect_exports.try(() => new Request(input, init));
171
310
  const client = yield* HttpClient_exports.HttpClient;
172
311
  const response = yield* client.execute(HttpClientRequest_exports.fromWeb(request)).pipe(
173
- Effect_exports.withSpan("provider.http.request", {
174
- attributes: { "http.request.method": request.method }
175
- }),
312
+ Effect_exports.withSpan(
313
+ "provider.http.request",
314
+ ownedBy("upstream", { attributes: { "http.request.method": request.method } })
315
+ ),
176
316
  Effect_exports.provideService(FetchHttpClient_exports.RequestInit, {
177
317
  cache: request.cache,
178
318
  credentials: request.credentials,
@@ -201,9 +341,12 @@ var invocationFetch = (signal) => Effect_exports.gen(function* () {
201
341
  streamed,
202
342
  HttpBody_exports.stream(
203
343
  body.stream.pipe(
204
- Stream_exports.withSpan("provider.http.response.read", {
205
- attributes: { "http.response.status_code": response.status }
206
- })
344
+ Stream_exports.withSpan(
345
+ "provider.http.response.read",
346
+ ownedBy("upstream", {
347
+ attributes: { "http.response.status_code": response.status }
348
+ })
349
+ )
207
350
  ),
208
351
  body.contentType,
209
352
  body.contentLength
@@ -991,6 +1134,8 @@ var spanAttributes = (clock, recordAll = false) => Layer_exports.effect(Tracer_e
991
1134
  if (recordAll && Option_exports.isSome(options.parent) && options.parent.value._tag === "ExternalSpan")
992
1135
  span.attribute("executor.trace.parent_sampled", options.parent.value.sampled);
993
1136
  if (clock !== void 0) span.attribute("executor.clock.type", clock);
1137
+ const owner = declaredOwner(options.annotations);
1138
+ if (owner !== void 0) span.attribute(ownerAttribute, owner);
994
1139
  return span;
995
1140
  }
996
1141
  }))
@@ -2344,10 +2489,15 @@ var appSpanNames = /* @__PURE__ */ new Set([
2344
2489
  "app.catalog.read",
2345
2490
  "app.skills.load",
2346
2491
  "app.skills.routers",
2492
+ "app.tool.resolve",
2347
2493
  "app.tool.approval",
2348
2494
  "app.tool.elicitation",
2495
+ "app.elicitation.wait",
2496
+ "app.workflow.control",
2349
2497
  "app.operation.execute",
2350
2498
  "app.sql.migrate",
2499
+ "app.code",
2500
+ "app.cache.call",
2351
2501
  "app.cache.get",
2352
2502
  "app.cache.load",
2353
2503
  "app.cache.command",
@@ -2491,6 +2641,10 @@ var status = (value) => {
2491
2641
  const found = integer(value);
2492
2642
  return found !== void 0 && found >= 100 && found <= 599 ? { intValue: found } : void 0;
2493
2643
  };
2644
+ var duration = (value) => {
2645
+ const found = typeof value["doubleValue"] === "number" ? value["doubleValue"] : integer(value);
2646
+ return found !== void 0 && Number.isFinite(found) && found >= 0 ? { doubleValue: found } : void 0;
2647
+ };
2494
2648
  var spanAttributes2 = {
2495
2649
  "executor.operation": oneOf(...operations, "mutation", "discover"),
2496
2650
  "executor.outcome": oneOf("failed"),
@@ -2529,7 +2683,28 @@ var spanAttributes2 = {
2529
2683
  "url.scheme": oneOf("http", "https"),
2530
2684
  "span.label": oneOf("\u26A0\uFE0E Interrupted"),
2531
2685
  "status.interrupted": flag,
2532
- "executor.milestone.reached": flag
2686
+ "executor.milestone.reached": flag,
2687
+ "executor.owner": oneOf("executor", "app", "upstream", "person"),
2688
+ "executor.app.code": oneOf(
2689
+ "factory",
2690
+ "router",
2691
+ "approval",
2692
+ "handler",
2693
+ "loader",
2694
+ "cache",
2695
+ "webhook",
2696
+ "check",
2697
+ "skills",
2698
+ "elicitation",
2699
+ "workflow",
2700
+ "step"
2701
+ ),
2702
+ "executor.workflow.operation": oneOf("start", "get", "list", "terminate"),
2703
+ "cache.method": oneOf("get", "revalidate", "read", "readMany", "write", "invalidate"),
2704
+ "executor.upstream.wait_ms": duration,
2705
+ "executor.elicitation.wait_ms": duration,
2706
+ "executor.authored_ms": duration,
2707
+ "executor.overhead_ms": duration
2533
2708
  };
2534
2709
  var appSpanAttributeKeys = new Set(Object.keys(spanAttributes2));
2535
2710
  var logMessages = /* @__PURE__ */ new Set([
@@ -2868,6 +3043,9 @@ var pendingSpan = (name, options) => Effect_exports.gen(function* () {
2868
3043
 
2869
3044
  export {
2870
3045
  CurrentTelemetryConfig,
3046
+ owned,
3047
+ measuredSpan,
3048
+ makeOwnershipAccounting,
2871
3049
  OtlpExporter_exports,
2872
3050
  telemetryLayer,
2873
3051
  captureTelemetry,