@fungi.computer/darkroom 0.0.1 → 0.2.0
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 +12 -3
- package/dist/app-media-contracts.d.ts +59 -31
- package/dist/app-media-contracts.js +7 -7
- package/dist/browser-failure.d.ts +7 -0
- package/dist/browser-failure.js +3 -0
- package/dist/cloudflare/provider.js +18 -19
- package/dist/cloudflare/reference-images.js +2 -2
- package/dist/cost-estimate.js +2 -2
- package/dist/execution-error.d.ts +10 -2
- package/dist/execution-error.js +7 -0
- package/dist/gateway-wire.d.ts +5 -5
- package/dist/gateway-wire.js +4 -4
- package/dist/index.d.ts +13 -13
- package/dist/index.js +11 -15
- package/dist/media-binding.d.ts +28 -22
- package/dist/media-binding.js +27 -5
- package/dist/media-operation-owner.d.ts +54 -17
- package/dist/media-operation-owner.js +43 -31
- package/dist/media-operation.js +17 -7
- package/dist/model-catalog.d.ts +14 -14
- package/dist/model-catalog.js +6 -6
- package/dist/server.d.ts +1 -1
- package/dist/server.js +3 -1
- package/dist/video-providers/minimax.js +2 -2
- package/docs/api/app-media-contracts.md +100 -110
- package/docs/api/browser.md +34 -2
- package/docs/api/cloudflare.md +35 -26
- package/docs/api/index.md +285 -343
- package/docs/api/server.md +561 -89
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -156,9 +156,18 @@ Agar's public `pendingSchema`. `appMediaModelsOutcomeSchema` and
|
|
|
156
156
|
closed admission codes, the Media attachment-budget refusal, the existing
|
|
157
157
|
`agentAppMediaLibraryFailureSchema`, and `appMediaBrokerFailureSchema`. The
|
|
158
158
|
latter preserves the broker projection: HTTP `code` becomes `error`, HTTP
|
|
159
|
-
`error` becomes `message`, and `stage
|
|
160
|
-
failures and transport envelopes are separate
|
|
161
|
-
as these outcomes.
|
|
159
|
+
`error` becomes `message`, and `stage`, `retryable` and optional `provider`
|
|
160
|
+
facts stay unchanged. HTTP failures and transport envelopes are separate
|
|
161
|
+
representations and do not decode as these outcomes.
|
|
162
|
+
|
|
163
|
+
Provider facts use Agar's canonical Media grammar: an allowlisted error category
|
|
164
|
+
and bounded numeric code, or `result_download` and a native HTTP status. The
|
|
165
|
+
durable owner retains those facts through interruption and replay, including
|
|
166
|
+
safety refusals, without retaining the original error message or cause in the
|
|
167
|
+
failure record. A terminal provider failure never redispatches the paid attempt.
|
|
168
|
+
The fresh pre-release schema replaces the safety-only refusal table; old preview
|
|
169
|
+
stores require an explicit host reset, not an automatic migration or dual
|
|
170
|
+
reader.
|
|
162
171
|
|
|
163
172
|
See the [generated API](docs/api/README.md) for signatures and host ports. The
|
|
164
173
|
Cloudflare entry needs the native Workers type declarations in a TypeScript
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
/** Bounded catalog decoded by the App media broker before host filtering. */
|
|
3
|
-
export declare const mediaModelsSchema: z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
3
|
+
export declare const mediaModelsSchema: z.ZodLazy<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
4
4
|
id: z.ZodString;
|
|
5
5
|
label: z.ZodString;
|
|
6
6
|
kind: z.ZodEnum<{
|
|
@@ -18,7 +18,7 @@ export declare const mediaModelsSchema: z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
|
18
18
|
readonly jpeg: "jpeg";
|
|
19
19
|
readonly webp: "webp";
|
|
20
20
|
}>>>;
|
|
21
|
-
input: z.ZodReadonly<z.ZodObject<{
|
|
21
|
+
input: z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
22
22
|
transport: z.ZodEnum<{
|
|
23
23
|
readonly json: "json";
|
|
24
24
|
readonly multipart: "multipart";
|
|
@@ -39,9 +39,9 @@ export declare const mediaModelsSchema: z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
|
39
39
|
defaultSteps: z.ZodNullable<z.ZodNumber>;
|
|
40
40
|
referenceField: z.ZodNullable<z.ZodString>;
|
|
41
41
|
maxReferences: z.ZodNumber;
|
|
42
|
-
}, z.core.$strict
|
|
42
|
+
}, z.core.$strict>>>;
|
|
43
43
|
sizes: z.ZodNullable<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
44
|
-
video: z.ZodNullable<z.ZodReadonly<z.ZodObject<{
|
|
44
|
+
video: z.ZodNullable<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
45
45
|
minSeconds: z.ZodNumber;
|
|
46
46
|
maxSeconds: z.ZodNumber;
|
|
47
47
|
defaultSeconds: z.ZodNumber;
|
|
@@ -51,7 +51,7 @@ export declare const mediaModelsSchema: z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
|
51
51
|
readonly veo: "veo";
|
|
52
52
|
readonly minimax: "minimax";
|
|
53
53
|
}>;
|
|
54
|
-
formats: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
54
|
+
formats: z.ZodReadonly<z.ZodArray<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
55
55
|
resolution: z.ZodEnum<{
|
|
56
56
|
readonly p480: "480p";
|
|
57
57
|
readonly p720: "720p";
|
|
@@ -70,7 +70,7 @@ export declare const mediaModelsSchema: z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
|
70
70
|
}>;
|
|
71
71
|
width: z.ZodNumber;
|
|
72
72
|
height: z.ZodNumber;
|
|
73
|
-
}, z.core.$strict
|
|
73
|
+
}, z.core.$strict>>>>>;
|
|
74
74
|
defaultResolution: z.ZodEnum<{
|
|
75
75
|
readonly p480: "480p";
|
|
76
76
|
readonly p720: "720p";
|
|
@@ -113,8 +113,8 @@ export declare const mediaModelsSchema: z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
|
113
113
|
silentMilliunitsPerSecond: z.ZodNumber;
|
|
114
114
|
audioMilliunitsPerSecond: z.ZodNumber;
|
|
115
115
|
}, z.core.$strict>>>>;
|
|
116
|
-
}, z.core.$strict
|
|
117
|
-
}, z.core.$strict
|
|
116
|
+
}, z.core.$strict>>>>;
|
|
117
|
+
}, z.core.$strict>>>>;
|
|
118
118
|
/** An absolute output path on the Computer admitted by the App host. */
|
|
119
119
|
export declare const destinationSchema: z.ZodObject<{
|
|
120
120
|
computerId: z.ZodString;
|
|
@@ -153,11 +153,11 @@ export declare const appMediaAdmissionErrorSchema: z.ZodObject<{
|
|
|
153
153
|
}>;
|
|
154
154
|
}, z.core.$strict>;
|
|
155
155
|
/** Attachment budget refusal emitted by the Media reservation owner. */
|
|
156
|
-
export declare const appMediaBudgetRefusalSchema: z.ZodObject<{
|
|
156
|
+
export declare const appMediaBudgetRefusalSchema: z.ZodLazy<z.ZodObject<{
|
|
157
157
|
error: z.ZodLiteral<"attachment_budget_exceeded">;
|
|
158
158
|
kind: z.ZodLiteral<"media">;
|
|
159
159
|
retryAfterMs: z.ZodNumber;
|
|
160
|
-
}, z.core.$strict
|
|
160
|
+
}, z.core.$strict>>;
|
|
161
161
|
/** Existing Media admission refusals, without an admitted selector or callable. */
|
|
162
162
|
export declare const appMediaAdmissionRefusalSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
163
163
|
error: z.ZodEnum<{
|
|
@@ -170,11 +170,11 @@ export declare const appMediaAdmissionRefusalSchema: z.ZodUnion<readonly [z.ZodO
|
|
|
170
170
|
/** Admission could not resolve the current resource. */
|
|
171
171
|
readonly unavailable: "unavailable";
|
|
172
172
|
}>;
|
|
173
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
173
|
+
}, z.core.$strict>, z.ZodLazy<z.ZodObject<{
|
|
174
174
|
error: z.ZodLiteral<"attachment_budget_exceeded">;
|
|
175
175
|
kind: z.ZodLiteral<"media">;
|
|
176
176
|
retryAfterMs: z.ZodNumber;
|
|
177
|
-
}, z.core.$strict
|
|
177
|
+
}, z.core.$strict>>]>;
|
|
178
178
|
/** Admission errors plus invalid/oversized inputs emitted directly by the broker. */
|
|
179
179
|
export declare const appMediaBrokerErrorSchema: z.ZodObject<{
|
|
180
180
|
error: z.ZodEnum<{
|
|
@@ -193,10 +193,10 @@ export declare const appMediaBrokerErrorSchema: z.ZodObject<{
|
|
|
193
193
|
}>;
|
|
194
194
|
}, z.core.$strict>;
|
|
195
195
|
/** Missing-library refusal decoded and returned by the App media broker. */
|
|
196
|
-
export declare const agentAppMediaLibraryFailureSchema: z.ZodObject<{
|
|
196
|
+
export declare const agentAppMediaLibraryFailureSchema: z.ZodLazy<z.ZodObject<{
|
|
197
197
|
error: z.ZodLiteral<"library_unavailable">;
|
|
198
198
|
message: z.ZodString;
|
|
199
|
-
}, z.core.$strict
|
|
199
|
+
}, z.core.$strict>>;
|
|
200
200
|
/** Broker projection of an HTTP failure: code becomes error and error becomes message. */
|
|
201
201
|
export declare const appMediaBrokerFailureSchema: z.ZodObject<{
|
|
202
202
|
error: z.ZodEnum<{
|
|
@@ -221,6 +221,13 @@ export declare const appMediaBrokerFailureSchema: z.ZodObject<{
|
|
|
221
221
|
readonly "destination-write": "destination-write";
|
|
222
222
|
}>;
|
|
223
223
|
retryable: z.ZodBoolean;
|
|
224
|
+
provider: z.ZodOptional<z.ZodPipe<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodTransform<Readonly<{
|
|
225
|
+
category: "InferenceUpstreamError" | "AiInternalError" | "TypeError" | "AbortError" | "TimeoutError" | "Error";
|
|
226
|
+
code: number | null;
|
|
227
|
+
}> | Readonly<{
|
|
228
|
+
category: "result_download";
|
|
229
|
+
status: number;
|
|
230
|
+
}>, unknown>>>;
|
|
224
231
|
}, z.core.$strict>;
|
|
225
232
|
/** Refusal payloads emitted by the App media broker, separate from transport errors. */
|
|
226
233
|
export declare const appMediaRefusalSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -238,14 +245,14 @@ export declare const appMediaRefusalSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
238
245
|
/** Admission could not resolve the current resource. */
|
|
239
246
|
readonly unavailable: "unavailable";
|
|
240
247
|
}>;
|
|
241
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
248
|
+
}, z.core.$strict>, z.ZodLazy<z.ZodObject<{
|
|
242
249
|
error: z.ZodLiteral<"attachment_budget_exceeded">;
|
|
243
250
|
kind: z.ZodLiteral<"media">;
|
|
244
251
|
retryAfterMs: z.ZodNumber;
|
|
245
|
-
}, z.core.$strict
|
|
252
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
246
253
|
error: z.ZodLiteral<"library_unavailable">;
|
|
247
254
|
message: z.ZodString;
|
|
248
|
-
}, z.core.$strict
|
|
255
|
+
}, z.core.$strict>>, z.ZodObject<{
|
|
249
256
|
error: z.ZodEnum<{
|
|
250
257
|
readonly CAPABILITY_DENIED: "CAPABILITY_DENIED";
|
|
251
258
|
readonly INSUFFICIENT_CREDIT: "INSUFFICIENT_CREDIT";
|
|
@@ -268,9 +275,16 @@ export declare const appMediaRefusalSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
268
275
|
readonly "destination-write": "destination-write";
|
|
269
276
|
}>;
|
|
270
277
|
retryable: z.ZodBoolean;
|
|
278
|
+
provider: z.ZodOptional<z.ZodPipe<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodTransform<Readonly<{
|
|
279
|
+
category: "InferenceUpstreamError" | "AiInternalError" | "TypeError" | "AbortError" | "TimeoutError" | "Error";
|
|
280
|
+
code: number | null;
|
|
281
|
+
}> | Readonly<{
|
|
282
|
+
category: "result_download";
|
|
283
|
+
status: number;
|
|
284
|
+
}>, unknown>>>;
|
|
271
285
|
}, z.core.$strict>]>;
|
|
272
286
|
/** Model-list payload or an existing broker refusal. */
|
|
273
|
-
export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
287
|
+
export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodLazy<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
274
288
|
id: z.ZodString;
|
|
275
289
|
label: z.ZodString;
|
|
276
290
|
kind: z.ZodEnum<{
|
|
@@ -288,7 +302,7 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
288
302
|
readonly jpeg: "jpeg";
|
|
289
303
|
readonly webp: "webp";
|
|
290
304
|
}>>>;
|
|
291
|
-
input: z.ZodReadonly<z.ZodObject<{
|
|
305
|
+
input: z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
292
306
|
transport: z.ZodEnum<{
|
|
293
307
|
readonly json: "json";
|
|
294
308
|
readonly multipart: "multipart";
|
|
@@ -309,9 +323,9 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
309
323
|
defaultSteps: z.ZodNullable<z.ZodNumber>;
|
|
310
324
|
referenceField: z.ZodNullable<z.ZodString>;
|
|
311
325
|
maxReferences: z.ZodNumber;
|
|
312
|
-
}, z.core.$strict
|
|
326
|
+
}, z.core.$strict>>>;
|
|
313
327
|
sizes: z.ZodNullable<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
314
|
-
video: z.ZodNullable<z.ZodReadonly<z.ZodObject<{
|
|
328
|
+
video: z.ZodNullable<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
315
329
|
minSeconds: z.ZodNumber;
|
|
316
330
|
maxSeconds: z.ZodNumber;
|
|
317
331
|
defaultSeconds: z.ZodNumber;
|
|
@@ -321,7 +335,7 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
321
335
|
readonly veo: "veo";
|
|
322
336
|
readonly minimax: "minimax";
|
|
323
337
|
}>;
|
|
324
|
-
formats: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
338
|
+
formats: z.ZodReadonly<z.ZodArray<z.ZodLazy<z.ZodReadonly<z.ZodObject<{
|
|
325
339
|
resolution: z.ZodEnum<{
|
|
326
340
|
readonly p480: "480p";
|
|
327
341
|
readonly p720: "720p";
|
|
@@ -340,7 +354,7 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
340
354
|
}>;
|
|
341
355
|
width: z.ZodNumber;
|
|
342
356
|
height: z.ZodNumber;
|
|
343
|
-
}, z.core.$strict
|
|
357
|
+
}, z.core.$strict>>>>>;
|
|
344
358
|
defaultResolution: z.ZodEnum<{
|
|
345
359
|
readonly p480: "480p";
|
|
346
360
|
readonly p720: "720p";
|
|
@@ -383,8 +397,8 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
383
397
|
silentMilliunitsPerSecond: z.ZodNumber;
|
|
384
398
|
audioMilliunitsPerSecond: z.ZodNumber;
|
|
385
399
|
}, z.core.$strict>>>>;
|
|
386
|
-
}, z.core.$strict
|
|
387
|
-
}, z.core.$strict
|
|
400
|
+
}, z.core.$strict>>>>;
|
|
401
|
+
}, z.core.$strict>>>>, z.ZodUnion<readonly [z.ZodObject<{
|
|
388
402
|
error: z.ZodEnum<{
|
|
389
403
|
/** The broker refused the input representation or selection. */
|
|
390
404
|
readonly invalid: "invalid";
|
|
@@ -399,14 +413,14 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
399
413
|
/** Admission could not resolve the current resource. */
|
|
400
414
|
readonly unavailable: "unavailable";
|
|
401
415
|
}>;
|
|
402
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
416
|
+
}, z.core.$strict>, z.ZodLazy<z.ZodObject<{
|
|
403
417
|
error: z.ZodLiteral<"attachment_budget_exceeded">;
|
|
404
418
|
kind: z.ZodLiteral<"media">;
|
|
405
419
|
retryAfterMs: z.ZodNumber;
|
|
406
|
-
}, z.core.$strict
|
|
420
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
407
421
|
error: z.ZodLiteral<"library_unavailable">;
|
|
408
422
|
message: z.ZodString;
|
|
409
|
-
}, z.core.$strict
|
|
423
|
+
}, z.core.$strict>>, z.ZodObject<{
|
|
410
424
|
error: z.ZodEnum<{
|
|
411
425
|
readonly CAPABILITY_DENIED: "CAPABILITY_DENIED";
|
|
412
426
|
readonly INSUFFICIENT_CREDIT: "INSUFFICIENT_CREDIT";
|
|
@@ -429,6 +443,13 @@ export declare const appMediaModelsOutcomeSchema: z.ZodUnion<readonly [z.ZodArra
|
|
|
429
443
|
readonly "destination-write": "destination-write";
|
|
430
444
|
}>;
|
|
431
445
|
retryable: z.ZodBoolean;
|
|
446
|
+
provider: z.ZodOptional<z.ZodPipe<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodTransform<Readonly<{
|
|
447
|
+
category: "InferenceUpstreamError" | "AiInternalError" | "TypeError" | "AbortError" | "TimeoutError" | "Error";
|
|
448
|
+
code: number | null;
|
|
449
|
+
}> | Readonly<{
|
|
450
|
+
category: "result_download";
|
|
451
|
+
status: number;
|
|
452
|
+
}>, unknown>>>;
|
|
432
453
|
}, z.core.$strict>]>]>;
|
|
433
454
|
/** Completed generation, Agar polling result, or an existing broker refusal. */
|
|
434
455
|
export declare const appMediaGenerationOutcomeSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -466,14 +487,14 @@ export declare const appMediaGenerationOutcomeSchema: z.ZodUnion<readonly [z.Zod
|
|
|
466
487
|
/** Admission could not resolve the current resource. */
|
|
467
488
|
readonly unavailable: "unavailable";
|
|
468
489
|
}>;
|
|
469
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
490
|
+
}, z.core.$strict>, z.ZodLazy<z.ZodObject<{
|
|
470
491
|
error: z.ZodLiteral<"attachment_budget_exceeded">;
|
|
471
492
|
kind: z.ZodLiteral<"media">;
|
|
472
493
|
retryAfterMs: z.ZodNumber;
|
|
473
|
-
}, z.core.$strict
|
|
494
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
474
495
|
error: z.ZodLiteral<"library_unavailable">;
|
|
475
496
|
message: z.ZodString;
|
|
476
|
-
}, z.core.$strict
|
|
497
|
+
}, z.core.$strict>>, z.ZodObject<{
|
|
477
498
|
error: z.ZodEnum<{
|
|
478
499
|
readonly CAPABILITY_DENIED: "CAPABILITY_DENIED";
|
|
479
500
|
readonly INSUFFICIENT_CREDIT: "INSUFFICIENT_CREDIT";
|
|
@@ -496,4 +517,11 @@ export declare const appMediaGenerationOutcomeSchema: z.ZodUnion<readonly [z.Zod
|
|
|
496
517
|
readonly "destination-write": "destination-write";
|
|
497
518
|
}>;
|
|
498
519
|
retryable: z.ZodBoolean;
|
|
520
|
+
provider: z.ZodOptional<z.ZodPipe<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodTransform<Readonly<{
|
|
521
|
+
category: "InferenceUpstreamError" | "AiInternalError" | "TypeError" | "AbortError" | "TimeoutError" | "Error";
|
|
522
|
+
code: number | null;
|
|
523
|
+
}> | Readonly<{
|
|
524
|
+
category: "result_download";
|
|
525
|
+
status: number;
|
|
526
|
+
}>, unknown>>>;
|
|
499
527
|
}, z.core.$strict>]>]>;
|
|
@@ -4,9 +4,7 @@ import { mediaResultSchema } from "./media-operation-contract.js";
|
|
|
4
4
|
import { pendingSchema } from "@fungi.computer/agar/backend-definition";
|
|
5
5
|
import { mediaFailureSchema } from "./browser-failure.js";
|
|
6
6
|
/** Bounded catalog decoded by the App media broker before host filtering. */
|
|
7
|
-
export const mediaModelsSchema = z
|
|
8
|
-
.array(mediaModelSchema)
|
|
9
|
-
.max(listMediaModels().length);
|
|
7
|
+
export const mediaModelsSchema = z.lazy(() => z.array(mediaModelSchema).max(listMediaModels().length));
|
|
10
8
|
/** An absolute output path on the Computer admitted by the App host. */
|
|
11
9
|
export const destinationSchema = z.strictObject({
|
|
12
10
|
/** Computer admitted by the host. */
|
|
@@ -36,14 +34,14 @@ export const appMediaAdmissionErrorSchema = z.strictObject({
|
|
|
36
34
|
}),
|
|
37
35
|
});
|
|
38
36
|
/** Attachment budget refusal emitted by the Media reservation owner. */
|
|
39
|
-
export const appMediaBudgetRefusalSchema = z.strictObject({
|
|
37
|
+
export const appMediaBudgetRefusalSchema = z.lazy(() => z.strictObject({
|
|
40
38
|
/** The attachment's operation budget refused this request. */
|
|
41
39
|
error: z.literal("attachment_budget_exceeded"),
|
|
42
40
|
/** Media reservations use the Media budget, not exec or write. */
|
|
43
41
|
kind: z.literal("media"),
|
|
44
42
|
/** Delay emitted by the reservation owner. */
|
|
45
43
|
retryAfterMs: z.number(),
|
|
46
|
-
});
|
|
44
|
+
}));
|
|
47
45
|
/** Existing Media admission refusals, without an admitted selector or callable. */
|
|
48
46
|
export const appMediaAdmissionRefusalSchema = z.union([
|
|
49
47
|
appMediaAdmissionErrorSchema,
|
|
@@ -61,12 +59,12 @@ export const appMediaBrokerErrorSchema = appMediaAdmissionErrorSchema.extend({
|
|
|
61
59
|
}),
|
|
62
60
|
});
|
|
63
61
|
/** Missing-library refusal decoded and returned by the App media broker. */
|
|
64
|
-
export const agentAppMediaLibraryFailureSchema = z.strictObject({
|
|
62
|
+
export const agentAppMediaLibraryFailureSchema = z.lazy(() => z.strictObject({
|
|
65
63
|
/** The calling Installation's library is unavailable. */
|
|
66
64
|
error: z.literal("library_unavailable"),
|
|
67
65
|
/** Existing library-owner presentation copy. */
|
|
68
66
|
message: z.string().max(4096),
|
|
69
|
-
});
|
|
67
|
+
}));
|
|
70
68
|
/** Broker projection of an HTTP failure: code becomes error and error becomes message. */
|
|
71
69
|
export const appMediaBrokerFailureSchema = z.strictObject({
|
|
72
70
|
/** Original typed HTTP failure code. */
|
|
@@ -77,6 +75,8 @@ export const appMediaBrokerFailureSchema = z.strictObject({
|
|
|
77
75
|
stage: mediaFailureSchema.shape.stage,
|
|
78
76
|
/** Original retry truth. */
|
|
79
77
|
retryable: mediaFailureSchema.shape.retryable,
|
|
78
|
+
/** Original bounded provider facts, when available. */
|
|
79
|
+
provider: mediaFailureSchema.shape.provider,
|
|
80
80
|
});
|
|
81
81
|
/** Refusal payloads emitted by the App media broker, separate from transport errors. */
|
|
82
82
|
export const appMediaRefusalSchema = z.union([
|
|
@@ -33,6 +33,13 @@ export declare const mediaFailureSchema: z.ZodObject<{
|
|
|
33
33
|
readonly SAFETY_FILTER_REFUSED: "SAFETY_FILTER_REFUSED";
|
|
34
34
|
}>;
|
|
35
35
|
retryable: z.ZodBoolean;
|
|
36
|
+
provider: z.ZodOptional<z.ZodPipe<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodTransform<Readonly<{
|
|
37
|
+
category: "InferenceUpstreamError" | "AiInternalError" | "TypeError" | "AbortError" | "TimeoutError" | "Error";
|
|
38
|
+
code: number | null;
|
|
39
|
+
}> | Readonly<{
|
|
40
|
+
category: "result_download";
|
|
41
|
+
status: number;
|
|
42
|
+
}>, unknown>>>;
|
|
36
43
|
}, z.core.$strict>;
|
|
37
44
|
/** Sanitized Media failure carried from the authenticated host to Agar. */
|
|
38
45
|
export type MediaFailure = z.output<typeof mediaFailureSchema>;
|
package/dist/browser-failure.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as z from "zod";
|
|
|
2
2
|
import { mediaFailureStageSchema } from "./execution-error.js";
|
|
3
3
|
import { Option, Schema } from "effect";
|
|
4
4
|
import { reportCatchFailure } from "./failure.js";
|
|
5
|
+
import { mediaProviderDiagnosticWireSchema } from "@fungi.computer/agar/errors";
|
|
5
6
|
/** Sanitized HTTP refusal emitted by a Media host and decoded at the browser boundary. */
|
|
6
7
|
export const mediaFailureSchema = z.strictObject({
|
|
7
8
|
/** Host-supplied presentation copy. */
|
|
@@ -23,6 +24,8 @@ export const mediaFailureSchema = z.strictObject({
|
|
|
23
24
|
}),
|
|
24
25
|
/** Whether repeating this exact attempt may recover. */
|
|
25
26
|
retryable: z.boolean(),
|
|
27
|
+
/** Allowlisted provider facts only; the original cause never crosses HTTP. */
|
|
28
|
+
provider: mediaProviderDiagnosticWireSchema.optional(),
|
|
26
29
|
});
|
|
27
30
|
const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Json));
|
|
28
31
|
function parseMediaFailureJson(json) {
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import * as Redacted from "effect/Redacted";
|
|
3
3
|
import { buildProviderInput, getMediaModel, estimateImageMilliunits, normalizeMediaProviderOutput, mediaProviderWireSchema, } from "../index.js";
|
|
4
4
|
import { MediaExecutionError, MediaSafetyFilterRefusal, } from "../execution-error.js";
|
|
5
|
+
import { decodeMediaProviderErrorCategory, } from "@fungi.computer/agar/errors";
|
|
5
6
|
import { estimateGatewayMilliunits, gatewayInput, isGatewayModel, } from "../gateway-models.js";
|
|
6
7
|
import { GATEWAY_VIDEO_MAX_BYTES, gatewayOutputSchema, isMp4, } from "../gateway-wire.js";
|
|
7
8
|
import { videoProviderAdapters } from "../video-providers/index.js";
|
|
@@ -25,31 +26,21 @@ export function estimate(settings, references) {
|
|
|
25
26
|
}
|
|
26
27
|
// Workers AI prefixes upstream error messages with its numeric internal code.
|
|
27
28
|
// Parse only that bounded identifier; the remaining message is never logged.
|
|
28
|
-
const providerFailureCode = z
|
|
29
|
+
const providerFailureCode = z.lazy(() => z
|
|
29
30
|
.string()
|
|
30
31
|
.regex(/^\d{4,5}: /u)
|
|
31
32
|
.transform((message) => Number(message.split(":", 1)[0]))
|
|
32
33
|
.nullable()
|
|
33
|
-
.catch(null);
|
|
34
|
-
const providerFailureCategory = z
|
|
35
|
-
.enum([
|
|
36
|
-
"InferenceUpstreamError",
|
|
37
|
-
"AiInternalError",
|
|
38
|
-
"TypeError",
|
|
39
|
-
"AbortError",
|
|
40
|
-
"TimeoutError",
|
|
41
|
-
"Error",
|
|
42
|
-
])
|
|
43
|
-
.catch("Error");
|
|
34
|
+
.catch(null));
|
|
44
35
|
// Recognize the refusal, not the generic Workers AI error number or prompt text.
|
|
45
|
-
const safetyFilterMessage = z.union([
|
|
36
|
+
const safetyFilterMessage = z.lazy(() => z.union([
|
|
46
37
|
z
|
|
47
38
|
.string()
|
|
48
39
|
.regex(/(?:^|:\s)(?:AiError:\s)?Input prompt contains NSFW content\b/iu),
|
|
49
40
|
// Veo's documented input-policy refusal; keep its details private as well.
|
|
50
41
|
// https://docs.cloud.google.com/vertex-ai/generative-ai/docs/video/responsible-ai-and-usage-guidelines
|
|
51
42
|
z.string().regex(/\bit might violate our policies\b/iu),
|
|
52
|
-
]);
|
|
43
|
+
]));
|
|
53
44
|
/** Encode multipart once with the platform's boundary, as required by AI.run. */
|
|
54
45
|
function workersAiInput(payload) {
|
|
55
46
|
if (payload.transport === "json")
|
|
@@ -64,17 +55,21 @@ function workersAiInput(payload) {
|
|
|
64
55
|
}
|
|
65
56
|
/** Retain the original provider failure alongside its bounded code and category. */
|
|
66
57
|
function providerFailure(model, cause) {
|
|
58
|
+
const provider = {
|
|
59
|
+
category: decodeMediaProviderErrorCategory(cause instanceof Error ? cause.name : undefined),
|
|
60
|
+
code: providerFailureCode.parse(cause instanceof Error ? cause.message : undefined),
|
|
61
|
+
};
|
|
67
62
|
// Workers correlates this structured event with the request trace. Never log
|
|
68
63
|
// the provider message/body: either can contain customer prompt content.
|
|
69
64
|
console.error("Media provider request failed", {
|
|
70
65
|
model,
|
|
71
|
-
providerCode:
|
|
72
|
-
category:
|
|
66
|
+
providerCode: provider.code,
|
|
67
|
+
category: provider.category,
|
|
73
68
|
}, Redacted.make(cause));
|
|
74
69
|
return cause instanceof Error &&
|
|
75
70
|
safetyFilterMessage.safeParse(cause.message).success
|
|
76
|
-
? new MediaSafetyFilterRefusal({ cause })
|
|
77
|
-
: new MediaExecutionError("provider", { cause });
|
|
71
|
+
? new MediaSafetyFilterRefusal({ cause, provider })
|
|
72
|
+
: new MediaExecutionError("provider", { cause, provider });
|
|
78
73
|
}
|
|
79
74
|
/** Run a gateway model and fetch its result URL within the byte bound. */
|
|
80
75
|
async function generateThroughGateway(ai, settings, references, signal, options, fetchResult, outputFormat) {
|
|
@@ -95,7 +90,9 @@ async function generateThroughGateway(ai, settings, references, signal, options,
|
|
|
95
90
|
const url = videoProviderAdapters[model.video.provider].decodeResultUrl(providerValue);
|
|
96
91
|
const response = await fetchResult(url, { signal: signal ?? null });
|
|
97
92
|
if (!response.ok)
|
|
98
|
-
throw new
|
|
93
|
+
throw new MediaExecutionError("normalization", {
|
|
94
|
+
provider: { category: "result_download", status: response.status },
|
|
95
|
+
});
|
|
99
96
|
const bytes = await readResponseBytes(response, GATEWAY_VIDEO_MAX_BYTES);
|
|
100
97
|
if (!isMp4(bytes))
|
|
101
98
|
throw new Error("gateway video is not an MP4");
|
|
@@ -107,6 +104,8 @@ async function generateThroughGateway(ai, settings, references, signal, options,
|
|
|
107
104
|
}), { fetchUrl: (url) => fetchResult(url, { signal: signal ?? null }) });
|
|
108
105
|
}
|
|
109
106
|
catch (cause) {
|
|
107
|
+
if (cause instanceof MediaExecutionError)
|
|
108
|
+
throw cause;
|
|
110
109
|
throw new MediaExecutionError("normalization", { cause });
|
|
111
110
|
}
|
|
112
111
|
}
|
|
@@ -2,11 +2,11 @@ import { z } from "zod";
|
|
|
2
2
|
import { MAX_REFERENCE_BYTES, MAX_REFERENCE_DIMENSION, MediaSettingsError, viewDimensionSchema, } from "../index.js";
|
|
3
3
|
/** The retained `read_image` encoding: JPEG at quality 80. */
|
|
4
4
|
const VIEW_JPEG_QUALITY = 80;
|
|
5
|
-
const metadata = z.object({
|
|
5
|
+
const metadata = z.lazy(() => z.object({
|
|
6
6
|
format: z.enum(["image/png", "image/jpeg", "image/gif", "image/webp"]),
|
|
7
7
|
width: z.number().int().positive(),
|
|
8
8
|
height: z.number().int().positive(),
|
|
9
|
-
});
|
|
9
|
+
}));
|
|
10
10
|
const formats = {
|
|
11
11
|
"image/png": "png",
|
|
12
12
|
"image/jpeg": "jpeg",
|
package/dist/cost-estimate.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as z from "zod";
|
|
|
4
4
|
const TILE = 512;
|
|
5
5
|
const MAX_DIMENSION = 4_096;
|
|
6
6
|
const MAX_REFERENCES = 4;
|
|
7
|
-
const imageParamsSchema = z
|
|
7
|
+
const imageParamsSchema = z.lazy(() => z
|
|
8
8
|
.object({
|
|
9
9
|
width: z.number().int().min(1).max(MAX_DIMENSION),
|
|
10
10
|
height: z.number().int().min(1).max(MAX_DIMENSION),
|
|
@@ -19,7 +19,7 @@ const imageParamsSchema = z
|
|
|
19
19
|
.max(MAX_REFERENCES)
|
|
20
20
|
.optional(),
|
|
21
21
|
})
|
|
22
|
-
.strict();
|
|
22
|
+
.strict());
|
|
23
23
|
const invalid = (message) => {
|
|
24
24
|
throw new MediaSettingsError(`image cost parameters are invalid: ${message}`);
|
|
25
25
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
import { type MediaProviderDiagnostic } from "@fungi.computer/agar/errors";
|
|
2
3
|
/** Public diagnostic labels only; never provider messages or request data. */
|
|
3
4
|
export declare const mediaFailureStageSchema: z.ZodEnum<{
|
|
4
5
|
/** Host admission before operation creation. */
|
|
@@ -26,17 +27,24 @@ export declare const mediaFailureStageSchema: z.ZodEnum<{
|
|
|
26
27
|
}>;
|
|
27
28
|
/** Execution stage at which a generation failed. */
|
|
28
29
|
export type MediaFailureStage = Exclude<z.output<typeof mediaFailureStageSchema>, "admission" | "settings">;
|
|
30
|
+
/** Private cause plus an independently decoded, safe provider diagnostic. */
|
|
31
|
+
export type MediaExecutionErrorOptions = ErrorOptions & {
|
|
32
|
+
/** Safe provider facts, when the failure came from provider transport. */
|
|
33
|
+
readonly provider?: MediaProviderDiagnostic | undefined;
|
|
34
|
+
};
|
|
29
35
|
/** A bounded stage marker for failures that cross the Media HTTP boundary. */
|
|
30
36
|
export declare class MediaExecutionError extends Error {
|
|
31
37
|
/** Execution stage where the failure occurred. */
|
|
32
38
|
readonly stage: MediaFailureStage;
|
|
39
|
+
/** Safe provider facts only; the original cause remains private. */
|
|
40
|
+
readonly provider: MediaProviderDiagnostic | undefined;
|
|
33
41
|
constructor(
|
|
34
42
|
/** Execution stage where the failure occurred. */
|
|
35
|
-
stage: MediaFailureStage, options?:
|
|
43
|
+
stage: MediaFailureStage, options?: MediaExecutionErrorOptions);
|
|
36
44
|
}
|
|
37
45
|
/** A provider safety filter refused generation; no output was delivered. */
|
|
38
46
|
export declare class MediaSafetyFilterRefusal extends MediaExecutionError {
|
|
39
|
-
constructor(options?:
|
|
47
|
+
constructor(options?: MediaExecutionErrorOptions);
|
|
40
48
|
}
|
|
41
49
|
/** Why the host's billing owner refused to admit a new generation. */
|
|
42
50
|
export type MediaBillingRefusalCode = "insufficient_credits" | "daily_limit_reached" | "denied";
|
package/dist/execution-error.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
import { decodeMediaProviderDiagnostic, } from "@fungi.computer/agar/errors";
|
|
2
3
|
/** Public diagnostic labels only; never provider messages or request data. */
|
|
3
4
|
export const mediaFailureStageSchema = z.enum({
|
|
4
5
|
/** Host admission before operation creation. */
|
|
@@ -27,12 +28,18 @@ export const mediaFailureStageSchema = z.enum({
|
|
|
27
28
|
/** A bounded stage marker for failures that cross the Media HTTP boundary. */
|
|
28
29
|
export class MediaExecutionError extends Error {
|
|
29
30
|
stage;
|
|
31
|
+
/** Safe provider facts only; the original cause remains private. */
|
|
32
|
+
provider;
|
|
30
33
|
constructor(
|
|
31
34
|
/** Execution stage where the failure occurred. */
|
|
32
35
|
stage, options) {
|
|
33
36
|
super(`Media ${stage} failed`, options);
|
|
34
37
|
this.stage = stage;
|
|
35
38
|
this.name = "MediaExecutionError";
|
|
39
|
+
this.provider =
|
|
40
|
+
options?.provider === undefined
|
|
41
|
+
? undefined
|
|
42
|
+
: decodeMediaProviderDiagnostic(options.provider);
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
/** A provider safety filter refused generation; no output was delivered. */
|
package/dist/gateway-wire.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/** A result URL every gateway provider must return as plain HTTPS. */
|
|
3
|
-
export declare const resultUrl: z.ZodURL
|
|
3
|
+
export declare const resultUrl: z.ZodLazy<z.ZodURL>;
|
|
4
4
|
/** The Unified AI gateway's normalized answer: a completed state and one
|
|
5
5
|
* result URL. Seedance and Veo answer this way; MiniMax does not. */
|
|
6
|
-
export declare const gatewayOutputSchema: z.ZodObject<{
|
|
6
|
+
export declare const gatewayOutputSchema: z.ZodLazy<z.ZodObject<{
|
|
7
7
|
state: z.ZodOptional<z.ZodLiteral<"Completed">>;
|
|
8
8
|
result: z.ZodObject<{
|
|
9
|
-
image: z.ZodOptional<z.ZodURL
|
|
10
|
-
video: z.ZodOptional<z.ZodURL
|
|
9
|
+
image: z.ZodOptional<z.ZodLazy<z.ZodURL>>;
|
|
10
|
+
video: z.ZodOptional<z.ZodLazy<z.ZodURL>>;
|
|
11
11
|
}, z.core.$loose>;
|
|
12
|
-
}, z.core.$loose
|
|
12
|
+
}, z.core.$loose>>;
|
|
13
13
|
/** Byte ceilings for fetched results; video stays within Worker memory. */
|
|
14
14
|
export declare const GATEWAY_VIDEO_MAX_BYTES: number;
|
|
15
15
|
/** An MP4 carries an `ftyp` box at byte 4. */
|
package/dist/gateway-wire.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/** A result URL every gateway provider must return as plain HTTPS. */
|
|
3
|
-
export const resultUrl = z
|
|
3
|
+
export const resultUrl = z.lazy(() => z
|
|
4
4
|
.url()
|
|
5
|
-
.refine((value) => value.startsWith("https://"), "result URLs must be HTTPS");
|
|
5
|
+
.refine((value) => value.startsWith("https://"), "result URLs must be HTTPS"));
|
|
6
6
|
/** The Unified AI gateway's normalized answer: a completed state and one
|
|
7
7
|
* result URL. Seedance and Veo answer this way; MiniMax does not. */
|
|
8
|
-
export const gatewayOutputSchema = z.looseObject({
|
|
8
|
+
export const gatewayOutputSchema = z.lazy(() => z.looseObject({
|
|
9
9
|
state: z.literal("Completed").optional(),
|
|
10
10
|
result: z.looseObject({
|
|
11
11
|
image: resultUrl.optional(),
|
|
12
12
|
video: resultUrl.optional(),
|
|
13
13
|
}),
|
|
14
|
-
});
|
|
14
|
+
}));
|
|
15
15
|
/** Byte ceilings for fetched results; video stays within Worker memory. */
|
|
16
16
|
export const GATEWAY_VIDEO_MAX_BYTES = 64 * 1024 * 1024;
|
|
17
17
|
/** An MP4 carries an `ftyp` box at byte 4. */
|