@fevex/core 0.1.0-alpha.4 → 0.1.0-alpha.6

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 (42) hide show
  1. package/README.md +240 -11
  2. package/dist/agents/index.d.mts +1 -1
  3. package/dist/artifacts/index.d.mts +2 -0
  4. package/dist/artifacts/index.mjs +2 -0
  5. package/dist/artifacts-gUzemET7.mjs +440 -0
  6. package/dist/channels/index.d.mts +1 -1
  7. package/dist/evals/index.d.mts +4 -4
  8. package/dist/fevex-B4QY5Z6e.d.mts +119 -0
  9. package/dist/http/index.d.mts +65 -5
  10. package/dist/http/index.mjs +238 -16
  11. package/dist/{index-C-IFfCNw.d.mts → index-1cHr7KB_.d.mts} +3 -3
  12. package/dist/{index-CqOjvtQ9.d.mts → index-5p3q2yIp.d.mts} +4 -2
  13. package/dist/{index-hhbgvfIt.d.mts → index-BJktlD4E.d.mts} +2 -2
  14. package/dist/{index-CTIwrVf9.d.mts → index-BgKFd9yw.d.mts} +1 -1
  15. package/dist/{index-dkFyTNh4.d.mts → index-CbACw6xZ.d.mts} +2 -2
  16. package/dist/index-CpLDt6Rw.d.mts +118 -0
  17. package/dist/{index-CknU-glw.d.mts → index-CseuTR-F.d.mts} +2 -2
  18. package/dist/{index-CaE864Kz.d.mts → index-CzAi2Y_Z.d.mts} +45 -6
  19. package/dist/{index-DyyNLuwO.d.mts → index-DVw0zOc_.d.mts} +3 -3
  20. package/dist/{index-CrOId2px.d.mts → index-Df84VWmN.d.mts} +1 -1
  21. package/dist/index.d.mts +13 -13
  22. package/dist/index.mjs +904 -153
  23. package/dist/knowledge/index.d.mts +1 -1
  24. package/dist/model-stream-JQdHDDcj.mjs +131 -0
  25. package/dist/models/index.d.mts +1 -1
  26. package/dist/observability/index.d.mts +2 -2
  27. package/dist/policies/index.d.mts +1 -1
  28. package/dist/{model-stream-u2xMsEaf.mjs → run-support-CmZ6Xo6H.mjs} +41 -130
  29. package/dist/runtime/index.d.mts +2 -2
  30. package/dist/runtime/index.mjs +43 -1
  31. package/dist/sandbox/index.d.mts +1 -1
  32. package/dist/sandbox/index.mjs +1 -1
  33. package/dist/teams/index.d.mts +1 -1
  34. package/dist/testing/index.d.mts +8 -7
  35. package/dist/testing/index.mjs +94 -2
  36. package/dist/tools/index.d.mts +2 -2
  37. package/dist/types-B8laW1hM.d.mts +561 -0
  38. package/dist/workflows/index.d.mts +1 -1
  39. package/package.json +6 -2
  40. package/dist/fevex-BoPbZ-Tw.d.mts +0 -60
  41. package/dist/index-voIZhQXB.d.mts +0 -80
  42. package/dist/types-CuoRx12Q.d.mts +0 -333
@@ -1,4 +1,6 @@
1
+ import { o as ArtifactError } from "../artifacts-gUzemET7.mjs";
1
2
  import { t as FevexRunError } from "../run-error-Cr17wPGH.mjs";
3
+ import { t as MAX_DEADLINE_MS } from "../run-support-CmZ6Xo6H.mjs";
2
4
  //#region src/http/protocol.ts
3
5
  const FEVEX_HTTP_PROTOCOL_VERSION = "3";
4
6
  const FEVEX_HTTP_PROTOCOL_VERSION_HEADER = "Fevex-Protocol-Version";
@@ -21,6 +23,8 @@ const FEVEX_RUN_ERROR_CODES = /* @__PURE__ */ new Set([
21
23
  "CHECKPOINT_UNSUPPORTED",
22
24
  "RUN_DEFINITION_CHANGED",
23
25
  "POLICY_DENIED",
26
+ "ADMISSION_DENIED",
27
+ "RUNTIME_CLOSED",
24
28
  "CREDENTIAL_NOT_FOUND",
25
29
  "SANDBOX_REQUIRED",
26
30
  "ELICITATION_INVALID",
@@ -32,69 +36,135 @@ const FEVEX_RUN_ERROR_CODES = /* @__PURE__ */ new Set([
32
36
  function createFevexHttpHandler(options) {
33
37
  const pollIntervalMs = options.pollIntervalMs ?? 100;
34
38
  const eventPageSize = options.eventPageSize ?? 100;
39
+ const maxConnections = options.maxConnections;
35
40
  if (!Number.isSafeInteger(eventPageSize) || eventPageSize < 1 || eventPageSize > 1e3) throw new TypeError("eventPageSize must be an integer between 1 and 1000");
36
41
  if (!Number.isFinite(pollIntervalMs) || pollIntervalMs < 1) throw new TypeError("pollIntervalMs must be a positive number");
42
+ if (maxConnections !== void 0 && (!Number.isSafeInteger(maxConnections) || maxConnections < 1)) throw new TypeError("maxConnections must be a positive safe integer");
43
+ let activeConnections = 0;
44
+ const authorize = async (access) => {
45
+ if (options.authorize && !await options.authorize(access)) throw new HttpProtocolError(403, "FORBIDDEN", "Forbidden");
46
+ };
47
+ const authorizeArtifact = async (access) => {
48
+ if (options.authorizeArtifact && !await options.authorizeArtifact(access)) throw new HttpProtocolError(403, "FORBIDDEN", "Forbidden");
49
+ };
37
50
  return async (request, handlerContext = {}) => {
38
51
  const url = new URL(request.url);
39
52
  const path = url.pathname;
53
+ const commitStart = async (run) => {
54
+ try {
55
+ await options.onRunStarted?.(run, handlerContext.context);
56
+ } catch (error) {
57
+ await options.fevex.cancelRun(run.id).catch(() => {});
58
+ throw error;
59
+ }
60
+ };
40
61
  try {
41
62
  const start = path.match(/^\/v1\/agents\/([^/]+)\/runs$/);
42
63
  if (start && request.method === "POST") {
43
64
  const body = await readJson(request);
44
65
  if (!hasOwn(body, "input")) throw badRequest("input is required");
66
+ const name = decodeURIComponent(start[1]);
45
67
  const sessionId = optionalId(body.sessionId, "sessionId");
46
68
  const model = optionalId(body.model, "model");
47
69
  const reasoning = optionalReasoning(body.reasoning);
48
- return json(await options.fevex.startAgent(decodeURIComponent(start[1]), {
70
+ const deadlineMs = optionalDeadline(body.deadlineMs, "deadlineMs");
71
+ await authorize({
72
+ action: "start",
73
+ kind: "agent",
74
+ name,
75
+ sessionId,
76
+ context: handlerContext.context
77
+ });
78
+ const run = await options.fevex.startAgent(name, {
49
79
  input: body.input,
50
80
  ...model ? { model } : {},
51
81
  ...reasoning === void 0 ? {} : { reasoning },
82
+ ...deadlineMs === void 0 ? {} : { deadlineMs },
52
83
  ...sessionId ? { sessionId } : {},
53
84
  ...handlerContext.context ? { context: handlerContext.context } : {}
54
- }), 202);
85
+ });
86
+ await commitStart(run);
87
+ return json(run, 202);
55
88
  }
56
89
  const startWorkflow = path.match(/^\/v1\/workflows\/([^/]+)\/runs$/);
57
90
  if (startWorkflow && request.method === "POST") {
58
91
  const body = await readJson(request);
59
92
  if (!hasOwn(body, "input")) throw badRequest("input is required");
93
+ const name = decodeURIComponent(startWorkflow[1]);
60
94
  const sessionId = optionalId(body.sessionId, "sessionId");
61
95
  const model = optionalId(body.model, "model");
62
96
  const reasoning = optionalReasoning(body.reasoning);
63
- return json(await options.fevex.startWorkflow(decodeURIComponent(startWorkflow[1]), {
97
+ const deadlineMs = optionalDeadline(body.deadlineMs, "deadlineMs");
98
+ await authorize({
99
+ action: "start",
100
+ kind: "workflow",
101
+ name,
102
+ sessionId,
103
+ context: handlerContext.context
104
+ });
105
+ const run = await options.fevex.startWorkflow(name, {
64
106
  input: body.input,
65
107
  ...model ? { model } : {},
66
108
  ...reasoning === void 0 ? {} : { reasoning },
109
+ ...deadlineMs === void 0 ? {} : { deadlineMs },
67
110
  ...sessionId ? { sessionId } : {},
68
111
  ...handlerContext.context ? { context: handlerContext.context } : {}
69
- }), 202);
112
+ });
113
+ await commitStart(run);
114
+ return json(run, 202);
70
115
  }
71
116
  const startTeam = path.match(/^\/v1\/teams\/([^/]+)\/runs$/);
72
117
  if (startTeam && request.method === "POST") {
73
118
  const body = await readJson(request);
74
119
  if (!hasOwn(body, "input")) throw badRequest("Run input is required");
120
+ const name = decodeURIComponent(startTeam[1]);
75
121
  const sessionId = optionalId(body.sessionId, "sessionId");
76
122
  const model = optionalId(body.model, "model");
77
123
  const reasoning = optionalReasoning(body.reasoning);
78
- return json(await options.fevex.startTeam(decodeURIComponent(startTeam[1]), {
124
+ const deadlineMs = optionalDeadline(body.deadlineMs, "deadlineMs");
125
+ await authorize({
126
+ action: "start",
127
+ kind: "team",
128
+ name,
129
+ sessionId,
130
+ context: handlerContext.context
131
+ });
132
+ const run = await options.fevex.startTeam(name, {
79
133
  input: body.input,
80
134
  ...model ? { model } : {},
81
135
  ...reasoning === void 0 ? {} : { reasoning },
136
+ ...deadlineMs === void 0 ? {} : { deadlineMs },
82
137
  ...sessionId ? { sessionId } : {},
83
138
  ...handlerContext.context ? { context: handlerContext.context } : {}
84
- }), 202);
139
+ });
140
+ await commitStart(run);
141
+ return json(run, 202);
85
142
  }
86
143
  const events = path.match(/^\/v1\/runs\/([^/]+)\/events$/);
87
144
  if (events && request.method === "GET") {
88
145
  const runId = decodeURIComponent(events[1]);
146
+ await authorize({
147
+ action: "observe",
148
+ runId,
149
+ context: handlerContext.context
150
+ });
89
151
  if (!await options.fevex.getRun(runId)) throw notFound("RUN_NOT_FOUND", "Run not found");
90
152
  const after = request.headers.get("last-event-id")?.trim() || void 0;
91
153
  const initial = await options.fevex.listEvents(runId, {
92
154
  after,
93
155
  limit: eventPageSize
94
156
  });
157
+ if (maxConnections !== void 0 && activeConnections >= maxConnections) throw new HttpProtocolError(429, "CONNECTION_LIMIT", "Too many event streams");
158
+ activeConnections += 1;
159
+ let released = false;
160
+ const release = () => {
161
+ if (released) return;
162
+ released = true;
163
+ activeConnections -= 1;
164
+ };
95
165
  const disconnected = new AbortController();
96
166
  const iterator = observeEvents(options.fevex, runId, initial, after, pollIntervalMs, AbortSignal.any([request.signal, disconnected.signal]), eventPageSize);
97
- return versioned(new Response(iteratorStream(iterator, () => disconnected.abort()), { headers: {
167
+ return versioned(new Response(iteratorStream(iterator, () => disconnected.abort(), release), { headers: {
98
168
  "content-type": `${SSE_TYPE}; charset=utf-8`,
99
169
  "cache-control": "no-cache, no-transform"
100
170
  } }));
@@ -102,28 +172,99 @@ function createFevexHttpHandler(options) {
102
172
  const resume = path.match(/^\/v1\/runs\/([^/]+)\/resume$/);
103
173
  if (resume && request.method === "POST") {
104
174
  const runId = decodeURIComponent(resume[1]);
105
- if (!await options.fevex.getRun(runId)) throw notFound("RUN_NOT_FOUND", "Run not found");
106
175
  const actor = handlerContext.context?.actor;
107
176
  if (!actor?.id?.trim()) throw new HttpProtocolError(401, "ACTOR_REQUIRED", "Authenticated actor is required");
177
+ await authorize({
178
+ action: "resume",
179
+ runId,
180
+ context: handlerContext.context
181
+ });
182
+ if (!await options.fevex.getRun(runId)) throw notFound("RUN_NOT_FOUND", "Run not found");
108
183
  const resolution = readResolution(await readJson(request), actor);
109
184
  return json(await options.fevex.resumeRun(runId, resolution), 202);
110
185
  }
111
186
  const recover = path.match(/^\/v1\/runs\/([^/]+)\/recover$/);
112
187
  if (recover && request.method === "POST") {
113
188
  const runId = decodeURIComponent(recover[1]);
114
- if (!await options.fevex.getRun(runId)) throw notFound("RUN_NOT_FOUND", "Run not found");
115
189
  const actor = handlerContext.context?.actor;
116
190
  if (!actor?.id?.trim()) throw new HttpProtocolError(401, "ACTOR_REQUIRED", "Authenticated actor is required");
191
+ await authorize({
192
+ action: "recover",
193
+ runId,
194
+ context: handlerContext.context
195
+ });
196
+ if (!await options.fevex.getRun(runId)) throw notFound("RUN_NOT_FOUND", "Run not found");
117
197
  return json(await options.fevex.recoverRun(runId, { actor }), 202);
118
198
  }
199
+ const runArtifacts = path.match(/^\/v1\/runs\/([^/]+)\/artifacts$/);
200
+ if (runArtifacts && request.method === "GET") {
201
+ const runId = decodeURIComponent(runArtifacts[1]);
202
+ await authorizeArtifact({
203
+ action: "read",
204
+ kind: "artifacts",
205
+ runId,
206
+ context: handlerContext.context
207
+ });
208
+ if (!options.artifactCatalog) throw new HttpProtocolError(501, "ARTIFACT_CATALOG_NOT_CONFIGURED", "Artifact catalog is not configured");
209
+ if (!await options.fevex.getRun(runId)) throw notFound("RUN_NOT_FOUND", "Run not found");
210
+ const limit = optionalLimit(url.searchParams.get("limit"));
211
+ return json((await options.artifactCatalog.list({
212
+ runId,
213
+ ...limit === void 0 ? {} : { limit }
214
+ }, artifactContext(handlerContext, request))).map(({ descriptor }) => descriptor));
215
+ }
216
+ const artifactRoute = path.match(/^\/v1\/artifacts\/([^/]+)$/);
217
+ if (artifactRoute && (request.method === "GET" || request.method === "HEAD")) {
218
+ const artifactId = decodeURIComponent(artifactRoute[1]);
219
+ await authorizeArtifact({
220
+ action: "read",
221
+ kind: "artifact",
222
+ artifactId,
223
+ context: handlerContext.context
224
+ });
225
+ if (!options.artifacts) throw new HttpProtocolError(501, "ARTIFACTS_NOT_CONFIGURED", "Artifact store is not configured");
226
+ const context = artifactContext(handlerContext, request);
227
+ if (request.method === "HEAD" && options.artifacts.head) {
228
+ const descriptor = await options.artifacts.head(artifactId, context);
229
+ if (!descriptor) throw notFound("ARTIFACT_NOT_FOUND", "Artifact not found");
230
+ return artifactResponse(descriptor, null);
231
+ }
232
+ const content = await options.artifacts.get(artifactId, context);
233
+ if (!content) throw notFound("ARTIFACT_NOT_FOUND", "Artifact not found");
234
+ return artifactResponse(content.descriptor, request.method === "HEAD" ? null : content.bytes);
235
+ }
236
+ if (artifactRoute && request.method === "DELETE") {
237
+ const artifactId = decodeURIComponent(artifactRoute[1]);
238
+ await authorizeArtifact({
239
+ action: "delete",
240
+ kind: "artifact",
241
+ artifactId,
242
+ context: handlerContext.context
243
+ });
244
+ if (!options.artifacts) throw new HttpProtocolError(501, "ARTIFACTS_NOT_CONFIGURED", "Artifact store is not configured");
245
+ if (!options.artifacts.delete) throw new HttpProtocolError(501, "ARTIFACT_DELETE_UNSUPPORTED", "Artifact store does not support deletion");
246
+ if (!await options.artifacts.delete(artifactId, artifactContext(handlerContext, request))) throw notFound("ARTIFACT_NOT_FOUND", "Artifact not found");
247
+ return versioned(new Response(null, { status: 204 }));
248
+ }
119
249
  const run = path.match(/^\/v1\/runs\/([^/]+)$/);
120
250
  if (run && request.method === "GET") {
121
- const value = await options.fevex.getRun(decodeURIComponent(run[1]));
251
+ const runId = decodeURIComponent(run[1]);
252
+ await authorize({
253
+ action: "read",
254
+ runId,
255
+ context: handlerContext.context
256
+ });
257
+ const value = await options.fevex.getRun(runId);
122
258
  if (!value) throw notFound("RUN_NOT_FOUND", "Run not found");
123
259
  return json(value);
124
260
  }
125
261
  if (run && request.method === "DELETE") {
126
262
  const runId = decodeURIComponent(run[1]);
263
+ await authorize({
264
+ action: "cancel",
265
+ runId,
266
+ context: handlerContext.context
267
+ });
127
268
  const value = await options.fevex.getRun(runId);
128
269
  if (!value) throw notFound("RUN_NOT_FOUND", "Run not found");
129
270
  if (value.status === "running" || value.status === "paused") {
@@ -131,7 +272,7 @@ function createFevexHttpHandler(options) {
131
272
  }
132
273
  return versioned(new Response(null, { status: 204 }));
133
274
  }
134
- if (start || startWorkflow || startTeam || events || resume || recover || run) throw new HttpProtocolError(405, "METHOD_NOT_ALLOWED", "Method not allowed");
275
+ if (start || startWorkflow || startTeam || events || resume || recover || runArtifacts || artifactRoute || run) throw new HttpProtocolError(405, "METHOD_NOT_ALLOWED", "Method not allowed");
135
276
  throw notFound("ROUTE_NOT_FOUND", "Route not found");
136
277
  } catch (error) {
137
278
  return problem(error, url.pathname, options.onError);
@@ -192,6 +333,17 @@ function createFevexHttpClient(options) {
192
333
  },
193
334
  async cancelRun(runId) {
194
335
  await assertResponse(await fetcher(`${baseUrl}/v1/runs/${encodeURIComponent(runId)}`, { method: "DELETE" }));
336
+ },
337
+ async getArtifact(artifactId) {
338
+ const response = await fetcher(`${baseUrl}/v1/artifacts/${encodeURIComponent(artifactId)}`);
339
+ await assertResponse(response);
340
+ return response;
341
+ },
342
+ listArtifacts(runId) {
343
+ return request(`/v1/runs/${encodeURIComponent(runId)}/artifacts`);
344
+ },
345
+ async deleteArtifact(artifactId) {
346
+ await assertResponse(await fetcher(`${baseUrl}/v1/artifacts/${encodeURIComponent(artifactId)}`, { method: "DELETE" }));
195
347
  }
196
348
  };
197
349
  }
@@ -220,18 +372,28 @@ async function* observeEvents(fevex, runId, initial, after, pollIntervalMs, sign
220
372
  });
221
373
  }
222
374
  }
223
- function iteratorStream(iterator, cancel) {
375
+ function iteratorStream(iterator, cancel, done) {
376
+ let finished = false;
377
+ const finish = () => {
378
+ if (finished) return;
379
+ finished = true;
380
+ done?.();
381
+ };
224
382
  return new ReadableStream({
225
383
  async pull(controller) {
226
384
  try {
227
385
  const next = await iterator.next();
228
- if (next.done) controller.close();
229
- else controller.enqueue(next.value);
386
+ if (next.done) {
387
+ finish();
388
+ controller.close();
389
+ } else controller.enqueue(next.value);
230
390
  } catch (error) {
391
+ finish();
231
392
  controller.error(error);
232
393
  }
233
394
  },
234
395
  async cancel() {
396
+ finish();
235
397
  cancel();
236
398
  await iterator.return(void 0);
237
399
  }
@@ -280,6 +442,37 @@ function findBoundary(value) {
280
442
  function formatEvent(event) {
281
443
  return `id: ${event.id}\nevent: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`;
282
444
  }
445
+ function artifactContext(handlerContext, request) {
446
+ const tenantId = handlerContext.context?.attributes?.tenantId;
447
+ if (tenantId !== void 0 && typeof tenantId !== "string") throw badRequest("tenantId attribute must be a string");
448
+ const actor = handlerContext.context?.actor;
449
+ return {
450
+ ...typeof tenantId === "string" ? { tenantId } : {},
451
+ ...actor === void 0 ? {} : { actor },
452
+ signal: request.signal
453
+ };
454
+ }
455
+ function optionalLimit(value) {
456
+ if (value === null) return void 0;
457
+ const parsed = Number(value);
458
+ if (!Number.isSafeInteger(parsed) || parsed < 1) throw badRequest("limit must be a positive integer");
459
+ return parsed;
460
+ }
461
+ function artifactResponse(descriptor, bytes) {
462
+ return versioned(new Response(bytes === null ? null : bytes.slice().buffer, { headers: {
463
+ "content-type": descriptor.mimeType,
464
+ "content-length": String(descriptor.size),
465
+ "content-disposition": contentDisposition(descriptor.filename),
466
+ "cache-control": "private, max-age=0, must-revalidate",
467
+ etag: `"${descriptor.sha256}"`,
468
+ "x-content-type-options": "nosniff",
469
+ "fevex-artifact-id": descriptor.artifactId,
470
+ "fevex-artifact-sha256": descriptor.sha256
471
+ } }));
472
+ }
473
+ function contentDisposition(filename) {
474
+ return `attachment; filename="${filename.replace(/[^\x20-\x7e]/gu, "_").replace(/["\\]/gu, "_")}"; filename*=UTF-8''${encodeURIComponent(filename).replace(/'/gu, "%27")}`;
475
+ }
283
476
  function readResolution(body, actor) {
284
477
  if (body.type === "elicitation" && typeof body.requestId === "string" && body.requestId.trim() && hasOwn(body, "value")) return {
285
478
  type: "elicitation",
@@ -334,6 +527,16 @@ function optionalId(value, name) {
334
527
  if (typeof value !== "string" || !value.trim()) throw badRequest(`${name} must be a string`);
335
528
  return value.trim();
336
529
  }
530
+ function optionalPositiveInteger(value, name) {
531
+ if (value === void 0) return void 0;
532
+ if (!Number.isSafeInteger(value) || value < 1) throw badRequest(`${name} must be a positive integer`);
533
+ return value;
534
+ }
535
+ function optionalDeadline(value, name) {
536
+ const deadlineMs = optionalPositiveInteger(value, name);
537
+ if (deadlineMs !== void 0 && deadlineMs > 2147483647) throw badRequest(`${name} must be at most ${MAX_DEADLINE_MS}`);
538
+ return deadlineMs;
539
+ }
337
540
  function optionalReasoning(value) {
338
541
  if (value === void 0) return void 0;
339
542
  if (typeof value !== "string" || ![
@@ -408,6 +611,11 @@ function problem(error, instance, onError) {
408
611
  ({status, code} = error);
409
612
  title = error.message;
410
613
  detail = error.message;
614
+ } else if (error instanceof ArtifactError) {
615
+ code = error.code;
616
+ status = statusForArtifactErrorCode(error.code);
617
+ title = titleForStatus(status);
618
+ detail = error.message;
411
619
  } else {
412
620
  const runError = readFevexRunError(error);
413
621
  if (runError) {
@@ -446,13 +654,27 @@ function statusForRunErrorCode(code) {
446
654
  if (code === "AGENT_NOT_FOUND" || code === "WORKFLOW_NOT_FOUND" || code === "TEAM_NOT_FOUND" || code === "SESSION_NOT_FOUND") return 404;
447
655
  if (code === "APPROVAL_INVALID" || code === "INVALID_CURSOR") return 400;
448
656
  if (code === "POLICY_DENIED") return 403;
657
+ if (code === "ADMISSION_DENIED") return 429;
658
+ if (code === "RUNTIME_CLOSED") return 503;
449
659
  return 409;
450
660
  }
661
+ function statusForArtifactErrorCode(code) {
662
+ if (code === "ARTIFACT_INVALID_ID" || code === "ARTIFACT_INVALID_INPUT" || code === "ARTIFACT_INVALID_CONTEXT") return 400;
663
+ if (code === "ARTIFACT_TOO_LARGE") return 413;
664
+ if (code === "ARTIFACT_MIME_UNSUPPORTED") return 415;
665
+ if (code === "ARTIFACT_CONFLICT") return 409;
666
+ return 500;
667
+ }
451
668
  function titleForStatus(status) {
452
- if (status === 404) return "Not Found";
453
669
  if (status === 400) return "Bad Request";
454
670
  if (status === 403) return "Forbidden";
455
- return "Conflict";
671
+ if (status === 404) return "Not Found";
672
+ if (status === 409) return "Conflict";
673
+ if (status === 413) return "Payload Too Large";
674
+ if (status === 415) return "Unsupported Media Type";
675
+ if (status === 429) return "Too Many Requests";
676
+ if (status === 501) return "Not Implemented";
677
+ return "Internal Server Error";
456
678
  }
457
679
  function wait(ms, signal) {
458
680
  return new Promise((resolve) => {
@@ -1,7 +1,7 @@
1
1
  import { t as ExactDefinition } from "./exact-definition-NHBBFlFR.mjs";
2
- import { o as ExecutionContext } from "./types-CuoRx12Q.mjs";
3
- import { n as AgentLimits } from "./index-CaE864Kz.mjs";
4
- import { t as WorkflowAgentResult } from "./index-CknU-glw.mjs";
2
+ import { o as ExecutionContext } from "./types-B8laW1hM.mjs";
3
+ import { n as AgentLimits } from "./index-CzAi2Y_Z.mjs";
4
+ import { t as WorkflowAgentResult } from "./index-CseuTR-F.mjs";
5
5
  import { StandardSchemaV1 } from "@standard-schema/spec";
6
6
  //#region src/teams/team.d.ts
7
7
  interface TeamMember {
@@ -1,6 +1,6 @@
1
1
  import { t as ExactDefinition } from "./exact-definition-NHBBFlFR.mjs";
2
- import { f as RunId, g as ToolSpec, h as ToolEventSource, l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-CuoRx12Q.mjs";
3
- import { i as SandboxCapabilities, r as Sandbox } from "./index-CrOId2px.mjs";
2
+ import { F as ArtifactStore, f as RunId, g as ToolSpec, h as ToolEventSource, l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-B8laW1hM.mjs";
3
+ import { i as SandboxCapabilities, r as Sandbox } from "./index-Df84VWmN.mjs";
4
4
  import { StandardSchemaV1 } from "@standard-schema/spec";
5
5
  //#region src/tools/tool.d.ts
6
6
  interface ToolExecutionContext {
@@ -10,6 +10,8 @@ interface ToolExecutionContext {
10
10
  idempotencyKey: string;
11
11
  getCredential(name: string): Promise<string>;
12
12
  sandbox?: Sandbox;
13
+ /** Optional artifact store; writes emit `artifact.created`. */
14
+ artifacts?: ArtifactStore;
13
15
  context?: ExecutionContext;
14
16
  signal?: AbortSignal;
15
17
  }
@@ -1,5 +1,5 @@
1
- import { l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-CuoRx12Q.mjs";
2
- import { M as SessionId } from "./index-CaE864Kz.mjs";
1
+ import { l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-B8laW1hM.mjs";
2
+ import { L as SessionId } from "./index-CzAi2Y_Z.mjs";
3
3
  //#region src/knowledge/knowledge.d.ts
4
4
  /** Runtime context supplied to knowledge providers and memory stores. */
5
5
  interface KnowledgeContext {
@@ -1,4 +1,4 @@
1
- import { g as ToolSpec, i as AgentMessage, l as JsonValue, m as ToolCall, s as JsonObject } from "./types-CuoRx12Q.mjs";
1
+ import { g as ToolSpec, i as AgentMessage, l as JsonValue, m as ToolCall, s as JsonObject } from "./types-B8laW1hM.mjs";
2
2
  //#region src/models/model.d.ts
3
3
  /** Provider-neutral reasoning levels accepted by model gateways. */
4
4
  type ReasoningEffort = 'provider-default' | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
@@ -1,5 +1,5 @@
1
- import { f as RunId, l as JsonValue, o as ExecutionContext } from "./types-CuoRx12Q.mjs";
2
- import { x as ToolRisk } from "./index-CqOjvtQ9.mjs";
1
+ import { f as RunId, l as JsonValue, o as ExecutionContext } from "./types-B8laW1hM.mjs";
2
+ import { x as ToolRisk } from "./index-5p3q2yIp.mjs";
3
3
  //#region src/policies/policy.d.ts
4
4
  /** Authorization outcome returned by a policy. */
5
5
  type PolicyDecision = 'allow' | 'deny' | 'require_approval';
@@ -0,0 +1,118 @@
1
+ import { f as RunId, l as JsonValue, s as JsonObject } from "./types-B8laW1hM.mjs";
2
+ import { r as ModelMetadata, s as ModelUsage } from "./index-BgKFd9yw.mjs";
3
+ import { L as SessionId } from "./index-CzAi2Y_Z.mjs";
4
+ //#region src/observability/trace.d.ts
5
+ /** Final state represented by an exported run trace. */
6
+ type TraceStatus = 'completed' | 'failed' | 'cancelled';
7
+ /** Kind of run that produced a trace. Absent means `agent` for older traces. */
8
+ type TraceRunKind = 'agent' | 'workflow' | 'team';
9
+ /** Model and tool calls are agent spans; steps belong to workflow and team traces. */
10
+ type TraceSpanKind = 'model' | 'tool' | 'step';
11
+ type TraceContentKind = 'run.output' | 'model.output' | 'error.message';
12
+ interface TraceCost {
13
+ amount: number;
14
+ currency: string;
15
+ }
16
+ interface TraceContent {
17
+ kind: TraceContentKind;
18
+ value: JsonValue;
19
+ }
20
+ interface TraceAnnotation {
21
+ name: string;
22
+ timestamp: string;
23
+ attributes?: JsonObject;
24
+ }
25
+ interface TraceSpan {
26
+ id: string;
27
+ /** Run or span that contains this span. */
28
+ parentId: string;
29
+ kind: TraceSpanKind;
30
+ name: string;
31
+ startedAt: string;
32
+ endedAt: string;
33
+ durationMs: number;
34
+ status: TraceStatus;
35
+ attributes: JsonObject;
36
+ annotations: TraceAnnotation[];
37
+ usage?: ModelUsage;
38
+ cost?: TraceCost;
39
+ content?: TraceContent[];
40
+ }
41
+ interface RunTrace {
42
+ schemaVersion: '1';
43
+ /** Absent on traces produced before coordinator traces existed; treat as `agent`. */
44
+ kind?: TraceRunKind;
45
+ traceId: string;
46
+ runId: RunId;
47
+ sessionId: SessionId;
48
+ /** Agent, workflow or team name. */
49
+ agentName: string;
50
+ /** Run that created this one, when it belongs to a workflow or team. */
51
+ parentRunId?: RunId;
52
+ /** Top-level run in the correlation tree. Defaults to `runId`. */
53
+ rootRunId?: RunId;
54
+ /** Only present on agent traces. */
55
+ modelRegistryName?: string;
56
+ model?: ModelMetadata;
57
+ startedAt: string;
58
+ endedAt: string;
59
+ durationMs: number;
60
+ status: TraceStatus;
61
+ attributes: JsonObject;
62
+ annotations: TraceAnnotation[];
63
+ spans: TraceSpan[];
64
+ usage?: ModelUsage;
65
+ cost?: TraceCost;
66
+ content?: TraceContent[];
67
+ }
68
+ interface CostCalculatorInput {
69
+ modelRegistryName: string;
70
+ model?: ModelMetadata;
71
+ usage: ModelUsage;
72
+ }
73
+ type CostCalculator = (input: CostCalculatorInput) => TraceCost | undefined;
74
+ interface TraceRedactorInput {
75
+ kind: TraceContentKind;
76
+ value: JsonValue;
77
+ }
78
+ type TraceRedactor = (input: TraceRedactorInput) => JsonValue | undefined;
79
+ interface TraceContentPolicy {
80
+ include: readonly TraceContentKind[];
81
+ redact?: TraceRedactor;
82
+ }
83
+ interface TraceExporter {
84
+ export(trace: Readonly<RunTrace>): void | Promise<void>;
85
+ }
86
+ interface TraceExportQueueOptions {
87
+ /** Traces exported at once. Defaults to 4. */
88
+ concurrency?: number;
89
+ /** Traces waiting for an export slot before new traces are dropped. Defaults to 100. */
90
+ maxQueued?: number;
91
+ /** Deadline for each exporter call. Defaults to 30 seconds. */
92
+ timeoutMs?: number;
93
+ /** Failures retained for the next `flushObservability` call. Defaults to 100. */
94
+ maxFailures?: number;
95
+ }
96
+ /** Queue and failure counters for the runtime's trace exporters. */
97
+ interface ObservabilityStats {
98
+ /** Traces exported successfully since the runtime started. */
99
+ exported: number;
100
+ /** Failed exports and dropped traces since the runtime started. */
101
+ failed: number;
102
+ /** Traces dropped because the queue was full. */
103
+ dropped: number;
104
+ /** Traces waiting for an export slot. */
105
+ queued: number;
106
+ /** Traces currently being exported. */
107
+ active: number;
108
+ /** Failures retained for the next flush. */
109
+ retainedFailures: number;
110
+ }
111
+ interface ObservabilityOptions {
112
+ exporters: readonly TraceExporter[];
113
+ calculateCost?: CostCalculator;
114
+ content?: TraceContentPolicy;
115
+ exportQueue?: TraceExportQueueOptions;
116
+ }
117
+ //#endregion
118
+ export { TraceSpanKind as _, RunTrace as a, TraceContentKind as c, TraceExportQueueOptions as d, TraceExporter as f, TraceSpan as g, TraceRunKind as h, ObservabilityStats as i, TraceContentPolicy as l, TraceRedactorInput as m, CostCalculatorInput as n, TraceAnnotation as o, TraceRedactor as p, ObservabilityOptions as r, TraceContent as s, CostCalculator as t, TraceCost as u, TraceStatus as v };
@@ -1,6 +1,6 @@
1
1
  import { t as ExactDefinition } from "./exact-definition-NHBBFlFR.mjs";
2
- import { f as RunId, l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-CuoRx12Q.mjs";
3
- import { D as RunRequest, M as SessionId, O as RunResult, n as AgentLimits } from "./index-CaE864Kz.mjs";
2
+ import { f as RunId, l as JsonValue, o as ExecutionContext, s as JsonObject } from "./types-B8laW1hM.mjs";
3
+ import { L as SessionId, M as RunRequest, N as RunResult, n as AgentLimits } from "./index-CzAi2Y_Z.mjs";
4
4
  import { StandardSchemaV1 } from "@standard-schema/spec";
5
5
  //#region src/workflows/workflow.d.ts
6
6
  /** Context shared with workflow steps and compensation handlers. */