@nodetool-ai/execution 0.8.1
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 +129 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/app-debug/app-spec.d.ts +94 -0
- package/dist/app-debug/app-spec.d.ts.map +1 -0
- package/dist/app-debug/app-spec.js +710 -0
- package/dist/app-debug/app-spec.js.map +1 -0
- package/dist/app-debug/application-target.d.ts +53 -0
- package/dist/app-debug/application-target.d.ts.map +1 -0
- package/dist/app-debug/application-target.js +126 -0
- package/dist/app-debug/application-target.js.map +1 -0
- package/dist/app-debug/bundle-target.d.ts +21 -0
- package/dist/app-debug/bundle-target.d.ts.map +1 -0
- package/dist/app-debug/bundle-target.js +51 -0
- package/dist/app-debug/bundle-target.js.map +1 -0
- package/dist/app-debug/graph-shape.d.ts +14 -0
- package/dist/app-debug/graph-shape.d.ts.map +1 -0
- package/dist/app-debug/graph-shape.js +23 -0
- package/dist/app-debug/graph-shape.js.map +1 -0
- package/dist/app-debug/index.d.ts +26 -0
- package/dist/app-debug/index.d.ts.map +1 -0
- package/dist/app-debug/index.js +19 -0
- package/dist/app-debug/index.js.map +1 -0
- package/dist/app-debug/markdown.d.ts +6 -0
- package/dist/app-debug/markdown.d.ts.map +1 -0
- package/dist/app-debug/markdown.js +133 -0
- package/dist/app-debug/markdown.js.map +1 -0
- package/dist/app-debug/runtime.d.ts +267 -0
- package/dist/app-debug/runtime.d.ts.map +1 -0
- package/dist/app-debug/runtime.js +633 -0
- package/dist/app-debug/runtime.js.map +1 -0
- package/dist/app-debug/script-operation.d.ts +58 -0
- package/dist/app-debug/script-operation.d.ts.map +1 -0
- package/dist/app-debug/script-operation.js +44 -0
- package/dist/app-debug/script-operation.js.map +1 -0
- package/dist/app-debug/simulate.d.ts +85 -0
- package/dist/app-debug/simulate.d.ts.map +1 -0
- package/dist/app-debug/simulate.js +991 -0
- package/dist/app-debug/simulate.js.map +1 -0
- package/dist/app-debug/summarize.d.ts +64 -0
- package/dist/app-debug/summarize.d.ts.map +1 -0
- package/dist/app-debug/summarize.js +65 -0
- package/dist/app-debug/summarize.js.map +1 -0
- package/dist/app-debug/types.d.ts +343 -0
- package/dist/app-debug/types.d.ts.map +1 -0
- package/dist/app-debug/types.js +2 -0
- package/dist/app-debug/types.js.map +1 -0
- package/dist/cost-ledger.d.ts +147 -0
- package/dist/cost-ledger.d.ts.map +1 -0
- package/dist/cost-ledger.js +288 -0
- package/dist/cost-ledger.js.map +1 -0
- package/dist/debug/collector.d.ts +28 -0
- package/dist/debug/collector.d.ts.map +1 -0
- package/dist/debug/collector.js +284 -0
- package/dist/debug/collector.js.map +1 -0
- package/dist/debug/index.d.ts +15 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +16 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/debug/types.d.ts +179 -0
- package/dist/debug/types.d.ts.map +1 -0
- package/dist/debug/types.js +11 -0
- package/dist/debug/types.js.map +1 -0
- package/dist/debug/verdict.d.ts +27 -0
- package/dist/debug/verdict.d.ts.map +1 -0
- package/dist/debug/verdict.js +51 -0
- package/dist/debug/verdict.js.map +1 -0
- package/dist/executor-resolver.d.ts +13 -0
- package/dist/executor-resolver.d.ts.map +1 -0
- package/dist/executor-resolver.js +13 -0
- package/dist/executor-resolver.js.map +1 -0
- package/dist/fal-output-decoder.d.ts +36 -0
- package/dist/fal-output-decoder.d.ts.map +1 -0
- package/dist/fal-output-decoder.js +129 -0
- package/dist/fal-output-decoder.js.map +1 -0
- package/dist/generation-lifecycle.d.ts +54 -0
- package/dist/generation-lifecycle.d.ts.map +1 -0
- package/dist/generation-lifecycle.js +431 -0
- package/dist/generation-lifecycle.js.map +1 -0
- package/dist/generation-recovery-worker.d.ts +100 -0
- package/dist/generation-recovery-worker.d.ts.map +1 -0
- package/dist/generation-recovery-worker.js +995 -0
- package/dist/generation-recovery-worker.js.map +1 -0
- package/dist/generation-tracker.d.ts +83 -0
- package/dist/generation-tracker.d.ts.map +1 -0
- package/dist/generation-tracker.js +436 -0
- package/dist/generation-tracker.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/js-script-debug/index.d.ts +13 -0
- package/dist/js-script-debug/index.d.ts.map +1 -0
- package/dist/js-script-debug/index.js +12 -0
- package/dist/js-script-debug/index.js.map +1 -0
- package/dist/js-script-debug/markdown.d.ts +6 -0
- package/dist/js-script-debug/markdown.d.ts.map +1 -0
- package/dist/js-script-debug/markdown.js +62 -0
- package/dist/js-script-debug/markdown.js.map +1 -0
- package/dist/js-script-debug/outputs.d.ts +20 -0
- package/dist/js-script-debug/outputs.d.ts.map +1 -0
- package/dist/js-script-debug/outputs.js +30 -0
- package/dist/js-script-debug/outputs.js.map +1 -0
- package/dist/js-script-debug/report.d.ts +15 -0
- package/dist/js-script-debug/report.d.ts.map +1 -0
- package/dist/js-script-debug/report.js +90 -0
- package/dist/js-script-debug/report.js.map +1 -0
- package/dist/js-script-debug/types.d.ts +63 -0
- package/dist/js-script-debug/types.d.ts.map +1 -0
- package/dist/js-script-debug/types.js +10 -0
- package/dist/js-script-debug/types.js.map +1 -0
- package/dist/js-script-debug/validate.d.ts +38 -0
- package/dist/js-script-debug/validate.d.ts.map +1 -0
- package/dist/js-script-debug/validate.js +137 -0
- package/dist/js-script-debug/validate.js.map +1 -0
- package/dist/message-stream.d.ts +33 -0
- package/dist/message-stream.d.ts.map +1 -0
- package/dist/message-stream.js +58 -0
- package/dist/message-stream.js.map +1 -0
- package/dist/normalize-graph.d.ts +13 -0
- package/dist/normalize-graph.d.ts.map +1 -0
- package/dist/normalize-graph.js +63 -0
- package/dist/normalize-graph.js.map +1 -0
- package/dist/output-names.d.ts +13 -0
- package/dist/output-names.d.ts.map +1 -0
- package/dist/output-names.js +13 -0
- package/dist/output-names.js.map +1 -0
- package/dist/predicates.d.ts +6 -0
- package/dist/predicates.d.ts.map +1 -0
- package/dist/predicates.js +6 -0
- package/dist/predicates.js.map +1 -0
- package/dist/preflight.d.ts +87 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +139 -0
- package/dist/preflight.js.map +1 -0
- package/dist/provider-secret-key.d.ts +3 -0
- package/dist/provider-secret-key.d.ts.map +1 -0
- package/dist/provider-secret-key.js +7 -0
- package/dist/provider-secret-key.js.map +1 -0
- package/dist/service/app-debug-service.d.ts +78 -0
- package/dist/service/app-debug-service.d.ts.map +1 -0
- package/dist/service/app-debug-service.js +201 -0
- package/dist/service/app-debug-service.js.map +1 -0
- package/dist/service/app-run-server.d.ts +28 -0
- package/dist/service/app-run-server.d.ts.map +1 -0
- package/dist/service/app-run-server.js +104 -0
- package/dist/service/app-run-server.js.map +1 -0
- package/dist/service/debug-sessions.d.ts +158 -0
- package/dist/service/debug-sessions.d.ts.map +1 -0
- package/dist/service/debug-sessions.js +358 -0
- package/dist/service/debug-sessions.js.map +1 -0
- package/dist/service/index.d.ts +22 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +17 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/job-progress.d.ts +40 -0
- package/dist/service/job-progress.d.ts.map +1 -0
- package/dist/service/job-progress.js +53 -0
- package/dist/service/job-progress.js.map +1 -0
- package/dist/service/workflow-run.d.ts +279 -0
- package/dist/service/workflow-run.d.ts.map +1 -0
- package/dist/service/workflow-run.js +598 -0
- package/dist/service/workflow-run.js.map +1 -0
- package/dist/service/workflow-workspace.d.ts +89 -0
- package/dist/service/workflow-workspace.d.ts.map +1 -0
- package/dist/service/workflow-workspace.js +160 -0
- package/dist/service/workflow-workspace.js.map +1 -0
- package/dist/session.d.ts +62 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +353 -0
- package/dist/session.js.map +1 -0
- package/dist/sketch-debug/index.d.ts +11 -0
- package/dist/sketch-debug/index.d.ts.map +1 -0
- package/dist/sketch-debug/index.js +10 -0
- package/dist/sketch-debug/index.js.map +1 -0
- package/dist/sketch-debug/markdown.d.ts +6 -0
- package/dist/sketch-debug/markdown.d.ts.map +1 -0
- package/dist/sketch-debug/markdown.js +93 -0
- package/dist/sketch-debug/markdown.js.map +1 -0
- package/dist/sketch-debug/report.d.ts +15 -0
- package/dist/sketch-debug/report.d.ts.map +1 -0
- package/dist/sketch-debug/report.js +98 -0
- package/dist/sketch-debug/report.js.map +1 -0
- package/dist/sketch-debug/types.d.ts +62 -0
- package/dist/sketch-debug/types.d.ts.map +1 -0
- package/dist/sketch-debug/types.js +10 -0
- package/dist/sketch-debug/types.js.map +1 -0
- package/dist/sketch-debug/validate.d.ts +14 -0
- package/dist/sketch-debug/validate.d.ts.map +1 -0
- package/dist/sketch-debug/validate.js +478 -0
- package/dist/sketch-debug/validate.js.map +1 -0
- package/dist/supervisor.d.ts +45 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +97 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/timeline-debug/index.d.ts +11 -0
- package/dist/timeline-debug/index.d.ts.map +1 -0
- package/dist/timeline-debug/index.js +10 -0
- package/dist/timeline-debug/index.js.map +1 -0
- package/dist/timeline-debug/legibility.d.ts +23 -0
- package/dist/timeline-debug/legibility.d.ts.map +1 -0
- package/dist/timeline-debug/legibility.js +240 -0
- package/dist/timeline-debug/legibility.js.map +1 -0
- package/dist/timeline-debug/markdown.d.ts +6 -0
- package/dist/timeline-debug/markdown.d.ts.map +1 -0
- package/dist/timeline-debug/markdown.js +103 -0
- package/dist/timeline-debug/markdown.js.map +1 -0
- package/dist/timeline-debug/motion.d.ts +20 -0
- package/dist/timeline-debug/motion.d.ts.map +1 -0
- package/dist/timeline-debug/motion.js +362 -0
- package/dist/timeline-debug/motion.js.map +1 -0
- package/dist/timeline-debug/report.d.ts +16 -0
- package/dist/timeline-debug/report.d.ts.map +1 -0
- package/dist/timeline-debug/report.js +100 -0
- package/dist/timeline-debug/report.js.map +1 -0
- package/dist/timeline-debug/showcase.d.ts +7 -0
- package/dist/timeline-debug/showcase.d.ts.map +1 -0
- package/dist/timeline-debug/showcase.js +347 -0
- package/dist/timeline-debug/showcase.js.map +1 -0
- package/dist/timeline-debug/types.d.ts +64 -0
- package/dist/timeline-debug/types.d.ts.map +1 -0
- package/dist/timeline-debug/types.js +10 -0
- package/dist/timeline-debug/types.js.map +1 -0
- package/dist/timeline-debug/validate.d.ts +24 -0
- package/dist/timeline-debug/validate.d.ts.map +1 -0
- package/dist/timeline-debug/validate.js +1432 -0
- package/dist/timeline-debug/validate.js.map +1 -0
- package/dist/types.d.ts +211 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +103 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { GenerationAttempt, Prediction, GenerationOutput, GenerationAttachment } from "@nodetool-ai/models";
|
|
3
|
+
import { decodeFalOutputs } from "./fal-output-decoder.js";
|
|
4
|
+
const LIVE_LEASE_MS = 120_000;
|
|
5
|
+
const RECOVERY_RETRY_MS = 60_000;
|
|
6
|
+
function startLiveLeaseHeartbeat(lifecycle, generationId, generationLeaseVersion, attemptId, attemptLeaseVersion, workerId) {
|
|
7
|
+
let stopped = false;
|
|
8
|
+
let renewing = false;
|
|
9
|
+
let leaseLost = false;
|
|
10
|
+
const renew = async () => {
|
|
11
|
+
if (stopped || renewing || leaseLost)
|
|
12
|
+
return;
|
|
13
|
+
renewing = true;
|
|
14
|
+
try {
|
|
15
|
+
const expiresAt = new Date(Date.now() + LIVE_LEASE_MS).toISOString();
|
|
16
|
+
const [generationRenewed, attemptRenewed] = await Promise.all([
|
|
17
|
+
lifecycle.renew(generationId, workerId, generationLeaseVersion, expiresAt),
|
|
18
|
+
lifecycle.renewAttempt(attemptId, workerId, attemptLeaseVersion, expiresAt)
|
|
19
|
+
]);
|
|
20
|
+
if (!generationRenewed || !attemptRenewed)
|
|
21
|
+
leaseLost = true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
leaseLost = true;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
renewing = false;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const timer = setInterval(() => void renew(), LIVE_LEASE_MS / 3);
|
|
31
|
+
return {
|
|
32
|
+
lost: () => leaseLost,
|
|
33
|
+
stop: () => {
|
|
34
|
+
stopped = true;
|
|
35
|
+
clearInterval(timer);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function jsonSafe(value) {
|
|
40
|
+
if (value instanceof Uint8Array) {
|
|
41
|
+
return {
|
|
42
|
+
byte_length: value.byteLength,
|
|
43
|
+
sha256: createHash("sha256").update(value).digest("hex")
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(value))
|
|
47
|
+
return value.map(jsonSafe);
|
|
48
|
+
if (value && typeof value === "object") {
|
|
49
|
+
return Object.fromEntries(Object.entries(value)
|
|
50
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
51
|
+
.map(([key, entry]) => [key, jsonSafe(entry)]));
|
|
52
|
+
}
|
|
53
|
+
if (value === null ||
|
|
54
|
+
value === undefined ||
|
|
55
|
+
typeof value === "boolean" ||
|
|
56
|
+
typeof value === "number" ||
|
|
57
|
+
typeof value === "string") {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
return String(value);
|
|
61
|
+
}
|
|
62
|
+
function callbackOrigin(value) {
|
|
63
|
+
if (!value)
|
|
64
|
+
return null;
|
|
65
|
+
try {
|
|
66
|
+
const url = new URL(value);
|
|
67
|
+
if (url.protocol !== "https:" || url.username || url.password)
|
|
68
|
+
return null;
|
|
69
|
+
return url.toString().replace(/\/$/u, "");
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function falRequestFingerprint(request) {
|
|
76
|
+
return createHash("sha256")
|
|
77
|
+
.update(JSON.stringify({
|
|
78
|
+
provider: request.provider,
|
|
79
|
+
model: request.model,
|
|
80
|
+
capability: request.capability,
|
|
81
|
+
params: jsonSafe(request.params ?? {})
|
|
82
|
+
}))
|
|
83
|
+
.digest("hex");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build the durable hooks used by workflow ProcessingContexts.
|
|
87
|
+
*
|
|
88
|
+
* This factory lives in execution so runtime stays independent of models and
|
|
89
|
+
* persistence. It is intentionally FAL-only. Other providers continue to use
|
|
90
|
+
* the existing in-memory receipt and billing path until their submission and
|
|
91
|
+
* recovery contracts are verified.
|
|
92
|
+
*/
|
|
93
|
+
export function createFalGenerationLifecycleHooks(options) {
|
|
94
|
+
const lifecycle = options.lifecycle ?? createDurableGenerationLifecycle();
|
|
95
|
+
const states = new Map();
|
|
96
|
+
const publicUrl = callbackOrigin(options.publicUrl);
|
|
97
|
+
const accountRef = options.providerAccountRef ?? `user:${options.userId}:secret:FAL_API_KEY`;
|
|
98
|
+
const onGenerationAccepted = async ({ generationId, request }) => {
|
|
99
|
+
if (request.provider !== "fal_ai")
|
|
100
|
+
return undefined;
|
|
101
|
+
const origin = request.origin ?? {};
|
|
102
|
+
const idempotencyKey = origin.request_id
|
|
103
|
+
? `fal_ai:${origin.request_id}`
|
|
104
|
+
: generationId;
|
|
105
|
+
const callbackToken = options.callbacks !== false && publicUrl && options.encryptCallbackToken
|
|
106
|
+
? randomUUID()
|
|
107
|
+
: null;
|
|
108
|
+
const callbackTokenCiphertext = callbackToken
|
|
109
|
+
? (options.encryptCallbackToken?.(callbackToken, options.userId) ?? null)
|
|
110
|
+
: null;
|
|
111
|
+
const metadata = { origin: jsonSafe(origin) };
|
|
112
|
+
if (request.destination) {
|
|
113
|
+
Object.assign(metadata, {
|
|
114
|
+
attachments: [jsonSafe(request.destination)]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const accepted = await lifecycle.accept({
|
|
118
|
+
id: generationId,
|
|
119
|
+
user_id: options.userId,
|
|
120
|
+
provider: "fal_ai",
|
|
121
|
+
model: request.model,
|
|
122
|
+
idempotency_key: idempotencyKey,
|
|
123
|
+
input_fingerprint: falRequestFingerprint(request),
|
|
124
|
+
node_id: request.nodeId,
|
|
125
|
+
capability: request.capability,
|
|
126
|
+
workflow_id: request.workflowId ?? null,
|
|
127
|
+
surface: origin.surface ?? null,
|
|
128
|
+
thread_id: origin.thread_id ?? null,
|
|
129
|
+
tool_call_id: origin.tool_call_id ?? null,
|
|
130
|
+
request_id: origin.request_id ?? null,
|
|
131
|
+
job_id: options.jobId ?? request.workflowId ?? null,
|
|
132
|
+
project_id: options.projectId ?? null,
|
|
133
|
+
parameters: jsonSafe(request.params ?? {}),
|
|
134
|
+
metadata,
|
|
135
|
+
document_id: request.destination?.document_id ?? null,
|
|
136
|
+
provider_account_ref: accountRef,
|
|
137
|
+
endpoint: request.model,
|
|
138
|
+
callback_token_hash: callbackToken
|
|
139
|
+
? createHash("sha256").update(callbackToken).digest("hex")
|
|
140
|
+
: null,
|
|
141
|
+
callback_token_ciphertext: callbackTokenCiphertext,
|
|
142
|
+
request_payload: jsonSafe(request.params ?? {})
|
|
143
|
+
});
|
|
144
|
+
if (!accepted.created) {
|
|
145
|
+
return {
|
|
146
|
+
skipProvider: true,
|
|
147
|
+
existingGenerationId: accepted.generation.id
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
const workerId = `generation:${randomUUID()}`;
|
|
151
|
+
const now = new Date();
|
|
152
|
+
const expiresAt = new Date(now.getTime() + LIVE_LEASE_MS).toISOString();
|
|
153
|
+
const claimedGeneration = await lifecycle.claim(accepted.generation.id, workerId, {
|
|
154
|
+
now: now.toISOString(),
|
|
155
|
+
expiresAt
|
|
156
|
+
});
|
|
157
|
+
const claimedAttempt = await lifecycle.claimAttempt(accepted.attempt.id, workerId, {
|
|
158
|
+
now: now.toISOString(),
|
|
159
|
+
expiresAt
|
|
160
|
+
});
|
|
161
|
+
if (!claimedGeneration || !claimedAttempt) {
|
|
162
|
+
throw new Error("Durable FAL generation lease could not be acquired");
|
|
163
|
+
}
|
|
164
|
+
await lifecycle.transitionAttempt(claimedAttempt.id, workerId, claimedAttempt.lease_version, { submission_status: "submitting", provider_status: "unknown" });
|
|
165
|
+
await lifecycle.transition(accepted.generation.id, workerId, claimedGeneration.lease_version, {
|
|
166
|
+
status: "pending",
|
|
167
|
+
submission_status: "submitting",
|
|
168
|
+
provider_status: "unknown"
|
|
169
|
+
});
|
|
170
|
+
const heartbeat = startLiveLeaseHeartbeat(lifecycle, accepted.generation.id, claimedGeneration.lease_version, accepted.attempt.id, claimedAttempt.lease_version, workerId);
|
|
171
|
+
states.set(generationId, {
|
|
172
|
+
generationId: accepted.generation.id,
|
|
173
|
+
attemptId: accepted.attempt.id,
|
|
174
|
+
workerId,
|
|
175
|
+
generationLeaseVersion: claimedGeneration.lease_version,
|
|
176
|
+
attemptLeaseVersion: claimedAttempt.lease_version,
|
|
177
|
+
heartbeat
|
|
178
|
+
});
|
|
179
|
+
const callbackOptions = {};
|
|
180
|
+
if (callbackToken && callbackTokenCiphertext && publicUrl) {
|
|
181
|
+
callbackOptions.webhookUrl = `${publicUrl}/api/providers/fal/webhook/${callbackToken}`;
|
|
182
|
+
callbackOptions.callbackToken = callbackToken;
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
...callbackOptions,
|
|
186
|
+
generationId: accepted.generation.id,
|
|
187
|
+
durable: true
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
const onProviderRequestBound = async (binding, generationId) => {
|
|
191
|
+
const value = jsonSafe(binding);
|
|
192
|
+
if (!value || typeof value !== "object")
|
|
193
|
+
return;
|
|
194
|
+
const requestId = value.providerRequestId;
|
|
195
|
+
if (typeof requestId !== "string" || requestId.length === 0)
|
|
196
|
+
return;
|
|
197
|
+
const state = generationId ? states.get(generationId) : undefined;
|
|
198
|
+
if (!state)
|
|
199
|
+
return;
|
|
200
|
+
await lifecycle.bindProviderRequest(state.generationId, state.workerId, state.generationLeaseVersion, requestId);
|
|
201
|
+
await lifecycle.bindAttemptProviderRequest(state.attemptId, state.workerId, state.attemptLeaseVersion, requestId);
|
|
202
|
+
};
|
|
203
|
+
const onGenerationTerminal = async ({ generationId, request, status, error, receipt, assetIds, output }) => {
|
|
204
|
+
if (!generationId)
|
|
205
|
+
return;
|
|
206
|
+
const state = states.get(generationId);
|
|
207
|
+
if (!state)
|
|
208
|
+
return;
|
|
209
|
+
try {
|
|
210
|
+
if (state.heartbeat.lost()) {
|
|
211
|
+
throw new Error("Durable FAL generation lease was lost before finalization");
|
|
212
|
+
}
|
|
213
|
+
if (status === "completed") {
|
|
214
|
+
const outputRecord = output && typeof output === "object" && !Array.isArray(output)
|
|
215
|
+
? output
|
|
216
|
+
: { result: output };
|
|
217
|
+
const descriptors = decodeFalOutputs(outputRecord);
|
|
218
|
+
const mediaCount = descriptors.filter((descriptor) => descriptor.outputType === "media").length;
|
|
219
|
+
const savedAssetIds = assetIds.filter((assetId) => typeof assetId === "string");
|
|
220
|
+
const needsRecovery = savedAssetIds.length < mediaCount;
|
|
221
|
+
// The caller attaches the asset to its destination after this hook
|
|
222
|
+
// returns, so the durable intent is still unapplied here. Keeping the
|
|
223
|
+
// attempt scheduled is what lets recovery finish an attachment the
|
|
224
|
+
// caller never committed; the attachment pass clears the schedule.
|
|
225
|
+
const needsAttachment = Boolean(request.destination?.target_id);
|
|
226
|
+
let mediaIndex = 0;
|
|
227
|
+
const fence = {
|
|
228
|
+
attemptId: state.attemptId,
|
|
229
|
+
workerId: state.workerId,
|
|
230
|
+
leaseVersion: state.attemptLeaseVersion
|
|
231
|
+
};
|
|
232
|
+
for (const descriptor of descriptors) {
|
|
233
|
+
const assetId = descriptor.outputType === "media"
|
|
234
|
+
? (assetIds[mediaIndex++] ?? null)
|
|
235
|
+
: null;
|
|
236
|
+
const saved = await GenerationOutput.upsertOutput({
|
|
237
|
+
generation_id: state.generationId,
|
|
238
|
+
attempt_id: state.attemptId,
|
|
239
|
+
output_key: descriptor.outputKey,
|
|
240
|
+
output_index: descriptor.outputIndex,
|
|
241
|
+
output_type: descriptor.outputType,
|
|
242
|
+
provider_ref: descriptor.providerRef,
|
|
243
|
+
raw_result: jsonSafe(descriptor.rawResult)
|
|
244
|
+
});
|
|
245
|
+
const transitioned = await lifecycle.saveOutput(saved.id, {
|
|
246
|
+
status: assetId ||
|
|
247
|
+
(!needsRecovery && descriptor.outputType === "structured")
|
|
248
|
+
? "ready"
|
|
249
|
+
: "retrying",
|
|
250
|
+
asset_id: assetId,
|
|
251
|
+
provider_ref: descriptor.providerRef,
|
|
252
|
+
error: null,
|
|
253
|
+
raw_result: jsonSafe(descriptor.rawResult)
|
|
254
|
+
}, fence);
|
|
255
|
+
if (!transitioned) {
|
|
256
|
+
throw new Error("Durable FAL output lease fence rejected finalization");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const nextCheckAt = needsRecovery || needsAttachment
|
|
260
|
+
? new Date(Date.now() + RECOVERY_RETRY_MS).toISOString()
|
|
261
|
+
: null;
|
|
262
|
+
if (!(await lifecycle.transition(state.generationId, state.workerId, state.generationLeaseVersion, {
|
|
263
|
+
status: needsRecovery ? "recovering" : "completed",
|
|
264
|
+
submission_status: "submitted",
|
|
265
|
+
provider_status: "succeeded",
|
|
266
|
+
output_status: needsRecovery ? "retrying" : "ready",
|
|
267
|
+
attachment_status: "pending",
|
|
268
|
+
asset_ids: savedAssetIds,
|
|
269
|
+
error: null,
|
|
270
|
+
next_check_at: nextCheckAt,
|
|
271
|
+
completed_at: needsRecovery ? null : new Date().toISOString()
|
|
272
|
+
}))) {
|
|
273
|
+
throw new Error("Durable FAL generation lease fence rejected finalization");
|
|
274
|
+
}
|
|
275
|
+
if (!(await lifecycle.transitionAttempt(state.attemptId, state.workerId, state.attemptLeaseVersion, {
|
|
276
|
+
submission_status: "submitted",
|
|
277
|
+
provider_status: "succeeded",
|
|
278
|
+
next_check_at: nextCheckAt,
|
|
279
|
+
raw_result_ref: needsRecovery
|
|
280
|
+
? JSON.stringify(jsonSafe(output))
|
|
281
|
+
: null
|
|
282
|
+
}))) {
|
|
283
|
+
throw new Error("Durable FAL attempt lease fence rejected finalization");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
else if (status === "recovering") {
|
|
287
|
+
const recoveryOutput = output &&
|
|
288
|
+
typeof output === "object" &&
|
|
289
|
+
!Array.isArray(output) &&
|
|
290
|
+
!(output instanceof Uint8Array)
|
|
291
|
+
? output
|
|
292
|
+
: null;
|
|
293
|
+
const descriptors = recoveryOutput
|
|
294
|
+
? decodeFalOutputs(recoveryOutput)
|
|
295
|
+
: [];
|
|
296
|
+
const fence = {
|
|
297
|
+
attemptId: state.attemptId,
|
|
298
|
+
workerId: state.workerId,
|
|
299
|
+
leaseVersion: state.attemptLeaseVersion
|
|
300
|
+
};
|
|
301
|
+
for (const descriptor of descriptors) {
|
|
302
|
+
const saved = await GenerationOutput.upsertOutput({
|
|
303
|
+
generation_id: state.generationId,
|
|
304
|
+
attempt_id: state.attemptId,
|
|
305
|
+
output_key: descriptor.outputKey,
|
|
306
|
+
output_index: descriptor.outputIndex,
|
|
307
|
+
output_type: descriptor.outputType,
|
|
308
|
+
provider_ref: descriptor.providerRef,
|
|
309
|
+
raw_result: descriptor.rawResult
|
|
310
|
+
});
|
|
311
|
+
if (!(await lifecycle.saveOutput(saved.id, {
|
|
312
|
+
status: "retrying",
|
|
313
|
+
provider_ref: descriptor.providerRef,
|
|
314
|
+
raw_result: descriptor.rawResult,
|
|
315
|
+
error: error ?? null
|
|
316
|
+
}, fence))) {
|
|
317
|
+
throw new Error("Durable FAL output lease fence rejected recovery scheduling");
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const nextCheckAt = new Date(Date.now() + RECOVERY_RETRY_MS).toISOString();
|
|
321
|
+
const generationRecovery = {
|
|
322
|
+
status: "recovering",
|
|
323
|
+
error: error ?? null,
|
|
324
|
+
next_check_at: nextCheckAt
|
|
325
|
+
};
|
|
326
|
+
if (descriptors.length > 0) {
|
|
327
|
+
generationRecovery.submission_status = "submitted";
|
|
328
|
+
generationRecovery.provider_status = "succeeded";
|
|
329
|
+
generationRecovery.output_status = "retrying";
|
|
330
|
+
}
|
|
331
|
+
if (!(await lifecycle.transition(state.generationId, state.workerId, state.generationLeaseVersion, generationRecovery))) {
|
|
332
|
+
throw new Error("Durable FAL generation lease fence rejected recovery scheduling");
|
|
333
|
+
}
|
|
334
|
+
const attemptRecovery = {
|
|
335
|
+
last_error: error ?? null,
|
|
336
|
+
next_check_at: nextCheckAt
|
|
337
|
+
};
|
|
338
|
+
if (descriptors.length > 0) {
|
|
339
|
+
attemptRecovery.submission_status = "submitted";
|
|
340
|
+
attemptRecovery.provider_status = "succeeded";
|
|
341
|
+
attemptRecovery.raw_result_ref = JSON.stringify(jsonSafe(output));
|
|
342
|
+
}
|
|
343
|
+
if (!(await lifecycle.transitionAttempt(state.attemptId, state.workerId, state.attemptLeaseVersion, attemptRecovery))) {
|
|
344
|
+
throw new Error("Durable FAL attempt lease fence rejected recovery scheduling");
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
if (!(await lifecycle.transition(state.generationId, state.workerId, state.generationLeaseVersion, {
|
|
349
|
+
status,
|
|
350
|
+
submission_status: "submitted",
|
|
351
|
+
provider_status: status === "cancelled" ? "cancelled" : "failed",
|
|
352
|
+
output_status: "unavailable",
|
|
353
|
+
error: error ?? null,
|
|
354
|
+
completed_at: new Date().toISOString()
|
|
355
|
+
}))) {
|
|
356
|
+
throw new Error("Durable FAL generation lease fence rejected finalization");
|
|
357
|
+
}
|
|
358
|
+
if (!(await lifecycle.transitionAttempt(state.attemptId, state.workerId, state.attemptLeaseVersion, {
|
|
359
|
+
submission_status: "submitted",
|
|
360
|
+
provider_status: status === "cancelled" ? "cancelled" : "failed",
|
|
361
|
+
last_error: error ?? null,
|
|
362
|
+
next_check_at: null
|
|
363
|
+
}))) {
|
|
364
|
+
throw new Error("Durable FAL attempt lease fence rejected finalization");
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// Cost reconciliation remains independent, but leave the receipt available
|
|
368
|
+
// to the existing ledger listener. It must not overwrite output state.
|
|
369
|
+
void receipt;
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
state.heartbeat.stop();
|
|
373
|
+
states.delete(generationId);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
return {
|
|
377
|
+
onGenerationAccepted,
|
|
378
|
+
onProviderRequestBound,
|
|
379
|
+
onGenerationTerminal
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Persistence/orchestration seam for provider workers. It deliberately has no
|
|
384
|
+
* provider or storage dependency: providers submit only after `accept()` and
|
|
385
|
+
* workers use the fenced version returned from `claim()` for every write.
|
|
386
|
+
*/
|
|
387
|
+
export class DurableGenerationLifecycle {
|
|
388
|
+
async accept(input) {
|
|
389
|
+
return Prediction.acceptGenerationWithAttempt(input);
|
|
390
|
+
}
|
|
391
|
+
async claim(generationId, workerId, window) {
|
|
392
|
+
return Prediction.claimGenerationLease(generationId, workerId, window.now, window.expiresAt);
|
|
393
|
+
}
|
|
394
|
+
async renew(generationId, workerId, leaseVersion, expiresAt) {
|
|
395
|
+
return Prediction.renewGenerationLease(generationId, workerId, leaseVersion, expiresAt);
|
|
396
|
+
}
|
|
397
|
+
async claimAttempt(attemptId, workerId, window) {
|
|
398
|
+
return GenerationAttempt.claimLease(attemptId, workerId, window.now, window.expiresAt);
|
|
399
|
+
}
|
|
400
|
+
async renewAttempt(attemptId, workerId, leaseVersion, expiresAt) {
|
|
401
|
+
return GenerationAttempt.renewLease(attemptId, workerId, leaseVersion, expiresAt);
|
|
402
|
+
}
|
|
403
|
+
async bindProviderRequest(generationId, workerId, leaseVersion, providerRequestId) {
|
|
404
|
+
return Prediction.bindProviderRequest(generationId, workerId, leaseVersion, providerRequestId);
|
|
405
|
+
}
|
|
406
|
+
async bindAttemptProviderRequest(attemptId, workerId, leaseVersion, providerRequestId) {
|
|
407
|
+
return GenerationAttempt.bindProviderRequest(attemptId, workerId, leaseVersion, providerRequestId);
|
|
408
|
+
}
|
|
409
|
+
async transitionAttempt(attemptId, workerId, leaseVersion, update) {
|
|
410
|
+
return GenerationAttempt.transition(attemptId, workerId, leaseVersion, update);
|
|
411
|
+
}
|
|
412
|
+
async transition(generationId, workerId, leaseVersion, update) {
|
|
413
|
+
return Prediction.transitionDurable(generationId, workerId, leaseVersion, update);
|
|
414
|
+
}
|
|
415
|
+
async recordAttemptObservation(attemptId, workerId, leaseVersion, observation) {
|
|
416
|
+
return GenerationAttempt.recordObservation(attemptId, workerId, leaseVersion, observation);
|
|
417
|
+
}
|
|
418
|
+
async saveOutput(outputId, state, fence) {
|
|
419
|
+
return GenerationOutput.transition(outputId, state, fence);
|
|
420
|
+
}
|
|
421
|
+
async attachOutput(attachmentId, change) {
|
|
422
|
+
return GenerationAttachment.transition(attachmentId, change);
|
|
423
|
+
}
|
|
424
|
+
async recover(now, limit = 100) {
|
|
425
|
+
return Prediction.recoverableGenerations(now, limit);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
export function createDurableGenerationLifecycle() {
|
|
429
|
+
return new DurableGenerationLifecycle();
|
|
430
|
+
}
|
|
431
|
+
//# sourceMappingURL=generation-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generation-lifecycle.js","sourceRoot":"","sources":["../src/generation-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { GenerationAttempt, GenerationAttachment, GenerationOutput, Prediction } from "@nodetool-ai/models";
|
|
2
|
+
import type { FalQueueOperations } from "@nodetool-ai/runtime";
|
|
3
|
+
import type { GenerationAttachmentTransition, GenerationOutputSaveState } from "@nodetool-ai/models";
|
|
4
|
+
import { type FalOutputDescriptor } from "./fal-output-decoder.js";
|
|
5
|
+
export interface DurableRecoveryProvider {
|
|
6
|
+
queueFor(attempt: GenerationAttempt): FalQueueOperations | Promise<FalQueueOperations>;
|
|
7
|
+
}
|
|
8
|
+
export interface DurableRecoverySubmission {
|
|
9
|
+
readonly providerRequestId: string;
|
|
10
|
+
readonly endpoint?: string | null;
|
|
11
|
+
readonly gatewayRequestId?: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface DurableGenerationRecoveryOptions {
|
|
14
|
+
readonly provider: DurableRecoveryProvider;
|
|
15
|
+
readonly workerId?: string;
|
|
16
|
+
readonly batchSize?: number;
|
|
17
|
+
readonly leaseMs?: number;
|
|
18
|
+
readonly now?: () => Date;
|
|
19
|
+
/** Submit an accepted, never-submitted attempt. Never call this for
|
|
20
|
+
* `submitting` or `submission_unknown`, because the paid POST is ambiguous. */
|
|
21
|
+
readonly submitAccepted?: (generation: Prediction, attempt: GenerationAttempt) => Promise<DurableRecoverySubmission>;
|
|
22
|
+
/** Persist provider media and return its durable storage state. */
|
|
23
|
+
readonly finalizeOutput?: (input: {
|
|
24
|
+
readonly generation: Prediction;
|
|
25
|
+
readonly attempt: GenerationAttempt;
|
|
26
|
+
readonly payload: Record<string, unknown>;
|
|
27
|
+
readonly descriptor: FalOutputDescriptor;
|
|
28
|
+
}) => Promise<GenerationOutputSaveState>;
|
|
29
|
+
/** Apply a destination-specific mutation after an output is saved. Returning
|
|
30
|
+
* null leaves the durable attachment intent pending for a later adapter. */
|
|
31
|
+
readonly attachOutput?: (input: {
|
|
32
|
+
readonly generation: Prediction;
|
|
33
|
+
readonly attempt: GenerationAttempt;
|
|
34
|
+
readonly output: GenerationOutput;
|
|
35
|
+
readonly attachment: GenerationAttachment;
|
|
36
|
+
}) => Promise<GenerationAttachmentTransition | null>;
|
|
37
|
+
}
|
|
38
|
+
export interface DurableRecoveryRunResult {
|
|
39
|
+
readonly deliveries: number;
|
|
40
|
+
readonly polledAttempts: number;
|
|
41
|
+
readonly completed: number;
|
|
42
|
+
readonly failed: number;
|
|
43
|
+
readonly skipped: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Bounded, lease-fenced finalization. Webhook rows are consumed before queue
|
|
47
|
+
* polling, so a callback that arrived during a process restart wins without
|
|
48
|
+
* spending another provider read. Every write is idempotent and guarded by
|
|
49
|
+
* the generation and attempt lease versions.
|
|
50
|
+
*/
|
|
51
|
+
export declare class DurableGenerationRecoveryWorker {
|
|
52
|
+
private readonly provider;
|
|
53
|
+
private readonly workerId;
|
|
54
|
+
private readonly batchSize;
|
|
55
|
+
private readonly leaseMs;
|
|
56
|
+
private readonly now;
|
|
57
|
+
private readonly finalizeOutput?;
|
|
58
|
+
private readonly submitAccepted?;
|
|
59
|
+
private readonly attachOutput?;
|
|
60
|
+
private pass;
|
|
61
|
+
constructor(options: DurableGenerationRecoveryOptions);
|
|
62
|
+
/**
|
|
63
|
+
* One pass at a time per instance. A pass polls the provider item by item,
|
|
64
|
+
* so it can outlast the interval the host runs it on; a second overlapping
|
|
65
|
+
* pass would reclaim leases the first still holds and redo its work.
|
|
66
|
+
*/
|
|
67
|
+
runOnce(): Promise<DurableRecoveryRunResult>;
|
|
68
|
+
/** A lease window measured at the moment of the claim it fences. A batch
|
|
69
|
+
* can take longer than one lease, so a window minted for the whole batch
|
|
70
|
+
* hands its last items an expiry that has already passed. */
|
|
71
|
+
private leaseWindow;
|
|
72
|
+
private runPass;
|
|
73
|
+
private finalizeDelivery;
|
|
74
|
+
private pollAttempt;
|
|
75
|
+
private finalizeAttempt;
|
|
76
|
+
/** Retry durable output saves from the committed raw result before asking
|
|
77
|
+
* fal for a queue result. This is important after result retention expires
|
|
78
|
+
* or after a crash between object upload and the output-row CAS. */
|
|
79
|
+
private retryStoredOutputs;
|
|
80
|
+
/**
|
|
81
|
+
* Commit the terminal generation from output rows that are already saved.
|
|
82
|
+
* The attempt's recorded provider result is the manifest of a complete
|
|
83
|
+
* result: every output identity it names must have a ready row before the
|
|
84
|
+
* generation is called completed, so a crash halfway through recording a
|
|
85
|
+
* multi-output result still falls back to the provider. Returning null means
|
|
86
|
+
* the state could not be repaired locally.
|
|
87
|
+
*/
|
|
88
|
+
private repairFromStoredOutputs;
|
|
89
|
+
private startLeaseRenewal;
|
|
90
|
+
private finalizeAttemptWithLeases;
|
|
91
|
+
/** Record on the generation that its destination work is done. A generation
|
|
92
|
+
* whose media is saved and ready is terminal and holds no lease, so the
|
|
93
|
+
* projection cannot ride on a fenced transition. */
|
|
94
|
+
private settleAttachmentProjection;
|
|
95
|
+
/** Apply each destination intent independently. A ready output can be
|
|
96
|
+
* retried after its generation is terminal, so attachment work must not be
|
|
97
|
+
* coupled to provider polling or storage retries. */
|
|
98
|
+
private retryPendingAttachments;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=generation-recovery-worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generation-recovery-worker.d.ts","sourceRoot":"","sources":["../src/generation-recovery-worker.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAEhB,UAAU,EACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,KAAK,EACV,8BAA8B,EAC9B,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CACN,OAAO,EAAE,iBAAiB,GACzB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B;mFAC+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,CACxB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACxC,mEAAmE;IACnE,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAChC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;QAChC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;QACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;KAC1C,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACzC;gFAC4E;IAC5E,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAC9B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;QAChC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;QACpC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;QAClC,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;KAC3C,KAAK,OAAO,CAAC,8BAA8B,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAkED;;;;;GAKG;AACH,qBAAa,+BAA+B;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAqD;IACrF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAqD;IACrF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAmD;IACjF,OAAO,CAAC,IAAI,CAAkD;IAE9D,YAAY,OAAO,EAAE,gCAAgC,EAYpD;IAED;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAMjD;IAED;;iEAE6D;IAC7D,OAAO,CAAC,WAAW;YAQL,OAAO;YAsEP,gBAAgB;YAuOhB,WAAW;YAsLX,eAAe;IAkD7B;;wEAEoE;YACtD,kBAAkB;IAmNhC;;;;;;;OAOG;YACW,uBAAuB;IA2ErC,OAAO,CAAC,iBAAiB;YAoDX,yBAAyB;IAoTvC;;wDAEoD;YACtC,0BAA0B;IASxC;;yDAEqD;YACvC,uBAAuB;CA0EtC"}
|