@oddington/sdk 0.1.23 → 0.1.25

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
@@ -405,44 +405,51 @@ var FileOperationError = class extends Error {
405
405
  retryable;
406
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;
407
407
  function parseFileDescriptor(value) {
408
- let invalid7 = () => {
408
+ let invalid8 = () => {
409
409
  throw new FileOperationError("unavailable", 503, !0);
410
410
  };
411
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
411
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
412
412
  let f = value;
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 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();
414
414
  let d = f.details;
415
415
  if (d.kind === "other") {
416
- if (Object.keys(d).length !== 1 || f.mediaType !== "application/octet-stream") return invalid7();
416
+ if (Object.keys(d).length !== 1 || ![
417
+ "application/octet-stream",
418
+ "text/plain",
419
+ "text/markdown",
420
+ "application/json",
421
+ "image/png",
422
+ "image/jpeg"
423
+ ].includes(f.mediaType)) return invalid8();
417
424
  } else if (d.kind === "csv") {
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 invalid7();
425
+ 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();
419
426
  } else if (d.kind === "pdf") {
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 invalid7();
421
- } else return invalid7();
427
+ 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();
428
+ } else return invalid8();
422
429
  for (let [name, descriptor] of Object.entries(f.enrichments)) {
423
- if (!safeEnrichmentName(name)) return invalid7();
430
+ if (!safeEnrichmentName(name)) return invalid8();
424
431
  parseEnrichmentDescriptor(descriptor);
425
432
  }
426
- return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ? invalid7() : f;
433
+ return new TextEncoder().encode(JSON.stringify(f)).byteLength > 16 * 1024 ? invalid8() : f;
427
434
  }
428
435
  function parseEnrichmentDescriptor(value) {
429
- let invalid7 = () => {
436
+ let invalid8 = () => {
430
437
  throw new FileOperationError("unavailable", 503, !0);
431
438
  };
432
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
439
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
433
440
  let d = value;
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) ? invalid7() : d;
441
+ 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;
435
442
  }
436
443
  function safeEnrichmentName(value) {
437
444
  return safeFileName(value) && !/^original(?:\.|$)/i.test(value);
438
445
  }
439
446
  function parseFileEnrichMetadata(value, maxBytes) {
440
- let invalid7 = () => {
447
+ let invalid8 = () => {
441
448
  throw new FileOperationError("invalid_input", 400);
442
449
  };
443
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
450
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
444
451
  let d = value;
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 invalid7();
452
+ 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();
446
453
  if (d.size > maxBytes) throw new FileOperationError("request_too_large", 413);
447
454
  return d;
448
455
  }
@@ -452,31 +459,36 @@ function safeFileName(value) {
452
459
  function safeFilePath(value) {
453
460
  return typeof value == "string" && value.length <= 1024 && value.split("/").every(safeFileName);
454
461
  }
462
+ var ORIGINAL_MEDIA_TYPES = ["application/pdf", "text/plain", "text/markdown", "application/json", "image/png", "image/jpeg"];
463
+ function declaredOriginalMediaType(value) {
464
+ let normalized = value.split(";", 1)[0].trim().toLowerCase();
465
+ return ORIGINAL_MEDIA_TYPES.includes(normalized) ? normalized : void 0;
466
+ }
455
467
  function parseFileCreateMetadata(value, maxBytes) {
456
- let invalid7 = () => {
468
+ let invalid8 = () => {
457
469
  throw new FileOperationError("invalid_input", 400);
458
470
  };
459
- if (!value || typeof value != "object" || Array.isArray(value)) return invalid7();
471
+ if (!value || typeof value != "object" || Array.isArray(value)) return invalid8();
460
472
  let input = value;
461
- if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "inputMediaType", "size", "requestKey"].includes(key))) return invalid7();
473
+ if (Object.keys(input).some((key) => !["name", "path", "storage", "csv", "inputMediaType", "size", "requestKey"].includes(key))) return invalid8();
462
474
  let path = input.path === void 0 ? "Files" : input.path;
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 invalid7();
475
+ 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 && (typeof input.inputMediaType != "string" || !ORIGINAL_MEDIA_TYPES.includes(input.inputMediaType)) || !Number.isSafeInteger(input.size) || input.size < 0) return invalid8();
464
476
  if (input.size > maxBytes) throw new FileOperationError("request_too_large", 413);
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 invalid7();
477
+ 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();
466
478
  let csv;
467
479
  if (input.csv !== void 0) {
468
- if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return invalid7();
480
+ if (!input.csv || typeof input.csv != "object" || Array.isArray(input.csv)) return invalid8();
469
481
  let hints = input.csv;
470
- if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return invalid7();
482
+ if (Object.keys(hints).some((key) => !["encoding", "delimiter", "headerRow"].includes(key))) return invalid8();
471
483
  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;
472
- if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return invalid7();
484
+ if (encoding !== "utf-8" && encoding !== "windows-1252" || ![",", ";", " "].includes(delimiter) || !Number.isSafeInteger(headerRow) || headerRow < 1 || headerRow > 1e5) return invalid8();
473
485
  csv = { encoding, delimiter, headerRow };
474
486
  }
475
487
  return {
476
488
  name: input.name,
477
489
  path,
478
490
  ...input.storage ? { storage: input.storage } : {},
479
- ...input.inputMediaType === "application/pdf" ? { inputMediaType: input.inputMediaType } : {},
491
+ ...input.inputMediaType === void 0 ? {} : { inputMediaType: input.inputMediaType },
480
492
  ...csv ? { csv } : {},
481
493
  size: input.size,
482
494
  requestKey: input.requestKey
@@ -590,14 +602,16 @@ function validateRoutineSchemaValue(schema2, value) {
590
602
  var ROUTINE_DECLARATION_SCHEMA = "https://schemas.oddington.ai/routine/v1.json", ROUTINE_SOURCE_LIMITS = { files: 2e4, bytes: 256 * 1024 * 1024, declarationBytes: 64 * 1024 };
591
603
  var invalid = (field) => {
592
604
  throw new Error(`Invalid routine declaration: ${field}`);
593
- }, object2 = (value, fields5, field) => ((!value || typeof value != "object" || Array.isArray(value) || Object.keys(value).some((key) => !fields5.includes(key))) && invalid(field), value), routineAlias = (value) => typeof value == "string" && /^[a-z][a-z0-9-]{0,62}$/.test(value), list = (value, field, allowed, qualified = !1) => value === void 0 ? [] : ((!Array.isArray(value) || value.length > 64 || value.some((item) => !(routineAlias(item) || qualified && typeof item == "string" && item.split("/").length === 2 && item.split("/").every(routineAlias)) || allowed && !allowed.includes(item)) || new Set(value).size !== value.length) && invalid(field), [...value].sort());
605
+ }, object2 = (value, fields5, field) => ((!value || typeof value != "object" || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null || Reflect.ownKeys(value).some((key) => typeof key != "string" || !fields5.includes(key) || !Object.getOwnPropertyDescriptor(value, key).enumerable || !Object.hasOwn(Object.getOwnPropertyDescriptor(value, key), "value"))) && invalid(field), value), routineAlias = (value) => typeof value == "string" && /^[a-z][a-z0-9-]{0,62}$/.test(value), list = (value, field, allowed, qualified = !1) => value === void 0 ? [] : ((!Array.isArray(value) || value.length > 64 || value.some((item) => !(routineAlias(item) || qualified && typeof item == "string" && item.split("/").length === 2 && item.split("/").every(routineAlias)) || allowed && !allowed.includes(item)) || new Set(value).size !== value.length) && invalid(field), [...value].sort());
594
606
  function routineAssetPattern(value) {
595
607
  return typeof value == "string" && value.length <= 512 && !value.startsWith("/") && !value.includes("\\") && !value.includes(":") && value.split("/").every((part) => !!part && part !== "." && part !== ".." && /^[a-zA-Z0-9_.*-]+$/.test(part));
596
608
  }
597
609
  function parseRoutineDeclaration(value) {
598
610
  let v = object2(value, ["$schema", "access", "runtime", "retry", "assets"], "fields");
599
611
  v.$schema !== ROUTINE_DECLARATION_SCHEMA && invalid("$schema");
600
- let access = object2(v.access === void 0 ? {} : v.access, ["repositories", "connections", "models", "files", "publish"], "access"), rawRepositories = access.repositories === void 0 ? {} : access.repositories, repositories = object2(rawRepositories, rawRepositories && typeof rawRepositories == "object" ? Object.keys(rawRepositories) : [], "access.repositories");
612
+ let access = object2(v.access === void 0 ? {} : v.access, ["repositories", "connections", "ai", "files", "publish"], "access");
613
+ Object.hasOwn(access, "ai") && access.ai !== !0 && invalid("access.ai");
614
+ let rawRepositories = access.repositories === void 0 ? {} : access.repositories, repositories = object2(rawRepositories, rawRepositories && typeof rawRepositories == "object" ? Object.keys(rawRepositories) : [], "access.repositories");
601
615
  Object.keys(repositories).length > 64 && invalid("access.repositories");
602
616
  let grants = {};
603
617
  for (let key of Object.keys(repositories).sort())
@@ -615,7 +629,7 @@ function parseRoutineDeclaration(value) {
615
629
  access: {
616
630
  repositories: grants,
617
631
  connections: list(access.connections, "access.connections", void 0, !0),
618
- models: list(access.models, "access.models"),
632
+ ...access.ai === !0 ? { ai: !0 } : {},
619
633
  ...access.files === void 0 ? {} : { files: access.files },
620
634
  publish: list(access.publish, "access.publish", ["asks", "digests"])
621
635
  },
@@ -663,7 +677,7 @@ function assertRoutineFields(value, allowed) {
663
677
  }
664
678
  function parseRoutineAccess(value) {
665
679
  try {
666
- value !== void 0 && assertRoutineJson(value), assertRoutineFields(value ?? {}, ["repositories", "connections", "models", "files", "publish"]);
680
+ value !== void 0 && assertRoutineJson(value), assertRoutineFields(value ?? {}, ["repositories", "connections", "ai", "files", "publish"]);
667
681
  let access = value, names = access?.connections ?? [];
668
682
  if (!Array.isArray(names) || names.length > 64 || new Set(names).size !== names.length || names.some((name) => typeof name != "string" || name.split("/").length !== 2 || name.split("/").some((part) => !isAppRoutineName(part)))) return invalidContract2();
669
683
  let parsed = parseRoutineDeclaration({ $schema: ROUTINE_DECLARATION_SCHEMA, access: { ...access, connections: [] } }).access;
@@ -673,6 +687,52 @@ function parseRoutineAccess(value) {
673
687
  }
674
688
  }
675
689
 
690
+ var ROUTINE_AI_VALUE_BYTES = 256 * 1024, ROUTINE_AI_EVIDENCE_BYTES = 4 * 1024;
691
+ var RoutineAIError = class extends Error {
692
+ constructor(code) {
693
+ super(code);
694
+ this.code = code;
695
+ this.name = "RoutineAIError";
696
+ }
697
+ code;
698
+ };
699
+ function capture(value, invalid8, oversized) {
700
+ try {
701
+ assertRoutineJson(value);
702
+ let encoded = JSON.stringify(value);
703
+ if (new TextEncoder().encode(encoded).byteLength > ROUTINE_AI_VALUE_BYTES) throw new RoutineAIError(oversized);
704
+ return freezeRoutineMetadata(JSON.parse(encoded));
705
+ } catch (error) {
706
+ throw error instanceof RoutineAIError ? error : new RoutineAIError(invalid8);
707
+ }
708
+ }
709
+ function parseRoutineAIRequest(value) {
710
+ let v = capture(value, "invalid_input", "input_too_large");
711
+ try {
712
+ if (assertRoutineFields(v, v.kind === "generateObject" ? ["kind", "instructions", "input", "schema"] : ["kind", "instructions", "input"]), !["generateText", "generateObject"].includes(v.kind) || typeof v.instructions != "string" || !v.instructions.trim()) throw new Error();
713
+ let input = typeof v.input == "string" ? v.input : parseFileDescriptor(v.input);
714
+ if (v.kind === "generateText") return freezeRoutineMetadata({ kind: v.kind, instructions: v.instructions, input });
715
+ let schema2 = parseAppRoutineContract({ routine: "ai", input: v.schema, steps: [{ id: "generate" }] }).input;
716
+ return freezeRoutineMetadata({ kind: v.kind, instructions: v.instructions, input, schema: schema2 });
717
+ } catch {
718
+ throw new RoutineAIError("invalid_input");
719
+ }
720
+ }
721
+ function parseRoutineAIResult(request2, value) {
722
+ let v = capture(value, "invalid_output", "output_too_large");
723
+ try {
724
+ if (request2.kind === "generateText") {
725
+ if (assertRoutineFields(v, ["text"]), typeof v.text != "string" || !v.text.trim()) throw new Error();
726
+ return freezeRoutineMetadata({ text: v.text });
727
+ } else {
728
+ if (assertRoutineFields(v, ["object"]), !Object.hasOwn(v, "object")) throw new Error();
729
+ return validateRoutineSchemaValue(request2.schema, v.object), freezeRoutineMetadata({ object: v.object });
730
+ }
731
+ } catch {
732
+ throw new RoutineAIError("invalid_output");
733
+ }
734
+ }
735
+
676
736
  var LIMIT = 256 * 1024, invalid3 = () => {
677
737
  throw new AppRoutineContractError("invalid_value");
678
738
  }, invalidContract3 = () => {
@@ -683,7 +743,7 @@ function captureJson(value) {
683
743
  let encoded = JSON.stringify(value);
684
744
  return new TextEncoder().encode(encoded).byteLength > LIMIT ? invalid3() : freezeRoutineMetadata(JSON.parse(encoded));
685
745
  }
686
- function capture(schema2, value) {
746
+ function capture2(schema2, value) {
687
747
  let captured = captureJson(value);
688
748
  return validateRoutineSchemaValue(schema2, captured), captured;
689
749
  }
@@ -709,7 +769,7 @@ function declaration(value, defaults) {
709
769
  } catch {
710
770
  return invalidContract3();
711
771
  }
712
- let parsed = freezeRoutineMetadata(parseAppRoutineContract({ routine: "definition", input: value, steps: [{ id: "inspect" }] }).input), captured = defaults ? capture(parsed, defaults.value) : void 0, builder = Object.defineProperty({ ...parsed }, "default", { value: (value2) => declaration(parsed, { value: value2 }) });
772
+ let parsed = freezeRoutineMetadata(parseAppRoutineContract({ routine: "definition", input: value, steps: [{ id: "inspect" }] }).input), captured = defaults ? capture2(parsed, defaults.value) : void 0, builder = Object.defineProperty({ ...parsed }, "default", { value: (value2) => declaration(parsed, { value: value2 }) });
713
773
  return schemas.set(builder, { schema: parsed, ...defaults ? { default: captured } : {} }), Object.freeze(builder);
714
774
  }
715
775
  var schema = {
@@ -794,10 +854,32 @@ function inspectRoutineDefinition(definition) {
794
854
  }
795
855
  function captureRoutineInput(definition, input) {
796
856
  let contract = inspectRoutineDefinition(definition);
797
- return capture(contract.input, input === void 0 && Object.hasOwn(contract, "inputDefault") ? contract.inputDefault : input);
857
+ return capture2(contract.input, input === void 0 && Object.hasOwn(contract, "inputDefault") ? contract.inputDefault : input);
798
858
  }
799
859
  async function executeRoutineDefinition(definition, input, runtime) {
800
- let captured = captureRoutineInput(definition, input), { contract, steps, run } = definitions.get(definition), active2 = !0, accepting = !0, broken = !1, work = Promise.resolve(), called = /* @__PURE__ */ new Set(), reached = /* @__PURE__ */ new Set(), guarded = (value, receiver) => typeof value == "function" ? (...args) => {
860
+ let captured = captureRoutineInput(definition, input), { contract, steps, run } = definitions.get(definition), active2 = !0, accepting = !0, broken = !1, work = Promise.resolve(), aiFailure, aiWork = /* @__PURE__ */ new Set(), generate = (kind, value) => {
861
+ let operation2 = (async () => {
862
+ if (!active2 || broken || contract.access.ai !== !0) throw new RoutineAIError("access_denied");
863
+ if (!runtime.ai) throw new RoutineAIError("capability_unavailable");
864
+ let request2;
865
+ try {
866
+ assertRoutineFields(value, kind === "generateObject" ? ["instructions", "input", "schema"] : ["instructions", "input"]), request2 = parseRoutineAIRequest({
867
+ kind,
868
+ instructions: value.instructions,
869
+ input: value.input,
870
+ ...kind === "generateObject" ? { schema: schemaMetadata(value.schema).schema } : {}
871
+ });
872
+ } catch (error) {
873
+ throw error instanceof RoutineAIError ? error : new RoutineAIError("invalid_input");
874
+ }
875
+ let result3 = await runtime.ai[kind](request2);
876
+ if (!active2 || broken) throw new RoutineAIError("access_denied");
877
+ return parseRoutineAIResult(request2, result3);
878
+ })();
879
+ return aiWork.add(operation2), operation2.then(() => aiWork.delete(operation2), (error) => {
880
+ aiFailure ??= error, broken = !0, aiWork.delete(operation2);
881
+ }), operation2;
882
+ }, called = /* @__PURE__ */ new Set(), reached = /* @__PURE__ */ new Set(), guarded = (value, receiver) => typeof value == "function" ? (...args) => {
801
883
  if (!active2 || broken) throw new Error("Run authority ended");
802
884
  return guarded(Reflect.apply(value, receiver, args));
803
885
  } : value && typeof value == "object" && !(value instanceof Promise) ? new Proxy({ ...value }, {
@@ -810,6 +892,10 @@ async function executeRoutineDefinition(definition, input, runtime) {
810
892
  ...guarded({
811
893
  ...runtime,
812
894
  run: freezeRoutineMetadata({ ...runtime.run }),
895
+ ai: {
896
+ generateText: (value) => generate("generateText", value),
897
+ generateObject: (value) => generate("generateObject", value)
898
+ },
813
899
  connections: { ...runtime.connections, get: async (identity) => {
814
900
  if (!active2 || broken || !contract.access.connections?.includes(identity)) throw new Error("Connection unavailable");
815
901
  let value = await runtime.connections.get(identity);
@@ -850,10 +936,11 @@ async function executeRoutineDefinition(definition, input, runtime) {
850
936
  } catch (error) {
851
937
  failure = error, broken = !0;
852
938
  }
853
- accepting = !1, await work, active2 = !1;
939
+ for (accepting = !1, await work; aiWork.size; ) await Promise.allSettled([...aiWork]);
940
+ active2 = !1;
854
941
  for (let step of contract.steps) reached.has(step.id) || await runtime.step(step.id, { status: "skipped" });
855
- if (broken) throw failure ?? new AppRoutineContractError("invalid_value");
856
- if (contract.result !== void 0) return capture(contract.result, result2);
942
+ if (broken) throw failure ?? aiFailure ?? new AppRoutineContractError("invalid_value");
943
+ if (contract.result !== void 0) return capture2(contract.result, result2);
857
944
  if (result2 !== void 0) return invalid3();
858
945
  }
859
946
 
@@ -957,6 +1044,15 @@ function captureRecordsSearchInput(query, options) {
957
1044
  return { query, options: captured };
958
1045
  }
959
1046
 
1047
+ function captureRecordsReadRefs(value) {
1048
+ if (!Array.isArray(value) || value.length < 1 || value.length > 100)
1049
+ throw new DataOperationError("invalid_query");
1050
+ let refs = historyArray(value);
1051
+ if (!refs.every((ref) => validRecordRef(ref) && !/[\r\n]/.test(ref)) || new Set(refs).size !== refs.length)
1052
+ throw new DataOperationError("invalid_query");
1053
+ return refs;
1054
+ }
1055
+
960
1056
  var DATA_REQUEST_LIMIT = 256 * 1024, invalidChange = () => {
961
1057
  throw new DataOperationError("invalid_change", !1, "unapplied");
962
1058
  };
@@ -1109,14 +1205,102 @@ async function resolveFilesContext() {
1109
1205
  }
1110
1206
  function filesContext(workspace, endpoint, headers) {
1111
1207
  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();
1112
- return { url: `${endpoint}/api/files`, headers: { ...headers, "x-oddington-workspace": workspace }, isCurrent: () => !0 };
1208
+ return { url: `${endpoint}/api/files`, headers: { ...headers, "x-os-workspace": workspace }, isCurrent: () => !0 };
1113
1209
  }
1114
1210
  function checked(workspace, endpoint, headers) {
1115
1211
  if (!workspace || !/^[a-z0-9][a-z0-9-]{0,127}$/.test(workspace)) throw new Error();
1116
1212
  let origin = new URL(endpoint);
1117
1213
  if (origin.protocol !== "https:" || origin.username || origin.password || origin.search || origin.hash || origin.pathname !== "/")
1118
1214
  throw new Error();
1119
- return { url: `${origin.origin}/api/data`, headers: { ...headers, "x-oddington-workspace": workspace } };
1215
+ return { url: `${origin.origin}/api/data`, headers: { ...headers, "x-os-workspace": workspace } };
1216
+ }
1217
+
1218
+ var invalid6 = () => {
1219
+ throw new DataOperationError("invalid_query");
1220
+ }, unavailable = () => {
1221
+ throw new DataOperationError("unavailable");
1222
+ }, text2 = (value) => typeof value == "string" && value.length > 0;
1223
+ function capture3(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
1224
+ if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return value;
1225
+ if (!value || typeof value != "object" || ancestors.has(value) || depth > 32) return invalid6();
1226
+ ancestors.add(value);
1227
+ try {
1228
+ return Array.isArray(value) ? historyArray(value).map((item) => capture3(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture3(descriptor.value, ancestors, depth + 1)]));
1229
+ } finally {
1230
+ ancestors.delete(value);
1231
+ }
1232
+ }
1233
+ function recordPagination(select) {
1234
+ function pages(query) {
1235
+ let captured = capture3(query), names = Object.keys(historyProperties(captured));
1236
+ for (let name of names) {
1237
+ let selection2 = historyProperties(captured[name]);
1238
+ if (Object.hasOwn(selection2, "$")) {
1239
+ let options = historyProperties(selection2.$.value);
1240
+ if (Object.hasOwn(options, "after")) return invalid6();
1241
+ }
1242
+ }
1243
+ return iterate();
1244
+ async function* iterate() {
1245
+ let state = new Map(names.map((name) => [name, {
1246
+ seen: /* @__PURE__ */ new Set(),
1247
+ total: 0,
1248
+ count: void 0,
1249
+ next: void 0
1250
+ }])), active2 = names, version;
1251
+ do {
1252
+ let request2 = Object.fromEntries(active2.map((name) => {
1253
+ let selection2 = captured[name], next = state.get(name).next;
1254
+ return [name, next === void 0 ? selection2 : { ...selection2, $: { ...selection2.$, after: next } }];
1255
+ })), response2 = await select(request2), page;
1256
+ try {
1257
+ page = capture3(response2);
1258
+ let keys4 = Object.keys(historyProperties(page));
1259
+ (keys4.length !== active2.length + 1 || keys4.some((key) => key !== "$meta" && !active2.includes(key))) && unavailable();
1260
+ let meta = page.$meta;
1261
+ (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();
1262
+ for (let name of active2) {
1263
+ let records = historyArray(page[name]), metadata = Object.hasOwn(meta.collections, name) ? meta.collections[name] : {};
1264
+ (Object.keys(historyProperties(metadata)).some((key) => key !== "count" && key !== "next") || Object.hasOwn(metadata, "next") && !text2(metadata.next)) && unavailable();
1265
+ for (let record3 of records) {
1266
+ historyProperties(record3);
1267
+ let row = record3;
1268
+ (!validRecordRef(row.$ref) || !text2(row.$version)) && unavailable();
1269
+ }
1270
+ let current2 = state.get(name);
1271
+ 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;
1272
+ }
1273
+ } catch {
1274
+ return unavailable();
1275
+ }
1276
+ let collections = Object.fromEntries(names.map((name) => {
1277
+ let current2 = state.get(name);
1278
+ return [name, {
1279
+ ...current2.count === void 0 ? {} : { count: current2.count },
1280
+ ...current2.next === void 0 ? {} : { next: current2.next }
1281
+ }];
1282
+ })), output = Object.fromEntries(names.map((name) => [name, active2.includes(name) ? page[name] : []]));
1283
+ active2 = active2.filter((name) => state.get(name).next !== void 0), yield { ...output, $meta: { version, collections } };
1284
+ } while (active2.length);
1285
+ }
1286
+ }
1287
+ async function all(query, options) {
1288
+ let properties = historyProperties(options), maxRecords = properties.maxRecords?.value;
1289
+ (Object.keys(properties).join(",") !== "maxRecords" || !Number.isSafeInteger(maxRecords) || maxRecords < 1) && invalid6();
1290
+ let result2, total = 0;
1291
+ for await (let page of pages(query)) {
1292
+ let names = Object.keys(page.$meta.collections), size = names.reduce((sum, name) => sum + page[name].length, 0);
1293
+ if (size > maxRecords - total) throw new DataOperationError("capacity");
1294
+ total += size, result2 ??= { ...Object.fromEntries(names.map((name) => [name, []])), $meta: page.$meta };
1295
+ for (let name of names) {
1296
+ let target = result2[name];
1297
+ for (let record3 of page[name]) target.push(record3);
1298
+ }
1299
+ result2.$meta = page.$meta;
1300
+ }
1301
+ return result2;
1302
+ }
1303
+ return { pages, all };
1120
1304
  }
1121
1305
 
1122
1306
  var data = {
@@ -1139,13 +1323,20 @@ var data = {
1139
1323
  throw error instanceof DataOperationError ? error : new DataOperationError("unavailable", !0);
1140
1324
  }
1141
1325
  }
1326
+ async function read2(input) {
1327
+ let refs = captureRecordsReadRefs(typeof input == "string" ? [input] : input), result2 = await send3({ operation: "records.read", refs });
1328
+ return typeof input == "string" ? result2.records[0] : result2;
1329
+ }
1330
+ let select = (query) => send3({ operation: "records.select", query });
1142
1331
  return {
1143
1332
  collections: {
1144
1333
  list: () => send3({ operation: "collections.list" }),
1145
1334
  schema: (name) => send3({ operation: "collections.schema", name })
1146
1335
  },
1147
1336
  records: {
1148
- select: (query) => send3({ operation: "records.select", query }),
1337
+ read: read2,
1338
+ select,
1339
+ ...recordPagination(select),
1149
1340
  search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
1150
1341
  },
1151
1342
  history: {
@@ -1270,7 +1461,7 @@ async function hostedContent(url, init2, parent, upstream = fetch, check = async
1270
1461
  }
1271
1462
  }
1272
1463
 
1273
- 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 = {
1464
+ 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 = {
1274
1465
  400: ["invalid_input", "unsupported_context"],
1275
1466
  401: ["unauthenticated"],
1276
1467
  403: ["access_denied"],
@@ -1290,9 +1481,9 @@ async function boundedBytes(stream, limit, signal) {
1290
1481
  try {
1291
1482
  for (; ; ) {
1292
1483
  let { done, value } = await reader.read();
1293
- if (signal?.aborted) throw unavailable();
1484
+ if (signal?.aborted) throw unavailable2();
1294
1485
  if (done) break;
1295
- if (!(value instanceof Uint8Array)) throw invalid6();
1486
+ if (!(value instanceof Uint8Array)) throw invalid7();
1296
1487
  if (size += value.byteLength, size > limit) throw new FileOperationError("request_too_large", 413);
1297
1488
  bytes.set(value, size - value.byteLength);
1298
1489
  }
@@ -1306,7 +1497,7 @@ async function boundedBytes(stream, limit, signal) {
1306
1497
  async function timed(work, parent, timeout = TIMEOUT_MS) {
1307
1498
  let controller = new AbortController(), timer, abort, expiry = new Promise((_, reject) => {
1308
1499
  abort = () => {
1309
- controller.abort(), reject(unavailable());
1500
+ controller.abort(), reject(unavailable2());
1310
1501
  }, timer = setTimeout(abort, timeout), parent?.addEventListener("abort", abort, { once: !0 }), parent?.aborted && abort();
1311
1502
  });
1312
1503
  try {
@@ -1320,12 +1511,12 @@ async function result(response2, maximum = RESULT_BYTES) {
1320
1511
  let bytes = await boundedBytes(response2.body, maximum);
1321
1512
  return JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes));
1322
1513
  } catch {
1323
- throw unavailable();
1514
+ throw unavailable2();
1324
1515
  }
1325
1516
  }
1326
1517
  async function send(suffix, init2, descriptor, initial, parent) {
1327
1518
  let original = initial, checkCurrent = (context2 = original) => {
1328
- if (parent?.aborted) throw unavailable();
1519
+ if (parent?.aborted) throw unavailable2();
1329
1520
  if (!original.isCurrent() || context2.url !== original.url) throw new FileOperationError("unsupported_context", 400);
1330
1521
  };
1331
1522
  for (let attempt = 0; attempt < ATTEMPTS; attempt++) {
@@ -1345,11 +1536,11 @@ async function send(suffix, init2, descriptor, initial, parent) {
1345
1536
  })();
1346
1537
  if (!response2.ok) {
1347
1538
  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);
1348
- throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable();
1539
+ throw code ? new FileOperationError(code, response2.status, code === "capacity" || code === "unavailable") : unavailable2();
1349
1540
  }
1350
1541
  if (response2.status !== (descriptor === 204 ? 204 : 200) || descriptor === 204 && response2.body !== null)
1351
1542
  throw response2.body?.cancel().catch(() => {
1352
- }), unavailable();
1543
+ }), unavailable2();
1353
1544
  try {
1354
1545
  checkCurrent();
1355
1546
  } catch (error) {
@@ -1363,21 +1554,21 @@ async function send(suffix, init2, descriptor, initial, parent) {
1363
1554
  return checkCurrent(), value;
1364
1555
  let parsed;
1365
1556
  if (descriptor === "enrichment") {
1366
- if (!value || typeof value != "object" || Array.isArray(value)) throw unavailable();
1557
+ if (!value || typeof value != "object" || Array.isArray(value)) throw unavailable2();
1367
1558
  let { name, ...metadata } = value;
1368
- if (!safeEnrichmentName(name)) throw unavailable();
1559
+ if (!safeEnrichmentName(name)) throw unavailable2();
1369
1560
  parsed = { name, ...parseEnrichmentDescriptor(metadata) };
1370
1561
  } else parsed = parseFileDescriptor(value);
1371
1562
  return checkCurrent(), parsed;
1372
1563
  } catch (error) {
1373
- let failure = error instanceof FileOperationError ? error : unavailable();
1564
+ let failure = error instanceof FileOperationError ? error : unavailable2();
1374
1565
  if (init2.body instanceof ReadableStream || !failure.retryable || attempt + 1 === ATTEMPTS) throw failure;
1375
1566
  }
1376
1567
  }
1377
- throw unavailable();
1568
+ throw unavailable2();
1378
1569
  }
1379
1570
  function idPath(id3) {
1380
- if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid6();
1571
+ if (typeof id3 != "string" || !FILE_ID_PATTERN.test(id3)) throw invalid7();
1381
1572
  return `/${id3}`;
1382
1573
  }
1383
1574
  async function multipartCreate(input, metadata, exchange, release = () => {
@@ -1388,18 +1579,18 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1388
1579
  return pending.add(task), task.then(() => pending.delete(task), () => pending.delete(task)), task;
1389
1580
  }, void 0, timeout), control = (body) => ({
1390
1581
  method: "POST",
1391
- headers: { "content-type": "application/json", ...ticket ? { "x-oddington-transfer": ticket } : {} },
1582
+ headers: { "content-type": "application/json", ...ticket ? { "x-os-transfer": ticket } : {} },
1392
1583
  body: JSON.stringify(body)
1393
1584
  });
1394
1585
  try {
1395
1586
  let start = await request2((signal) => exchange(`${route}/start`, control(upload?.file ?? metadata), "control", signal));
1396
- if (!start || typeof start != "object" || Array.isArray(start)) throw unavailable();
1587
+ if (!start || typeof start != "object" || Array.isArray(start)) throw unavailable2();
1397
1588
  let session = start;
1398
- 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();
1589
+ 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();
1399
1590
  ticket = session.ticket, input.file instanceof ReadableStream && (reader = input.file.getReader());
1400
1591
  let lastProgress = Date.now(), next = async () => {
1401
1592
  try {
1402
- if (Date.now() - lastProgress >= TIMEOUT_MS) throw unavailable();
1593
+ if (Date.now() - lastProgress >= TIMEOUT_MS) throw unavailable2();
1403
1594
  let value = await request2(() => reader.read(), Math.max(1, TIMEOUT_MS - (Date.now() - lastProgress)));
1404
1595
  return value.value?.byteLength && (lastProgress = Date.now()), value;
1405
1596
  } catch (error) {
@@ -1420,41 +1611,41 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1420
1611
  if (!chunk || offset === chunk.byteLength) {
1421
1612
  chunk = void 0, offset = 0;
1422
1613
  let value2 = await next();
1423
- if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw invalid6();
1614
+ if (value2.done || !(value2.value instanceof Uint8Array) || (chunk = value2.value, chunk.byteLength > metadata.size - sent - filled)) throw invalid7();
1424
1615
  }
1425
1616
  let take = Math.min(length - filled, chunk.byteLength - offset);
1426
1617
  part.set(chunk.subarray(offset, offset + take), filled), filled += take, offset += take, offset === chunk.byteLength && (chunk = void 0, offset = 0);
1427
1618
  }
1428
1619
  }
1429
- if (part.byteLength !== length) throw invalid6();
1620
+ if (part.byteLength !== length) throw invalid7();
1430
1621
  if (reader && sent + length === metadata.size)
1431
1622
  for (lastProgress = Date.now(); ; ) {
1432
1623
  let value2 = await next();
1433
1624
  if (value2.done) break;
1434
- if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid6();
1625
+ if (!(value2.value instanceof Uint8Array) || value2.value.byteLength) throw invalid7();
1435
1626
  }
1436
1627
  let value = await request2((signal) => exchange(`${route}/part`, {
1437
1628
  method: "POST",
1438
- headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket, "x-oddington-part": String(partNumber) },
1629
+ headers: { "content-type": "application/octet-stream", "x-os-transfer": ticket, "x-os-part": String(partNumber) },
1439
1630
  body: part.buffer
1440
1631
  }, "control", signal));
1441
1632
  part = void 0;
1442
1633
  let receipt = value;
1443
- 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();
1634
+ 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();
1444
1635
  receipts.push({ partNumber, etag: receipt.etag }), sent += length, lastProgress = Date.now();
1445
1636
  }
1446
1637
  if (upload) for (let name of Object.keys(upload.file.enrichments)) {
1447
1638
  let bytes = await request2(() => upload.enrichment(name));
1448
- if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw invalid6();
1639
+ if (bytes.byteLength !== upload.file.enrichments[name].size || bytes.byteLength > MAX_BYTES) throw invalid7();
1449
1640
  await request2((signal) => exchange(`${route}/enrichments/${encodeURIComponent(name)}`, {
1450
1641
  method: "POST",
1451
- headers: { "content-type": "application/octet-stream", "x-oddington-transfer": ticket },
1642
+ headers: { "content-type": "application/octet-stream", "x-os-transfer": ticket },
1452
1643
  body: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)
1453
1644
  }, "control", signal));
1454
1645
  }
1455
1646
  await upload?.beforeComplete();
1456
1647
  let completion = control({ parts: receipts });
1457
- if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable();
1648
+ if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable2();
1458
1649
  return parseFileDescriptor(await request2(
1459
1650
  (signal) => exchange(`${route}/complete`, completion, !0, signal),
1460
1651
  TIMEOUT_MS + Math.ceil(metadata.size / (1024 * 1024)) * 1e3
@@ -1462,7 +1653,7 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1462
1653
  } catch (error) {
1463
1654
  throw reader && await reader.cancel(error).catch(() => {
1464
1655
  }), ticket && await request2((signal) => exchange(`${route}/abort`, control({}), "control", signal)).catch(() => {
1465
- }), error instanceof FileOperationError ? error : unavailable();
1656
+ }), error instanceof FileOperationError ? error : unavailable2();
1466
1657
  } finally {
1467
1658
  chunk = void 0, reader?.releaseLock(), pending.size ? Promise.allSettled([...pending]).then(release) : release();
1468
1659
  }
@@ -1479,13 +1670,13 @@ async function operation(work, initial, parent) {
1479
1670
  }
1480
1671
  }, signal = context2.signal && parent ? AbortSignal.any([context2.signal, parent]) : context2.signal ?? parent;
1481
1672
  return context2.localFiles ? execute(signal ?? new AbortController().signal) : timed(execute, signal).catch((error) => {
1482
- throw error instanceof FileOperationError ? error : unavailable();
1673
+ throw error instanceof FileOperationError ? error : unavailable2();
1483
1674
  });
1484
1675
  }
1485
1676
  function contentPath(id3, name) {
1486
1677
  let path = idPath(id3);
1487
1678
  if (name === void 0) return `${path}/content`;
1488
- if (!safeEnrichmentName(name)) throw invalid6();
1679
+ if (!safeEnrichmentName(name)) throw invalid7();
1489
1680
  return `${path}/enrichments/${encodeURIComponent(name)}/content`;
1490
1681
  }
1491
1682
  async function read(id3, names) {
@@ -1494,12 +1685,12 @@ async function read(id3, names) {
1494
1685
  let path = contentPath(id3, names);
1495
1686
  return operation((context3, signal) => send(path, { method: "GET" }, !1, context3, signal), context2);
1496
1687
  }
1497
- if (!Array.isArray(names)) throw invalid6();
1688
+ if (!Array.isArray(names)) throw invalid7();
1498
1689
  let distinct = [], seen = /* @__PURE__ */ new Set();
1499
1690
  for (let name of names) {
1500
- if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid6();
1691
+ if (typeof name != "string" || !safeEnrichmentName(name)) throw invalid7();
1501
1692
  if (!seen.has(name)) {
1502
- if (seen.size === 16) throw invalid6();
1693
+ if (seen.size === 16) throw invalid7();
1503
1694
  seen.add(name), distinct.push(name);
1504
1695
  }
1505
1696
  }
@@ -1527,32 +1718,32 @@ var files = {
1527
1718
  async upload(id3) {
1528
1719
  return operation(async (context2, signal) => {
1529
1720
  let file2 = await send(`${idPath(id3)}/upload`, { method: "POST" }, !0, context2, signal);
1530
- if (file2.id !== id3) throw unavailable();
1721
+ if (file2.id !== id3) throw unavailable2();
1531
1722
  return file2;
1532
1723
  });
1533
1724
  },
1534
1725
  async create(input, options) {
1535
1726
  let context2 = await resolveFilesContext();
1536
1727
  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")))
1537
- throw invalid6();
1728
+ throw invalid7();
1538
1729
  let blob = input.file instanceof Blob, array3 = input.file instanceof Uint8Array, stream = input.file instanceof ReadableStream;
1539
- if (!blob && !array3 && !stream) throw invalid6();
1730
+ if (!blob && !array3 && !stream) throw invalid7();
1540
1731
  let intrinsic = blob ? input.file.size : array3 ? input.file.byteLength : void 0;
1541
- if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid6();
1732
+ if (intrinsic !== void 0 && input.size !== void 0 && input.size !== intrinsic) throw invalid7();
1542
1733
  let name = input.name;
1543
1734
  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));
1544
- let metadata = parseFileCreateMetadata({
1735
+ let inputMediaType = blob ? declaredOriginalMediaType(input.file.type) : void 0, metadata = parseFileCreateMetadata({
1545
1736
  name,
1546
1737
  size: intrinsic ?? input.size,
1547
1738
  path: input.path,
1548
1739
  storage: input.storage,
1549
1740
  csv: input.csv,
1550
- ...blob && input.file.type === "application/pdf" ? { inputMediaType: "application/pdf" } : {},
1741
+ ...inputMediaType === void 0 ? {} : { inputMediaType },
1551
1742
  requestKey: options?.requestKey === void 0 ? routineTransport()?.key("files") ?? crypto.randomUUID() : options.requestKey
1552
1743
  }, FILE_ORIGINAL_MAX_BYTES);
1553
1744
  if (!context2.local && !context2.localFiles && metadata.storage === "local") throw new FileOperationError("unsupported_context", 400);
1554
1745
  let header = encodeURIComponent(JSON.stringify(metadata));
1555
- if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid6();
1746
+ if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid7();
1556
1747
  if (active >= MAX_ACTIVE) throw new FileOperationError("capacity", 429, !0);
1557
1748
  if (active++, context2.localFiles && !routineTransport() && metadata.size > MAX_BYTES) {
1558
1749
  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({
@@ -1568,7 +1759,7 @@ var files = {
1568
1759
  try {
1569
1760
  return await send("", { method: "POST", headers: {
1570
1761
  "content-type": "application/octet-stream",
1571
- "x-oddington-file": header
1762
+ "x-os-file": header
1572
1763
  }, body }, !0, context2, signal);
1573
1764
  } finally {
1574
1765
  active--;
@@ -1581,23 +1772,23 @@ var files = {
1581
1772
  metadata.size,
1582
1773
  signal
1583
1774
  );
1584
- if (bytes.byteLength !== metadata.size) throw invalid6();
1585
- if (signal.aborted) throw unavailable();
1775
+ if (bytes.byteLength !== metadata.size) throw invalid7();
1776
+ if (signal.aborted) throw unavailable2();
1586
1777
  return await send("", {
1587
1778
  method: "POST",
1588
- headers: { "content-type": "application/octet-stream", "x-oddington-file": header },
1779
+ headers: { "content-type": "application/octet-stream", "x-os-file": header },
1589
1780
  body: bytes.buffer
1590
1781
  }, !0, context2, signal);
1591
1782
  } finally {
1592
1783
  active--;
1593
1784
  }
1594
1785
  }, context2.signal).catch((error) => {
1595
- throw error instanceof FileOperationError ? error : unavailable();
1786
+ throw error instanceof FileOperationError ? error : unavailable2();
1596
1787
  });
1597
1788
  },
1598
1789
  async enrich(input) {
1599
1790
  let context2 = await resolveFilesContext();
1600
- 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();
1791
+ 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();
1601
1792
  let path = `${idPath(input.file)}/enrichments`;
1602
1793
  if (typeof input.content == "string" ? input.content.length > MAX_BYTES : input.content.byteLength > MAX_BYTES)
1603
1794
  throw new FileOperationError("request_too_large", 413);
@@ -1614,12 +1805,12 @@ var files = {
1614
1805
  ...input.mediaType === void 0 ? {} : { mediaType: input.mediaType },
1615
1806
  ...input.replace === void 0 ? {} : { replace: input.replace }
1616
1807
  }, MAX_BYTES), header = encodeURIComponent(JSON.stringify(metadata));
1617
- if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid6();
1808
+ if (new TextEncoder().encode(header).byteLength > METADATA_BYTES) throw invalid7();
1618
1809
  let result2 = await send(path, { method: "POST", headers: {
1619
1810
  "content-type": "application/octet-stream",
1620
- "x-oddington-enrichment": header
1811
+ "x-os-enrichment": header
1621
1812
  }, body: bytes.buffer }, "enrichment", context3, signal);
1622
- if (result2.name !== metadata.name) throw unavailable();
1813
+ if (result2.name !== metadata.name) throw unavailable2();
1623
1814
  return result2;
1624
1815
  }, context2);
1625
1816
  },
@@ -1629,29 +1820,58 @@ var files = {
1629
1820
  read
1630
1821
  };
1631
1822
 
1823
+ function validDropboxRootPath(value) {
1824
+ return typeof value == "string" && value.length <= 2048 && value.startsWith("/") && !/[\\\x00-\x1f\x7f]/.test(value) && value.slice(1).split("/").every((segment) => segment.length > 0 && segment.trim() === segment && segment !== "." && segment !== "..");
1825
+ }
1632
1826
  function validGoogleScopes(value) {
1633
1827
  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;
1634
1828
  }
1829
+ var DROPBOX_FILE_SCOPES = ["account_info.read", "files.metadata.read", "files.content.read", "files.content.write"];
1830
+ function validDropboxFileScopes(value) {
1831
+ return Array.isArray(value) && value.length === DROPBOX_FILE_SCOPES.length && new Set(value).size === value.length && DROPBOX_FILE_SCOPES.every((scope) => value.includes(scope));
1832
+ }
1635
1833
 
1636
- var ROUTINE_CONNECTION_CREDENTIALS_ENV = "ODDINGTON_ROUTINE_CONNECTION_CREDENTIALS";
1834
+ var ROUTINE_CONNECTION_CREDENTIALS_ENV = "OS_ROUTINE_CONNECTION_CREDENTIALS";
1835
+ function parseRoutineConnectionNames(value) {
1836
+ if (!Array.isArray(value) || value.some((name) => typeof name != "string" || !/^(gmail|airtable|dropbox)\/[a-z0-9][a-z0-9-]{0,62}$/.test(name)) || new Set(value).size !== value.length)
1837
+ throw new Error("Invalid routine connections");
1838
+ return value;
1839
+ }
1637
1840
  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);
1638
1841
  function runtimeConnection(lease) {
1639
- return lease.provider === "gmail" ? {
1640
- id: `gmail/${lease.name}`,
1641
- provider: lease.provider,
1642
- name: lease.name,
1643
- accountEmail: lease.accountEmail,
1644
- scopes: [...lease.scopes],
1645
- accessToken: lease.accessToken,
1646
- expiresAt: lease.expiresAt
1647
- } : {
1648
- id: `airtable/${lease.name}`,
1649
- provider: lease.provider,
1650
- name: lease.name,
1651
- baseId: lease.baseId,
1652
- accessToken: lease.accessToken,
1653
- runExpiresAt: lease.runExpiresAt
1654
- };
1842
+ switch (lease.provider) {
1843
+ case "gmail":
1844
+ return {
1845
+ id: `gmail/${lease.name}`,
1846
+ provider: lease.provider,
1847
+ name: lease.name,
1848
+ accountEmail: lease.accountEmail,
1849
+ scopes: [...lease.scopes],
1850
+ accessToken: lease.accessToken,
1851
+ expiresAt: lease.expiresAt
1852
+ };
1853
+ case "airtable":
1854
+ return {
1855
+ id: `airtable/${lease.name}`,
1856
+ provider: lease.provider,
1857
+ name: lease.name,
1858
+ baseId: lease.baseId,
1859
+ accessToken: lease.accessToken,
1860
+ runExpiresAt: lease.runExpiresAt
1861
+ };
1862
+ case "dropbox":
1863
+ return {
1864
+ id: `dropbox/${lease.name}`,
1865
+ provider: lease.provider,
1866
+ name: lease.name,
1867
+ accountId: lease.accountId,
1868
+ access: lease.access,
1869
+ rootPath: lease.rootPath,
1870
+ scopes: [...lease.scopes],
1871
+ accessToken: lease.accessToken,
1872
+ expiresAt: lease.expiresAt
1873
+ };
1874
+ }
1655
1875
  }
1656
1876
  function parseConnectionLease(raw, now = Date.now()) {
1657
1877
  let v = raw;
@@ -1662,7 +1882,7 @@ function parseConnectionLease(raw, now = Date.now()) {
1662
1882
  throw new Error("Invalid connection credential");
1663
1883
  return v;
1664
1884
  }
1665
- if (v.provider === "airtable" && Object.keys(v).sort().join(",") === "accessToken,baseId,connectionId,name,provider,runExpiresAt,runId" && typeof v.baseId == "string" && /^app[A-Za-z0-9]+$/.test(v.baseId) && typeof v.runExpiresAt == "string" && Number.isFinite(Date.parse(v.runExpiresAt)) && Date.parse(v.runExpiresAt) > now + 6e4 && Date.parse(v.runExpiresAt) <= now + 15 * 6e4)
1885
+ if (v.provider === "airtable" && Object.keys(v).sort().join(",") === "accessToken,baseId,connectionId,name,provider,runExpiresAt,runId" && typeof v.baseId == "string" && /^app[A-Za-z0-9]+$/.test(v.baseId) && typeof v.runExpiresAt == "string" && Number.isFinite(Date.parse(v.runExpiresAt)) && Date.parse(v.runExpiresAt) > now + 6e4 && Date.parse(v.runExpiresAt) <= now + 15 * 6e4 || v.provider === "dropbox" && Object.keys(v).sort().join(",") === "access,accessToken,accountId,connectionId,expiresAt,name,provider,rootPath,runId,scopes" && typeof v.accountId == "string" && /^dbid:[A-Za-z0-9_-]{1,128}$/.test(v.accountId) && v.access === "full_dropbox" && validDropboxRootPath(v.rootPath) && validDropboxFileScopes(v.scopes) && typeof v.expiresAt == "string" && Number.isFinite(Date.parse(v.expiresAt)) && Date.parse(v.expiresAt) > now + 6e4 && Date.parse(v.expiresAt) <= now + 144e5)
1666
1886
  return v;
1667
1887
  throw new Error("Invalid connection credential");
1668
1888
  }
@@ -1688,12 +1908,12 @@ function object3(v) {
1688
1908
  function keys2(v, allowed, required = allowed) {
1689
1909
  (Object.keys(v).some((k) => !allowed.includes(k)) || required.some((k) => !Object.hasOwn(v, k))) && fail2("Invalid Airtable input");
1690
1910
  }
1691
- function text2(v) {
1911
+ function text3(v) {
1692
1912
  return typeof v == "string" && v.length > 0 && v.length <= 1024;
1693
1913
  }
1694
1914
  function fields3(v, nonempty = !1) {
1695
1915
  let result2 = object3(v);
1696
- (nonempty && !Object.keys(result2).length || Object.keys(result2).some((k) => !text2(k))) && fail2("Invalid Airtable fields");
1916
+ (nonempty && !Object.keys(result2).length || Object.keys(result2).some((k) => !text3(k))) && fail2("Invalid Airtable fields");
1697
1917
  try {
1698
1918
  return serializable(result2);
1699
1919
  } catch {
@@ -1780,10 +2000,10 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1780
2000
  Array.isArray(page.tables) || fail2("Malformed Airtable tables");
1781
2001
  for (let value of page.tables) {
1782
2002
  let t = object3(value);
1783
- (!tableId(t.id) || !text2(t.name) || !text2(t.primaryFieldId) || !Array.isArray(t.fields) || tables.some((existing) => existing.id === t.id)) && fail2("Malformed Airtable table");
2003
+ (!tableId(t.id) || !text3(t.name) || !text3(t.primaryFieldId) || !Array.isArray(t.fields) || tables.some((existing) => existing.id === t.id)) && fail2("Malformed Airtable table");
1784
2004
  let metadata = t.fields.map((value2) => {
1785
2005
  let f = object3(value2);
1786
- 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) } };
2006
+ 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) } };
1787
2007
  });
1788
2008
  (!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 });
1789
2009
  }
@@ -1791,7 +2011,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1791
2011
  } while (offset);
1792
2012
  return tables;
1793
2013
  }
1794
- (!text2(input.table) || input.table === "." || input.table === "..") && fail2("Invalid Airtable table"), mutation && !tableId(input.table) && fail2("Airtable writes require a stable table ID");
2014
+ (!text3(input.table) || input.table === "." || input.table === "..") && fail2("Invalid Airtable table"), mutation && !tableId(input.table) && fail2("Airtable writes require a stable table ID");
1795
2015
  let path = `${baseId}/${encodeURIComponent(input.table)}`;
1796
2016
  if (operation2 === "records.get") {
1797
2017
  keys2(input, ["table", "id"]), recordId(input.id) || fail2("Invalid Airtable record ID");
@@ -1799,7 +2019,7 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1799
2019
  return result3.id !== input.id && fail2("Malformed Airtable record"), result3;
1800
2020
  }
1801
2021
  if (operation2 === "records.list") {
1802
- 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");
2022
+ 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");
1803
2023
  let records2 = [], ids2 = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set(), offset;
1804
2024
  do {
1805
2025
  let query2 = new URLSearchParams();
@@ -1856,10 +2076,10 @@ async function executeAirtableOperation(authority, operation2, raw, options = {}
1856
2076
  }
1857
2077
  function nextOffset(value, seen) {
1858
2078
  if (value !== void 0)
1859
- return (!text2(value) || seen.has(value)) && fail2("Malformed Airtable pagination"), seen.add(value), value;
2079
+ return (!text3(value) || seen.has(value)) && fail2("Malformed Airtable pagination"), seen.add(value), value;
1860
2080
  }
1861
2081
 
1862
- var MANAGED_CONNECTION_CAPABILITY_ENV = "ODDINGTON_MANAGED_CONNECTION_CAPABILITY";
2082
+ var MANAGED_CONNECTION_CAPABILITY_ENV = "OS_MANAGED_CONNECTION_CAPABILITY";
1863
2083
  function managedConnections(capability) {
1864
2084
  let endpoint = new URL(capability.endpoint);
1865
2085
  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");
@@ -2015,7 +2235,7 @@ function object4(value) {
2015
2235
  function keys3(value, allowed, required = allowed) {
2016
2236
  assert(Object.keys(value).every((key) => allowed.includes(key)) && required.every((key) => Object.hasOwn(value, key)));
2017
2237
  }
2018
- function text3(value, empty2 = !1) {
2238
+ function text4(value, empty2 = !1) {
2019
2239
  return typeof value == "string" && (empty2 || !!value.trim());
2020
2240
  }
2021
2241
  function id2(value) {
@@ -2025,7 +2245,7 @@ function integer(value, minimum = 1) {
2025
2245
  return Number.isSafeInteger(value) && Number(value) >= minimum;
2026
2246
  }
2027
2247
  function date(value) {
2028
- return text3(value) && Number.isFinite(Date.parse(value));
2248
+ return text4(value) && Number.isFinite(Date.parse(value));
2029
2249
  }
2030
2250
  function optionalDate(value) {
2031
2251
  return value === null || date(value);
@@ -2047,7 +2267,7 @@ function json(value, ancestors = /* @__PURE__ */ new Set()) {
2047
2267
  }
2048
2268
  function recordReference(value) {
2049
2269
  let record3 = object4(value);
2050
- 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;
2270
+ 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;
2051
2271
  }
2052
2272
  function responseDefinition(value) {
2053
2273
  let definition = object4(value);
@@ -2059,75 +2279,75 @@ function responseDefinition(value) {
2059
2279
  assert(options.length > 0);
2060
2280
  let values = options.map((value2) => {
2061
2281
  let option = object4(value2);
2062
- 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) {
2282
+ 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) {
2063
2283
  let note = object4(option.note);
2064
- keys3(note, ["placeholder"]), assert(text3(note.placeholder));
2284
+ keys3(note, ["placeholder"]), assert(text4(note.placeholder));
2065
2285
  }
2066
2286
  return option.value;
2067
2287
  });
2068
2288
  if (assert(new Set(values).size === values.length), "search" in source || "suggestions" in source) {
2069
2289
  let search = object4(source.search);
2070
- keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text3(search.triggerLabel) && text3(search.placeholder) && text3(search.emptyLabel));
2290
+ keys3(search, ["triggerLabel", "placeholder", "emptyLabel"]), assert(text4(search.triggerLabel) && text4(search.placeholder) && text4(search.emptyLabel));
2071
2291
  let suggestions2 = array2(source.suggestions);
2072
- assert(suggestions2.length <= 8 && suggestions2.every((value2) => text3(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
2292
+ assert(suggestions2.length <= 8 && suggestions2.every((value2) => text4(value2) && values.includes(value2)) && new Set(suggestions2).size === suggestions2.length);
2073
2293
  } else assert(options.length <= 9);
2074
2294
  return;
2075
2295
  }
2076
2296
  assert(source.type === "records"), keys3(source, ["type", "collection", "refPrefix", "where", "display", "suggestions"], ["type", "collection", "display"]);
2077
2297
  let collection = object4(source.collection);
2078
- 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));
2298
+ 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));
2079
2299
  let where = object4(source.where ?? {});
2080
2300
  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))));
2081
2301
  let display = object4(source.display);
2082
2302
  keys3(display, ["labelFields"]);
2083
2303
  let labels = array2(display.labelFields);
2084
- 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)));
2304
+ 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)));
2085
2305
  let suggestions = array2(source.suggestions ?? []), refs = suggestions.map((value2) => {
2086
2306
  let suggestion = object4(value2);
2087
2307
  keys3(suggestion, ["record", "reason"], ["record"]);
2088
2308
  let record3 = recordReference(suggestion.record);
2089
- return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text3(suggestion.reason)), record3.ref;
2309
+ return assert(record3.repository === collection.repository), "reason" in suggestion && assert(text4(suggestion.reason)), record3.ref;
2090
2310
  });
2091
2311
  assert(suggestions.length <= 8 && new Set(refs).size === refs.length);
2092
2312
  }
2093
2313
  function inboxFile(value) {
2094
2314
  let file2 = object4(value);
2095
- 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));
2315
+ 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));
2096
2316
  let details = object4(file2.details);
2097
2317
  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)));
2098
2318
  }
2099
2319
  function fields4(value) {
2100
2320
  let labels = array2(value).map((value2) => {
2101
2321
  let field = object4(value2);
2102
- return keys3(field, ["label", "value"]), assert(text3(field.label) && text3(field.value)), field.label;
2322
+ return keys3(field, ["label", "value"]), assert(text4(field.label) && text4(field.value)), field.label;
2103
2323
  });
2104
2324
  assert(new Set(labels).size === labels.length);
2105
2325
  }
2106
2326
  function block(value) {
2107
2327
  let entry = object4(value);
2108
2328
  if (entry.kind === "rich-text") {
2109
- keys3(entry, ["kind", "markdown"]), assert(text3(entry.markdown));
2329
+ keys3(entry, ["kind", "markdown"]), assert(text4(entry.markdown));
2110
2330
  return;
2111
2331
  }
2112
2332
  if (entry.kind === "asks") {
2113
2333
  keys3(entry, ["kind", "problem", "asks"]);
2114
2334
  let asks = array2(entry.asks);
2115
- assert(text3(entry.problem) && asks.length > 0 && asks.every(id2) && new Set(asks).size === asks.length);
2335
+ assert(text4(entry.problem) && asks.length > 0 && asks.every(id2) && new Set(asks).size === asks.length);
2116
2336
  return;
2117
2337
  }
2118
2338
  if (assert(["record", "records", "files"].includes(String(entry.kind))), keys3(
2119
2339
  entry,
2120
2340
  ["kind", "label", "initiallyExpanded", ...entry.kind === "record" ? ["record", "view"] : entry.kind === "records" ? ["records", "view"] : ["files"]],
2121
2341
  ["kind", "label", entry.kind === "record" ? "record" : entry.kind === "records" ? "records" : "files"]
2122
- ), 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") {
2342
+ ), 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") {
2123
2343
  let record3 = object4(entry.record);
2124
- keys3(record3, ["ref", "title", "fields"]), assert(text3(record3.ref) && record3.ref === record3.ref.trim() && text3(record3.title)), fields4(record3.fields);
2344
+ keys3(record3, ["ref", "title", "fields"]), assert(text4(record3.ref) && record3.ref === record3.ref.trim() && text4(record3.title)), fields4(record3.fields);
2125
2345
  return;
2126
2346
  }
2127
2347
  if (entry.kind === "records") {
2128
2348
  let records = array2(entry.records), refs = records.map((value2) => {
2129
2349
  let record3 = object4(value2);
2130
- 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;
2350
+ 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;
2131
2351
  });
2132
2352
  assert(records.length > 0 && new Set(refs).size === refs.length);
2133
2353
  return;
@@ -2137,7 +2357,7 @@ function block(value) {
2137
2357
  }
2138
2358
  function response(value) {
2139
2359
  let answer = object4(value);
2140
- 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;
2360
+ 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;
2141
2361
  }
2142
2362
  function parseInboxRequest(value) {
2143
2363
  try {
@@ -2146,70 +2366,70 @@ function parseInboxRequest(value) {
2146
2366
  let operation2 = envelope.operation, input = { ...object4(envelope.input) }, required = operations[operation2];
2147
2367
  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)));
2148
2368
  for (let key of ["itemId", "personId", "fileId"]) key in input && assert(id2(input[key]));
2149
- 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 };
2369
+ 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 };
2150
2370
  } catch {
2151
2371
  throw new InboxOperationError(400, "invalid_input");
2152
2372
  }
2153
2373
  }
2154
2374
  function parseInboxCurrent(value) {
2155
2375
  let current2 = object4(value), workspace = object4(current2.workspace), viewer = object4(current2.viewer);
2156
- 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)), {
2376
+ 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)), {
2157
2377
  workspace: { id: workspace.id, slug: workspace.slug, name: workspace.name, locale: workspace.locale, timezone: workspace.timezone },
2158
2378
  viewer: { id: viewer.id, name: viewer.name, email: viewer.email }
2159
2379
  };
2160
2380
  }
2161
2381
  function parseInboxItem(value) {
2162
2382
  let item = object4(json(value));
2163
- 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)), item.kind === "ask" ? askMetadata(item) : assert(!("tags" in item) && !("recordRefs" in item)), array2(item.body).forEach(block), array2(item.views).forEach((value2) => {
2383
+ 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) => {
2164
2384
  let view = object4(value2);
2165
- assert(text3(view.id) && text3(view.view) && text3(view.implementation)), json(view.input);
2385
+ assert(text4(view.id) && text4(view.view) && text4(view.implementation)), json(view.input);
2166
2386
  }), array2(item.people).forEach((value2) => {
2167
2387
  let person = object4(value2);
2168
- assert(id2(person.id) && text3(person.name));
2388
+ assert(id2(person.id) && text4(person.name));
2169
2389
  }), array2(item.questions).forEach((value2) => {
2170
2390
  let question2 = object4(value2);
2171
- 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) {
2391
+ 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) {
2172
2392
  let accepted = object4(question2.acceptedResponse);
2173
- 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));
2393
+ 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));
2174
2394
  }
2175
2395
  if (question2.execution !== null) {
2176
2396
  let execution = object4(question2.execution);
2177
2397
  if (assert(id2(execution.id) && ["pending", "running", "completed", "failed"].includes(String(execution.state)) && integer(execution.attempt, 0)), "consequence" in execution) {
2178
2398
  let consequence = object4(execution.consequence);
2179
- 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) => {
2399
+ 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) => {
2180
2400
  let receipt = object4(value3);
2181
- assert(text3(receipt.repository) && text3(receipt.commit) && text3(receipt.diff, !0));
2401
+ assert(text4(receipt.repository) && text4(receipt.commit) && text4(receipt.diff, !0));
2182
2402
  });
2183
2403
  }
2184
2404
  }
2185
2405
  }), array2(item.linkedAsks).forEach((value2) => {
2186
2406
  let linked = object4(value2);
2187
2407
  if (assert(id2(linked.id)), linked.state === "unavailable") assert(typeof linked.done == "boolean");
2188
- else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text3(linked.title)), linked.state === "theirs") {
2408
+ else if (assert(["yours", "done", "open", "theirs"].includes(String(linked.state)) && text4(linked.title)), linked.state === "theirs") {
2189
2409
  let assignee = object4(linked.assignee);
2190
- assert(id2(assignee.id) && text3(assignee.name));
2410
+ assert(id2(assignee.id) && text4(assignee.name));
2191
2411
  }
2192
2412
  }), array2(item.activity).forEach((value2) => {
2193
2413
  let event = object4(value2);
2194
- 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);
2414
+ 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);
2195
2415
  }), array2(item.work).forEach((value2) => {
2196
2416
  let work = object4(value2);
2197
- assert(id2(work.id) && text3(work.questionId) && text3(work.reason) && optionalDate(work.settledAt));
2417
+ assert(id2(work.id) && text4(work.questionId) && text4(work.reason) && optionalDate(work.settledAt));
2198
2418
  }), item;
2199
2419
  }
2200
2420
  function parseAnswerableQuestion(value) {
2201
2421
  let entry = object4(json(value));
2202
2422
  keys3(
2203
2423
  entry,
2204
- ["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "tags", "recordRefs", "instructions"],
2205
- ["itemId", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable"]
2206
- ), assert(id2(entry.itemId) && integer(entry.revision) && text3(entry.title) && text3(entry.inboxUrl));
2424
+ ["itemId", "number", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable", "tags", "recordRefs", "instructions"],
2425
+ ["itemId", "number", "revision", "title", "inboxUrl", "questionId", "routine", "prompt", "response", "answerable"]
2426
+ ), assert(id2(entry.itemId) && integer(entry.number) && integer(entry.revision) && text4(entry.title) && text4(entry.inboxUrl));
2207
2427
  let link = new URL(entry.inboxUrl), slug = link.hostname.slice(0, -13);
2208
- 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) && 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), askMetadata(entry), entry;
2428
+ 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;
2209
2429
  }
2210
2430
  function askMetadata(entry) {
2211
2431
  let tags = array2(entry.tags === void 0 ? [] : entry.tags);
2212
- assert(tags.length <= 32 && tags.every((tag) => text3(tag) && new TextEncoder().encode(tag).byteLength <= 64)), assert(new Set(tags).size === tags.length);
2432
+ assert(tags.length <= 32 && tags.every((tag) => text4(tag) && new TextEncoder().encode(tag).byteLength <= 64)), assert(new Set(tags).size === tags.length);
2213
2433
  let refs = array2(entry.recordRefs === void 0 ? [] : entry.recordRefs);
2214
2434
  refs.forEach((value) => {
2215
2435
  let ref = object4(value);
@@ -2221,7 +2441,7 @@ function askMetadata(entry) {
2221
2441
  }
2222
2442
  function parseInboxAcceptance(value) {
2223
2443
  let accepted = object4(value);
2224
- 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;
2444
+ 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;
2225
2445
  }
2226
2446
  function parseInboxResult(operation2, value) {
2227
2447
  if (operation2 === "current") return parseInboxCurrent(value);
@@ -2252,7 +2472,7 @@ function parseInboxResult(operation2, value) {
2252
2472
  let candidates = array2(value);
2253
2473
  return candidates.forEach((value2) => {
2254
2474
  let person = object4(value2);
2255
- assert(id2(person.id) && text3(person.name) && text3(person.email));
2475
+ assert(id2(person.id) && text4(person.name) && text4(person.email));
2256
2476
  }), assert(new Set(candidates.map((value2) => object4(value2).id)).size === candidates.length), candidates;
2257
2477
  }
2258
2478
  if (operation2 === "items.addRecipient") {
@@ -2262,10 +2482,10 @@ function parseInboxResult(operation2, value) {
2262
2482
  if (operation2 === "questions.answer") return parseInboxAcceptance(value);
2263
2483
  if (operation2 === "questions.searchRecords") {
2264
2484
  let result2 = object4(value);
2265
- assert(text3(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
2485
+ assert(text4(result2.recordType) && integer(result2.eligibleCount, 0) && integer(result2.matchCount, 0) && Number(result2.matchCount) <= Number(result2.eligibleCount));
2266
2486
  let labeled = (value2) => {
2267
2487
  let record3 = object4(value2);
2268
- recordReference({ repository: record3.repository, ref: record3.ref }), assert(text3(record3.label)), "reason" in record3 && assert(text3(record3.reason));
2488
+ recordReference({ repository: record3.repository, ref: record3.ref }), assert(text4(record3.label)), "reason" in record3 && assert(text4(record3.reason));
2269
2489
  };
2270
2490
  return array2(result2.matches).forEach(labeled), array2(result2.suggestions).forEach(labeled), "selected" in result2 && labeled(result2.selected), result2;
2271
2491
  }
@@ -2379,7 +2599,7 @@ async function appResponse(response2, maximum, signal) {
2379
2599
  });
2380
2600
  };
2381
2601
  signal.addEventListener("abort", abort, { once: !0 });
2382
- let bytes = 0, text4 = "", decoder = new TextDecoder("utf-8", { fatal: !0 });
2602
+ let bytes = 0, text5 = "", decoder = new TextDecoder("utf-8", { fatal: !0 });
2383
2603
  try {
2384
2604
  for (; ; ) {
2385
2605
  let chunk;
@@ -2390,13 +2610,13 @@ async function appResponse(response2, maximum, signal) {
2390
2610
  }
2391
2611
  if (signal.aborted) throw new Error();
2392
2612
  if (chunk.done) {
2393
- let value = JSON.parse(text4 + decoder.decode());
2613
+ let value = JSON.parse(text5 + decoder.decode());
2394
2614
  if (await responseChecks.get(response2)?.(value), signal.aborted) throw new Error();
2395
2615
  return value;
2396
2616
  }
2397
2617
  if (bytes += chunk.value.byteLength, bytes > maximum)
2398
2618
  throw abort(), new Error();
2399
- text4 += decoder.decode(chunk.value, { stream: !0 });
2619
+ text5 += decoder.decode(chunk.value, { stream: !0 });
2400
2620
  }
2401
2621
  } finally {
2402
2622
  signal.removeEventListener("abort", abort), reader.releaseLock();
@@ -2622,16 +2842,16 @@ function appContext(origin, active2) {
2622
2842
  return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, {}, !1, !0);
2623
2843
  }
2624
2844
  async function requestFiles(suffix, init2, parent) {
2625
- let unavailable3 = () => new FileOperationError("unsupported_context", 400);
2845
+ let unavailable4 = () => new FileOperationError("unsupported_context", 400);
2626
2846
  if (!current2() || !/^(?:|\/[0-9a-f-]{36}(?:\/(?:content|upload|enrichments(?:\/[^/?#]+\/content)?))?)$/i.test(suffix))
2627
- throw unavailable3();
2628
- let admitted = credential, signal = parent ? AbortSignal.any([access.signal, parent]) : access.signal, failure = () => current2() && !signal.aborted ? new FileOperationError("unavailable", 503, !0) : unavailable3();
2847
+ throw unavailable4();
2848
+ let admitted = credential, signal = parent ? AbortSignal.any([access.signal, parent]) : access.signal, failure = () => current2() && !signal.aborted ? new FileOperationError("unavailable", 503, !0) : unavailable4();
2629
2849
  try {
2630
2850
  return await hostedContent("", init2, signal, (_url, request2) => untilAborted(
2631
2851
  send3(`files${suffix}`, admitted, signal, request2).then((value) => {
2632
2852
  if (signal.aborted)
2633
2853
  throw value.body?.cancel().catch(() => {
2634
- }), unavailable3();
2854
+ }), unavailable4();
2635
2855
  return value;
2636
2856
  }),
2637
2857
  signal
@@ -2733,9 +2953,9 @@ function validPair(value) {
2733
2953
  return validProof(pair.credential) && validProof(pair.renewalCredential) && pair.credential !== pair.renewalCredential && validBinding(pair.context);
2734
2954
  }
2735
2955
 
2736
- var unavailable2 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable");
2956
+ var unavailable3 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable");
2737
2957
  function hostFailure(error, context2) {
2738
- 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();
2958
+ 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();
2739
2959
  }
2740
2960
  async function send2(operation2, input) {
2741
2961
  let envelope = parseInboxRequest({ operation: operation2, input }), context2;
@@ -2755,12 +2975,12 @@ async function send2(operation2, input) {
2755
2975
  [400, 401, 403, 409].includes(response2.status) ? response2.status : 503,
2756
2976
  response2.status === 400 ? "invalid_input" : response2.status === 401 ? "authority_unavailable" : response2.status === 403 ? "access_denied" : response2.status === 409 ? "conflict" : "unavailable"
2757
2977
  );
2758
- if (response2.status !== 200) throw unavailable2();
2978
+ if (response2.status !== 200) throw unavailable3();
2759
2979
  let parsed = parseInboxResult(operation2, value);
2760
- if (check2(), operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable2();
2980
+ if (check2(), operation2 === "questions.answer" && typeof envelope.input.response.selection == "object" && !parsed.label?.trim()) throw unavailable3();
2761
2981
  return parsed;
2762
2982
  } catch (error) {
2763
- throw check2(), error instanceof InboxOperationError ? error : unavailable2();
2983
+ throw check2(), error instanceof InboxOperationError ? error : unavailable3();
2764
2984
  }
2765
2985
  }
2766
2986
  if (context2.endpoint !== `https://${context2.workspace}.oddington.ai` || ["auth", "www", "api", "os"].includes(context2.workspace)) throw stale();
@@ -2771,7 +2991,7 @@ async function send2(operation2, input) {
2771
2991
  } catch (error) {
2772
2992
  throw hostFailure(error, context2);
2773
2993
  }
2774
- if (!host) throw unavailable2();
2994
+ if (!host) throw unavailable3();
2775
2995
  }
2776
2996
  let check = () => {
2777
2997
  if (!context2.isCurrent() || host && !host.isCurrent() || !Number.isFinite(context2.expiresAt) || context2.expiresAt <= Date.now()) throw stale();
@@ -2801,9 +3021,9 @@ async function send2(operation2, input) {
2801
3021
  );
2802
3022
  if (response2.status !== 200)
2803
3023
  throw response2.body?.cancel().catch(() => {
2804
- }), unavailable2();
3024
+ }), unavailable3();
2805
3025
  if (operation2 === "files.read") {
2806
- if (!response2.body) throw unavailable2();
3026
+ if (!response2.body) throw unavailable3();
2807
3027
  let source = response2.body, reader, size = 0, cancel = async (reason) => {
2808
3028
  try {
2809
3029
  await (reader ? reader.cancel(reason) : source.cancel(reason));
@@ -2819,7 +3039,7 @@ async function send2(operation2, input) {
2819
3039
  reader.releaseLock(), controller.close();
2820
3040
  return;
2821
3041
  }
2822
- if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable2();
3042
+ if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable3();
2823
3043
  controller.enqueue(next.value);
2824
3044
  } catch (error) {
2825
3045
  controller.error(error), await cancel(error).catch(() => {
@@ -2831,16 +3051,16 @@ async function send2(operation2, input) {
2831
3051
  return new Response(body, { status: response2.status, headers: response2.headers });
2832
3052
  }
2833
3053
  let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
2834
- if (check(), !bytes) throw unavailable2();
3054
+ if (check(), !bytes) throw unavailable3();
2835
3055
  let value = JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes)), parsed = parseInboxResult(operation2, value);
2836
- if (check(), operation2 === "current" && parsed.workspace.slug !== context2.workspace) throw unavailable2();
3056
+ if (check(), operation2 === "current" && parsed.workspace.slug !== context2.workspace) throw unavailable3();
2837
3057
  if ("itemId" in envelope.input) {
2838
3058
  let item = operation2 === "items.read" ? parsed : operation2 === "items.rename" || operation2 === "items.setLifecycle" || operation2 === "items.addRecipient" ? parsed.item : void 0;
2839
- 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();
3059
+ 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();
2840
3060
  }
2841
3061
  return parsed;
2842
3062
  } catch (error) {
2843
- throw check(), error instanceof InboxOperationError ? error : unavailable2();
3063
+ throw check(), error instanceof InboxOperationError ? error : unavailable3();
2844
3064
  }
2845
3065
  }
2846
3066
  var inbox = {
@@ -2860,14 +3080,14 @@ var inbox = {
2860
3080
  throw hostFailure(error, initial);
2861
3081
  }
2862
3082
  if (initial.kind === "local") throw new InboxOperationError(403, "access_denied");
2863
- if (!host) throw unavailable2();
3083
+ if (!host) throw unavailable3();
2864
3084
  let check = () => {
2865
3085
  if (!initial.isCurrent() || !host.isCurrent() || initial.expiresAt <= Date.now()) throw stale();
2866
3086
  };
2867
3087
  do {
2868
3088
  check();
2869
3089
  let page = await send2("items.list", beforeNumber === void 0 ? {} : { beforeNumber });
2870
- if (check(), beforeNumber !== void 0 && (page.items.some((item) => item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable2();
3090
+ if (check(), beforeNumber !== void 0 && (page.items.some((item) => item.number >= beforeNumber) || page.nextBeforeNumber !== null && page.nextBeforeNumber >= beforeNumber)) throw unavailable3();
2871
3091
  if (items.push(...page.items), page.nextBeforeNumber === null) return items;
2872
3092
  beforeNumber = page.nextBeforeNumber;
2873
3093
  } while (!0);
@@ -2901,7 +3121,7 @@ var inbox = {
2901
3121
  routines,
2902
3122
  ...beforeNumber === void 0 ? {} : { beforeNumber }
2903
3123
  });
2904
- 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();
3124
+ 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();
2905
3125
  if (questions.push(...page.questions), page.nextBeforeNumber === null) return questions;
2906
3126
  beforeNumber = page.nextBeforeNumber;
2907
3127
  } while (!0);
@@ -3483,7 +3703,7 @@ function handle(key, id3, context2) {
3483
3703
  async function describeAppRoutine(key) {
3484
3704
  let descriptor = appDescriptors().find((item) => item.id === key);
3485
3705
  if (!descriptor) return fail3("authority_unavailable");
3486
- let unavailable3 = () => ({
3706
+ let unavailable4 = () => ({
3487
3707
  ...structuredClone(descriptor),
3488
3708
  connections: descriptor.connections.map((connection) => ({ ...connection, available: !1 })),
3489
3709
  readiness: { state: "unavailable", reason: "capability_unavailable", message: "Routine capability unavailable." }
@@ -3492,11 +3712,11 @@ async function describeAppRoutine(key) {
3492
3712
  let value = await request(key, "describe", void 0, 1048576);
3493
3713
  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;
3494
3714
  } catch {
3495
- return unavailable3();
3715
+ return unavailable4();
3496
3716
  }
3497
3717
  }
3498
3718
  function appRoutineBinding(key) {
3499
- return Object.freeze({
3719
+ return (typeof key != "string" || !identifier.test(key) || !appDescriptors().some((item) => item.id === key)) && fail3("authority_unavailable"), Object.freeze({
3500
3720
  describe: () => describeAppRoutine(key),
3501
3721
  async run(...args) {
3502
3722
  args.length > 1 && fail3("invalid_input");
@@ -3530,6 +3750,7 @@ function appRoutineBinding(key) {
3530
3750
 
3531
3751
  var app = Object.freeze({
3532
3752
  listRoutines: () => Promise.all(appDescriptors().map(({ id: id3 }) => describeAppRoutine(id3))),
3753
+ routine: appRoutineBinding,
3533
3754
  routines: new Proxy(/* @__PURE__ */ Object.create(null), {
3534
3755
  get(_target, key) {
3535
3756
  if (!(typeof key != "string" || !appDescriptors().some((item) => item.id === key)))
@@ -3569,10 +3790,10 @@ function routineDataEnvelope(command) {
3569
3790
  }
3570
3791
 
3571
3792
  function routinePublicationClient2(options = {}) {
3572
- let environment = {}, installed2 = routineTransport(), local3 = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.ODDINGTON_ROUTINE_WORKSPACE, capability = options.capability ?? environment.ODDINGTON_ROUTINE_RUN;
3793
+ 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;
3573
3794
  if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
3574
3795
  throw new Error("A workspace and valid optional routine capability are required");
3575
- let workingRoot = options.workingRoot ?? environment.ODDINGTON_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-oddington-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
3796
+ let workingRoot = options.workingRoot ?? environment.OS_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-os-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
3576
3797
  if (path === "/api/data") return fetch(`https://${workspace}.oddington.ai/api/data`, { ...init2, redirect: "error" });
3577
3798
  let origin = `https://${workspace}.oddington.ai`, target = new URL(path, `${origin}/`);
3578
3799
  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")
@@ -3588,7 +3809,7 @@ function routinePublicationClient2(options = {}) {
3588
3809
  headers: {
3589
3810
  "content-type": "application/json",
3590
3811
  ...headers,
3591
- ...writing || reading ? { "x-oddington-workspace": workspace, "x-oddington-captured-records": "1" } : {}
3812
+ ...writing || reading ? { "x-os-workspace": workspace, "x-os-captured-records": "1" } : {}
3592
3813
  },
3593
3814
  body: JSON.stringify(writing ? routineDataEnvelope(validateRoutineRecordWrite(body)) : reading ? { operation: "records.select", request: validateRecordRead(body) } : body)
3594
3815
  }), result2 = await response2.json();