@oddington/sdk 0.1.22 → 0.1.24

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.
package/dist/browser.js CHANGED
@@ -285,7 +285,7 @@ function validatePublication(value) {
285
285
  "views",
286
286
  "body",
287
287
  "notifyImmediately",
288
- ...source.kind === "ask" ? ["questions"] : []
288
+ ...source.kind === "ask" ? ["questions", "tags", "recordRefs"] : []
289
289
  ], "publication"), source.notifyImmediately !== void 0 && typeof source.notifyImmediately != "boolean" && fail("notifyImmediately must be a boolean");
290
290
  let itemPresentation = { ...presentation(source), ...source.notifyImmediately === void 0 ? {} : { notifyImmediately: source.notifyImmediately } }, linkedAsks = (itemPresentation.body ?? []).flatMap((block2) => block2.kind === "asks" ? block2.asks : []);
291
291
  if (new Set(linkedAsks).size !== linkedAsks.length && fail("Ask belongs to more than one problem"), source.kind === "digest") return {
@@ -297,10 +297,24 @@ function validatePublication(value) {
297
297
  let questions = array(source.questions === void 0 ? [] : source.questions, "questions").map((value2) => question(value2));
298
298
  new Set(questions.map((entry) => entry.id)).size !== questions.length && fail("Duplicate question ID");
299
299
  let extra = source.recipients === void 0 ? [] : distinctPeople(source.recipients, "recipients", !1);
300
- return !questions.length && !extra.length && fail("Ask requires at least one recipient"), {
300
+ !questions.length && !extra.length && fail("Ask requires at least one recipient");
301
+ let tags = array(source.tags === void 0 ? [] : source.tags, "Ask tags").map((value2) => {
302
+ let tag = text(value2, "Ask tag");
303
+ return new TextEncoder().encode(tag).byteLength > 64 && fail("Ask tag exceeds 64 UTF-8 bytes"), tag;
304
+ });
305
+ (tags.length > 32 || new Set(tags).size !== tags.length) && fail("Ask tags exceed bounds or contain duplicates");
306
+ let recordRefs = array(source.recordRefs === void 0 ? [] : source.recordRefs, "Ask Record references").map((value2) => {
307
+ let row = object(value2, "Ask Record reference");
308
+ keys(row, ["repository", "id"], "Ask Record reference");
309
+ let { repository, ref } = validateRecordReference({ repository: row.repository, ref: row.id });
310
+ return { repository, id: ref };
311
+ });
312
+ return new Set(recordRefs.map((ref) => JSON.stringify([ref.repository, ref.id]))).size !== recordRefs.length && fail("Ask Record references contain duplicates"), {
301
313
  kind: "ask",
302
314
  ...itemPresentation,
303
315
  questions,
316
+ tags,
317
+ recordRefs,
304
318
  recipients: [.../* @__PURE__ */ new Set([...extra, ...questions.flatMap((entry) => [entry.to, ...entry.allowedResponders])])]
305
319
  };
306
320
  }
@@ -335,7 +349,7 @@ function createInboxPublisher(transport) {
335
349
  return {
336
350
  async publishAsk(value, options) {
337
351
  let source = object(value, "ask");
338
- keys(source, ["title", "description", "recipients", "views", "body", "questions", "notifyImmediately"], "ask");
352
+ keys(source, ["title", "description", "recipients", "views", "body", "questions", "notifyImmediately", "tags", "recordRefs"], "ask");
339
353
  let result2 = await transport.publish({
340
354
  requestKey: publicationRequestKey(options),
341
355
  item: validatePublication({ ...source, kind: "ask" })
@@ -391,44 +405,44 @@ var FileOperationError = class extends Error {
391
405
  retryable;
392
406
  }, FILE_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, FILE_ORIGINAL_MAX_BYTES = 5 * 1024 ** 3;
393
407
  function parseFileDescriptor(value) {
394
- let invalid7 = () => {
408
+ let invalid8 = () => {
395
409
  throw new FileOperationError("unavailable", 503, !0);
396
410
  };
397
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
411
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
398
412
  let f = value;
399
- if (Object.keys(f).sort().join(",") !== "details,enrichments,id,mediaType,name,path,sha256,size" || typeof f.id != "string" || !FILE_ID_PATTERN.test(f.id) || !safeFileName(f.name) || !safeFilePath(f.path) || !Number.isSafeInteger(f.size) || f.size < 0 || f.size > FILE_ORIGINAL_MAX_BYTES || typeof f.sha256 != "string" || !/^[0-9a-f]{64}$/.test(f.sha256) || !f.enrichments || typeof f.enrichments != "object" || Array.isArray(f.enrichments) || !f.details || typeof f.details != "object" || Array.isArray(f.details)) return invalid7();
413
+ if (Object.keys(f).sort().join(",") !== "details,enrichments,id,mediaType,name,path,sha256,size" || typeof f.id != "string" || !FILE_ID_PATTERN.test(f.id) || !safeFileName(f.name) || !safeFilePath(f.path) || !Number.isSafeInteger(f.size) || f.size < 0 || f.size > FILE_ORIGINAL_MAX_BYTES || typeof f.sha256 != "string" || !/^[0-9a-f]{64}$/.test(f.sha256) || !f.enrichments || typeof f.enrichments != "object" || Array.isArray(f.enrichments) || !f.details || typeof f.details != "object" || Array.isArray(f.details)) return invalid8();
400
414
  let d = f.details;
401
415
  if (d.kind === "other") {
402
- if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return invalid7();
416
+ if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return invalid8();
403
417
  } else if (d.kind === "csv") {
404
- if (Object.keys(d).sort().join(",") !== "dataRows,delimiter,encoding,headerRow,kind" || f.mediaType !== "text/csv" || !["utf-8", "windows-1252"].includes(d.encoding) || ![",", ";", " "].includes(d.delimiter) || !Number.isSafeInteger(d.headerRow) || d.headerRow < 1 || !Number.isSafeInteger(d.dataRows) || d.dataRows < 0) return invalid7();
418
+ if (Object.keys(d).sort().join(",") !== "dataRows,delimiter,encoding,headerRow,kind" || f.mediaType !== "text/csv" || !["utf-8", "windows-1252"].includes(d.encoding) || ![",", ";", " "].includes(d.delimiter) || !Number.isSafeInteger(d.headerRow) || d.headerRow < 1 || !Number.isSafeInteger(d.dataRows) || d.dataRows < 0) return invalid8();
405
419
  } else if (d.kind === "pdf") {
406
- if (f.mediaType !== "application/pdf" || Object.keys(d).some((key) => !["kind", "pages"].includes(key)) || "pages" in d && (!Number.isSafeInteger(d.pages) || d.pages < 1)) return invalid7();
407
- } else return invalid7();
420
+ if (f.mediaType !== "application/pdf" || Object.keys(d).some((key) => !["kind", "pages"].includes(key)) || "pages" in d && (!Number.isSafeInteger(d.pages) || d.pages < 1)) return invalid8();
421
+ } else return invalid8();
408
422
  for (let [name, descriptor] of Object.entries(f.enrichments)) {
409
- if (!safeEnrichmentName(name)) return invalid7();
423
+ if (!safeEnrichmentName(name)) return invalid8();
410
424
  parseEnrichmentDescriptor(descriptor);
411
425
  }
412
- return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ? invalid7() : f;
426
+ return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ? invalid8() : f;
413
427
  }
414
428
  function parseEnrichmentDescriptor(value) {
415
- let invalid7 = () => {
429
+ let invalid8 = () => {
416
430
  throw new FileOperationError("unavailable", 503, !0);
417
431
  };
418
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
432
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
419
433
  let d = value;
420
- return Object.keys(d).sort().join(",") !== "mediaType,sha256,size" || !["application/octet-stream", "text/plain", "text/markdown", "application/json"].includes(d.mediaType) || !Number.isSafeInteger(d.size) || d.size < 0 || d.size > 16 * 1024 * 1024 || typeof d.sha256 != "string" || !/^[0-9a-f]{64}$/.test(d.sha256) ? invalid7() : d;
434
+ return Object.keys(d).sort().join(",") !== "mediaType,sha256,size" || !["application/octet-stream", "text/plain", "text/markdown", "application/json"].includes(d.mediaType) || !Number.isSafeInteger(d.size) || d.size < 0 || d.size > 16 * 1024 * 1024 || typeof d.sha256 != "string" || !/^[0-9a-f]{64}$/.test(d.sha256) ? invalid8() : d;
421
435
  }
422
436
  function safeEnrichmentName(value) {
423
437
  return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
424
438
  }
425
439
  function parseFileEnrichMetadata(value, maxBytes) {
426
- let invalid7 = () => {
440
+ let invalid8 = () => {
427
441
  throw new FileOperationError("invalid_input", 400);
428
442
  };
429
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
443
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
430
444
  let d = value;
431
- if (Object.keys(d).some((key) => !["name", "size", "mediaType", "replace"].includes(key)) || !safeEnrichmentName(d.name) || !Number.isSafeInteger(d.size) || d.size < 0 || d.mediaType !== void 0 && (typeof d.mediaType != "string" || d.mediaType.length > 255 || /[\u0000-\u001f\u007f]/.test(d.mediaType)) || d.replace !== void 0 && (typeof d.replace != "string" || !/^[0-9a-f]{64}$/.test(d.replace))) return invalid7();
445
+ if (Object.keys(d).some((key) => !["name", "size", "mediaType", "replace"].includes(key)) || !safeEnrichmentName(d.name) || !Number.isSafeInteger(d.size) || d.size < 0 || d.mediaType !== void 0 && (typeof d.mediaType != "string" || d.mediaType.length > 255 || /[\u0000-\u001f\u007f]/.test(d.mediaType)) || d.replace !== void 0 && (typeof d.replace != "string" || !/^[0-9a-f]{64}$/.test(d.replace))) return invalid8();
432
446
  if (d.size > maxBytes) throw new FileOperationError("request_too_large", 413);
433
447
  return d;
434
448
  }
@@ -439,23 +453,23 @@ function safeFilePath(value) {
439
453
  return typeof value == "string" && value.length <= 1024 && value.split("/").every(safeFileName);
440
454
  }
441
455
  function parseFileCreateMetadata(value, maxBytes) {
442
- let invalid7 = () => {
456
+ let invalid8 = () => {
443
457
  throw new FileOperationError("invalid_input", 400);
444
458
  };
445
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
459
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
446
460
  let input = value;
447
- if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "inputMediaType", "size", "requestKey"].includes(key))) return invalid7();
461
+ if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "inputMediaType", "size", "requestKey"].includes(key))) return invalid8();
448
462
  let path = input.path === void 0 ? "Files" : input.path;
449
- if (!safeFileName(input.name) || !safeFilePath(path) || path.split("/")[0].toLowerCase() === ".os" || input.storage !== void 0 && input.storage !== "remote" && input.storage !== "local" || input.inputMediaType !== void 0 && input.inputMediaType !== "application/pdf" || !Number.isSafeInteger(input.size) || input.size < 0) return invalid7();
463
+ if (!safeFileName(input.name) || !safeFilePath(path) || path.split("/")[0].toLowerCase() === ".os" || input.storage !== void 0 && input.storage !== "remote" && input.storage !== "local" || input.inputMediaType !== void 0 && input.inputMediaType !== "application/pdf" || !Number.isSafeInteger(input.size) || input.size < 0) return invalid8();
450
464
  if (input.size > maxBytes) throw new FileOperationError("request_too_large", 413);
451
- if (typeof input.requestKey != "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey)) return invalid7();
465
+ if (typeof input.requestKey != "string" || input.requestKey.length < 1 || input.requestKey.length > 256 || input.requestKey !== input.requestKey.trim() || /[\u0000-\u001f\u007f]/.test(input.requestKey)) return invalid8();
452
466
  let csv;
453
467
  if (input.csv !== void 0) {
454
- if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return invalid7();
468
+ if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return invalid8();
455
469
  let hints = input.csv;
456
- if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return invalid7();
470
+ if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return invalid8();
457
471
  let encoding = hints.encoding === void 0 ? "utf-8" : hints.encoding, delimiter = hints.delimiter === void 0 ? "," : hints.delimiter, headerRow = hints.headerRow === void 0 ? 1 : hints.headerRow;
458
- if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return invalid7();
472
+ if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return invalid8();
459
473
  csv = { encoding, delimiter, headerRow };
460
474
  }
461
475
  return {
@@ -517,8 +531,9 @@ function parseAppRoutineContract(value) {
517
531
  case "array":
518
532
  return !fields2(value2, ["type", "items", "maxItems"]) || !Number.isSafeInteger(value2.maxItems) || value2.maxItems < 1 || value2.maxItems > 64 ? invalidContract() : { type: "array", items: schema2(value2.items, depth + 1), maxItems: value2.maxItems };
519
533
  case "boolean":
520
- case "file":
521
534
  return fields2(value2, ["type"]) ? { type: value2.type } : invalidContract();
535
+ case "file":
536
+ return !fields2(value2, ["type"], ["storage"]) || owns(value2, "storage") && value2.storage !== "local" && value2.storage !== "remote" ? invalidContract() : { type: "file", ...owns(value2, "storage") ? { storage: value2.storage } : {} };
522
537
  case "string":
523
538
  return !fields2(value2, ["type"], ["maxLength"]) || owns(value2, "maxLength") && (!Number.isSafeInteger(value2.maxLength) || value2.maxLength < 0 || value2.maxLength > 4096) ? invalidContract() : { type: "string", ...owns(value2, "maxLength") ? { maxLength: value2.maxLength } : {} };
524
539
  case "integer":
@@ -716,7 +731,7 @@ var schema = {
716
731
  boolean() {
717
732
  return declaration({ type: "boolean" });
718
733
  }
719
- }, file = () => declaration({ type: "file" }), definitions = /* @__PURE__ */ new WeakMap(), defineRoutine = (definition) => {
734
+ }, file = (options = {}) => (assertRoutineFields(options, ["storage"]), declaration({ type: "file", ...options })), definitions = /* @__PURE__ */ new WeakMap(), defineRoutine = (definition) => {
720
735
  if (assertRoutineFields(definition, ["id", "title", "input", "steps", "result", "access", "responses", "run"]), !isAppRoutineName(definition.id) || definition.title !== void 0 && !routineTitle(definition.title) || typeof definition.run != "function") return invalidContract3();
721
736
  let input = definition.input === void 0 ? { schema: empty, default: {} } : schemaMetadata(definition.input), result2 = definition.result === void 0 ? void 0 : schemaMetadata(definition.result).schema, access = parseRoutineAccess(definition.access);
722
737
  assertRoutineFields(definition.steps ?? {});
@@ -795,6 +810,12 @@ async function executeRoutineDefinition(definition, input, runtime) {
795
810
  ...guarded({
796
811
  ...runtime,
797
812
  run: freezeRoutineMetadata({ ...runtime.run }),
813
+ connections: { ...runtime.connections, get: async (identity) => {
814
+ if (!active2 || broken || !contract.access.connections?.includes(identity)) throw new Error("Connection unavailable");
815
+ let value = await runtime.connections.get(identity);
816
+ if (!active2 || broken) throw new Error("Run authority ended");
817
+ return value;
818
+ } },
798
819
  inbox: { ...runtime.inbox, publishAsk: (value, options) => runtime.inbox.publishAsk(qualify(value), options) }
799
820
  }),
800
821
  step(id3, ...input2) {
@@ -936,6 +957,15 @@ function captureRecordsSearchInput(query, options) {
936
957
  return { query, options: captured };
937
958
  }
938
959
 
960
+ function captureRecordsReadRefs(value) {
961
+ if (!Array.isArray(value) || value.length < 1 || value.length > 100)
962
+ throw new DataOperationError("invalid_query");
963
+ let refs = historyArray(value);
964
+ if (!refs.every((ref) => validRecordRef(ref) && !/[\r\n]/.test(ref)) || new Set(refs).size !== refs.length)
965
+ throw new DataOperationError("invalid_query");
966
+ return refs;
967
+ }
968
+
939
969
  var DATA_REQUEST_LIMIT = 256 * 1024, invalidChange = () => {
940
970
  throw new DataOperationError("invalid_change", !1, "unapplied");
941
971
  };
@@ -1029,16 +1059,16 @@ function routineTransport() {
1029
1059
  return installed;
1030
1060
  }
1031
1061
 
1032
- var memberContext;
1033
- function installMemberContext(resolve) {
1034
- return memberContext = resolve, () => {
1035
- memberContext === resolve && (memberContext = void 0);
1062
+ var memberContext, retainedContext;
1063
+ function installMemberContext(resolve, retained = resolve) {
1064
+ return memberContext = resolve, retainedContext = retained, () => {
1065
+ memberContext === resolve && (memberContext = void 0, retainedContext = void 0);
1036
1066
  };
1037
1067
  }
1038
- async function resolveAppContext() {
1068
+ async function resolveAppContext(retained = !1) {
1039
1069
  let host = memberContext;
1040
1070
  if (!host) throw new Error("App context unavailable.");
1041
- let context2 = await host();
1071
+ let context2 = await (retained ? retainedContext : host)();
1042
1072
  if (host !== memberContext || !context2.isCurrent() || context2.expiresAt <= Date.now() || context2.kind !== "local" && (typeof context2.accessToken != "string" || !/^[^\s]{1,8192}$/.test(context2.accessToken)))
1043
1073
  throw new Error("App context unavailable.");
1044
1074
  return context2;
@@ -1063,13 +1093,22 @@ async function resolveFilesContext() {
1063
1093
  let environment = {}, host = memberContext;
1064
1094
  if (host) {
1065
1095
  let context2 = await host();
1066
- if (context2.kind === "local") throw new Error();
1096
+ if (host !== memberContext || !context2.isCurrent() || context2.expiresAt <= Date.now()) throw new Error();
1097
+ if (context2.kind === "local") return {
1098
+ url: `private:app:${context2.workspace}/${context2.memberId}`,
1099
+ headers: {},
1100
+ isCurrent: context2.isCurrent,
1101
+ signal: context2.signal,
1102
+ local: void 0,
1103
+ localFiles: context2.requestFiles
1104
+ };
1067
1105
  if (!Number.isFinite(context2.expiresAt) || context2.expiresAt <= Date.now() || typeof context2.accessToken != "string" || !/^[^\s]{1,8192}$/.test(context2.accessToken)) throw new Error();
1068
1106
  return {
1069
1107
  ...filesContext(context2.workspace, context2.endpoint, { authorization: `Bearer ${context2.accessToken}` }),
1070
1108
  isCurrent: context2.isCurrent,
1071
1109
  local: void 0,
1072
- localFiles: void 0
1110
+ localFiles: void 0,
1111
+ signal: void 0
1073
1112
  };
1074
1113
  }
1075
1114
  throw new Error();
@@ -1079,14 +1118,102 @@ async function resolveFilesContext() {
1079
1118
  }
1080
1119
  function filesContext(workspace, endpoint, headers) {
1081
1120
  if (!workspace || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(workspace) || workspace.length > 63 || ["auth", "www", "api", "os"].includes(workspace) || endpoint !== `https://${workspace}.oddington.ai`) throw new Error();
1082
- return { url: `${endpoint}/api/files`, headers: { ...headers, "x-oddington-workspace": workspace }, isCurrent: () => !0 };
1121
+ return { url: `${endpoint}/api/files`, headers: { ...headers, "x-os-workspace": workspace }, isCurrent: () => !0 };
1083
1122
  }
1084
1123
  function checked(workspace, endpoint, headers) {
1085
1124
  if (!workspace || !/^[a-z0-9][a-z0-9-]{0,127}$/.test(workspace)) throw new Error();
1086
1125
  let origin = new URL(endpoint);
1087
1126
  if (origin.protocol !== "https:" || origin.username || origin.password || origin.search || origin.hash || origin.pathname !== "/")
1088
1127
  throw new Error();
1089
- return { url: `${origin.origin}/api/data`, headers: { ...headers, "x-oddington-workspace": workspace } };
1128
+ return { url: `${origin.origin}/api/data`, headers: { ...headers, "x-os-workspace": workspace } };
1129
+ }
1130
+
1131
+ var invalid6 = () => {
1132
+ throw new DataOperationError("invalid_query");
1133
+ }, unavailable = () => {
1134
+ throw new DataOperationError("unavailable");
1135
+ }, text2 = (value) => typeof value == "string" && value.length > 0;
1136
+ function capture2(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
1137
+ if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return value;
1138
+ if (!value || typeof value != "object" || ancestors.has(value) || depth > 32) return invalid6();
1139
+ ancestors.add(value);
1140
+ try {
1141
+ return Array.isArray(value) ? historyArray(value).map((item) => capture2(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture2(descriptor.value, ancestors, depth + 1)]));
1142
+ } finally {
1143
+ ancestors.delete(value);
1144
+ }
1145
+ }
1146
+ function recordPagination(select) {
1147
+ function pages(query) {
1148
+ let captured = capture2(query), names = Object.keys(historyProperties(captured));
1149
+ for (let name of names) {
1150
+ let selection2 = historyProperties(captured[name]);
1151
+ if (Object.hasOwn(selection2, "$")) {
1152
+ let options = historyProperties(selection2.$.value);
1153
+ if (Object.hasOwn(options, "after")) return invalid6();
1154
+ }
1155
+ }
1156
+ return iterate();
1157
+ async function* iterate() {
1158
+ let state = new Map(names.map((name) => [name, {
1159
+ seen: /* @__PURE__ */ new Set(),
1160
+ total: 0,
1161
+ count: void 0,
1162
+ next: void 0
1163
+ }])), active2 = names, version;
1164
+ do {
1165
+ let request2 = Object.fromEntries(active2.map((name) => {
1166
+ let selection2 = captured[name], next = state.get(name).next;
1167
+ return [name, next === void 0 ? selection2 : { ...selection2, $: { ...selection2.$, after: next } }];
1168
+ })), response2 = await select(request2), page;
1169
+ try {
1170
+ page = capture2(response2);
1171
+ let keys4 = Object.keys(historyProperties(page));
1172
+ (keys4.length !== active2.length + 1 || keys4.some((key) => key !== "$meta" && !active2.includes(key))) && unavailable();
1173
+ let meta = page.$meta;
1174
+ (Object.keys(historyProperties(meta)).sort().join(",") !== "collections,version" || !text2(meta.version) || version !== void 0 && version !== meta.version) && unavailable(), version = meta.version, Object.keys(historyProperties(meta.collections)).some((key) => !active2.includes(key)) && unavailable();
1175
+ for (let name of active2) {
1176
+ let records = historyArray(page[name]), metadata = Object.hasOwn(meta.collections, name) ? meta.collections[name] : {};
1177
+ (Object.keys(historyProperties(metadata)).some((key) => key !== "count" && key !== "next") || Object.hasOwn(metadata, "next") && !text2(metadata.next)) && unavailable();
1178
+ for (let record3 of records) {
1179
+ historyProperties(record3);
1180
+ let row = record3;
1181
+ (!validRecordRef(row.$ref) || !text2(row.$version)) && unavailable();
1182
+ }
1183
+ let current2 = state.get(name);
1184
+ captured[name].$?.count === !0 ? ((!Number.isSafeInteger(metadata.count) || metadata.count < 0 || current2.count !== void 0 && current2.count !== metadata.count) && unavailable(), current2.count = metadata.count) : Object.hasOwn(metadata, "count") && unavailable(), current2.total += records.length, (!Number.isSafeInteger(current2.total) || current2.count !== void 0 && (current2.total > current2.count || metadata.next === void 0 && current2.total !== current2.count)) && unavailable(), metadata.next !== void 0 && (current2.seen.has(metadata.next) && unavailable(), current2.seen.add(metadata.next)), current2.next = metadata.next;
1185
+ }
1186
+ } catch {
1187
+ return unavailable();
1188
+ }
1189
+ let collections = Object.fromEntries(names.map((name) => {
1190
+ let current2 = state.get(name);
1191
+ return [name, {
1192
+ ...current2.count === void 0 ? {} : { count: current2.count },
1193
+ ...current2.next === void 0 ? {} : { next: current2.next }
1194
+ }];
1195
+ })), output = Object.fromEntries(names.map((name) => [name, active2.includes(name) ? page[name] : []]));
1196
+ active2 = active2.filter((name) => state.get(name).next !== void 0), yield { ...output, $meta: { version, collections } };
1197
+ } while (active2.length);
1198
+ }
1199
+ }
1200
+ async function all(query, options) {
1201
+ let properties = historyProperties(options), maxRecords = properties.maxRecords?.value;
1202
+ (Object.keys(properties).join(",") !== "maxRecords" || !Number.isSafeInteger(maxRecords) || maxRecords < 1) && invalid6();
1203
+ let result2, total = 0;
1204
+ for await (let page of pages(query)) {
1205
+ let names = Object.keys(page.$meta.collections), size = names.reduce((sum, name) => sum + page[name].length, 0);
1206
+ if (size > maxRecords - total) throw new DataOperationError("capacity");
1207
+ total += size, result2 ??= { ...Object.fromEntries(names.map((name) => [name, []])), $meta: page.$meta };
1208
+ for (let name of names) {
1209
+ let target = result2[name];
1210
+ for (let record3 of page[name]) target.push(record3);
1211
+ }
1212
+ result2.$meta = page.$meta;
1213
+ }
1214
+ return result2;
1215
+ }
1216
+ return { pages, all };
1090
1217
  }
1091
1218
 
1092
1219
  var data = {
@@ -1109,13 +1236,20 @@ var data = {
1109
1236
  throw error instanceof DataOperationError ? error : new DataOperationError("unavailable", !0);
1110
1237
  }
1111
1238
  }
1239
+ async function read2(input) {
1240
+ let refs = captureRecordsReadRefs(typeof input == "string" ? [input] : input), result2 = await send3({ operation: "records.read", refs });
1241
+ return typeof input == "string" ? result2.records[0] : result2;
1242
+ }
1243
+ let select = (query) => send3({ operation: "records.select", query });
1112
1244
  return {
1113
1245
  collections: {
1114
1246
  list: () => send3({ operation: "collections.list" }),
1115
1247
  schema: (name) => send3({ operation: "collections.schema", name })
1116
1248
  },
1117
1249
  records: {
1118
- select: (query) => send3({ operation: "records.select", query }),
1250
+ read: read2,
1251
+ select,
1252
+ ...recordPagination(select),
1119
1253
  search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
1120
1254
  },
1121
1255
  history: {
@@ -1182,7 +1316,65 @@ var data = {
1182
1316
  }
1183
1317
  };
1184
1318
 
1185
- var MAX_BYTES = 16 * 1024 * 1024, PART_BYTES = 8 * 1024 * 1024, METADATA_BYTES = 4096, RESULT_BYTES = 16 * 1024, CONTROL_RESULT_BYTES = 128 * 1024, TIMEOUT_MS = 3e4, MAX_ACTIVE = 4, ATTEMPTS = 2, active = 0, invalid6 = () => new FileOperationError("invalid_input", 400), unavailable = () => new FileOperationError("unavailable", 503, !0), failures = {
1319
+ async function hostedContent(url, init2, parent, upstream = fetch, check = async () => {
1320
+ }, failure) {
1321
+ let delivery = new AbortController(), abort = () => delivery.abort(parent.reason);
1322
+ parent.addEventListener("abort", abort, { once: !0 }), parent.aborted && abort();
1323
+ let detach = () => parent.removeEventListener("abort", abort);
1324
+ try {
1325
+ let response2 = await upstream(url, { ...init2, signal: delivery.signal });
1326
+ try {
1327
+ if (await check(), delivery.signal.aborted) throw failure?.() ?? new FileOperationError("unavailable", 503, !0);
1328
+ } catch (error) {
1329
+ throw response2.body?.cancel().catch(() => {
1330
+ }), error;
1331
+ }
1332
+ if (!response2.body)
1333
+ return detach(), response2;
1334
+ let source = response2.body, reader, settled = !1, output, cancel = async (reason) => {
1335
+ if (!settled) {
1336
+ settled = !0, detach(), delivery.signal.removeEventListener("abort", stop), delivery.abort(reason);
1337
+ try {
1338
+ await (reader ? reader.cancel(reason) : source.cancel(reason));
1339
+ } catch (error) {
1340
+ if (error !== delivery.signal.reason && !(error instanceof Error && error.name === "AbortError")) throw error;
1341
+ } finally {
1342
+ reader?.releaseLock();
1343
+ }
1344
+ }
1345
+ }, stop = () => {
1346
+ if (settled) return;
1347
+ let error = failure?.() ?? delivery.signal.reason;
1348
+ cancel(error).catch(() => {
1349
+ }), output.error(error);
1350
+ }, body = new ReadableStream({
1351
+ start(controller) {
1352
+ output = controller, delivery.signal.addEventListener("abort", stop, { once: !0 }), delivery.signal.aborted && stop();
1353
+ },
1354
+ async pull(controller) {
1355
+ try {
1356
+ if (await check(), settled) return;
1357
+ reader ??= source.getReader();
1358
+ let { done, value } = await reader.read();
1359
+ if (await check(), settled) return;
1360
+ done ? (settled = !0, detach(), delivery.signal.removeEventListener("abort", stop), reader.releaseLock(), controller.close()) : controller.enqueue(value);
1361
+ } catch (error) {
1362
+ if (settled) return;
1363
+ controller.error(failure?.() ?? error), await cancel(error).catch(() => {
1364
+ });
1365
+ }
1366
+ },
1367
+ cancel
1368
+ }, { highWaterMark: 0 }), wrapped = new Response(body, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
1369
+ for (let key of ["url", "redirected", "type"])
1370
+ Object.defineProperty(wrapped, key, { value: response2[key] });
1371
+ return wrapped;
1372
+ } catch (error) {
1373
+ throw detach(), delivery.abort(error), error;
1374
+ }
1375
+ }
1376
+
1377
+ var MAX_BYTES = 16 * 1024 * 1024, PART_BYTES = 8 * 1024 * 1024, METADATA_BYTES = 4096, RESULT_BYTES = 16 * 1024, CONTROL_RESULT_BYTES = 128 * 1024, TIMEOUT_MS = 3e4, MAX_ACTIVE = 4, ATTEMPTS = 2, active = 0, invalid7 = () => new FileOperationError("invalid_input", 400), unavailable2 = () => new FileOperationError("unavailable", 503, !0), failures = {
1186
1378
  400: ["invalid_input", "unsupported_context"],
1187
1379
  401: ["unauthenticated"],
1188
1380
  403: ["access_denied"],
@@ -1192,26 +1384,33 @@ var MAX_BYTES = 16 * 1024 * 1024, PART_BYTES = 8 * 1024 * 1024, METADATA_BYTES =
1192
1384
  429: ["capacity"],
1193
1385
  503: ["integrity", "unavailable"]
1194
1386
  };
1195
- async function boundedBytes(stream, limit) {
1387
+ async function boundedBytes(stream, limit, signal) {
1196
1388
  if (!stream) return new Uint8Array();
1197
- let reader = stream.getReader(), bytes = new Uint8Array(limit), size = 0;
1389
+ let reader = stream.getReader(), bytes = new Uint8Array(limit), size = 0, cancel = () => {
1390
+ reader.cancel().catch(() => {
1391
+ });
1392
+ };
1393
+ signal?.addEventListener("abort", cancel, { once: !0 }), signal?.aborted && cancel();
1198
1394
  try {
1199
1395
  for (; ; ) {
1200
1396
  let { done, value } = await reader.read();
1397
+ if (signal?.aborted) throw unavailable2();
1201
1398
  if (done) break;
1202
- if (!(value instanceof Uint8Array)) throw invalid6();
1399
+ if (!(value instanceof Uint8Array)) throw invalid7();
1203
1400
  if (size += value.byteLength, size > limit) throw new FileOperationError("request_too_large", 413);
1204
1401
  bytes.set(value, size - value.byteLength);
1205
1402
  }
1403
+ } catch (error) {
1404
+ throw cancel(), error;
1206
1405
  } finally {
1207
- reader.releaseLock();
1406
+ signal?.removeEventListener("abort", cancel), reader.releaseLock();
1208
1407
  }
1209
1408
  return bytes.slice(0, size);
1210
1409
  }
1211
1410
  async function timed(work, parent, timeout = TIMEOUT_MS) {
1212
1411
  let controller = new AbortController(), timer, abort, expiry = new Promise((_, reject) => {
1213
1412
  abort = () => {
1214
- controller.abort(), reject(unavailable());
1413
+ controller.abort(), reject(unavailable2());
1215
1414
  }, timer = setTimeout(abort, timeout), parent?.addEventListener("abort", abort, { once: !0 }), parent?.aborted && abort();
1216
1415
  });
1217
1416
  try {
@@ -1225,56 +1424,12 @@ async function result(response2, maximum = RESULT_BYTES) {
1225
1424
  let bytes = await boundedBytes(response2.body, maximum);
1226
1425
  return JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes));
1227
1426
  } catch {
1228
- throw unavailable();
1229
- }
1230
- }
1231
- async function hostedContent(url, init2, parent, upstream = fetch) {
1232
- let delivery = new AbortController(), abort = () => delivery.abort(parent.reason);
1233
- parent.addEventListener("abort", abort, { once: !0 }), parent.aborted && abort();
1234
- let detach = () => parent.removeEventListener("abort", abort);
1235
- try {
1236
- let response2 = await upstream(url, { ...init2, signal: delivery.signal });
1237
- if (delivery.signal.aborted)
1238
- throw response2.body?.cancel().catch(() => {
1239
- }), unavailable();
1240
- if (!response2.body)
1241
- return detach(), response2;
1242
- let source = response2.body, reader, settled = !1, cancel = async (reason) => {
1243
- if (!settled) {
1244
- settled = !0, detach(), delivery.abort(reason);
1245
- try {
1246
- await (reader ? reader.cancel(reason) : source.cancel(reason));
1247
- } catch (error) {
1248
- if (error !== delivery.signal.reason && !(error instanceof Error && error.name === "AbortError")) throw error;
1249
- } finally {
1250
- reader?.releaseLock();
1251
- }
1252
- }
1253
- }, body = new ReadableStream({
1254
- async pull(controller) {
1255
- try {
1256
- reader ??= source.getReader();
1257
- let { done, value } = await reader.read();
1258
- if (settled) return;
1259
- done ? (settled = !0, detach(), reader.releaseLock(), controller.close()) : controller.enqueue(value);
1260
- } catch (error) {
1261
- if (settled) return;
1262
- controller.error(error), await cancel(error).catch(() => {
1263
- });
1264
- }
1265
- },
1266
- cancel
1267
- }, { highWaterMark: 0 }), wrapped = new Response(body, { status: response2.status, statusText: response2.statusText, headers: response2.headers });
1268
- for (let key of ["url", "redirected", "type"])
1269
- Object.defineProperty(wrapped, key, { value: response2[key] });
1270
- return wrapped;
1271
- } catch (error) {
1272
- throw detach(), delivery.abort(error), error;
1427
+ throw unavailable2();
1273
1428
  }
1274
1429
  }
1275
1430
  async function send(suffix, init2, descriptor, initial, parent) {
1276
1431
  let original = initial, checkCurrent = (context2 = original) => {
1277
- if (parent?.aborted) throw unavailable();
1432
+ if (parent?.aborted) throw unavailable2();
1278
1433
  if (!original.isCurrent() || context2.url !== original.url) throw new FileOperationError("unsupported_context", 400);
1279
1434
  };
1280
1435
  for (let attempt = 0; attempt < ATTEMPTS; attempt++) {
@@ -1282,7 +1437,7 @@ async function send(suffix, init2, descriptor, initial, parent) {
1282
1437
  let context2 = await resolveFilesContext();
1283
1438
  checkCurrent(context2);
1284
1439
  try {
1285
- let response2 = await (async () => {
1440
+ let response2 = context2.localFiles ? await context2.localFiles(suffix, init2, parent) : await (async () => {
1286
1441
  let url = `${context2.url}${suffix}`, request2 = {
1287
1442
  ...init2,
1288
1443
  signal: parent,
@@ -1294,11 +1449,11 @@ async function send(suffix, init2, descriptor, initial, parent) {
1294
1449
  })();
1295
1450
  if (!response2.ok) {
1296
1451
  let value2 = await result(response2), error = value2 && typeof value2 == "object" && "error" in value2 ? value2.error : void 0, received = error && typeof error == "object" && "code" in error ? error.code : void 0, code = failures[response2.status]?.find((code2) => code2 === received);
1297
- throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable();
1452
+ throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable2();
1298
1453
  }
1299
1454
  if (response2.status !== (descriptor === 204 ? 204 : 200) || descriptor === 204 && response2.body !== null)
1300
1455
  throw response2.body?.cancel().catch(() => {
1301
- }), unavailable();
1456
+ }), unavailable2();
1302
1457
  try {
1303
1458
  checkCurrent();
1304
1459
  } catch (error) {
@@ -1312,21 +1467,21 @@ async function send(suffix, init2, descriptor, initial, parent) {
1312
1467
  return checkCurrent(), value;
1313
1468
  let parsed;
1314
1469
  if (descriptor === "enrichment") {
1315
- if (!value || typeof value != "object" || Array.isArray(value)) throw unavailable();
1470
+ if (!value || typeof value != "object" || Array.isArray(value)) throw unavailable2();
1316
1471
  let { name, ...metadata } = value;
1317
- if (!safeEnrichmentName(name)) throw unavailable();
1472
+ if (!safeEnrichmentName(name)) throw unavailable2();
1318
1473
  parsed = { name, ...parseEnrichmentDescriptor(metadata) };
1319
1474
  } else parsed = parseFileDescriptor(value);
1320
1475
  return checkCurrent(), parsed;
1321
1476
  } catch (error) {
1322
- let failure = error instanceof FileOperationError ? error : unavailable();
1477
+ let failure = error instanceof FileOperationError ? error : unavailable2();
1323
1478
  if (init2.body instanceof ReadableStream || !failure.retryable || attempt + 1 === ATTEMPTS) throw failure;
1324
1479
  }
1325
1480
  }
1326
- throw unavailable();
1481
+ throw unavailable2();
1327
1482
  }
1328
1483
  function idPath(id3) {
1329
- if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid6();
1484
+ if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid7();
1330
1485
  return `/${id3}`;
1331
1486
  }
1332
1487
  async function multipartCreate(input, metadata, exchange, release = () => {
@@ -1337,18 +1492,18 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1337
1492
  return pending.add(task), task.then(() => pending.delete(task), () => pending.delete(task)), task;
1338
1493
  }, void 0, timeout), control = (body) => ({
1339
1494
  method: "POST",
1340
- headers: { "content-type": "application/json", ...ticket ? { "x-oddington-transfer": ticket } : {} },
1495
+ headers: { "content-type": "application/json", ...ticket ? { "x-os-transfer": ticket } : {} },
1341
1496
  body: JSON.stringify(body)
1342
1497
  });
1343
1498
  try {
1344
1499
  let start = await request2((signal) => exchange(`${route}/start`, control(upload?.file ?? metadata), "control", signal));
1345
- if (!start || typeof start != "object" || Array.isArray(start)) throw unavailable();
1500
+ if (!start || typeof start != "object" || Array.isArray(start)) throw unavailable2();
1346
1501
  let session = start;
1347
- if (Object.keys(session).sort().join(",") !== "partBytes,ticket" || session.partBytes !== PART_BYTES || typeof session.ticket != "string" || !session.ticket || session.ticket.length > 64 * 1024) throw unavailable();
1502
+ if (Object.keys(session).sort().join(",") !== "partBytes,ticket" || session.partBytes !== PART_BYTES || typeof session.ticket != "string" || !session.ticket || session.ticket.length > 64 * 1024) throw unavailable2();
1348
1503
  ticket = session.ticket, input.file instanceof ReadableStream && (reader = input.file.getReader());
1349
1504
  let lastProgress = Date.now(), next = async () => {
1350
1505
  try {
1351
- if (Date.now() - lastProgress >= TIMEOUT_MS) throw unavailable();
1506
+ if (Date.now() - lastProgress >= TIMEOUT_MS) throw unavailable2();
1352
1507
  let value = await request2(() => reader.read(), Math.max(1, TIMEOUT_MS - (Date.now() - lastProgress)));
1353
1508
  return value.value?.byteLength && (lastProgress = Date.now()), value;
1354
1509
  } catch (error) {
@@ -1369,41 +1524,41 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1369
1524
  if (!chunk || offset === chunk.byteLength) {
1370
1525
  chunk = void 0, offset = 0;
1371
1526
  let value2 = await next();
1372
- if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw invalid6();
1527
+ if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw invalid7();
1373
1528
  }
1374
1529
  let take = Math.min(length - filled, chunk.byteLength - offset);
1375
1530
  part.set(chunk.subarray(offset, offset + take), filled), filled += take, offset += take, offset === chunk.byteLength && (chunk = void 0, offset = 0);
1376
1531
  }
1377
1532
  }
1378
- if (part.byteLength !== length) throw invalid6();
1533
+ if (part.byteLength !== length) throw invalid7();
1379
1534
  if (reader && sent + length === metadata.size)
1380
1535
  for (lastProgress = Date.now(); ; ) {
1381
1536
  let value2 = await next();
1382
1537
  if (value2.done) break;
1383
- if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid6();
1538
+ if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid7();
1384
1539
  }
1385
1540
  let value = await request2((signal) => exchange(`${route}/part`, {
1386
1541
  method: "POST",
1387
- headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket, "x-oddington-part": String(partNumber) },
1542
+ headers: { "content-type": "application/octet-stream", "x-os-transfer": ticket, "x-os-part": String(partNumber) },
1388
1543
  body: part.buffer
1389
1544
  }, "control", signal));
1390
1545
  part = void 0;
1391
1546
  let receipt = value;
1392
- if (!receipt || typeof receipt != "object" || Object.keys(receipt).sort().join(",") !== "etag,partNumber" || receipt.partNumber !== partNumber || typeof receipt.etag != "string" || !receipt.etag || receipt.etag.length > 256 || /[\u0000-\u001f\u007f]/.test(receipt.etag)) throw unavailable();
1547
+ if (!receipt || typeof receipt != "object" || Object.keys(receipt).sort().join(",") !== "etag,partNumber" || receipt.partNumber !== partNumber || typeof receipt.etag != "string" || !receipt.etag || receipt.etag.length > 256 || /[\u0000-\u001f\u007f]/.test(receipt.etag)) throw unavailable2();
1393
1548
  receipts.push({ partNumber, etag: receipt.etag }), sent += length, lastProgress = Date.now();
1394
1549
  }
1395
1550
  if (upload) for (let name of Object.keys(upload.file.enrichments)) {
1396
1551
  let bytes = await request2(() => upload.enrichment(name));
1397
- if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw invalid6();
1552
+ if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw invalid7();
1398
1553
  await request2((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
1399
1554
  method: "POST",
1400
- headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
1555
+ headers: { "content-type": "application/octet-stream", "x-os-transfer": ticket },
1401
1556
  body: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)
1402
1557
  }, "control", signal));
1403
1558
  }
1404
1559
  await upload?.beforeComplete();
1405
1560
  let completion = control({ parts: receipts });
1406
- if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable();
1561
+ if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable2();
1407
1562
  return parseFileDescriptor(await request2(
1408
1563
  (signal) => exchange(`${route}/complete`, completion, !0, signal),
1409
1564
  TIMEOUT_MS + Math.ceil(metadata.size / (1024 * 1024)) * 1e3
@@ -1411,7 +1566,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1411
1566
  } catch (error) {
1412
1567
  throw reader && await reader.cancel(error).catch(() => {
1413
1568
  }), ticket && await request2((signal) => exchange(`${route}/abort`, control({}), "control", signal)).catch(() => {
1414
- }), error instanceof FileOperationError ? error : unavailable();
1569
+ }), error instanceof FileOperationError ? error : unavailable2();
1415
1570
  } finally {
1416
1571
  chunk = void 0, reader?.releaseLock(), pending.size ? Promise.allSettled([...pending]).then(release) : release();
1417
1572
  }
@@ -1419,20 +1574,22 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1419
1574
  async function operation(work, initial, parent) {
1420
1575
  let context2 = initial ?? await resolveFilesContext();
1421
1576
  if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
1422
- return active++, timed(async (signal) => {
1577
+ active++;
1578
+ let execute = async (signal2) => {
1423
1579
  try {
1424
- return await work(context2, signal);
1580
+ return await work(context2, signal2);
1425
1581
  } finally {
1426
1582
  active--;
1427
1583
  }
1428
- }, parent).catch((error) => {
1429
- throw error instanceof FileOperationError ? error : unavailable();
1584
+ }, signal = context2.signal && parent ? AbortSignal.any([context2.signal, parent]) : context2.signal ?? parent;
1585
+ return context2.localFiles ? execute(signal ?? new AbortController().signal) : timed(execute, signal).catch((error) => {
1586
+ throw error instanceof FileOperationError ? error : unavailable2();
1430
1587
  });
1431
1588
  }
1432
1589
  function contentPath(id3, name) {
1433
1590
  let path = idPath(id3);
1434
1591
  if (name === void 0) return `${path}/content`;
1435
- if (!safeEnrichmentName(name)) throw invalid6();
1592
+ if (!safeEnrichmentName(name)) throw invalid7();
1436
1593
  return `${path}/enrichments/${encodeURIComponent(name)}/content`;
1437
1594
  }
1438
1595
  async function read(id3, names) {
@@ -1441,12 +1598,12 @@ async function read(id3, names) {
1441
1598
  let path = contentPath(id3, names);
1442
1599
  return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
1443
1600
  }
1444
- if (!Array.isArray(names)) throw invalid6();
1601
+ if (!Array.isArray(names)) throw invalid7();
1445
1602
  let distinct = [], seen = /* @__PURE__ */ new Set();
1446
1603
  for (let name of names) {
1447
- if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid6();
1604
+ if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid7();
1448
1605
  if (!seen.has(name)) {
1449
- if (seen.size === 16) throw invalid6();
1606
+ if (seen.size === 16) throw invalid7();
1450
1607
  seen.add(name), distinct.push(name);
1451
1608
  }
1452
1609
  }
@@ -1474,18 +1631,18 @@ var files = {
1474
1631
  async upload(id3) {
1475
1632
  return operation(async (context2, signal) => {
1476
1633
  let file2 = await send(`${idPath(id3)}/upload`, { method: "POST" }, !0, context2, signal);
1477
- if (file2.id !== id3) throw unavailable();
1634
+ if (file2.id !== id3) throw unavailable2();
1478
1635
  return file2;
1479
1636
  });
1480
1637
  },
1481
1638
  async create(input, options) {
1482
1639
  let context2 = await resolveFilesContext();
1483
1640
  if (!input || typeof input != "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "size", "path", "name", "storage", "csv"].includes(key)) || options !== void 0 && (!options || typeof options != "object" || Array.isArray(options) || Object.keys(options).some((key) => key !== "requestKey")))
1484
- throw invalid6();
1641
+ throw invalid7();
1485
1642
  let blob = input.file instanceof Blob, array3 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
1486
- if (!blob && !array3 && !stream) throw invalid6();
1643
+ if (!blob && !array3 && !stream) throw invalid7();
1487
1644
  let intrinsic = blob ? input.file.size : array3 ? input.file.byteLength : void 0;
1488
- if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid6();
1645
+ if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid7();
1489
1646
  let name = input.name;
1490
1647
  name === void 0 && blob && "name" in input.file && typeof input.file.name == "string" && (name = typeof globalThis.File < "u" && input.file instanceof globalThis.File ? input.file.name : input.file.name.split(/[\\/]/).at(-1));
1491
1648
  let metadata = parseFileCreateMetadata({
@@ -1497,33 +1654,54 @@ var files = {
1497
1654
  ...blob && input.file.type === "application/pdf" ? { inputMediaType: "application/pdf" } : {},
1498
1655
  requestKey: options?.requestKey === void 0 ? routineTransport()?.key("files") ?? crypto.randomUUID() : options.requestKey
1499
1656
  }, FILE_ORIGINAL_MAX_BYTES);
1500
- if (!context2.local && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
1657
+ if (!context2.local && !context2.localFiles && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
1501
1658
  let header = encodeURIComponent(JSON.stringify(metadata));
1502
- if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid6();
1659
+ if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid7();
1503
1660
  if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
1504
- return active++, metadata.size > MAX_BYTES ? multipartCreate(input, metadata, (suffix, init2, kind, signal) => kind === !0 ? send(suffix, init2, !0, context2, signal) : send(suffix, init2, "control", context2, signal)) : timed(async (signal) => {
1661
+ if (active++, context2.localFiles && !routineTransport() && metadata.size > MAX_BYTES) {
1662
+ let signal = context2.signal ?? new AbortController().signal, file2 = input.file, offset = 0, body = file2 instanceof Blob ? context2.signal ? file2 : file2.stream() : file2 instanceof ReadableStream ? file2 : new ReadableStream({
1663
+ pull(controller) {
1664
+ if (offset === file2.byteLength) {
1665
+ controller.close();
1666
+ return;
1667
+ }
1668
+ let end = Math.min(offset + 256 * 1024, file2.byteLength);
1669
+ controller.enqueue(file2.subarray(offset, end)), offset = end;
1670
+ }
1671
+ }, { highWaterMark: 0 });
1672
+ try {
1673
+ return await send("", { method: "POST", headers: {
1674
+ "content-type": "application/octet-stream",
1675
+ "x-os-file": header
1676
+ }, body }, !0, context2, signal);
1677
+ } finally {
1678
+ active--;
1679
+ }
1680
+ }
1681
+ return metadata.size > MAX_BYTES ? multipartCreate(input, metadata, (suffix, init2, kind, signal) => kind === !0 ? send(suffix, init2, !0, context2, signal) : send(suffix, init2, "control", context2, signal)) : timed(async (signal) => {
1505
1682
  try {
1506
1683
  let bytes = array3 ? input.file.slice() : await boundedBytes(
1507
1684
  blob ? input.file.stream() : input.file,
1508
- metadata.size
1685
+ metadata.size,
1686
+ signal
1509
1687
  );
1510
- if (bytes.byteLength !== metadata.size) throw invalid6();
1511
- if (signal.aborted) throw unavailable();
1688
+ if (bytes.byteLength !== metadata.size) throw invalid7();
1689
+ if (signal.aborted) throw unavailable2();
1512
1690
  return await send("", {
1513
1691
  method: "POST",
1514
- headers: { "content-type": "application/octet-stream", "x-oddington-file": header },
1692
+ headers: { "content-type": "application/octet-stream", "x-os-file": header },
1515
1693
  body: bytes.buffer
1516
1694
  }, !0, context2, signal);
1517
1695
  } finally {
1518
1696
  active--;
1519
1697
  }
1520
- }).catch((error) => {
1521
- throw error instanceof FileOperationError ? error : unavailable();
1698
+ }, context2.signal).catch((error) => {
1699
+ throw error instanceof FileOperationError ? error : unavailable2();
1522
1700
  });
1523
1701
  },
1524
1702
  async enrich(input) {
1525
1703
  let context2 = await resolveFilesContext();
1526
- if (!input || typeof input != "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "name", "content", "mediaType", "replace"].includes(key)) || typeof input.content != "string" && !(input.content instanceof Uint8Array)) throw invalid6();
1704
+ if (!input || typeof input != "object" || Array.isArray(input) || Object.keys(input).some((key) => !["file", "name", "content", "mediaType", "replace"].includes(key)) || typeof input.content != "string" && !(input.content instanceof Uint8Array)) throw invalid7();
1527
1705
  let path = `${idPath(input.file)}/enrichments`;
1528
1706
  if (typeof input.content == "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
1529
1707
  throw new FileOperationError("request_too_large", 413);
@@ -1540,12 +1718,12 @@ var files = {
1540
1718
  ...input.mediaType === void 0 ? {} : { mediaType: input.mediaType },
1541
1719
  ...input.replace === void 0 ? {} : { replace: input.replace }
1542
1720
  }, MAX_BYTES), header = encodeURIComponent(JSON.stringify(metadata));
1543
- if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid6();
1721
+ if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid7();
1544
1722
  let result2 = await send(path, { method: "POST", headers: {
1545
1723
  "content-type": "application/octet-stream",
1546
- "x-oddington-enrichment": header
1724
+ "x-os-enrichment": header
1547
1725
  }, body: bytes.buffer }, "enrichment", context3, signal);
1548
- if (result2.name !== metadata.name) throw unavailable();
1726
+ if (result2.name !== metadata.name) throw unavailable2();
1549
1727
  return result2;
1550
1728
  }, context2);
1551
1729
  },
@@ -1559,8 +1737,26 @@ function validGoogleScopes(value) {
1559
1737
  return Array.isArray(value) && value.length > 0 && value.length <= 32 && value.every((scope) => typeof scope == "string" && scope.length <= 256 && /^(https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._-]+|https:\/\/mail\.google\.com\/|openid|email|profile)$/.test(scope)) && new Set(value).size === value.length;
1560
1738
  }
1561
1739
 
1562
- var ROUTINE_CONNECTION_CREDENTIALS_ENV = "ODDINGTON_ROUTINE_CONNECTION_CREDENTIALS";
1740
+ var ROUTINE_CONNECTION_CREDENTIALS_ENV = "OS_ROUTINE_CONNECTION_CREDENTIALS";
1563
1741
  var connectionUuid = (v) => typeof v == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(v);
1742
+ function runtimeConnection(lease) {
1743
+ return lease.provider === "gmail" ? {
1744
+ id: `gmail/${lease.name}`,
1745
+ provider: lease.provider,
1746
+ name: lease.name,
1747
+ accountEmail: lease.accountEmail,
1748
+ scopes: [...lease.scopes],
1749
+ accessToken: lease.accessToken,
1750
+ expiresAt: lease.expiresAt
1751
+ } : {
1752
+ id: `airtable/${lease.name}`,
1753
+ provider: lease.provider,
1754
+ name: lease.name,
1755
+ baseId: lease.baseId,
1756
+ accessToken: lease.accessToken,
1757
+ runExpiresAt: lease.runExpiresAt
1758
+ };
1759
+ }
1564
1760
  function parseConnectionLease(raw, now = Date.now()) {
1565
1761
  let v = raw;
1566
1762
  if (!v || typeof v != "object" || Array.isArray(v) || !connectionUuid(v.connectionId) || !connectionUuid(v.runId) || typeof v.name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(v.name) || typeof v.accessToken != "string" || !/^[A-Za-z0-9._~+/-]{1,8192}={0,2}$/.test(v.accessToken))
@@ -1596,12 +1792,12 @@ function object3(v) {
1596
1792
  function keys2(v, allowed, required = allowed) {
1597
1793
  (Object.keys(v).some((k) => !allowed.includes(k)) || required.some((k) => !Object.hasOwn(v, k))) && fail2("Invalid Airtable input");
1598
1794
  }
1599
- function text2(v) {
1795
+ function text3(v) {
1600
1796
  return typeof v == "string" && v.length > 0 && v.length <= 1024;
1601
1797
  }
1602
1798
  function fields3(v, nonempty = !1) {
1603
1799
  let result2 = object3(v);
1604
- (nonempty && !Object.keys(result2).length || Object.keys(result2).some((k) => !text2(k))) && fail2("Invalid Airtable fields");
1800
+ (nonempty && !Object.keys(result2).length || Object.keys(result2).some((k) => !text3(k))) && fail2("Invalid Airtable fields");
1605
1801
  try {
1606
1802
  return serializable(result2);
1607
1803
  } catch {
@@ -1622,7 +1818,9 @@ function equal(a, b) {
1622
1818
  ));
1623
1819
  }
1624
1820
  function createConnections(transport) {
1625
- return { airtable(name) {
1821
+ return { async get() {
1822
+ throw new Error("Connection unavailable");
1823
+ }, airtable(name) {
1626
1824
  (typeof name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(name)) && fail2("Invalid Airtable connection name");
1627
1825
  let call = (operation2, input) => transport(name, operation2, input);
1628
1826
  return {
@@ -1686,10 +1884,10 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1686
1884
  Array.isArray(page.tables) || fail2("Malformed Airtable tables");
1687
1885
  for (let value of page.tables) {
1688
1886
  let t = object3(value);
1689
- (!tableId(t.id) || !text2(t.name) || !text2(t.primaryFieldId) || !Array.isArray(t.fields) || tables.some((existing) => existing.id === t.id)) && fail2("Malformed Airtable table");
1887
+ (!tableId(t.id) || !text3(t.name) || !text3(t.primaryFieldId) || !Array.isArray(t.fields) || tables.some((existing) => existing.id === t.id)) && fail2("Malformed Airtable table");
1690
1888
  let metadata = t.fields.map((value2) => {
1691
1889
  let f = object3(value2);
1692
- return (typeof f.id != "string" || !/^fld[A-Za-z0-9]+$/.test(f.id) || !text2(f.name) || !text2(f.type)) && fail2("Malformed Airtable field"), { id: f.id, name: f.name, type: f.type, ...f.options === void 0 ? {} : { options: serializable(f.options) } };
1890
+ return (typeof f.id != "string" || !/^fld[A-Za-z0-9]+$/.test(f.id) || !text3(f.name) || !text3(f.type)) && fail2("Malformed Airtable field"), { id: f.id, name: f.name, type: f.type, ...f.options === void 0 ? {} : { options: serializable(f.options) } };
1693
1891
  });
1694
1892
  (!metadata.some((f) => f.id === t.primaryFieldId) || new Set(metadata.map((f) => f.id)).size !== metadata.length) && fail2("Malformed Airtable fields"), tables.push({ id: t.id, name: t.name, primaryFieldId: t.primaryFieldId, fields: metadata });
1695
1893
  }
@@ -1697,7 +1895,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1697
1895
  } while (offset);
1698
1896
  return tables;
1699
1897
  }
1700
- (!text2(input.table) || input.table === "." || input.table === "..") && fail2("Invalid Airtable table"), mutation && !tableId(input.table) && fail2("Airtable writes require a stable table ID");
1898
+ (!text3(input.table) || input.table === "." || input.table === "..") && fail2("Invalid Airtable table"), mutation && !tableId(input.table) && fail2("Airtable writes require a stable table ID");
1701
1899
  let path = `${baseId}/${encodeURIComponent(input.table)}`;
1702
1900
  if (operation2 === "records.get") {
1703
1901
  keys2(input, ["table", "id"]), recordId(input.id) || fail2("Invalid Airtable record ID");
@@ -1705,7 +1903,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1705
1903
  return result3.id !== input.id && fail2("Malformed Airtable record"), result3;
1706
1904
  }
1707
1905
  if (operation2 === "records.list") {
1708
- keys2(input, ["table", "fields"], ["table"]), input.fields !== void 0 && (!Array.isArray(input.fields) || !input.fields.length || input.fields.some((f) => !text2(f)) || new Set(input.fields).size !== input.fields.length) && fail2("Invalid Airtable field selection");
1906
+ keys2(input, ["table", "fields"], ["table"]), input.fields !== void 0 && (!Array.isArray(input.fields) || !input.fields.length || input.fields.some((f) => !text3(f)) || new Set(input.fields).size !== input.fields.length) && fail2("Invalid Airtable field selection");
1709
1907
  let records2 = [], ids2 = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set(), offset;
1710
1908
  do {
1711
1909
  let query2 = new URLSearchParams();
@@ -1762,10 +1960,10 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1762
1960
  }
1763
1961
  function nextOffset(value, seen) {
1764
1962
  if (value !== void 0)
1765
- return (!text2(value) || seen.has(value)) && fail2("Malformed Airtable pagination"), seen.add(value), value;
1963
+ return (!text3(value) || seen.has(value)) && fail2("Malformed Airtable pagination"), seen.add(value), value;
1766
1964
  }
1767
1965
 
1768
- var MANAGED_CONNECTION_CAPABILITY_ENV = "ODDINGTON_MANAGED_CONNECTION_CAPABILITY";
1966
+ var MANAGED_CONNECTION_CAPABILITY_ENV = "OS_MANAGED_CONNECTION_CAPABILITY";
1769
1967
  function managedConnections(capability) {
1770
1968
  let endpoint = new URL(capability.endpoint);
1771
1969
  if (endpoint.protocol !== "http:" || endpoint.hostname !== "127.0.0.1" || !endpoint.port || endpoint.pathname !== "/" || endpoint.search || endpoint.hash || endpoint.username || endpoint.password || !/^[0-9a-f-]{36}$/.test(capability.token)) throw new AirtableOperationError("Airtable capability unavailable");
@@ -1804,46 +2002,19 @@ async function reportLocalRoutineEffect(value) {
1804
2002
  await observer?.(value);
1805
2003
  }
1806
2004
 
1807
- var connections = /* @__PURE__ */ createConnections(async (name, operation2, input) => {
1808
- try {
1809
- let installed2 = routineTransport();
1810
- if (installed2) return await installed2.request("airtable", { name, operation: operation2, input: serializable(input) });
1811
- let managed = process.env[MANAGED_CONNECTION_CAPABILITY_ENV];
1812
- if (managed) {
1813
- let client = managedConnections(JSON.parse(managed)).airtable(name);
1814
- return operation2 === "tables.list" ? await client.tables.list() : await client.records[operation2.slice(8)](input);
1815
- }
1816
- let raw = JSON.parse(process.env[ROUTINE_CONNECTION_CREDENTIALS_ENV] ?? "[]");
1817
- if (!Array.isArray(raw)) throw new Error();
1818
- let leases = raw.map((value) => parseConnectionLease(value));
1819
- if (leases.some((lease2) => lease2.provider !== "airtable") || new Set(leases.map((lease2) => lease2.name)).size !== leases.length) throw new Error();
1820
- let lease = leases.find((lease2) => lease2.name === name);
1821
- if (!lease || lease.provider !== "airtable") throw new Error();
1822
- let writing = ["records.create", "records.update", "records.delete"].includes(operation2), captured = serializable(input), result2;
1823
- try {
1824
- result2 = await executeAirtableOperation(lease, operation2, captured);
1825
- } catch (error) {
1826
- throw writing && error instanceof AirtableOperationError && await reportLocalRoutineEffect({
1827
- type: "effect",
1828
- connection: `airtable/${name}`,
1829
- operation: operation2,
1830
- input: captured,
1831
- effect: error.effect,
1832
- receipts: error.receipts
1833
- }), error;
1834
- }
1835
- return writing && await reportLocalRoutineEffect({
1836
- type: "effect",
1837
- connection: `airtable/${name}`,
1838
- operation: operation2,
1839
- input: captured,
1840
- effect: "confirmed",
1841
- receipts: [result2.receipt]
1842
- }), result2;
1843
- } catch (error) {
1844
- throw error instanceof AirtableOperationError ? error : new AirtableOperationError("Airtable connection unavailable");
1845
- }
2005
+ var local;
2006
+ var airtable = /* @__PURE__ */ createConnections(async (name, operation2, input) => {
2007
+ throw new AirtableOperationError("Airtable connection unavailable");
1846
2008
  });
2009
+ function runtimeConnections() {
2010
+ return {
2011
+ ...airtable,
2012
+ async get(identity) {
2013
+ throw new Error("Connection unavailable");
2014
+ }
2015
+ };
2016
+ }
2017
+ var connections = /* @__PURE__ */ runtimeConnections();
1847
2018
 
1848
2019
  var LOCAL_ROUTINE_VALUE_BYTES = 256 * 1024;
1849
2020
 
@@ -1948,7 +2119,7 @@ function object4(value) {
1948
2119
  function keys3(value, allowed, required = allowed) {
1949
2120
  assert(Object.keys(value).every((key) => allowed.includes(key)) && required.every((key) => Object.hasOwn(value, key)));
1950
2121
  }
1951
- function text3(value, empty2 = !1) {
2122
+ function text4(value, empty2 = !1) {
1952
2123
  return typeof value == "string" && (empty2 || !!value.trim());
1953
2124
  }
1954
2125
  function id2(value) {
@@ -1958,7 +2129,7 @@ function integer(value, minimum = 1) {
1958
2129
  return Number.isSafeInteger(value) && Number(value) >= minimum;
1959
2130
  }
1960
2131
  function date(value) {
1961
- return text3(value) && Number.isFinite(Date.parse(value));
2132
+ return text4(value) && Number.isFinite(Date.parse(value));
1962
2133
  }
1963
2134
  function optionalDate(value) {
1964
2135
  return value === null || date(value);
@@ -1980,7 +2151,7 @@ function json(value, ancestors = /* @__PURE__ */ new Set()) {
1980
2151
  }
1981
2152
  function recordReference(value) {
1982
2153
  let record3 = object4(value);
1983
- return keys3(record3, ["repository", "ref"]), assert(text3(record3.repository) && record3.repository === record3.repository.trim() && /^[a-z0-9][a-z0-9._/-]{0,127}$/.test(record3.repository) && !/\.\.|\/\//.test(record3.repository) && text3(record3.ref) && record3.ref === record3.ref.trim() && record3.ref.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)+$/.test(record3.ref)), record3;
2154
+ return keys3(record3, ["repository", "ref"]), assert(text4(record3.repository) && record3.repository === record3.repository.trim() && /^[a-z0-9][a-z0-9._/-]{0,127}$/.test(record3.repository) && !/\.\.|\/\//.test(record3.repository) && text4(record3.ref) && record3.ref === record3.ref.trim() && record3.ref.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)+$/.test(record3.ref)), record3;
1984
2155
  }
1985
2156
  function responseDefinition(value) {
1986
2157
  let definition = object4(value);
@@ -1992,75 +2163,75 @@ function responseDefinition(value) {
1992
2163
  assert(options.length > 0);
1993
2164
  let values = options.map((value2) => {
1994
2165
  let option = object4(value2);
1995
- if (keys3(option, ["value", "label", "description", "note"], ["value", "label"]), assert(text3(option.value) && option.value === option.value.trim() && text3(option.label)), "description" in option && assert(text3(option.description)), "note" in option) {
2166
+ if (keys3(option, ["value", "label", "description", "note"], ["value", "label"]), assert(text4(option.value) && option.value === option.value.trim() && text4(option.label)), "description" in option && assert(text4(option.description)), "note" in option) {
1996
2167
  let note = object4(option.note);
1997
- keys3(note, ["placeholder"]), assert(text3(note.placeholder));
2168
+ keys3(note, ["placeholder"]), assert(text4(note.placeholder));
1998
2169
  }
1999
2170
  return option.value;
2000
2171
  });
2001
2172
  if (assert(new Set(values).size === values.length), "search" in source || "suggestions" in source) {
2002
2173
  let search = object4(source.search);
2003
- keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text3(search.triggerLabel) && text3(search.placeholder) && text3(search.emptyLabel));
2174
+ keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text4(search.triggerLabel) && text4(search.placeholder) && text4(search.emptyLabel));
2004
2175
  let suggestions2 = array2(source.suggestions);
2005
- assert(suggestions2.length <= 8 && suggestions2.every((value2) => text3(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
2176
+ assert(suggestions2.length <= 8 && suggestions2.every((value2) => text4(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
2006
2177
  } else assert(options.length <= 9);
2007
2178
  return;
2008
2179
  }
2009
2180
  assert(source.type === "records"), keys3(source, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
2010
2181
  let collection = object4(source.collection);
2011
- keys3(collection, ["repository", "name"]), recordReference({ repository: collection.repository, ref: "records/example" }), assert(text3(collection.name) && /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(collection.name)), "refPrefix" in source && assert(text3(source.refPrefix) && source.refPrefix.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)*\/$/.test(source.refPrefix));
2182
+ keys3(collection, ["repository", "name"]), recordReference({ repository: collection.repository, ref: "records/example" }), assert(text4(collection.name) && /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(collection.name)), "refPrefix" in source && assert(text4(source.refPrefix) && source.refPrefix.length <= 512 && /^[_a-zA-Z0-9][a-zA-Z0-9_-]*(\/[_a-zA-Z0-9][a-zA-Z0-9_-]*)*\/$/.test(source.refPrefix));
2012
2183
  let where = object4(source.where ?? {});
2013
2184
  assert(Object.entries(where).every(([name, value2]) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) && !["constructor", "prototype"].includes(name) && (value2 === null || typeof value2 == "string" || typeof value2 == "boolean" || typeof value2 == "number" && Number.isFinite(value2))));
2014
2185
  let display = object4(source.display);
2015
2186
  keys3(display, ["labelFields"]);
2016
2187
  let labels = array2(display.labelFields);
2017
- assert(labels.length > 0 && labels.length <= 2 && new Set(labels).size === labels.length && labels.every((value2) => text3(value2) && /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value2)));
2188
+ assert(labels.length > 0 && labels.length <= 2 && new Set(labels).size === labels.length && labels.every((value2) => text4(value2) && /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value2)));
2018
2189
  let suggestions = array2(source.suggestions ?? []), refs = suggestions.map((value2) => {
2019
2190
  let suggestion = object4(value2);
2020
2191
  keys3(suggestion, ["record", "reason"], ["record"]);
2021
2192
  let record3 = recordReference(suggestion.record);
2022
- return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text3(suggestion.reason)), record3.ref;
2193
+ return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text4(suggestion.reason)), record3.ref;
2023
2194
  });
2024
2195
  assert(suggestions.length <= 8 && new Set(refs).size === refs.length);
2025
2196
  }
2026
2197
  function inboxFile(value) {
2027
2198
  let file2 = object4(value);
2028
- keys3(file2, ["id", "name", "mediaType", "size", "sha256", "details"]), assert(id2(file2.id) && text3(file2.name) && !/[\x00-\x1f\x7f/\\]/.test(file2.name) && text3(file2.mediaType) && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(file2.mediaType) && integer(file2.size, 0) && file2.size <= 25 * 1024 * 1024 && typeof file2.sha256 == "string" && /^[0-9a-f]{64}$/.test(file2.sha256));
2199
+ keys3(file2, ["id", "name", "mediaType", "size", "sha256", "details"]), assert(id2(file2.id) && text4(file2.name) && !/[\x00-\x1f\x7f/\\]/.test(file2.name) && text4(file2.mediaType) && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(file2.mediaType) && integer(file2.size, 0) && file2.size <= 25 * 1024 * 1024 && typeof file2.sha256 == "string" && /^[0-9a-f]{64}$/.test(file2.sha256));
2029
2200
  let details = object4(file2.details);
2030
2201
  details.kind === "csv" ? (keys3(details, ["kind", "encoding", "delimiter", "headerRow", "dataRows"]), assert(file2.mediaType === "text/csv" && ["utf-8", "windows-1252"].includes(String(details.encoding)) && [",", ";", " "].includes(String(details.delimiter)) && integer(details.headerRow, 0) && integer(details.dataRows, 0))) : details.kind === "pdf" ? (keys3(details, ["kind", "pages"], ["kind"]), assert(file2.mediaType === "application/pdf" && (!("pages" in details) || integer(details.pages)))) : (keys3(details, ["kind"]), assert(details.kind === "other" && !["text/csv", "application/pdf"].includes(file2.mediaType)));
2031
2202
  }
2032
2203
  function fields4(value) {
2033
2204
  let labels = array2(value).map((value2) => {
2034
2205
  let field = object4(value2);
2035
- return keys3(field, ["label", "value"]), assert(text3(field.label) && text3(field.value)), field.label;
2206
+ return keys3(field, ["label", "value"]), assert(text4(field.label) && text4(field.value)), field.label;
2036
2207
  });
2037
2208
  assert(new Set(labels).size === labels.length);
2038
2209
  }
2039
2210
  function block(value) {
2040
2211
  let entry = object4(value);
2041
2212
  if (entry.kind === "rich-text") {
2042
- keys3(entry, ["kind", "markdown"]), assert(text3(entry.markdown));
2213
+ keys3(entry, ["kind", "markdown"]), assert(text4(entry.markdown));
2043
2214
  return;
2044
2215
  }
2045
2216
  if (entry.kind === "asks") {
2046
2217
  keys3(entry, ["kind", "problem", "asks"]);
2047
2218
  let asks = array2(entry.asks);
2048
- assert(text3(entry.problem) && asks.length > 0 && asks.every(id2) && new Set(asks).size === asks.length);
2219
+ assert(text4(entry.problem) && asks.length > 0 && asks.every(id2) && new Set(asks).size === asks.length);
2049
2220
  return;
2050
2221
  }
2051
2222
  if (assert(["record", "records", "files"].includes(String(entry.kind))), keys3(
2052
2223
  entry,
2053
2224
  ["kind", "label", "initiallyExpanded", ...entry.kind === "record" ? ["record", "view"] : entry.kind === "records" ? ["records", "view"] : ["files"]],
2054
2225
  ["kind", "label", entry.kind === "record" ? "record" : entry.kind === "records" ? "records" : "files"]
2055
- ), assert(text3(entry.label) && (!("initiallyExpanded" in entry) || typeof entry.initiallyExpanded == "boolean") && (!("view" in entry) || text3(entry.view) && entry.view === entry.view.trim())), entry.kind === "record") {
2226
+ ), assert(text4(entry.label) && (!("initiallyExpanded" in entry) || typeof entry.initiallyExpanded == "boolean") && (!("view" in entry) || text4(entry.view) && entry.view === entry.view.trim())), entry.kind === "record") {
2056
2227
  let record3 = object4(entry.record);
2057
- keys3(record3, ["ref", "title", "fields"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), fields4(record3.fields);
2228
+ keys3(record3, ["ref", "title", "fields"]), assert(text4(record3.ref) && record3.ref === record3.ref.trim() && text4(record3.title)), fields4(record3.fields);
2058
2229
  return;
2059
2230
  }
2060
2231
  if (entry.kind === "records") {
2061
2232
  let records = array2(entry.records), refs = records.map((value2) => {
2062
2233
  let record3 = object4(value2);
2063
- return keys3(record3, ["ref", "title", "description", "facts", "view"], ["ref", "title"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), "description" in record3 && assert(text3(record3.description)), "facts" in record3 && fields4(record3.facts), "view" in record3 && assert(text3(record3.view) && record3.view === record3.view.trim()), record3.ref;
2234
+ return keys3(record3, ["ref", "title", "description", "facts", "view"], ["ref", "title"]), assert(text4(record3.ref) && record3.ref === record3.ref.trim() && text4(record3.title)), "description" in record3 && assert(text4(record3.description)), "facts" in record3 && fields4(record3.facts), "view" in record3 && assert(text4(record3.view) && record3.view === record3.view.trim()), record3.ref;
2064
2235
  });
2065
2236
  assert(records.length > 0 && new Set(refs).size === refs.length);
2066
2237
  return;
@@ -2070,7 +2241,7 @@ function block(value) {
2070
2241
  }
2071
2242
  function response(value) {
2072
2243
  let answer = object4(value);
2073
- return assert(Object.keys(answer).every((key) => ["selection", "note"].includes(key))), typeof answer.selection == "string" ? assert(text3(answer.selection) && answer.selection === answer.selection.trim()) : recordReference(answer.selection), Object.hasOwn(answer, "note") && assert(text3(answer.note)), answer;
2244
+ return assert(Object.keys(answer).every((key) => ["selection", "note"].includes(key))), typeof answer.selection == "string" ? assert(text4(answer.selection) && answer.selection === answer.selection.trim()) : recordReference(answer.selection), Object.hasOwn(answer, "note") && assert(text4(answer.note)), answer;
2074
2245
  }
2075
2246
  function parseInboxRequest(value) {
2076
2247
  try {
@@ -2079,78 +2250,82 @@ function parseInboxRequest(value) {
2079
2250
  let operation2 = envelope.operation, input = { ...object4(envelope.input) }, required = operations[operation2];
2080
2251
  assert(required.every((key) => Object.hasOwn(input, key)) && Object.keys(input).every((key) => required.includes(key) || operation2 === "questions.searchRecords" && key === "selected" || (operation2 === "items.list" || operation2 === "questions.list") && key === "beforeNumber" || operation2 === "questions.list" && key === "routines")), operation2 === "questions.list" && (assert(Object.hasOwn(input, "routines")), assert(array2(input.routines).every(isAppRoutineName)));
2081
2252
  for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
2082
- return "revision" in input && assert(integer(input.revision)), "beforeNumber" in input && assert(integer(input.beforeNumber)), "questionId" in input && assert(text3(input.questionId) && input.questionId === input.questionId.trim()), "title" in input && assert(text3(input.title)), "lifecycle" in input && assert(input.lifecycle === "open" || input.lifecycle === "closed"), "query" in input && assert(text3(input.query, !0) && input.query.length <= 256), "selected" in input && recordReference(input.selected), "response" in input && response(input.response), assert(new TextEncoder().encode(JSON.stringify(envelope)).byteLength <= INBOX_INPUT_BYTES), "routines" in input && (input.routines = [...new Set(input.routines)]), { operation: operation2, input };
2253
+ return "revision" in input && assert(integer(input.revision)), "beforeNumber" in input && assert(integer(input.beforeNumber)), "questionId" in input && assert(text4(input.questionId) && input.questionId === input.questionId.trim()), "title" in input && assert(text4(input.title)), "lifecycle" in input && assert(input.lifecycle === "open" || input.lifecycle === "closed"), "query" in input && assert(text4(input.query, !0) && input.query.length <= 256), "selected" in input && recordReference(input.selected), "response" in input && response(input.response), assert(new TextEncoder().encode(JSON.stringify(envelope)).byteLength <= INBOX_INPUT_BYTES), "routines" in input && (input.routines = [...new Set(input.routines)]), { operation: operation2, input };
2083
2254
  } catch {
2084
2255
  throw new InboxOperationError(400, "invalid_input");
2085
2256
  }
2086
2257
  }
2087
2258
  function parseInboxCurrent(value) {
2088
2259
  let current2 = object4(value), workspace = object4(current2.workspace), viewer = object4(current2.viewer);
2089
- return assert(id2(workspace.id) && text3(workspace.slug) && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(workspace.slug) && text3(workspace.name) && text3(workspace.locale) && text3(workspace.timezone)), assert(id2(viewer.id) && text3(viewer.name) && text3(viewer.email)), {
2260
+ return assert(id2(workspace.id) && text4(workspace.slug) && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(workspace.slug) && text4(workspace.name) && text4(workspace.locale) && text4(workspace.timezone)), assert(id2(viewer.id) && text4(viewer.name) && text4(viewer.email)), {
2090
2261
  workspace: { id: workspace.id, slug: workspace.slug, name: workspace.name, locale: workspace.locale, timezone: workspace.timezone },
2091
2262
  viewer: { id: viewer.id, name: viewer.name, email: viewer.email }
2092
2263
  };
2093
2264
  }
2094
2265
  function parseInboxItem(value) {
2095
2266
  let item = object4(json(value));
2096
- return assert(id2(item.id) && id2(item.workspaceId) && integer(item.number) && integer(item.revision) && integer(item.activityVersion, 0) && ["ask", "digest"].includes(String(item.kind)) && ["open", "closed"].includes(String(item.lifecycle)) && text3(item.title) && text3(item.description, !0) && text3(item.author) && date(item.publishedAt) && optionalDate(item.seenAt) && optionalDate(item.digestReadAt)), item.outcome !== null && assert(text3(object4(item.outcome).outcome)), "canonicalRoutineId" in item && assert(item.canonicalRoutineId === null || isAppRoutineName(item.canonicalRoutineId)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
2267
+ return assert(id2(item.id) && id2(item.workspaceId) && integer(item.number) && integer(item.revision) && integer(item.activityVersion, 0) && ["ask", "digest"].includes(String(item.kind)) && ["open", "closed"].includes(String(item.lifecycle)) && text4(item.title) && text4(item.description, !0) && text4(item.author) && date(item.publishedAt) && optionalDate(item.seenAt) && optionalDate(item.digestReadAt)), item.outcome !== null && assert(text4(object4(item.outcome).outcome)), "canonicalRoutineId" in item && assert(item.canonicalRoutineId === null || isAppRoutineName(item.canonicalRoutineId)), item.kind === "ask" ? askMetadata(item) : assert(!("tags" in item) && !("recordRefs" in item)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
2097
2268
  let view = object4(value2);
2098
- assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json(view.input);
2269
+ assert(text4(view.id) && text4(view.view) && text4(view.implementation)), json(view.input);
2099
2270
  }), array2(item.people).forEach((value2) => {
2100
2271
  let person = object4(value2);
2101
- assert(id2(person.id) && text3(person.name));
2272
+ assert(id2(person.id) && text4(person.name));
2102
2273
  }), array2(item.questions).forEach((value2) => {
2103
2274
  let question2 = object4(value2);
2104
- if (assert(text3(question2.id) && id2(question2.to) && text3(question2.prompt) && (question2.instructions === null || text3(question2.instructions, !0)) && typeof question2.available == "boolean"), responseDefinition(question2.response), assert(array2(question2.allowedResponders).every(id2)), question2.acceptedResponse !== null) {
2275
+ if (assert(text4(question2.id) && id2(question2.to) && text4(question2.prompt) && (question2.instructions === null || text4(question2.instructions, !0)) && typeof question2.available == "boolean"), responseDefinition(question2.response), assert(array2(question2.allowedResponders).every(id2)), question2.acceptedResponse !== null) {
2105
2276
  let accepted = object4(question2.acceptedResponse);
2106
- assert(id2(accepted.id) && id2(accepted.userId) && date(accepted.acceptedAt)), response(accepted.response), accepted.label === null ? delete accepted.label : "label" in accepted && assert(text3(accepted.label)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder));
2277
+ assert(id2(accepted.id) && id2(accepted.userId) && date(accepted.acceptedAt)), response(accepted.response), accepted.label === null ? delete accepted.label : "label" in accepted && assert(text4(accepted.label)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder));
2107
2278
  }
2108
2279
  if (question2.execution !== null) {
2109
2280
  let execution = object4(question2.execution);
2110
2281
  if (assert(id2(execution.id) && ["pending", "running", "completed", "failed"].includes(String(execution.state)) && integer(execution.attempt, 0)), "consequence" in execution) {
2111
2282
  let consequence = object4(execution.consequence);
2112
- assert(["pending", "running", "applied", "no-write", "stopped", "partial", "uncertain"].includes(String(consequence.state)) && (consequence.phase === null || ["loading", "invoking", "committing"].includes(String(consequence.phase))) && date(consequence.updatedAt) && typeof consequence.needsReconciliation == "boolean" && (consequence.reason === null || text3(consequence.reason, !0))), array2(consequence.evidence).forEach((value3) => {
2283
+ assert(["pending", "running", "applied", "no-write", "stopped", "partial", "uncertain"].includes(String(consequence.state)) && (consequence.phase === null || ["loading", "invoking", "committing"].includes(String(consequence.phase))) && date(consequence.updatedAt) && typeof consequence.needsReconciliation == "boolean" && (consequence.reason === null || text4(consequence.reason, !0))), array2(consequence.evidence).forEach((value3) => {
2113
2284
  let receipt = object4(value3);
2114
- assert(text3(receipt.repository) && text3(receipt.commit) && text3(receipt.diff, !0));
2285
+ assert(text4(receipt.repository) && text4(receipt.commit) && text4(receipt.diff, !0));
2115
2286
  });
2116
2287
  }
2117
2288
  }
2118
2289
  }), array2(item.linkedAsks).forEach((value2) => {
2119
2290
  let linked = object4(value2);
2120
2291
  if (assert(id2(linked.id)), linked.state === "unavailable") assert(typeof linked.done == "boolean");
2121
- else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text3(linked.title)), linked.state === "theirs") {
2292
+ else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text4(linked.title)), linked.state === "theirs") {
2122
2293
  let assignee = object4(linked.assignee);
2123
- assert(id2(assignee.id) && text3(assignee.name));
2294
+ assert(id2(assignee.id) && text4(assignee.name));
2124
2295
  }
2125
2296
  }), array2(item.activity).forEach((value2) => {
2126
2297
  let event = object4(value2);
2127
- assert(integer(event.id) && text3(event.type) && (event.actorId === null || id2(event.actorId)) && (event.questionId === null || text3(event.questionId)) && integer(event.revision) && date(event.createdAt)), object4(event.data);
2298
+ assert(integer(event.id) && text4(event.type) && (event.actorId === null || id2(event.actorId)) && (event.questionId === null || text4(event.questionId)) && integer(event.revision) && date(event.createdAt)), object4(event.data);
2128
2299
  }), array2(item.work).forEach((value2) => {
2129
2300
  let work = object4(value2);
2130
- assert(id2(work.id) && text3(work.questionId) && text3(work.reason) && optionalDate(work.settledAt));
2301
+ assert(id2(work.id) && text4(work.questionId) && text4(work.reason) && optionalDate(work.settledAt));
2131
2302
  }), item;
2132
2303
  }
2133
2304
  function parseAnswerableQuestion(value) {
2134
2305
  let entry = object4(json(value));
2135
2306
  keys3(
2136
2307
  entry,
2137
- ["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "recordRefs", "instructions"],
2138
- ["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "recordRefs"]
2139
- ), assert(id2(entry.itemId) && integer(entry.revision) && text3(entry.title) && text3(entry.inboxUrl));
2308
+ ["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "tags", "recordRefs", "instructions"],
2309
+ ["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable"]
2310
+ ), assert(id2(entry.itemId) && integer(entry.revision) && text4(entry.title) && text4(entry.inboxUrl));
2140
2311
  let link = new URL(entry.inboxUrl), slug = link.hostname.slice(0, -13);
2141
- assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && entry.inboxUrl === `https://${slug}.oddington.ai/inbox/${entry.itemId}`), assert(isAppRoutineName(entry.routine) && text3(entry.questionId) && entry.questionId === entry.questionId.trim() && text3(entry.prompt) && (!("instructions" in entry) || text3(entry.instructions, !0)) && typeof entry.answerable == "boolean"), responseDefinition(entry.response);
2142
- let refs = array2(entry.recordRefs);
2143
- return refs.forEach((value2) => {
2144
- let ref = object4(value2);
2145
- keys3(ref, ["repository", "id"]), assert(validRepositoryAlias(ref.repository) && text3(ref.id) && /^[a-zA-Z0-9][a-zA-Z0-9._/-]*$/.test(ref.id) && !ref.id.split("/").some((part) => !part || part === "." || part === ".."));
2146
- }), assert(new Set(refs.map((value2) => {
2147
- let ref = object4(value2);
2312
+ return assert(link.hostname.endsWith(".oddington.ai") && slug.length <= 63 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) && !["auth", "www", "api", "os"].includes(slug) && entry.inboxUrl === `https://${slug}.oddington.ai/inbox/${entry.itemId}`), assert(isAppRoutineName(entry.routine) && text4(entry.questionId) && entry.questionId === entry.questionId.trim() && text4(entry.prompt) && (!("instructions" in entry) || text4(entry.instructions, !0)) && typeof entry.answerable == "boolean"), responseDefinition(entry.response), askMetadata(entry), entry;
2313
+ }
2314
+ function askMetadata(entry) {
2315
+ let tags = array2(entry.tags === void 0 ? [] : entry.tags);
2316
+ assert(tags.length <= 32 && tags.every((tag) => text4(tag) && new TextEncoder().encode(tag).byteLength <= 64)), assert(new Set(tags).size === tags.length);
2317
+ let refs = array2(entry.recordRefs === void 0 ? [] : entry.recordRefs);
2318
+ refs.forEach((value) => {
2319
+ let ref = object4(value);
2320
+ keys3(ref, ["repository", "id"]), recordReference({ repository: ref.repository, ref: ref.id });
2321
+ }), assert(new Set(refs.map((value) => {
2322
+ let ref = object4(value);
2148
2323
  return JSON.stringify([ref.repository, ref.id]);
2149
- })).size === refs.length), entry;
2324
+ })).size === refs.length), entry.tags = tags, entry.recordRefs = refs;
2150
2325
  }
2151
2326
  function parseInboxAcceptance(value) {
2152
2327
  let accepted = object4(value);
2153
- return assert(id2(accepted.responseId) && date(accepted.acceptedAt)), "executionId" in accepted && assert(id2(accepted.executionId)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder)), "label" in accepted && assert(text3(accepted.label)), accepted;
2328
+ return assert(id2(accepted.responseId) && date(accepted.acceptedAt)), "executionId" in accepted && assert(id2(accepted.executionId)), "acceptanceOrder" in accepted && assert(integer(accepted.acceptanceOrder)), "label" in accepted && assert(text4(accepted.label)), accepted;
2154
2329
  }
2155
2330
  function parseInboxResult(operation2, value) {
2156
2331
  if (operation2 === "current") return parseInboxCurrent(value);
@@ -2181,7 +2356,7 @@ function parseInboxResult(operation2, value) {
2181
2356
  let candidates = array2(value);
2182
2357
  return candidates.forEach((value2) => {
2183
2358
  let person = object4(value2);
2184
- assert(id2(person.id) && text3(person.name) && text3(person.email));
2359
+ assert(id2(person.id) && text4(person.name) && text4(person.email));
2185
2360
  }), assert(new Set(candidates.map((value2) => object4(value2).id)).size === candidates.length), candidates;
2186
2361
  }
2187
2362
  if (operation2 === "items.addRecipient") {
@@ -2191,10 +2366,10 @@ function parseInboxResult(operation2, value) {
2191
2366
  if (operation2 === "questions.answer") return parseInboxAcceptance(value);
2192
2367
  if (operation2 === "questions.searchRecords") {
2193
2368
  let result2 = object4(value);
2194
- assert(text3(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
2369
+ assert(text4(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
2195
2370
  let labeled = (value2) => {
2196
2371
  let record3 = object4(value2);
2197
- recordReference({ repository: record3.repository, ref: record3.ref }), assert(text3(record3.label)), "reason" in record3 && assert(text3(record3.reason));
2372
+ recordReference({ repository: record3.repository, ref: record3.ref }), assert(text4(record3.label)), "reason" in record3 && assert(text4(record3.reason));
2198
2373
  };
2199
2374
  return array2(result2.matches).forEach(labeled), array2(result2.suggestions).forEach(labeled), "selected" in result2 && labeled(result2.selected), result2;
2200
2375
  }
@@ -2308,7 +2483,7 @@ async function appResponse(response2, maximum, signal) {
2308
2483
  });
2309
2484
  };
2310
2485
  signal.addEventListener("abort", abort, { once: !0 });
2311
- let bytes = 0, text4 = "", decoder = new TextDecoder("utf-8", { fatal: !0 });
2486
+ let bytes = 0, text5 = "", decoder = new TextDecoder("utf-8", { fatal: !0 });
2312
2487
  try {
2313
2488
  for (; ; ) {
2314
2489
  let chunk;
@@ -2319,13 +2494,13 @@ async function appResponse(response2, maximum, signal) {
2319
2494
  }
2320
2495
  if (signal.aborted) throw new Error();
2321
2496
  if (chunk.done) {
2322
- let value = JSON.parse(text4 + decoder.decode());
2497
+ let value = JSON.parse(text5 + decoder.decode());
2323
2498
  if (await responseChecks.get(response2)?.(value), signal.aborted) throw new Error();
2324
2499
  return value;
2325
2500
  }
2326
2501
  if (bytes += chunk.value.byteLength, bytes > maximum)
2327
2502
  throw abort(), new Error();
2328
- text4 += decoder.decode(chunk.value, { stream: !0 });
2503
+ text5 += decoder.decode(chunk.value, { stream: !0 });
2329
2504
  }
2330
2505
  } finally {
2331
2506
  signal.removeEventListener("abort", abort), reader.releaseLock();
@@ -2376,10 +2551,12 @@ function appContext(origin, active2) {
2376
2551
  credentials: "omit",
2377
2552
  redirect: "error",
2378
2553
  cache: "no-store",
2554
+ ...init2.body instanceof ReadableStream ? { duplex: "half" } : {},
2379
2555
  referrerPolicy: "no-referrer",
2380
2556
  signal,
2381
2557
  headers: {
2382
2558
  ...init2.body === void 0 ? {} : { "content-type": "application/json" },
2559
+ ...Object.fromEntries(new Headers(init2.headers)),
2383
2560
  authorization: `Bearer ${candidate}`
2384
2561
  }
2385
2562
  });
@@ -2545,11 +2722,37 @@ function appContext(origin, active2) {
2545
2722
  async function requestRoutine(key, suffix, init2 = {}) {
2546
2723
  return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, init2);
2547
2724
  }
2548
- async function requestChecked(path, init2, inbox2 = !1) {
2725
+ async function requestRetainedRoutine(key, suffix) {
2726
+ return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, {}, !1, !0);
2727
+ }
2728
+ async function requestFiles(suffix, init2, parent) {
2729
+ let unavailable4 = () => new FileOperationError("unsupported_context", 400);
2730
+ if (!current2() || !/^(?:|\/[0-9a-f-]{36}(?:\/(?:content|upload|enrichments(?:\/[^/?#]+\/content)?))?)$/i.test(suffix))
2731
+ throw unavailable4();
2732
+ let admitted = credential, signal = parent ? AbortSignal.any([access.signal, parent]) : access.signal, failure = () => current2() && !signal.aborted ? new FileOperationError("unavailable", 503, !0) : unavailable4();
2733
+ try {
2734
+ return await hostedContent("", init2, signal, (_url, request2) => untilAborted(
2735
+ send3(`files${suffix}`, admitted, signal, request2).then((value) => {
2736
+ if (signal.aborted)
2737
+ throw value.body?.cancel().catch(() => {
2738
+ }), unavailable4();
2739
+ return value;
2740
+ }),
2741
+ signal
2742
+ ), () => settledAccess(signal), failure);
2743
+ } catch {
2744
+ throw failure();
2745
+ }
2746
+ }
2747
+ async function requestChecked(path, init2, inbox2 = !1, retained2 = !1) {
2549
2748
  if (!current2()) throw new Error("Local app context unavailable.");
2550
- let admitted = credential, signal = access.signal, response2 = await send3(path, credential, signal, init2);
2551
- return await settledAccess(signal), (response2.status === 401 || !inbox2 && response2.status === 403) && admitted === credential && current2() && invalidate(), responseChecks.set(response2, async (value) => {
2552
- await settledAccess(signal), admitted === credential && current2() && value && typeof value == "object" && "error" in value && value.error === "authority_unavailable" && invalidate();
2749
+ let admitted = credential, signal = access.signal, response2 = await send3(path, credential, signal, init2), check = async () => {
2750
+ if (retained2) {
2751
+ if (signal.aborted || !current2()) throw new Error("Local app context unavailable.");
2752
+ } else await settledAccess(signal);
2753
+ };
2754
+ return await check(), (response2.status === 401 || !inbox2 && response2.status === 403) && admitted === credential && current2() && invalidate(), responseChecks.set(response2, async (value) => {
2755
+ await check(), admitted === credential && current2() && value && typeof value == "object" && "error" in value && value.error === "authority_unavailable" && invalidate();
2553
2756
  }), response2;
2554
2757
  }
2555
2758
  function context2() {
@@ -2566,8 +2769,10 @@ function appContext(origin, active2) {
2566
2769
  issued === credential && current2() && invalidate();
2567
2770
  },
2568
2771
  requestRoutine,
2772
+ requestRetainedRoutine,
2569
2773
  requestData,
2570
2774
  requestInbox,
2775
+ requestFiles,
2571
2776
  requestAvailability: (key) => requestRoutine(key, "availability", { method: "GET" })
2572
2777
  };
2573
2778
  }
@@ -2576,22 +2781,22 @@ function appContext(origin, active2) {
2576
2781
  try {
2577
2782
  if (!alive()) throw new Error();
2578
2783
  if (!pair) {
2579
- let candidate2 = stored(), retained2 = readPair(candidate2);
2580
- pair = retained2, binding = { ...retained2.context }, credential = retained2.credential, serialized = candidate2;
2784
+ let candidate2 = stored(), retained3 = readPair(candidate2);
2785
+ pair = retained3, binding = { ...retained3.context }, credential = retained3.credential, serialized = candidate2;
2581
2786
  }
2582
2787
  if (expireAccess(), binding.expiresAt <= Date.now()) {
2583
2788
  if (await renew(), !current2()) throw new AppRenewalUnavailable();
2584
2789
  return context2();
2585
2790
  }
2586
2791
  await synchronize();
2587
- let candidate = stored(), retained = readPair(candidate);
2792
+ let candidate = stored(), retained2 = readPair(candidate);
2588
2793
  if (attempted = candidate ?? void 0, !current2()) throw new AppRenewalUnavailable();
2589
- let value = await proof(retained.credential);
2794
+ let value = await proof(retained2.credential);
2590
2795
  if (stored() !== candidate || serialized !== candidate)
2591
2796
  return await synchronize(), context2();
2592
2797
  if (!current2()) throw new Error();
2593
2798
  if (expiry && binding && value.expiresAt > binding.expiresAt) throw new Error();
2594
- return (!expiry || value.expiresAt !== binding.expiresAt) && install(value, retained, candidate), context2();
2799
+ return (!expiry || value.expiresAt !== binding.expiresAt) && install(value, retained2, candidate), context2();
2595
2800
  } catch (error) {
2596
2801
  if (alive() && error instanceof AppRenewalUnavailable)
2597
2802
  throw new Error();
@@ -2606,7 +2811,12 @@ function appContext(origin, active2) {
2606
2811
  }, resolve = () => resolution2 || (resolution2 = resolveOnce().finally(() => {
2607
2812
  resolution2 = void 0;
2608
2813
  }), resolution2);
2609
- return { resolve, start: () => {
2814
+ return { resolve, retained: async () => {
2815
+ if (!expiry && alive() && (binding ? current2() && resolution2 : readPair(stored()).context.expiresAt > Date.now()))
2816
+ return resolve();
2817
+ if (!expiry || !current2()) throw new Error("Local app context unavailable.");
2818
+ return context2();
2819
+ }, start: () => {
2610
2820
  startup = setTimeout(() => {
2611
2821
  alive() && !resolution2 && !binding && resolve().catch(() => {
2612
2822
  });
@@ -2627,9 +2837,9 @@ function validPair(value) {
2627
2837
  return validProof(pair.credential) && validProof(pair.renewalCredential) && pair.credential !== pair.renewalCredential && validBinding(pair.context);
2628
2838
  }
2629
2839
 
2630
- var unavailable2 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable");
2840
+ var unavailable3 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable");
2631
2841
  function hostFailure(error, context2) {
2632
- return !context2.isCurrent() || context2.expiresAt <= Date.now() || error instanceof InboxContextError && error.status === 401 ? stale() : error instanceof InboxContextError && error.status === 403 ? new InboxOperationError(403, "access_denied") : unavailable2();
2842
+ return !context2.isCurrent() || context2.expiresAt <= Date.now() || error instanceof InboxContextError && error.status === 401 ? stale() : error instanceof InboxContextError && error.status === 403 ? new InboxOperationError(403, "access_denied") : unavailable3();
2633
2843
  }
2634
2844
  async function send2(operation2, input) {
2635
2845
  let envelope = parseInboxRequest({ operation: operation2, input }), context2;
@@ -2649,12 +2859,12 @@ async function send2(operation2, input) {
2649
2859
  [400, 401, 403, 409].includes(response2.status) ? response2.status : 503,
2650
2860
  response2.status === 400 ? "invalid_input" : response2.status === 401 ? "authority_unavailable" : response2.status === 403 ? "access_denied" : response2.status === 409 ? "conflict" : "unavailable"
2651
2861
  );
2652
- if (response2.status !== 200) throw unavailable2();
2862
+ if (response2.status !== 200) throw unavailable3();
2653
2863
  let parsed = parseInboxResult(operation2, value);
2654
- if (check2(), operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable2();
2864
+ if (check2(), operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable3();
2655
2865
  return parsed;
2656
2866
  } catch (error) {
2657
- throw check2(), error instanceof InboxOperationError ? error : unavailable2();
2867
+ throw check2(), error instanceof InboxOperationError ? error : unavailable3();
2658
2868
  }
2659
2869
  }
2660
2870
  if (context2.endpoint !== `https://${context2.workspace}.oddington.ai` || ["auth", "www", "api", "os"].includes(context2.workspace)) throw stale();
@@ -2665,7 +2875,7 @@ async function send2(operation2, input) {
2665
2875
  } catch (error) {
2666
2876
  throw hostFailure(error, context2);
2667
2877
  }
2668
- if (!host) throw unavailable2();
2878
+ if (!host) throw unavailable3();
2669
2879
  }
2670
2880
  let check = () => {
2671
2881
  if (!context2.isCurrent() || host && !host.isCurrent() || !Number.isFinite(context2.expiresAt) || context2.expiresAt <= Date.now()) throw stale();
@@ -2695,9 +2905,9 @@ async function send2(operation2, input) {
2695
2905
  );
2696
2906
  if (response2.status !== 200)
2697
2907
  throw response2.body?.cancel().catch(() => {
2698
- }), unavailable2();
2908
+ }), unavailable3();
2699
2909
  if (operation2 === "files.read") {
2700
- if (!response2.body) throw unavailable2();
2910
+ if (!response2.body) throw unavailable3();
2701
2911
  let source = response2.body, reader, size = 0, cancel = async (reason) => {
2702
2912
  try {
2703
2913
  await (reader ? reader.cancel(reason) : source.cancel(reason));
@@ -2713,7 +2923,7 @@ async function send2(operation2, input) {
2713
2923
  reader.releaseLock(), controller.close();
2714
2924
  return;
2715
2925
  }
2716
- if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable2();
2926
+ if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable3();
2717
2927
  controller.enqueue(next.value);
2718
2928
  } catch (error) {
2719
2929
  controller.error(error), await cancel(error).catch(() => {
@@ -2725,16 +2935,16 @@ async function send2(operation2, input) {
2725
2935
  return new Response(body, { status: response2.status, headers: response2.headers });
2726
2936
  }
2727
2937
  let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
2728
- if (check(), !bytes) throw unavailable2();
2938
+ if (check(), !bytes) throw unavailable3();
2729
2939
  let value = JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes)), parsed = parseInboxResult(operation2, value);
2730
- if (check(), operation2 === "current" && parsed.workspace.slug !== context2.workspace) throw unavailable2();
2940
+ if (check(), operation2 === "current" && parsed.workspace.slug !== context2.workspace) throw unavailable3();
2731
2941
  if ("itemId" in envelope.input) {
2732
2942
  let item = operation2 === "items.read" ? parsed : operation2 === "items.rename" || operation2 === "items.setLifecycle" || operation2 === "items.addRecipient" ? parsed.item : void 0;
2733
- if (item && (item.id !== envelope.input.itemId || "revision" in envelope.input && item.revision !== envelope.input.revision) || operation2 === "items.addRecipient" && parsed.addedPersonId !== envelope.input.personId || operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable2();
2943
+ if (item && (item.id !== envelope.input.itemId || "revision" in envelope.input && item.revision !== envelope.input.revision) || operation2 === "items.addRecipient" && parsed.addedPersonId !== envelope.input.personId || operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable3();
2734
2944
  }
2735
2945
  return parsed;
2736
2946
  } catch (error) {
2737
- throw check(), error instanceof InboxOperationError ? error : unavailable2();
2947
+ throw check(), error instanceof InboxOperationError ? error : unavailable3();
2738
2948
  }
2739
2949
  }
2740
2950
  var inbox = {
@@ -2754,14 +2964,14 @@ var inbox = {
2754
2964
  throw hostFailure(error, initial);
2755
2965
  }
2756
2966
  if (initial.kind === "local") throw new InboxOperationError(403, "access_denied");
2757
- if (!host) throw unavailable2();
2967
+ if (!host) throw unavailable3();
2758
2968
  let check = () => {
2759
2969
  if (!initial.isCurrent() || !host.isCurrent() || initial.expiresAt <= Date.now()) throw stale();
2760
2970
  };
2761
2971
  do {
2762
2972
  check();
2763
2973
  let page = await send2("items.list", beforeNumber === void 0 ? {} : { beforeNumber });
2764
- if (check(), beforeNumber !== void 0 && (page.items.some((item) => item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable2();
2974
+ if (check(), beforeNumber !== void 0 && (page.items.some((item) => item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable3();
2765
2975
  if (items.push(...page.items), page.nextBeforeNumber === null) return items;
2766
2976
  beforeNumber = page.nextBeforeNumber;
2767
2977
  } while (!0);
@@ -2795,7 +3005,7 @@ var inbox = {
2795
3005
  routines,
2796
3006
  ...beforeNumber === void 0 ? {} : { beforeNumber }
2797
3007
  });
2798
- if (check(), page.questions.some((question2) => question2.inboxUrl !== `https://${initial.workspace}.oddington.ai/inbox/${question2.itemId}` || !routines.includes(question2.routine)) || beforeNumber !== void 0 && page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber) throw unavailable2();
3008
+ if (check(), page.questions.some((question2) => question2.inboxUrl !== `https://${initial.workspace}.oddington.ai/inbox/${question2.itemId}` || !routines.includes(question2.routine)) || beforeNumber !== void 0 && page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber) throw unavailable3();
2799
3009
  if (questions.push(...page.questions), page.nextBeforeNumber === null) return questions;
2800
3010
  beforeNumber = page.nextBeforeNumber;
2801
3011
  } while (!0);
@@ -2832,8 +3042,8 @@ function init({ auth: input }) {
2832
3042
  url.protocol === "https:" && !url.port && !url.username && !url.password && !url.search && !url.hash && url.pathname === "/" && /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(slug) && slug !== "auth" && (endpoint = url.origin, workspace = slug);
2833
3043
  } catch {
2834
3044
  }
2835
- let active2 = !0, revision = 0, person, token, binding = {}, local2 = localOrigin ? appContext(localOrigin, () => active2) : void 0, subscription, stopDisposal, uninstall = installMemberContext(async () => {
2836
- if (local2) return local2.resolve();
3045
+ let active2 = !0, revision = 0, person, token, binding = {}, local3 = localOrigin ? appContext(localOrigin, () => active2) : void 0, subscription, stopDisposal, resolve = async () => {
3046
+ if (local3) return local3.resolve();
2837
3047
  if (!active2 || !endpoint || !workspace || globalThis.location.origin !== endpoint) throw new Error("Hosted Data context unavailable.");
2838
3048
  let started = revision, { data: { session }, error } = await auth2.getSession();
2839
3049
  if (!active2 || globalThis.location.origin !== endpoint || started !== revision || error || !session || person !== void 0 && person !== session.user.id)
@@ -2852,13 +3062,13 @@ function init({ auth: input }) {
2852
3062
  memberId: session.user.id,
2853
3063
  binding
2854
3064
  };
2855
- }), dispose = () => {
2856
- active2 && (active2 = !1, local2?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
3065
+ }, uninstall = installMemberContext(resolve, local3 ? local3.retained : resolve), dispose = () => {
3066
+ active2 && (active2 = !1, local3?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
2857
3067
  };
2858
3068
  installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((event, session) => {
2859
3069
  let next = session?.user.id ?? null;
2860
- (event === "SIGNED_OUT" || person !== void 0 && next !== person || registered && person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++, local2?.invalidate()), person = next, token = session?.access_token;
2861
- }).data.subscription, local2?.start());
3070
+ (event === "SIGNED_OUT" || person !== void 0 && next !== person || registered && person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++, local3?.invalidate()), person = next, token = session?.access_token;
3071
+ }).data.subscription, local3?.start());
2862
3072
  }
2863
3073
  var os = { init };
2864
3074
 
@@ -3303,16 +3513,16 @@ function current(context2) {
3303
3513
  function appDescriptors() {
3304
3514
  return globalThis[/* @__PURE__ */ Symbol.for("oddington.app.descriptor")]?.routines ?? [];
3305
3515
  }
3306
- async function local() {
3307
- let context2 = await resolveAppContext().catch(() => fail3("authority_unavailable"));
3516
+ async function local2(retained = !1) {
3517
+ let context2 = await resolveAppContext(retained).catch(() => fail3("authority_unavailable"));
3308
3518
  return context2.kind !== "local" ? fail3("execution_unavailable") : (current(context2), context2);
3309
3519
  }
3310
- async function request(key, suffix, init2, maximum = SUMMARY_BYTES, retained) {
3520
+ async function request(key, suffix, init2, maximum = SUMMARY_BYTES, retained, read2 = !1) {
3311
3521
  (!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable");
3312
- let context2 = retained ?? await local();
3522
+ let context2 = retained ?? await local2(read2);
3313
3523
  current(context2);
3314
3524
  try {
3315
- let response2 = await context2.requestRoutine(key, suffix, init2), value = await appResponse(response2, maximum, context2.signal);
3525
+ let response2 = await (read2 ? context2.requestRetainedRoutine(key, suffix) : context2.requestRoutine(key, suffix, init2)), value = await appResponse(response2, maximum, context2.signal);
3316
3526
  if (current(context2), !response2.ok) {
3317
3527
  let reason = value?.error;
3318
3528
  reason === "authority_unavailable" && (context2.invalidate(), fail3(reason)), (reason === "invalid_input" || reason === "execution_unavailable") && fail3(reason), fail3("execution_unavailable");
@@ -3358,11 +3568,15 @@ function structure(value) {
3358
3568
  return JSON.stringify(value, (_key, item) => item && typeof item == "object" && !Array.isArray(item) ? Object.fromEntries(Object.keys(item).sort().map((key) => [key, item[key]])) : item);
3359
3569
  }
3360
3570
  function handle(key, id3, context2) {
3361
- return (typeof id3 != "string" || !uuid.test(id3)) && fail3("invalid_input"), routineRunHandle({
3362
- current: async () => summary(await request(key, `runs/${id3}`, void 0, SUMMARY_BYTES, context2), key, id3),
3571
+ (!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable"), (typeof id3 != "string" || !uuid.test(id3)) && fail3("invalid_input");
3572
+ let read2 = async () => summary(await request(key, `runs/${id3}`, void 0, SUMMARY_BYTES, context2, !0), key, id3);
3573
+ return routineRunHandle({
3574
+ async current() {
3575
+ return current(context2), read2();
3576
+ },
3363
3577
  async step(step) {
3364
3578
  (typeof step != "string" || !identifier.test(step)) && fail3("invalid_input");
3365
- let value = await request(key, `runs/${id3}/steps/${step}`, void 0, 514 * 1024, context2);
3579
+ let value = await request(key, `runs/${id3}/steps/${step}`, void 0, 514 * 1024, context2, !0);
3366
3580
  return (!only(value, "id,title,status,startedAt,finishedAt,summary,data") || value.id !== step || !validStep(value)) && fail3("execution_unavailable"), value;
3367
3581
  },
3368
3582
  async publish() {
@@ -3373,7 +3587,7 @@ function handle(key, id3, context2) {
3373
3587
  async function describeAppRoutine(key) {
3374
3588
  let descriptor = appDescriptors().find((item) => item.id === key);
3375
3589
  if (!descriptor) return fail3("authority_unavailable");
3376
- let unavailable3 = () => ({
3590
+ let unavailable4 = () => ({
3377
3591
  ...structuredClone(descriptor),
3378
3592
  connections: descriptor.connections.map((connection) => ({ ...connection, available: !1 })),
3379
3593
  readiness: { state: "unavailable", reason: "capability_unavailable", message: "Routine capability unavailable." }
@@ -3382,11 +3596,11 @@ async function describeAppRoutine(key) {
3382
3596
  let value = await request(key, "describe", void 0, 1048576);
3383
3597
  return (!only(value, "id,title,input,connections,steps,readiness") || !value.readiness || !Array.isArray(value.connections) || structure({ ...value, readiness: void 0, connections: value.connections.map(({ available, ...item }) => item) }) !== structure(descriptor) || value.connections.some((item) => typeof item.available != "boolean") || !(value.readiness.state === "ready" && only(value.readiness, "state,placement") && value.readiness.placement === "local" || value.readiness.state === "unavailable" && only(value.readiness, "state,reason,message") && ["not_deployed", "definition_invalid", "capability_unavailable"].includes(value.readiness.reason) && message(value.readiness.message))) && fail3("execution_unavailable"), value;
3384
3598
  } catch {
3385
- return unavailable3();
3599
+ return unavailable4();
3386
3600
  }
3387
3601
  }
3388
3602
  function appRoutineBinding(key) {
3389
- return Object.freeze({
3603
+ return (typeof key != "string" || !identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable"), Object.freeze({
3390
3604
  describe: () => describeAppRoutine(key),
3391
3605
  async run(...args) {
3392
3606
  args.length > 1 && fail3("invalid_input");
@@ -3401,19 +3615,18 @@ function appRoutineBinding(key) {
3401
3615
  } catch {
3402
3616
  return fail3("invalid_input");
3403
3617
  }
3404
- let context2 = await local(), run = summary(await request(key, "runs", { method: "POST", body: encoded }, SUMMARY_BYTES, context2), key);
3618
+ let context2 = await local2(), run = summary(await request(key, "runs", { method: "POST", body: encoded }, SUMMARY_BYTES, context2), key);
3405
3619
  return handle(key, run.id, context2);
3406
3620
  },
3407
3621
  runs: Object.freeze({
3408
3622
  async list() {
3409
- let value = await request(key, "runs", void 0, 20 * SUMMARY_BYTES);
3623
+ let value = await request(key, "runs", void 0, 20 * SUMMARY_BYTES, void 0, !0);
3410
3624
  if (!Array.isArray(value) || value.length > 20) return fail3("execution_unavailable");
3411
3625
  let runs = value.map((run) => summary(run, key));
3412
3626
  return new Set(runs.map((run) => run.id)).size !== runs.length && fail3("execution_unavailable"), runs;
3413
3627
  },
3414
3628
  async get(id3) {
3415
- let run = handle(key, id3, await local());
3416
- return await run.current(), run;
3629
+ return (typeof id3 != "string" || !uuid.test(id3)) && fail3("invalid_input"), (!identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable"), handle(key, id3, await local2(!0));
3417
3630
  }
3418
3631
  })
3419
3632
  });
@@ -3421,6 +3634,7 @@ function appRoutineBinding(key) {
3421
3634
 
3422
3635
  var app = Object.freeze({
3423
3636
  listRoutines: () => Promise.all(appDescriptors().map(({ id: id3 }) => describeAppRoutine(id3))),
3637
+ routine: appRoutineBinding,
3424
3638
  routines: new Proxy(/* @__PURE__ */ Object.create(null), {
3425
3639
  get(_target, key) {
3426
3640
  if (!(typeof key != "string" || !appDescriptors().some((item) => item.id === key)))
@@ -3460,10 +3674,10 @@ function routineDataEnvelope(command) {
3460
3674
  }
3461
3675
 
3462
3676
  function routinePublicationClient2(options = {}) {
3463
- let environment = {}, installed2 = routineTransport(), local2 = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE, capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
3677
+ let environment = {}, installed2 = routineTransport(), local3 = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.OS_ROUTINE_WORKSPACE, capability = options.capability ?? environment.OS_ROUTINE_RUN;
3464
3678
  if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
3465
3679
  throw new Error("A workspace and valid optional routine capability are required");
3466
- let workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-oddington-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
3680
+ let workingRoot = options.workingRoot ?? environment.OS_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-os-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
3467
3681
  if (path === "/api/data") return fetch(`https://${workspace}.oddington.ai/api/data`, { ...init2, redirect: "error" });
3468
3682
  let origin = `https://${workspace}.oddington.ai`, target = new URL(path, `${origin}/`);
3469
3683
  if (workspace.length > 63 || ["auth", "www", "api", "os"].includes(workspace) || target.origin !== origin || target.search || target.hash || target.username || target.password || !/^\/api\/inbox\/(check|publish|resolve|files)$/.test(path) || init2?.method !== "POST")
@@ -3473,13 +3687,13 @@ function routinePublicationClient2(options = {}) {
3473
3687
  throw new Error("Member publication requires a host-supplied request");
3474
3688
  });
3475
3689
  async function send3(operation2, body) {
3476
- if (local2) return await local2(operation2, body);
3690
+ if (local3) return await local3(operation2, body);
3477
3691
  let writing = operation2 === "records/update", reading = operation2 === "records/read", response2 = await request2(writing || reading ? "/api/data" : `/api/inbox/${operation2}`, {
3478
3692
  method: "POST",
3479
3693
  headers: {
3480
3694
  "content-type": "application/json",
3481
3695
  ...headers,
3482
- ...writing || reading ? { "x-oddington-workspace": workspace, "x-oddington-captured-records": "1" } : {}
3696
+ ...writing || reading ? { "x-os-workspace": workspace, "x-os-captured-records": "1" } : {}
3483
3697
  },
3484
3698
  body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(body)) : reading ? { operation: "records.select", request: validateRecordRead(body) } : body)
3485
3699
  }), result2 = await response2.json();
@@ -3520,7 +3734,7 @@ function routinePublicationClient2(options = {}) {
3520
3734
  files: {
3521
3735
  async add(value) {
3522
3736
  let input = validateFileAddOptions(value);
3523
- if (local2) return validateInboxFile(await local2("files/add", input));
3737
+ if (local3) return validateInboxFile(await local3("files/add", input));
3524
3738
  throw workingRoot ? new Error("Inbox file reads require a Node working root") : new Error("Inbox file reads require a working root");
3525
3739
  }
3526
3740
  },