@oddington/sdk 0.1.40 → 0.1.42
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/README.md +47 -9
- package/dist/browser.js +200 -56
- package/dist/index.js +17 -4
- package/dist/types/packages/sdk/src/data-schema-types.d.ts +2 -2
- package/dist/types/packages/sdk/src/public.d.ts +5 -0
- package/dist/types/packages/sdk/src/routine-definition-types.d.ts +7 -0
- package/dist/types/shared/data-contract.d.ts +1 -1
- package/dist/types/shared/files-contract.d.ts +15 -1
- package/dist/types/shared/routine-ai-contract.d.ts +6 -4
- package/dist/types/shared/routine-ai-error-detail.d.ts +19 -0
- package/dist/types/shared/routine-ai-output-detail.d.ts +2 -0
- package/dist/types/shared/routine-deployment-contract.d.ts +1 -1
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -3,19 +3,27 @@ var fileValidationReasons = {
|
|
|
3
3
|
invalid_name: "File name must be 1\u2013255 characters, with no reserved names, path separators, control characters or trailing spaces/dots.",
|
|
4
4
|
invalid_path: "File path must contain safe relative folder names and cannot start with .os.",
|
|
5
5
|
invalid_storage: "File storage must be local or remote.",
|
|
6
|
-
invalid_media_type: "
|
|
6
|
+
invalid_media_type: "The media type must use a value such as text/markdown or application/json.",
|
|
7
7
|
invalid_size: "File size must be a non-negative safe integer byte count.",
|
|
8
8
|
invalid_request_key: "File request key must contain 1\u2013256 characters, with no surrounding whitespace or control characters.",
|
|
9
|
-
invalid_enrichment_name: "
|
|
10
|
-
|
|
9
|
+
invalid_enrichment_name: "The enrichment name must be a filename without folders, such as read.md. Names such as original and original.pdf are reserved.",
|
|
10
|
+
invalid_enrichment_request: "The save request has invalid content or metadata.",
|
|
11
|
+
invalid_replacement: "To replace an enrichment, pass its current SHA-256 value as replace.",
|
|
11
12
|
invalid_bytes: "File content must contain byte chunks.",
|
|
12
13
|
original_changed: "The selected file changed while OS was reading it. Wait for it to finish saving, then try again."
|
|
14
|
+
}, localStorageReasons = {
|
|
15
|
+
local_storage_legacy: `OS found an older local file storage layout: the internal metadata folder is still named .oddington-files.
|
|
16
|
+
|
|
17
|
+
Stop any OS routines using this workspace, then rename .oddington-files to .os in the same directory and rerun your command. Keep the folder\u2019s contents intact.`,
|
|
18
|
+
local_storage_ambiguous: "OS found both .oddington-files and .os metadata folders in local file storage and could not safely choose one. Reconcile their metadata before continuing; do not overwrite either folder. Your stored files have been left in place.",
|
|
19
|
+
local_storage_unrecognized: "OS could not open its local file storage because the folder contains files but has no recognized metadata. The storage folder needs to be checked before continuing. Your stored files have been left in place.",
|
|
20
|
+
local_storage_tracked: "OS could not use its local file storage because it contains Git-tracked files. Local file storage must be outside tracked repository content. Your stored files have been left in place."
|
|
13
21
|
};
|
|
14
22
|
function parseFileErrorDetail(value) {
|
|
15
23
|
if (!value || typeof value != "object" || Array.isArray(value)) return;
|
|
16
24
|
let v = value;
|
|
17
25
|
if (typeof v.reason != "string") return;
|
|
18
|
-
if (Object.hasOwn(fileValidationReasons, v.reason))
|
|
26
|
+
if (Object.hasOwn(fileValidationReasons, v.reason) || Object.hasOwn(localStorageReasons, v.reason))
|
|
19
27
|
return Object.keys(v).length === 1 ? { reason: v.reason } : void 0;
|
|
20
28
|
if (v.reason !== "size_mismatch" && v.reason !== "size_limit") return;
|
|
21
29
|
let count = v.reason === "size_mismatch" ? "expectedBytes" : "limitBytes";
|
|
@@ -28,16 +36,57 @@ function parseFileErrorDetail(value) {
|
|
|
28
36
|
};
|
|
29
37
|
}
|
|
30
38
|
function fileErrorExplanation(detail) {
|
|
31
|
-
return detail.reason === "size_mismatch" ? `
|
|
32
|
-
}
|
|
33
|
-
|
|
39
|
+
return detail.reason === "size_mismatch" ? `The request declared ${detail.expectedBytes} bytes, but contained ${detail.receivedAtLeast ? "at least " : ""}${detail.receivedBytes} bytes.` : detail.reason === "size_limit" ? `The file content exceeds the ${fileSizeLabel(detail.limitBytes)} limit; received ${detail.receivedAtLeast ? "at least " : ""}${fileSizeLabel(detail.receivedBytes)}.` : Object.hasOwn(localStorageReasons, detail.reason) ? localStorageReasons[detail.reason] : fileValidationReasons[detail.reason];
|
|
40
|
+
}
|
|
41
|
+
function fileSizeLabel(bytes) {
|
|
42
|
+
for (let [unit, size] of [["GiB", 1024 ** 3], ["MiB", 1024 ** 2], ["KiB", 1024]])
|
|
43
|
+
if (bytes >= size && bytes % size === 0) return `${bytes / size} ${unit}`;
|
|
44
|
+
return `${bytes} bytes`;
|
|
45
|
+
}
|
|
46
|
+
function fileErrorDetailForCode(code, detail) {
|
|
47
|
+
let parsed = parseFileErrorDetail(detail);
|
|
48
|
+
if (!parsed) return;
|
|
49
|
+
if (Object.hasOwn(localStorageReasons, parsed.reason) ? code === "unavailable" : ["invalid_input", "request_too_large"].includes(code)) return parsed;
|
|
50
|
+
}
|
|
51
|
+
var FILE_CAPACITY_MESSAGE = "OS reached its file-processing limit. Try again in a moment. If this keeps happening with a large batch, split the files into smaller groups.", FILE_INTEGRITY_MESSAGE = "OS could not verify this File against its saved record. Try again. If the problem continues, add the original file again.";
|
|
52
|
+
function fileErrorMessage(error) {
|
|
53
|
+
let detail = fileErrorDetailForCode(error.code, error.detail);
|
|
54
|
+
if (detail)
|
|
55
|
+
return `${["invalid_enrichment_name", "invalid_enrichment_request", "invalid_replacement"].includes(detail.reason) ? `Couldn\u2019t save the file\u2019s enrichment.
|
|
56
|
+
` : ""}${fileErrorExplanation(detail)}`;
|
|
57
|
+
switch (error.code) {
|
|
58
|
+
case "invalid_input":
|
|
59
|
+
return "The file request is invalid.";
|
|
60
|
+
case "unsupported_context":
|
|
61
|
+
return "This environment does not support this file operation.";
|
|
62
|
+
case "unauthenticated":
|
|
63
|
+
return "Sign in to OS before accessing files.";
|
|
64
|
+
case "access_denied":
|
|
65
|
+
return "You don\u2019t have access to this file operation.";
|
|
66
|
+
case "request_too_large":
|
|
67
|
+
return "The file request exceeds the size limit.";
|
|
68
|
+
case "conflict":
|
|
69
|
+
return "The saved file or enrichment doesn\u2019t match this request. Reload it before trying again.";
|
|
70
|
+
case "local_only":
|
|
71
|
+
return "This file is stored on a computer and isn\u2019t available through remote storage.";
|
|
72
|
+
case "integrity":
|
|
73
|
+
return FILE_INTEGRITY_MESSAGE;
|
|
74
|
+
case "capacity":
|
|
75
|
+
return FILE_CAPACITY_MESSAGE;
|
|
76
|
+
case "method_not_allowed":
|
|
77
|
+
return "This request uses an unsupported file operation.";
|
|
78
|
+
case "unavailable":
|
|
79
|
+
return `OS couldn\u2019t complete the file operation.${error.retryable ? " Try again." : ""}`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
var FileOperationError = class extends Error {
|
|
34
83
|
constructor(code, status, retryable = !1, detail) {
|
|
35
|
-
let safe =
|
|
36
|
-
super(
|
|
84
|
+
let safe = fileErrorDetailForCode(code, detail);
|
|
85
|
+
super(fileErrorMessage({ code, retryable, detail: safe }));
|
|
37
86
|
this.code = code;
|
|
38
87
|
this.status = status;
|
|
39
88
|
this.retryable = retryable;
|
|
40
|
-
safe && (this.detail = Object.freeze(safe));
|
|
89
|
+
safe && (this.detail = Object.freeze(safe)), safe && Object.hasOwn(localStorageReasons, safe.reason) && (this.retryable = !1);
|
|
41
90
|
}
|
|
42
91
|
code;
|
|
43
92
|
status;
|
|
@@ -666,7 +715,7 @@ function parseRoutineDeclaration(value) {
|
|
|
666
715
|
(!routineAlias(key) || !["read", "write"].includes(repositories[key])) && invalid(`access.repositories.${key}`), grants[key] = repositories[key];
|
|
667
716
|
access.files !== void 0 && !["read", "read-write"].includes(access.files) && invalid("access.files");
|
|
668
717
|
let runtime = object2(v.runtime === void 0 ? {} : v.runtime, ["features", "resources", "maxDuration"], "runtime");
|
|
669
|
-
runtime.features !== void 0 && (!Array.isArray(runtime.features) || runtime.features.length !== 0) && invalid("runtime.features"), runtime.resources !== void 0 && runtime.resources !== "standard" && invalid("runtime.resources"), runtime.maxDuration !== void 0 && runtime.maxDuration
|
|
718
|
+
runtime.features !== void 0 && (!Array.isArray(runtime.features) || runtime.features.length !== 0) && invalid("runtime.features"), runtime.resources !== void 0 && runtime.resources !== "standard" && invalid("runtime.resources"), runtime.maxDuration !== void 0 && !["15m", "60m"].includes(runtime.maxDuration) && invalid("runtime.maxDuration");
|
|
670
719
|
let retry = object2(v.retry === void 0 ? {} : v.retry, ["maxAttempts"], "retry");
|
|
671
720
|
retry.maxAttempts !== void 0 && retry.maxAttempts !== 1 && invalid("retry.maxAttempts");
|
|
672
721
|
let assets = v.assets === void 0 ? [] : v.assets;
|
|
@@ -679,7 +728,11 @@ function parseRoutineDeclaration(value) {
|
|
|
679
728
|
...access.files === void 0 ? {} : { files: access.files },
|
|
680
729
|
publish: list(access.publish, "access.publish", ["asks", "digests"])
|
|
681
730
|
},
|
|
682
|
-
runtime: {
|
|
731
|
+
runtime: {
|
|
732
|
+
features: [],
|
|
733
|
+
resources: "standard",
|
|
734
|
+
maxDuration: runtime.maxDuration ?? "60m"
|
|
735
|
+
},
|
|
683
736
|
retry: { maxAttempts: 1 },
|
|
684
737
|
assets: [...assets].sort()
|
|
685
738
|
};
|
|
@@ -732,7 +785,7 @@ function parseRoutineAccess(value) {
|
|
|
732
785
|
function parseRoutineAIOutputIssue(value) {
|
|
733
786
|
if (!value || typeof value != "object" || Array.isArray(value)) return;
|
|
734
787
|
let v = value;
|
|
735
|
-
if (["invalid_json", "invalid_response", "empty_text"].includes(String(v.reason)))
|
|
788
|
+
if (["invalid_json", "invalid_response", "empty_text", "structured_output_limit"].includes(String(v.reason)))
|
|
736
789
|
return Object.keys(v).join(",") === "reason" ? { reason: v.reason } : void 0;
|
|
737
790
|
if (!(!["missing_field", "unexpected_field", "wrong_type", "out_of_bounds", "invalid_file"].includes(String(v.reason)) || typeof v.path != "string" || v.path.length > 256 || !/^\$(?:\.[a-z][A-Za-z0-9]*|\[(?:0|[1-9][0-9]*)\])*$/.test(v.path) || !["object", "array", "boolean", "string", "integer", "number", "file"].includes(String(v.expected)) || !["missing", "null", "object", "array", "boolean", "string", "number", "other"].includes(String(v.received)) || Object.keys(v).some((key) => !["reason", "path", "expected", "received", "constraint", "limit"].includes(key)))) {
|
|
738
791
|
if (v.reason === "out_of_bounds") {
|
|
@@ -748,6 +801,7 @@ function parseRoutineAIOutputIssue(value) {
|
|
|
748
801
|
}
|
|
749
802
|
}
|
|
750
803
|
function routineAIOutputMessage(issue) {
|
|
804
|
+
if (issue.reason === "structured_output_limit") return "AI couldn\u2019t produce an answer matching the requested format within its submission limit.";
|
|
751
805
|
if (issue.reason === "invalid_json") return "AI replied, but its answer could not be read as JSON.";
|
|
752
806
|
if (issue.reason === "invalid_response") return "AI returned a response OS could not read.";
|
|
753
807
|
if (issue.reason === "empty_text") return "AI returned an empty answer.";
|
|
@@ -789,11 +843,83 @@ function routineAIOutputMessage(issue) {
|
|
|
789
843
|
${field}: expected ${expected}; received ${received}.`;
|
|
790
844
|
}
|
|
791
845
|
|
|
846
|
+
function parseRoutineAIErrorDetail(code, value) {
|
|
847
|
+
if (code === "invalid_output") return parseRoutineAIOutputIssue(value);
|
|
848
|
+
if (!value || typeof value != "object" || Array.isArray(value)) return;
|
|
849
|
+
let v = value, only2 = (...keys4) => Object.keys(v).every((key) => ["reason", ...keys4].includes(key));
|
|
850
|
+
if (code === "provider_failure") {
|
|
851
|
+
if (v.reason === "turn_limit" && only2("limit") && Number.isSafeInteger(v.limit) && Number(v.limit) >= 1 && Number(v.limit) <= 1024)
|
|
852
|
+
return { reason: "turn_limit", limit: v.limit };
|
|
853
|
+
if (v.reason === "runner_exit" && only2("exitCode") && (v.exitCode === void 0 || Number.isSafeInteger(v.exitCode) && Number(v.exitCode) >= 1 && Number(v.exitCode) <= 255))
|
|
854
|
+
return { reason: "runner_exit", ...v.exitCode === void 0 ? {} : { exitCode: v.exitCode } };
|
|
855
|
+
if (only2() && ["runner_error", "invalid_runner_response", "unexpected_runner_configuration"].includes(String(v.reason)))
|
|
856
|
+
return { reason: v.reason };
|
|
857
|
+
}
|
|
858
|
+
if (code === "invalid_input" && only2() && ["invalid_tools", "tools_require_file"].includes(String(v.reason)))
|
|
859
|
+
return { reason: v.reason };
|
|
860
|
+
if (code === "unsupported_file" && v.reason === "unsupported_media_type" && only2("mediaType") && typeof v.mediaType == "string" && isCanonicalOriginalMediaType(v.mediaType))
|
|
861
|
+
return { reason: "unsupported_media_type", mediaType: v.mediaType };
|
|
862
|
+
}
|
|
863
|
+
function routineAIErrorMessage(code, value) {
|
|
864
|
+
let detail = parseRoutineAIErrorDetail(code, value);
|
|
865
|
+
if (code === "invalid_output" && detail) return routineAIOutputMessage(detail);
|
|
866
|
+
if (detail) switch (detail.reason) {
|
|
867
|
+
case "turn_limit":
|
|
868
|
+
return `AI stopped before finishing the request.
|
|
869
|
+
It reached the ${detail.limit}-turn limit.`;
|
|
870
|
+
case "runner_exit":
|
|
871
|
+
return `AI couldn\u2019t complete the request.
|
|
872
|
+
The local AI runner stopped before returning a usable answer.`;
|
|
873
|
+
case "runner_error":
|
|
874
|
+
return `AI couldn\u2019t complete the request.
|
|
875
|
+
The local AI runner reported an error. No more specific reason was available.`;
|
|
876
|
+
case "invalid_runner_response":
|
|
877
|
+
return `AI couldn\u2019t complete the request.
|
|
878
|
+
The local AI runner did not return a complete, readable response.`;
|
|
879
|
+
case "unexpected_runner_configuration":
|
|
880
|
+
return `OS couldn\u2019t accept the AI response.
|
|
881
|
+
The runner\u2019s model, tools or configuration did not match the permitted setup.`;
|
|
882
|
+
case "invalid_tools":
|
|
883
|
+
return `The AI request is invalid.
|
|
884
|
+
Set tools to true or false.`;
|
|
885
|
+
case "tools_require_file":
|
|
886
|
+
return `The AI request is invalid.
|
|
887
|
+
Using tools requires a File input.`;
|
|
888
|
+
case "unsupported_media_type":
|
|
889
|
+
return `AI couldn\u2019t read this file.
|
|
890
|
+
Its media type is ${detail.mediaType}, which this input path doesn\u2019t support.
|
|
891
|
+
|
|
892
|
+
Check the file\u2019s stored media type before retrying. The model was not called.`;
|
|
893
|
+
}
|
|
894
|
+
switch (code) {
|
|
895
|
+
case "access_denied":
|
|
896
|
+
return "This routine doesn\u2019t currently have permission to use AI.";
|
|
897
|
+
case "capability_unavailable":
|
|
898
|
+
return "AI is unavailable in this execution environment.";
|
|
899
|
+
case "invalid_input":
|
|
900
|
+
return "The AI request is invalid. Check its input, instructions and schema.";
|
|
901
|
+
case "unsupported_file":
|
|
902
|
+
return "AI couldn\u2019t read this file in the requested format.";
|
|
903
|
+
case "file_unavailable":
|
|
904
|
+
return "AI couldn\u2019t read or verify the file.";
|
|
905
|
+
case "input_too_large":
|
|
906
|
+
return "The AI input exceeds the size limit for this execution path.";
|
|
907
|
+
case "output_too_large":
|
|
908
|
+
return "The AI response exceeds the size limit for this execution path.";
|
|
909
|
+
case "provider_failure":
|
|
910
|
+
return "AI couldn\u2019t complete the request. No more specific reason was recorded.";
|
|
911
|
+
case "invalid_output":
|
|
912
|
+
return "AI returned an answer OS could not accept.";
|
|
913
|
+
case "cancelled":
|
|
914
|
+
return "The AI operation was stopped before it completed.";
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
792
918
|
var ROUTINE_AI_VALUE_BYTES = 256 * 1024, ROUTINE_AI_RESULT_BYTES = 6 * ROUTINE_AI_VALUE_BYTES + 1024, ROUTINE_AI_EVIDENCE_BYTES = 4 * 1024;
|
|
793
919
|
var AIError = class extends Error {
|
|
794
920
|
constructor(code, options = {}) {
|
|
795
|
-
let detail = code
|
|
796
|
-
super(
|
|
921
|
+
let detail = parseRoutineAIErrorDetail(code, options.detail);
|
|
922
|
+
super(routineAIErrorMessage(code, detail));
|
|
797
923
|
this.code = code;
|
|
798
924
|
this.name = "AIError", detail && (this.detail = Object.freeze(detail)), code === "invalid_output" && typeof options.text == "string" && new TextEncoder().encode(options.text).byteLength <= ROUTINE_AI_VALUE_BYTES && Object.defineProperty(this, "text", { value: options.text });
|
|
799
925
|
}
|
|
@@ -813,13 +939,18 @@ function capture(value, invalid9, oversized, limit = ROUTINE_AI_VALUE_BYTES) {
|
|
|
813
939
|
function parseRoutineAIRequest(value) {
|
|
814
940
|
let v = capture(value, "invalid_input", "input_too_large");
|
|
815
941
|
try {
|
|
816
|
-
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();
|
|
942
|
+
if (assertRoutineFields(v, v.kind === "generateObject" ? ["kind", "instructions", "input", "schema", "tools"] : ["kind", "instructions", "input", "tools"]), !["generateText", "generateObject"].includes(v.kind) || typeof v.instructions != "string" || !v.instructions.trim()) throw new Error();
|
|
817
943
|
let input = typeof v.input == "string" ? v.input : parseFileDescriptor(v.input);
|
|
818
|
-
if (v
|
|
944
|
+
if (Object.hasOwn(v, "tools") && typeof v.tools != "boolean")
|
|
945
|
+
throw new AIError("invalid_input", { detail: { reason: "invalid_tools" } });
|
|
946
|
+
if (v.tools === !0 && typeof input == "string")
|
|
947
|
+
throw new AIError("invalid_input", { detail: { reason: "tools_require_file" } });
|
|
948
|
+
let tools = v.tools === !0 ? { tools: !0 } : {};
|
|
949
|
+
if (v.kind === "generateText") return freezeRoutineMetadata({ kind: v.kind, instructions: v.instructions, input, ...tools });
|
|
819
950
|
let schema2 = parseAppRoutineContract({ routine: "ai", input: v.schema, steps: [{ id: "generate" }] }).input;
|
|
820
|
-
return freezeRoutineMetadata({ kind: v.kind, instructions: v.instructions, input, schema: schema2 });
|
|
821
|
-
} catch {
|
|
822
|
-
throw new AIError("invalid_input");
|
|
951
|
+
return freezeRoutineMetadata({ kind: v.kind, instructions: v.instructions, input, schema: schema2, ...tools });
|
|
952
|
+
} catch (error) {
|
|
953
|
+
throw error instanceof AIError ? error : new AIError("invalid_input");
|
|
823
954
|
}
|
|
824
955
|
}
|
|
825
956
|
function parseRoutineAIResult(request2, value) {
|
|
@@ -995,11 +1126,12 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
995
1126
|
if (!runtime.ai) throw new AIError("capability_unavailable");
|
|
996
1127
|
let request2;
|
|
997
1128
|
try {
|
|
998
|
-
assertRoutineFields(value, kind === "generateObject" ? ["instructions", "input", "schema"] : ["instructions", "input"]), request2 = parseRoutineAIRequest({
|
|
1129
|
+
assertRoutineFields(value, kind === "generateObject" ? ["instructions", "input", "schema", "tools"] : ["instructions", "input", "tools"]), request2 = parseRoutineAIRequest({
|
|
999
1130
|
kind,
|
|
1000
1131
|
instructions: value.instructions,
|
|
1001
1132
|
input: value.input,
|
|
1002
|
-
...kind === "generateObject" ? { schema: schemaMetadata(value.schema).schema } : {}
|
|
1133
|
+
...kind === "generateObject" ? { schema: schemaMetadata(value.schema).schema } : {},
|
|
1134
|
+
...value.tools === void 0 ? {} : { tools: value.tools }
|
|
1003
1135
|
});
|
|
1004
1136
|
} catch (error) {
|
|
1005
1137
|
throw error instanceof AIError ? error : new AIError("invalid_input");
|
|
@@ -1021,10 +1153,16 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
1021
1153
|
}) : value, validateHandlers = (value) => {
|
|
1022
1154
|
for (let question2 of value.questions ?? []) if (question2.handler && !contract.responses.some((handler) => handler.id === question2.handler.id)) return invalid3();
|
|
1023
1155
|
return value;
|
|
1024
|
-
}, os2 = Object.freeze({
|
|
1156
|
+
}, activeStep, progress2 = /* @__PURE__ */ new Map(), os2 = Object.freeze({
|
|
1025
1157
|
...guarded({
|
|
1026
1158
|
...runtime,
|
|
1027
|
-
run: freezeRoutineMetadata({
|
|
1159
|
+
run: freezeRoutineMetadata({ id: runtime.run.id, async progress(value) {
|
|
1160
|
+
assertRoutineFields(value, ["completed", "total"]);
|
|
1161
|
+
let { completed, total } = value, prior = activeStep ? progress2.get(activeStep) : void 0;
|
|
1162
|
+
if (!active2 || broken || !activeStep || !Number.isSafeInteger(completed) || !Number.isSafeInteger(total) || completed < 1 || completed > total || prior && (prior.total !== total || completed <= prior.completed)) return invalid3();
|
|
1163
|
+
let accepted = freezeRoutineMetadata({ step: activeStep, completed, total });
|
|
1164
|
+
await runtime.run.progress(accepted), progress2.set(activeStep, accepted);
|
|
1165
|
+
} }),
|
|
1028
1166
|
ai: {
|
|
1029
1167
|
generateText: (value) => generate("generateText", value),
|
|
1030
1168
|
generateObject: (value) => generate("generateObject", value)
|
|
@@ -1049,13 +1187,13 @@ async function executeRoutineDefinition(definition, input, runtime) {
|
|
|
1049
1187
|
if (broken) return invalid3();
|
|
1050
1188
|
reached.add(id3);
|
|
1051
1189
|
try {
|
|
1052
|
-
await runtime.step(id3, { status: "running" });
|
|
1190
|
+
await runtime.step(id3, { status: "running" }), activeStep = id3;
|
|
1053
1191
|
let output = await steps[id3].run(saved, os2);
|
|
1054
1192
|
if (assertRoutineFields(output, ["summary", "data"]), !Object.hasOwn(output, "summary") || !Object.hasOwn(output, "data")) return invalid3();
|
|
1055
1193
|
let summary2 = captureJson(output.summary), data3 = captureJson(output.data);
|
|
1056
|
-
return await runtime.step(id3, { status: "completed", summary: summary2, data: data3 }), freezeRoutineMetadata({ summary: summary2, data: data3 });
|
|
1194
|
+
return await runtime.step(id3, { status: "completed", summary: summary2, data: data3 }), activeStep = void 0, freezeRoutineMetadata({ summary: summary2, data: data3 });
|
|
1057
1195
|
} catch (error) {
|
|
1058
|
-
throw broken = !0, await runtime.step(id3, { status: "failed" }), error;
|
|
1196
|
+
throw broken = !0, activeStep = void 0, await runtime.step(id3, { status: "failed" }), error;
|
|
1059
1197
|
}
|
|
1060
1198
|
});
|
|
1061
1199
|
return work = next.then(() => {
|
|
@@ -1541,7 +1679,7 @@ function capture3(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
|
|
|
1541
1679
|
ancestors.delete(value);
|
|
1542
1680
|
}
|
|
1543
1681
|
}
|
|
1544
|
-
function recordPagination(
|
|
1682
|
+
function recordPagination(queryRecords) {
|
|
1545
1683
|
function pages(query) {
|
|
1546
1684
|
let captured = capture3(query), names = Object.keys(historyProperties(captured));
|
|
1547
1685
|
for (let name2 of names) {
|
|
@@ -1563,7 +1701,7 @@ function recordPagination(select) {
|
|
|
1563
1701
|
let request2 = Object.fromEntries(active2.map((name2) => {
|
|
1564
1702
|
let selection2 = captured[name2], next = state.get(name2).next;
|
|
1565
1703
|
return [name2, next === void 0 ? selection2 : { ...selection2, $: { ...selection2.$, after: next } }];
|
|
1566
|
-
})), response2 = await
|
|
1704
|
+
})), response2 = await queryRecords(request2), page;
|
|
1567
1705
|
try {
|
|
1568
1706
|
page = capture3(response2);
|
|
1569
1707
|
let keys4 = Object.keys(historyProperties(page));
|
|
@@ -1647,7 +1785,7 @@ var genericData = {
|
|
|
1647
1785
|
let refs = captureRecordsReadRefs(typeof input == "string" ? [input] : input), captured = captureRecordsReadOptions(options), result2 = await send3({ operation: "records.read", refs, ...options === void 0 ? {} : { options: captured } });
|
|
1648
1786
|
return typeof input == "string" ? result2.records[0] : result2;
|
|
1649
1787
|
}
|
|
1650
|
-
let
|
|
1788
|
+
let queryRecords = (query) => send3({ operation: "records.query", query });
|
|
1651
1789
|
return {
|
|
1652
1790
|
collections: {
|
|
1653
1791
|
list: () => send3({ operation: "collections.list" }),
|
|
@@ -1655,8 +1793,8 @@ var genericData = {
|
|
|
1655
1793
|
},
|
|
1656
1794
|
records: {
|
|
1657
1795
|
read: read2,
|
|
1658
|
-
|
|
1659
|
-
...recordPagination(
|
|
1796
|
+
query: queryRecords,
|
|
1797
|
+
...recordPagination(queryRecords),
|
|
1660
1798
|
search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
|
|
1661
1799
|
},
|
|
1662
1800
|
history: {
|
|
@@ -2301,16 +2439,16 @@ function parseConnectionLease(raw, now = Date.now()) {
|
|
|
2301
2439
|
if (!v || typeof v != "object" || Array.isArray(v) || !connectionUuid(v.connectionId) || !connectionUuid(v.runId) || typeof v.name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(v.name) || typeof v.accessToken != "string" || !/^[A-Za-z0-9._~+/-]{1,8192}={0,2}$/.test(v.accessToken))
|
|
2302
2440
|
throw new Error("Invalid connection credential");
|
|
2303
2441
|
if (v.provider === "outlook" || v.provider === "sharepoint") {
|
|
2304
|
-
if (!(v.provider === "outlook" ? Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,mailboxEmail,name,provider,runId" && validMicrosoftMailbox(v.mailboxEmail) : Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,name,provider,runId,siteId,siteUrl" && typeof v.siteUrl == "string" && canonicalSharePointSiteUrl(v.siteUrl) === v.siteUrl && validSharePointSiteId(v.siteId, v.siteUrl)) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now
|
|
2442
|
+
if (!(v.provider === "outlook" ? Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,mailboxEmail,name,provider,runId" && validMicrosoftMailbox(v.mailboxEmail) : Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,name,provider,runId,siteId,siteUrl" && typeof v.siteUrl == "string" && canonicalSharePointSiteUrl(v.siteUrl) === v.siteUrl && validSharePointSiteId(v.siteId, v.siteUrl)) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now || Date.parse(v.expiresAt) > now + 36e5)
|
|
2305
2443
|
throw new Error("Invalid connection credential");
|
|
2306
2444
|
return v;
|
|
2307
2445
|
}
|
|
2308
2446
|
if (v.provider === "gmail") {
|
|
2309
|
-
if (Object.keys(v).sort().join(",") !== "accessToken,accountEmail,connectionId,expiresAt,name,provider,runId,scopes" || typeof v.accountEmail != "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.accountEmail) || !validGoogleScopes(v.scopes) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now
|
|
2447
|
+
if (Object.keys(v).sort().join(",") !== "accessToken,accountEmail,connectionId,expiresAt,name,provider,runId,scopes" || typeof v.accountEmail != "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.accountEmail) || !validGoogleScopes(v.scopes) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now || Date.parse(v.expiresAt) > now + 36e5)
|
|
2310
2448
|
throw new Error("Invalid connection credential");
|
|
2311
2449
|
return v;
|
|
2312
2450
|
}
|
|
2313
|
-
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
|
|
2451
|
+
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 && 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 && Date.parse(v.expiresAt) <= now + 144e5)
|
|
2314
2452
|
return v;
|
|
2315
2453
|
throw new Error("Invalid connection credential");
|
|
2316
2454
|
}
|
|
@@ -3476,22 +3614,22 @@ function validPair(value) {
|
|
|
3476
3614
|
return validProof(pair.credential) && validProof(pair.renewalCredential) && pair.credential !== pair.renewalCredential && validBinding(pair.context);
|
|
3477
3615
|
}
|
|
3478
3616
|
|
|
3479
|
-
var
|
|
3617
|
+
var WorkspaceAccessError = class extends Error {
|
|
3480
3618
|
constructor(status) {
|
|
3481
|
-
super("Workspace
|
|
3619
|
+
super("Workspace access is unavailable.");
|
|
3482
3620
|
this.status = status;
|
|
3483
3621
|
}
|
|
3484
3622
|
status;
|
|
3485
3623
|
};
|
|
3486
3624
|
|
|
3487
|
-
var unavailable3 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable"), contextFailure = (error) => error instanceof
|
|
3625
|
+
var unavailable3 = () => new InboxOperationError(503, "unavailable"), stale = () => new InboxOperationError(401, "authority_unavailable"), contextFailure = (error) => error instanceof WorkspaceAccessError ? new InboxOperationError(error.status, error.status === 401 ? "authority_unavailable" : error.status === 403 ? "access_denied" : "unavailable") : stale();
|
|
3488
3626
|
function hostFailure(error, context) {
|
|
3489
3627
|
return !context.isCurrent() || context.expiresAt <= Date.now() || error instanceof InboxContextError && error.status === 401 ? stale() : error instanceof InboxContextError && error.status === 403 ? new InboxOperationError(403, "access_denied") : unavailable3();
|
|
3490
3628
|
}
|
|
3491
|
-
async function send2(operation2, input,
|
|
3629
|
+
async function send2(operation2, input, resolved) {
|
|
3492
3630
|
let envelope = parseInboxRequest({ operation: operation2, input }), context;
|
|
3493
3631
|
try {
|
|
3494
|
-
context =
|
|
3632
|
+
context = resolved ?? await resolveAppContext();
|
|
3495
3633
|
} catch (error) {
|
|
3496
3634
|
throw contextFailure(error);
|
|
3497
3635
|
}
|
|
@@ -3669,7 +3807,7 @@ function init({ auth: input }) {
|
|
|
3669
3807
|
let expiresAt = (session.expires_at ?? 0) * 1e3;
|
|
3670
3808
|
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now() || !session.user.id)
|
|
3671
3809
|
throw new Error("Hosted Data context unavailable.");
|
|
3672
|
-
if (person = session.user.id, registered && await registered.
|
|
3810
|
+
if (person = session.user.id, registered && await registered.checkWorkspaceAccess(), !active2 || globalThis.location.origin !== endpoint || started !== revision || person !== session.user.id)
|
|
3673
3811
|
throw new Error("Hosted Data context unavailable.");
|
|
3674
3812
|
let isCurrent = () => active2 && globalThis.location.origin === endpoint && revision === started && person === session.user.id;
|
|
3675
3813
|
return {
|
|
@@ -3817,11 +3955,11 @@ function createBrowserAuth(runtime) {
|
|
|
3817
3955
|
function current2(c, origin, revision) {
|
|
3818
3956
|
return c.session && !validSession(c.session) && expire(c), c.active && c.revision === revision && globalThis.location?.origin === origin;
|
|
3819
3957
|
}
|
|
3820
|
-
async function
|
|
3958
|
+
async function checkWorkspaceAccess(c, origin) {
|
|
3821
3959
|
if (origin === "https://auth.oddington.ai" || origin === "http://127.0.0.1:5176") return;
|
|
3822
3960
|
let revision = c.revision;
|
|
3823
3961
|
if (!current2(c, origin, revision) || !c.session || c.state.pending === "sign_out") throw runtime.failure("stale");
|
|
3824
|
-
if (c.
|
|
3962
|
+
if (c.workspaceAccess?.revision !== revision) {
|
|
3825
3963
|
let token = c.session.access_token, result2 = (async () => {
|
|
3826
3964
|
let status;
|
|
3827
3965
|
try {
|
|
@@ -3835,17 +3973,17 @@ function createBrowserAuth(runtime) {
|
|
|
3835
3973
|
});
|
|
3836
3974
|
status = response2.status;
|
|
3837
3975
|
let value = status === 200 ? await response2.json() : null;
|
|
3838
|
-
status === 200 && value?.
|
|
3976
|
+
status === 200 && value?.allowed !== !0 && (status = 503), status !== 200 && response2.body?.cancel().catch(() => {
|
|
3839
3977
|
});
|
|
3840
3978
|
} catch {
|
|
3841
3979
|
status = 503;
|
|
3842
3980
|
}
|
|
3843
3981
|
if (!current2(c, origin, revision) || c.state.pending === "sign_out") throw runtime.failure("stale");
|
|
3844
|
-
if (status !== 200) throw new
|
|
3982
|
+
if (status !== 200) throw new WorkspaceAccessError(status === 401 ? 401 : status === 403 ? 403 : 503);
|
|
3845
3983
|
})();
|
|
3846
|
-
c.
|
|
3984
|
+
c.workspaceAccess = { revision, result: result2 };
|
|
3847
3985
|
}
|
|
3848
|
-
if (await c.
|
|
3986
|
+
if (await c.workspaceAccess.result, !current2(c, origin, revision)) throw runtime.failure("stale");
|
|
3849
3987
|
}
|
|
3850
3988
|
return { create() {
|
|
3851
3989
|
let origin = globalThis.location?.origin ?? "", c = coordinators.get(origin);
|
|
@@ -3951,9 +4089,9 @@ function createBrowserAuth(runtime) {
|
|
|
3951
4089
|
if (!current2(coordinator, origin, revision) && (coordinator.session?.access_token !== data3.session.access_token || coordinator.revision !== revision + 1 || coordinator.state.pending !== "verify_code")) throw runtime.failure("stale");
|
|
3952
4090
|
accept(coordinator, "SIGNED_IN", data3.session);
|
|
3953
4091
|
try {
|
|
3954
|
-
await
|
|
4092
|
+
await checkWorkspaceAccess(coordinator, origin);
|
|
3955
4093
|
} catch (error2) {
|
|
3956
|
-
if (!(error2 instanceof
|
|
4094
|
+
if (!(error2 instanceof WorkspaceAccessError)) throw error2;
|
|
3957
4095
|
}
|
|
3958
4096
|
});
|
|
3959
4097
|
},
|
|
@@ -3983,8 +4121,8 @@ function createBrowserAuth(runtime) {
|
|
|
3983
4121
|
async ready() {
|
|
3984
4122
|
assertActive(), await coordinator.ready, assertActive();
|
|
3985
4123
|
},
|
|
3986
|
-
async
|
|
3987
|
-
assertActive(), await
|
|
4124
|
+
async checkWorkspaceAccess() {
|
|
4125
|
+
assertActive(), await checkWorkspaceAccess(coordinator, origin), assertActive();
|
|
3988
4126
|
},
|
|
3989
4127
|
onDispose(callback) {
|
|
3990
4128
|
return active2 ? (disposalObservers.add(callback), () => {
|
|
@@ -4173,6 +4311,11 @@ function times(value) {
|
|
|
4173
4311
|
function bounded(value) {
|
|
4174
4312
|
return assertRoutineJson(value), new TextEncoder().encode(JSON.stringify(value)).byteLength > 256 * 1024 ? invalid8() : value;
|
|
4175
4313
|
}
|
|
4314
|
+
function progress(value) {
|
|
4315
|
+
if (value === void 0) return {};
|
|
4316
|
+
let v = record3(value);
|
|
4317
|
+
return Object.keys(v).sort().join(",") !== "completed,total" || !Number.isSafeInteger(v.completed) || !Number.isSafeInteger(v.total) || v.completed < 1 || v.completed > v.total ? invalid8() : { progress: { completed: v.completed, total: v.total } };
|
|
4318
|
+
}
|
|
4176
4319
|
function parseRunStep(value, expected) {
|
|
4177
4320
|
let v = record3(value);
|
|
4178
4321
|
return typeof v.id != "string" || !name.test(v.id) || expected !== void 0 && v.id !== expected || typeof v.title != "string" || !v.title.trim() || v.title.length > 256 || !["pending", "running", "completed", "failed", "skipped"].includes(v.status) ? invalid8() : {
|
|
@@ -4180,6 +4323,7 @@ function parseRunStep(value, expected) {
|
|
|
4180
4323
|
title: v.title,
|
|
4181
4324
|
status: v.status,
|
|
4182
4325
|
...times(v),
|
|
4326
|
+
...progress(v.progress),
|
|
4183
4327
|
...Object.hasOwn(v, "summary") ? { summary: bounded(v.summary) } : {},
|
|
4184
4328
|
...Object.hasOwn(v, "data") ? { data: bounded(v.data) } : {}
|
|
4185
4329
|
};
|
|
@@ -4283,12 +4427,12 @@ async function request(key, suffix, init2, maximum = SUMMARY_BYTES, retained, re
|
|
|
4283
4427
|
function summary(value, key, context, id3) {
|
|
4284
4428
|
if (context.kind !== "local")
|
|
4285
4429
|
try {
|
|
4286
|
-
return (!only(value, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure") || !Array.isArray(value.steps) || value.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,summary,detailAvailable")) || value.failure !== void 0 && !only(value.failure, "message")) && fail3("execution_unavailable"), parseRemoteRun(value, { routine: key, id: id3 });
|
|
4430
|
+
return (!only(value, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure") || !Array.isArray(value.steps) || value.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,progress,summary,detailAvailable")) || value.failure !== void 0 && !only(value.failure, "message")) && fail3("execution_unavailable"), parseRemoteRun(value, { routine: key, id: id3 });
|
|
4287
4431
|
} catch {
|
|
4288
4432
|
return fail3("execution_unavailable");
|
|
4289
4433
|
}
|
|
4290
4434
|
let run = value;
|
|
4291
|
-
return (!only(run, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure,local") || typeof run.id != "string" || !uuid2.test(run.id) || id3 !== void 0 && run.id !== id3 || run.routine !== key || run.placement !== "local" || !["queued", "running", "succeeded", "failed"].includes(run.status) || !timestamp(run.createdAt) || !optionalTimes(run) || !Array.isArray(run.steps) || run.steps.length > 64 || run.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,summary,detailAvailable") || typeof step.detailAvailable != "boolean" || !validStep(step)) || new Set(run.steps.map((step) => step.id)).size !== run.steps.length || Object.hasOwn(run, "result") && (run.status !== "succeeded" || !bounded2(run.result)) || run.failure !== void 0 && (run.status !== "failed" || !only(run.failure, "message") || !message(run.failure.message)) || run.local !== void 0 && !validLocalActivity(run.local)) && fail3("execution_unavailable"), run;
|
|
4435
|
+
return (!only(run, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure,local") || typeof run.id != "string" || !uuid2.test(run.id) || id3 !== void 0 && run.id !== id3 || run.routine !== key || run.placement !== "local" || !["queued", "running", "succeeded", "failed"].includes(run.status) || !timestamp(run.createdAt) || !optionalTimes(run) || !Array.isArray(run.steps) || run.steps.length > 64 || run.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,progress,summary,detailAvailable") || typeof step.detailAvailable != "boolean" || !validStep(step)) || new Set(run.steps.map((step) => step.id)).size !== run.steps.length || Object.hasOwn(run, "result") && (run.status !== "succeeded" || !bounded2(run.result)) || run.failure !== void 0 && (run.status !== "failed" || !only(run.failure, "message") || !message(run.failure.message)) || run.local !== void 0 && !validLocalActivity(run.local)) && fail3("execution_unavailable"), run;
|
|
4292
4436
|
}
|
|
4293
4437
|
function only(value, allowed) {
|
|
4294
4438
|
return !!value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).every((key) => allowed.split(",").includes(key));
|
|
@@ -4298,7 +4442,7 @@ function optionalTimes(value) {
|
|
|
4298
4442
|
return (value.startedAt === void 0 || timestamp(value.startedAt)) && (value.finishedAt === void 0 || timestamp(value.finishedAt));
|
|
4299
4443
|
}
|
|
4300
4444
|
function validStep(step) {
|
|
4301
|
-
return typeof step.id == "string" && identifier.test(step.id) && typeof step.title == "string" && step.title.length > 0 && step.title.length <= 256 && ["pending", "running", "completed", "failed", "skipped"].includes(step.status) && optionalTimes(step) && (!Object.hasOwn(step, "summary") || bounded2(step.summary)) && (!Object.hasOwn(step, "data") || bounded2(step.data));
|
|
4445
|
+
return typeof step.id == "string" && identifier.test(step.id) && typeof step.title == "string" && step.title.length > 0 && step.title.length <= 256 && ["pending", "running", "completed", "failed", "skipped"].includes(step.status) && optionalTimes(step) && (step.progress === void 0 || only(step.progress, "completed,total") && Number.isSafeInteger(step.progress.completed) && Number.isSafeInteger(step.progress.total) && step.progress.completed > 0 && step.progress.completed <= step.progress.total) && (!Object.hasOwn(step, "summary") || bounded2(step.summary)) && (!Object.hasOwn(step, "data") || bounded2(step.data));
|
|
4302
4446
|
}
|
|
4303
4447
|
function validLocalActivity(value) {
|
|
4304
4448
|
let paths = (value2) => Array.isArray(value2) && value2.every((path) => typeof path == "string" && path.length > 0 && path.length <= 4096 && !path.startsWith("/") && !path.includes("\\") && !path.split("/").some((part) => !part || part === "." || part === "..") && !/[\x00-\x1f\x7f]/.test(path));
|
|
@@ -4339,11 +4483,11 @@ function handle(key, id3, context) {
|
|
|
4339
4483
|
let value = await request(key, `runs/${id3}/steps/${step}`, void 0, 514 * 1024, context, !0);
|
|
4340
4484
|
if (context.kind !== "local")
|
|
4341
4485
|
try {
|
|
4342
|
-
return only(value, "id,title,status,startedAt,finishedAt,summary,data") || fail3("execution_unavailable"), parseRunStep(value, step);
|
|
4486
|
+
return only(value, "id,title,status,startedAt,finishedAt,progress,summary,data") || fail3("execution_unavailable"), parseRunStep(value, step);
|
|
4343
4487
|
} catch {
|
|
4344
4488
|
return fail3("execution_unavailable");
|
|
4345
4489
|
}
|
|
4346
|
-
return (!only(value, "id,title,status,startedAt,finishedAt,summary,data") || value.id !== step || !validStep(value)) && fail3("execution_unavailable"), value;
|
|
4490
|
+
return (!only(value, "id,title,status,startedAt,finishedAt,progress,summary,data") || value.id !== step || !validStep(value)) && fail3("execution_unavailable"), value;
|
|
4347
4491
|
}
|
|
4348
4492
|
});
|
|
4349
4493
|
}
|