@nodaro/sdk 2.54.0 → 2.56.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/dist/{chunk-P6AM42UB.cjs → chunk-2KX5ZE6M.cjs} +2 -2
- package/dist/chunk-2KX5ZE6M.cjs.map +1 -0
- package/dist/{chunk-JOVJAKBT.cjs → chunk-2LOTDOUV.cjs} +6 -6
- package/dist/chunk-2LOTDOUV.cjs.map +1 -0
- package/dist/{chunk-AN36M6HO.js → chunk-37LL6BPM.js} +5 -5
- package/dist/chunk-37LL6BPM.js.map +1 -0
- package/dist/{chunk-22P4X3N5.cjs → chunk-3CVWTUK5.cjs} +26 -8
- package/dist/chunk-3CVWTUK5.cjs.map +1 -0
- package/dist/{chunk-7CUWAVWB.js → chunk-4FSWJTRS.js} +3 -3
- package/dist/{chunk-7CUWAVWB.js.map → chunk-4FSWJTRS.js.map} +1 -1
- package/dist/{chunk-DV6GTEX5.js → chunk-4SZUSZXK.js} +2 -2
- package/dist/{chunk-DV6GTEX5.js.map → chunk-4SZUSZXK.js.map} +1 -1
- package/dist/{chunk-L6T44A3G.js → chunk-4VP2GFIZ.js} +20 -5
- package/dist/chunk-4VP2GFIZ.js.map +1 -0
- package/dist/{chunk-NKH2UFSD.cjs → chunk-4WOT5OAY.cjs} +5 -5
- package/dist/{chunk-NKH2UFSD.cjs.map → chunk-4WOT5OAY.cjs.map} +1 -1
- package/dist/{chunk-W5RMFTPA.cjs → chunk-57GANTLV.cjs} +2 -2
- package/dist/chunk-57GANTLV.cjs.map +1 -0
- package/dist/{chunk-HK5FSTKG.cjs → chunk-A3XA6UNM.cjs} +2 -2
- package/dist/chunk-A3XA6UNM.cjs.map +1 -0
- package/dist/{chunk-AUKHMT53.js → chunk-BGOZRZHY.js} +3 -3
- package/dist/{chunk-AUKHMT53.js.map → chunk-BGOZRZHY.js.map} +1 -1
- package/dist/{chunk-PBFODIFT.js → chunk-CBDUHYTR.js} +2 -2
- package/dist/chunk-CBDUHYTR.js.map +1 -0
- package/dist/{chunk-OSMKIRKI.cjs → chunk-DFT4LD2H.cjs} +4 -4
- package/dist/{chunk-OSMKIRKI.cjs.map → chunk-DFT4LD2H.cjs.map} +1 -1
- package/dist/{chunk-RBX3QTKB.js → chunk-E6X6BGRO.js} +3 -3
- package/dist/{chunk-RBX3QTKB.js.map → chunk-E6X6BGRO.js.map} +1 -1
- package/dist/{chunk-47ULSVO2.js → chunk-FTCAT2LK.js} +3 -3
- package/dist/chunk-FTCAT2LK.js.map +1 -0
- package/dist/{chunk-QGVOAPUI.js → chunk-GIQDM2MH.js} +2 -2
- package/dist/chunk-GIQDM2MH.js.map +1 -0
- package/dist/{chunk-65VIIZEF.cjs → chunk-GJH73EGF.cjs} +2 -2
- package/dist/{chunk-65VIIZEF.cjs.map → chunk-GJH73EGF.cjs.map} +1 -1
- package/dist/{chunk-HAVIVOLO.js → chunk-HFYNZ4SO.js} +2 -2
- package/dist/chunk-HFYNZ4SO.js.map +1 -0
- package/dist/{chunk-THLTFB6I.js → chunk-HJLSOT5C.js} +2 -2
- package/dist/chunk-HJLSOT5C.js.map +1 -0
- package/dist/{chunk-D2ILCSOQ.js → chunk-HK6XP5EN.js} +3 -3
- package/dist/{chunk-D2ILCSOQ.js.map → chunk-HK6XP5EN.js.map} +1 -1
- package/dist/{chunk-HWSYNUSC.js → chunk-HUYI5G3D.js} +2 -2
- package/dist/chunk-HUYI5G3D.js.map +1 -0
- package/dist/{chunk-JVDUGVLX.cjs → chunk-MIXRL6I2.cjs} +2 -2
- package/dist/chunk-MIXRL6I2.cjs.map +1 -0
- package/dist/{chunk-SF2CMKWA.cjs → chunk-OMJ45CW4.cjs} +9 -9
- package/dist/{chunk-SF2CMKWA.cjs.map → chunk-OMJ45CW4.cjs.map} +1 -1
- package/dist/{chunk-DAONQZPI.cjs → chunk-PDX742CC.cjs} +2 -2
- package/dist/chunk-PDX742CC.cjs.map +1 -0
- package/dist/{chunk-EZXFDCII.js → chunk-PQ6G5EM7.js} +15 -15
- package/dist/{chunk-EZXFDCII.js.map → chunk-PQ6G5EM7.js.map} +1 -1
- package/dist/{chunk-FRQJNGJS.cjs → chunk-Q4MFQC2J.cjs} +5 -5
- package/dist/{chunk-FRQJNGJS.cjs.map → chunk-Q4MFQC2J.cjs.map} +1 -1
- package/dist/{chunk-VHTDOACT.cjs → chunk-Q7W4QNE5.cjs} +22 -22
- package/dist/chunk-Q7W4QNE5.cjs.map +1 -0
- package/dist/{chunk-XZRBRXGJ.cjs → chunk-RIMDKJSQ.cjs} +28 -28
- package/dist/{chunk-XZRBRXGJ.cjs.map → chunk-RIMDKJSQ.cjs.map} +1 -1
- package/dist/{chunk-BQAW4RX2.js → chunk-VEQLP5TA.js} +25 -7
- package/dist/chunk-VEQLP5TA.js.map +1 -0
- package/dist/{chunk-I3MEBVLP.js → chunk-XZPSJG2X.js} +2 -2
- package/dist/chunk-XZPSJG2X.js.map +1 -0
- package/dist/{chunk-O74MSMFH.cjs → chunk-XZQ6Z4T6.cjs} +2 -2
- package/dist/chunk-XZQ6Z4T6.cjs.map +1 -0
- package/dist/{chunk-FM2KM5TY.cjs → chunk-Z4B4SZ33.cjs} +21 -4
- package/dist/chunk-Z4B4SZ33.cjs.map +1 -0
- package/dist/{developer-apps-zSQXWmEG.d.ts → developer-apps-CMUzKpE9.d.cts} +2 -0
- package/dist/{developer-apps-zSQXWmEG.d.cts → developer-apps-CMUzKpE9.d.ts} +2 -0
- package/dist/entries/apps.d.cts +1 -1
- package/dist/entries/apps.d.ts +1 -1
- package/dist/entries/audio.d.cts +1 -1
- package/dist/entries/audio.d.ts +1 -1
- package/dist/entries/billing.d.cts +1 -1
- package/dist/entries/billing.d.ts +1 -1
- package/dist/entries/cast-swap.cjs +2 -2
- package/dist/entries/cast-swap.d.cts +13 -1
- package/dist/entries/cast-swap.d.ts +13 -1
- package/dist/entries/cast-swap.js +1 -1
- package/dist/entries/catalogs.d.cts +1 -1
- package/dist/entries/catalogs.d.ts +1 -1
- package/dist/entries/characters.cjs +10 -10
- package/dist/entries/characters.d.cts +11 -3
- package/dist/entries/characters.d.ts +11 -3
- package/dist/entries/characters.js +1 -1
- package/dist/entries/client.cjs +21 -21
- package/dist/entries/client.d.cts +5 -5
- package/dist/entries/client.d.ts +5 -5
- package/dist/entries/client.js +16 -16
- package/dist/entries/collections.d.cts +1 -1
- package/dist/entries/collections.d.ts +1 -1
- package/dist/entries/community.d.cts +1 -1
- package/dist/entries/community.d.ts +1 -1
- package/dist/entries/competitors.d.cts +1 -1
- package/dist/entries/competitors.d.ts +1 -1
- package/dist/entries/copilot.cjs +4 -4
- package/dist/entries/copilot.d.cts +1 -1
- package/dist/entries/copilot.d.ts +1 -1
- package/dist/entries/copilot.js +3 -3
- package/dist/entries/core.cjs +6 -6
- package/dist/entries/core.d.cts +1 -1
- package/dist/entries/core.d.ts +1 -1
- package/dist/entries/core.js +2 -2
- package/dist/entries/creatures.cjs +6 -6
- package/dist/entries/creatures.d.cts +11 -3
- package/dist/entries/creatures.d.ts +11 -3
- package/dist/entries/creatures.js +1 -1
- package/dist/entries/credits.d.cts +1 -1
- package/dist/entries/credits.d.ts +1 -1
- package/dist/entries/developer-apps.d.cts +1 -1
- package/dist/entries/developer-apps.d.ts +1 -1
- package/dist/entries/edit.cjs +7 -7
- package/dist/entries/edit.d.cts +1 -1
- package/dist/entries/edit.d.ts +1 -1
- package/dist/entries/edit.js +2 -2
- package/dist/entries/errors.cjs +32 -24
- package/dist/entries/errors.d.cts +28 -4
- package/dist/entries/errors.d.ts +28 -4
- package/dist/entries/errors.js +1 -1
- package/dist/entries/executions.d.cts +1 -1
- package/dist/entries/executions.d.ts +1 -1
- package/dist/entries/gallery.d.cts +1 -1
- package/dist/entries/gallery.d.ts +1 -1
- package/dist/entries/jobs.cjs +2 -2
- package/dist/entries/jobs.d.cts +7 -4
- package/dist/entries/jobs.d.ts +7 -4
- package/dist/entries/jobs.js +1 -1
- package/dist/entries/keepers.d.cts +1 -1
- package/dist/entries/keepers.d.ts +1 -1
- package/dist/entries/library.d.cts +1 -1
- package/dist/entries/library.d.ts +1 -1
- package/dist/entries/llm.d.cts +1 -1
- package/dist/entries/llm.d.ts +1 -1
- package/dist/entries/locations.cjs +5 -5
- package/dist/entries/locations.d.cts +11 -3
- package/dist/entries/locations.d.ts +11 -3
- package/dist/entries/locations.js +1 -1
- package/dist/entries/media.cjs +4 -4
- package/dist/entries/media.d.cts +34 -5
- package/dist/entries/media.d.ts +34 -5
- package/dist/entries/media.js +3 -3
- package/dist/entries/models.d.cts +1 -1
- package/dist/entries/models.d.ts +1 -1
- package/dist/entries/moodboards.d.cts +1 -1
- package/dist/entries/moodboards.d.ts +1 -1
- package/dist/entries/node-presets.d.cts +1 -1
- package/dist/entries/node-presets.d.ts +1 -1
- package/dist/entries/nodes.cjs +3 -3
- package/dist/entries/nodes.d.cts +3 -3
- package/dist/entries/nodes.d.ts +3 -3
- package/dist/entries/nodes.js +2 -2
- package/dist/entries/oauth.d.cts +1 -1
- package/dist/entries/oauth.d.ts +1 -1
- package/dist/entries/objects.cjs +6 -6
- package/dist/entries/objects.d.cts +11 -3
- package/dist/entries/objects.d.ts +11 -3
- package/dist/entries/objects.js +1 -1
- package/dist/entries/organizations.d.cts +1 -1
- package/dist/entries/organizations.d.ts +1 -1
- package/dist/entries/palettes.d.cts +1 -1
- package/dist/entries/palettes.d.ts +1 -1
- package/dist/entries/picker-catalogs.d.cts +1 -1
- package/dist/entries/picker-catalogs.d.ts +1 -1
- package/dist/entries/pipelines.d.cts +1 -1
- package/dist/entries/pipelines.d.ts +1 -1
- package/dist/entries/projects.d.cts +1 -1
- package/dist/entries/projects.d.ts +1 -1
- package/dist/entries/prompt-helper.d.cts +1 -1
- package/dist/entries/prompt-helper.d.ts +1 -1
- package/dist/entries/recast.d.cts +1 -1
- package/dist/entries/recast.d.ts +1 -1
- package/dist/entries/reduce.d.cts +1 -1
- package/dist/entries/reduce.d.ts +1 -1
- package/dist/entries/saved-posts.d.cts +1 -1
- package/dist/entries/saved-posts.d.ts +1 -1
- package/dist/entries/scene3d.d.cts +4 -4
- package/dist/entries/scene3d.d.ts +4 -4
- package/dist/entries/sessions.d.cts +1 -1
- package/dist/entries/sessions.d.ts +1 -1
- package/dist/entries/shots.d.cts +1 -1
- package/dist/entries/shots.d.ts +1 -1
- package/dist/entries/studio.cjs +5 -5
- package/dist/entries/studio.d.cts +3 -3
- package/dist/entries/studio.d.ts +3 -3
- package/dist/entries/studio.js +2 -2
- package/dist/entries/templates.d.cts +1 -1
- package/dist/entries/templates.d.ts +1 -1
- package/dist/entries/trash.d.cts +1 -1
- package/dist/entries/trash.d.ts +1 -1
- package/dist/entries/trends.cjs +2 -2
- package/dist/entries/trends.d.cts +37 -17
- package/dist/entries/trends.d.ts +37 -17
- package/dist/entries/trends.js +1 -1
- package/dist/entries/tutorials.d.cts +1 -1
- package/dist/entries/tutorials.d.ts +1 -1
- package/dist/entries/uploads.d.cts +1 -1
- package/dist/entries/uploads.d.ts +1 -1
- package/dist/entries/user-settings.d.cts +1 -1
- package/dist/entries/user-settings.d.ts +1 -1
- package/dist/entries/video-pro.d.cts +1 -1
- package/dist/entries/video-pro.d.ts +1 -1
- package/dist/entries/voices.d.cts +1 -1
- package/dist/entries/voices.d.ts +1 -1
- package/dist/entries/webhooks.d.cts +3 -3
- package/dist/entries/webhooks.d.ts +3 -3
- package/dist/entries/workflows.d.cts +1 -1
- package/dist/entries/workflows.d.ts +1 -1
- package/dist/entries/workspaces.d.cts +1 -1
- package/dist/entries/workspaces.d.ts +1 -1
- package/dist/index.cjs +90 -82
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +16 -16
- package/dist/{nodes-DuXF6XVv.d.ts → nodes-1u7MPrD5.d.ts} +11 -1
- package/dist/{nodes-bY51Z1Os.d.cts → nodes-BZavad1T.d.cts} +11 -1
- package/dist/{studio-productions-r2-VZsKj.d.cts → studio-productions-CMiS827q.d.cts} +1 -1
- package/dist/{studio-productions-DtTE8mdl.d.ts → studio-productions-DkI51Z9M.d.ts} +1 -1
- package/dist/{webhooks-BJawEIz8.d.ts → webhooks-C2DZTK4n.d.ts} +1 -1
- package/dist/{webhooks-Dn_DtNTD.d.cts → webhooks-tg3VN39V.d.cts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-22P4X3N5.cjs.map +0 -1
- package/dist/chunk-47ULSVO2.js.map +0 -1
- package/dist/chunk-AN36M6HO.js.map +0 -1
- package/dist/chunk-BQAW4RX2.js.map +0 -1
- package/dist/chunk-DAONQZPI.cjs.map +0 -1
- package/dist/chunk-FM2KM5TY.cjs.map +0 -1
- package/dist/chunk-HAVIVOLO.js.map +0 -1
- package/dist/chunk-HK5FSTKG.cjs.map +0 -1
- package/dist/chunk-HWSYNUSC.js.map +0 -1
- package/dist/chunk-I3MEBVLP.js.map +0 -1
- package/dist/chunk-JOVJAKBT.cjs.map +0 -1
- package/dist/chunk-JVDUGVLX.cjs.map +0 -1
- package/dist/chunk-L6T44A3G.js.map +0 -1
- package/dist/chunk-O74MSMFH.cjs.map +0 -1
- package/dist/chunk-P6AM42UB.cjs.map +0 -1
- package/dist/chunk-PBFODIFT.js.map +0 -1
- package/dist/chunk-QGVOAPUI.js.map +0 -1
- package/dist/chunk-THLTFB6I.js.map +0 -1
- package/dist/chunk-VHTDOACT.cjs.map +0 -1
- package/dist/chunk-W5RMFTPA.cjs.map +0 -1
|
@@ -25,13 +25,24 @@ var UnauthorizedError = class extends NodaroError {
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
var ForbiddenError = class extends NodaroError {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
/** `code` defaults to `"forbidden"`; {@link ModelUnavailableError} passes its own. */
|
|
29
|
+
constructor(message = "Forbidden", missingScope, code = "forbidden") {
|
|
30
|
+
super(message, code, 403);
|
|
30
31
|
this.missingScope = missingScope;
|
|
31
32
|
this.name = "ForbiddenError";
|
|
32
33
|
}
|
|
33
34
|
missingScope;
|
|
34
35
|
};
|
|
36
|
+
var MODEL_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
|
|
37
|
+
"model_not_available",
|
|
38
|
+
"model_disabled"
|
|
39
|
+
]);
|
|
40
|
+
var ModelUnavailableError = class extends ForbiddenError {
|
|
41
|
+
constructor(code, message = "This model is not available") {
|
|
42
|
+
super(message, void 0, code);
|
|
43
|
+
this.name = "ModelUnavailableError";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
35
46
|
var NotFoundError = class extends NodaroError {
|
|
36
47
|
constructor(message = "Not found") {
|
|
37
48
|
super(message, "not_found", 404);
|
|
@@ -276,6 +287,10 @@ function selectError(status, body) {
|
|
|
276
287
|
throw new AppRunVersionChangedError(message, finite(parsed.runVersion), finite(parsed.appVersion));
|
|
277
288
|
}
|
|
278
289
|
if (status === 422 && code === "job_blocked") throw new JobBlockedError(read.message);
|
|
290
|
+
const modelCode = read.code;
|
|
291
|
+
if (status === 403 && modelCode !== void 0 && MODEL_UNAVAILABLE_CODES.has(modelCode)) {
|
|
292
|
+
throw new ModelUnavailableError(modelCode, read.message);
|
|
293
|
+
}
|
|
279
294
|
if (status === 403 && code === "insufficient_scope") {
|
|
280
295
|
throw new ForbiddenError(read.message, envelope.missingScope);
|
|
281
296
|
}
|
|
@@ -295,6 +310,6 @@ function selectError(status, body) {
|
|
|
295
310
|
throw new NodaroError(message, code, status);
|
|
296
311
|
}
|
|
297
312
|
|
|
298
|
-
export { AlreadyRunningError, AppRunVersionChangedError, CREDIT_CAP_CODES, ContinuationPreviewPendingError, ContinuationRefusedError, CreditCapExceededError, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, NodaroError, NotFoundError, RateLimitedError, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, UnauthorizedError, WorkflowConflictError, throwFromResponse };
|
|
299
|
-
//# sourceMappingURL=chunk-
|
|
300
|
-
//# sourceMappingURL=chunk-
|
|
313
|
+
export { AlreadyRunningError, AppRunVersionChangedError, CREDIT_CAP_CODES, ContinuationPreviewPendingError, ContinuationRefusedError, CreditCapExceededError, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, MODEL_UNAVAILABLE_CODES, ModelUnavailableError, NodaroError, NotFoundError, RateLimitedError, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, UnauthorizedError, WorkflowConflictError, throwFromResponse };
|
|
314
|
+
//# sourceMappingURL=chunk-4VP2GFIZ.js.map
|
|
315
|
+
//# sourceMappingURL=chunk-4VP2GFIZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":"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","file":"chunk-4VP2GFIZ.js","sourcesContent":["import type { StudioOpsResponse } from \"./resources/studio-productions.js\"\n\nexport class NodaroError extends Error {\n /**\n * Every other field of the server's error envelope (`{ error: { code,\n * message, … } }`), as it was sent: for example a trend refusal's `slot`, a\n * publish refusal's `reasons`, a validation error's `issues`. Empty when the\n * envelope had nothing else, or for an error the SDK made itself. A copy —\n * changing it changes nothing else.\n */\n public readonly details: Readonly<Record<string, unknown>> = {}\n\n constructor(\n message: string,\n public readonly code: string,\n public readonly status: number,\n details?: Readonly<Record<string, unknown>>,\n ) {\n super(message)\n this.name = \"NodaroError\"\n if (details) this.details = { ...details }\n }\n}\n\nexport class UnauthorizedError extends NodaroError {\n constructor(message = \"Authentication required\") {\n super(message, \"unauthorized\", 401)\n this.name = \"UnauthorizedError\"\n }\n}\n\nexport class ForbiddenError extends NodaroError {\n /** `code` defaults to `\"forbidden\"`; {@link ModelUnavailableError} passes its own. */\n constructor(message = \"Forbidden\", public readonly missingScope?: string, code = \"forbidden\") {\n super(message, code, 403)\n this.name = \"ForbiddenError\"\n }\n}\n\nexport type ModelUnavailableCode = \"model_not_available\" | \"model_disabled\"\n\n/**\n * The 403 codes {@link ModelUnavailableError} carries: a model this\n * deployment does not offer (`model_not_available` — outside its edition or\n * surface, or hidden by its operator) and a model an admin switched off on\n * the models page (`model_disabled`).\n */\nexport const MODEL_UNAVAILABLE_CODES: ReadonlySet<ModelUnavailableCode> = new Set<ModelUnavailableCode>([\n \"model_not_available\",\n \"model_disabled\",\n])\n\n/**\n * HTTP 403 refusing the MODEL, not the caller: this deployment does not offer\n * it, or an admin switched it off. Answered by the credit guard before any\n * credits are held (the LLM and pipeline lanes still answer a switched-off\n * model with a 402 for now).\n * Choosing another model is the remedy — retrying, topping up or a wider\n * scope changes nothing. A {@link ForbiddenError}, so existing catches keep\n * working; `code` is the server's own code and says which. The envelope\n * names no model: what was refused is the request's own `provider` (or, for\n * a fan-out, one of its `models`).\n */\nexport class ModelUnavailableError extends ForbiddenError {\n declare readonly code: ModelUnavailableCode\n\n constructor(code: ModelUnavailableCode, message = \"This model is not available\") {\n super(message, undefined, code)\n this.name = \"ModelUnavailableError\"\n }\n}\n\nexport class NotFoundError extends NodaroError {\n constructor(message = \"Not found\") {\n super(message, \"not_found\", 404)\n this.name = \"NotFoundError\"\n }\n}\n\nexport class RateLimitedError extends NodaroError {\n constructor(message = \"Rate limited\") {\n super(message, \"rate_limited\", 429)\n this.name = \"RateLimitedError\"\n }\n}\n\n/**\n * HTTP 402: the run costs more than the caller may spend. `code` is the\n * refusal's own code — `insufficient_credits` for the caller's own balance, or\n * another 402 code such as `free_video_limit`. A spending cap someone else set\n * (a workspace budget, a member cap, a per-user allowance) is the subclass\n * {@link CreditCapExceededError}, so `instanceof InsufficientCreditsError`\n * still catches every 402.\n */\nexport class InsufficientCreditsError extends NodaroError {\n constructor(\n message = \"Insufficient credits\",\n public readonly required?: number,\n public readonly available?: number,\n code = \"insufficient_credits\",\n ) {\n super(message, code, 402)\n this.name = \"InsufficientCreditsError\"\n }\n}\n\n/** The 402 codes of a spending cap set by someone other than the caller. */\nexport type CreditCapCode = \"budget_exceeded\" | \"member_cap_exceeded\" | \"user_allowance_exceeded\"\n\n/**\n * The 402 codes {@link CreditCapExceededError} carries: the workspace's budget\n * (`budget_exceeded`), the caller's cap in that workspace\n * (`member_cap_exceeded`), the deployment's per-user allowance\n * (`user_allowance_exceeded`).\n */\nexport const CREDIT_CAP_CODES: ReadonlySet<CreditCapCode> = new Set<CreditCapCode>([\n \"budget_exceeded\",\n \"member_cap_exceeded\",\n \"user_allowance_exceeded\",\n])\n\n/**\n * HTTP 402 from a spending cap, not from the caller's own balance: topping up\n * does not help — whoever set the cap (the workspace's owner, the deployment's\n * operator) has to raise it. An {@link InsufficientCreditsError}, so existing\n * catches keep working; `code` says which cap. `available`, when sent, is what\n * the cap has left.\n */\nexport class CreditCapExceededError extends InsufficientCreditsError {\n declare readonly code: CreditCapCode\n\n constructor(code: CreditCapCode, message = \"A credit cap cannot cover this run\", required?: number, available?: number) {\n super(message, required, available, code)\n this.name = \"CreditCapExceededError\"\n }\n}\n\nexport class StorageExceededError extends NodaroError {\n constructor(message = \"Storage exceeded\", public readonly limitBytes?: number) {\n super(message, \"storage_exceeded\", 413)\n this.name = \"StorageExceededError\"\n }\n}\n\n/**\n * Optimistic-concurrency rejection (HTTP 409 `workflow_conflict`): the workflow\n * was written by another tab/device after the state carried in\n * `expectedUpdatedAt`/`expectedVersion` was read. `currentRecord` — when the\n * server includes it — is the full current workflow: merge your changes onto it\n * and retry with its fresh `updatedAt`, no follow-up GET needed.\n */\nexport class WorkflowConflictError extends NodaroError {\n constructor(\n message = \"Workflow was updated by another writer\",\n public readonly currentUpdatedAt?: string,\n public readonly currentVersion?: number,\n public readonly currentRecord?: Record<string, unknown>,\n /**\n * The wire code this conflict actually arrived with.\n *\n * `production_busy` is the studio production routes' own 409: the row\n * changed under a read-modify-write and the server exhausted its retries.\n * It is the same situation and the same remedy — re-read and apply again —\n * so it is the same ERROR, and a caller catching `WorkflowConflictError`\n * handles both. The code stays truthful because a caller that logs or\n * branches on it should see what the server said, not what the class is\n * usually called.\n */\n code: WorkflowConflictCode = \"workflow_conflict\",\n ) {\n super(message, code, 409)\n this.name = \"WorkflowConflictError\"\n }\n}\n\n/** The 409 codes that mean \"somebody else wrote first; re-read and retry\". */\nexport type WorkflowConflictCode = \"workflow_conflict\" | \"production_busy\"\n\n/**\n * A studio operation batch was refused, and the error names WHICH operation\n * (`opIndex`, zero-based) was wrong. Nothing in the batch was written: a batch\n * applies atomically or not at all, so fix that one operation and send the\n * whole batch again.\n *\n * Selected by SHAPE — any 4xx carrying a numeric `opIndex` — not by a list of\n * codes, so a new refusal reason (`op_invalid`, `op_target_missing`, whatever\n * the server adds next) reaches the caller as this error without an SDK\n * release. `code` is whatever the server sent.\n */\nexport class StudioOpError extends NodaroError {\n constructor(\n message: string,\n code: string,\n status: number,\n /** Zero-based index into the `ops` array that was sent. */\n public readonly opIndex: number,\n ) {\n super(message, code, status)\n this.name = \"StudioOpError\"\n }\n}\n\n/** The 409 codes whose answer names the job to turn to instead (a top-level `jobId`). */\nconst CONTINUATION_REFUSAL_CODES: ReadonlySet<string> = new Set([\n \"already_running\",\n \"continuation_superseded\",\n \"render_final_already_rendered\",\n])\n\n/**\n * A 409 that names the job to turn to instead: continuing a use-case run\n * (`client.edit.continueUseCase`) answers `already_running` (a continuation is\n * under way, or one that already completed — follow `jobId`),\n * `continuation_superseded` (a later continuation failed too — continue\n * `jobId` instead) or `render_final_already_rendered` (a Render final with this\n * very edit already completed — `jobId` holds the result). `code` and `status`\n * are what the server sent. Selected for exactly those three codes when the\n * answer carries a top-level `jobId`; every other 409 stays a plain\n * `NodaroError`.\n */\nexport class ContinuationRefusedError extends NodaroError {\n constructor(\n message: string,\n code: string,\n /** The job the refusal names. */\n public readonly jobId: string,\n ) {\n super(message, code, 409)\n this.name = \"ContinuationRefusedError\"\n }\n}\n\n/**\n * The one run that finishes a continuation held at a Preview review (the\n * `next` of {@link ContinuationPreviewPendingError}): pass these three fields\n * to `client.workflows.run`. It continues that execution, runs each held render\n * at Final and each held Tighten Episode continuing the run that made its\n * Preview, then every node after them.\n */\nexport interface HeldFinalRun {\n continueFromExecutionId: string\n /** The nodes it runs, in canvas order. */\n nodeIds: string[]\n /** For this run only: each held render at Final, each held use-case node's `useCaseContinue`. */\n inputOverrides: Record<string, Record<string, unknown>>\n}\n\n/**\n * HTTP 409 `continuation_preview_pending`: a continue-from-failed\n * (`client.workflows.run` with `continueMode: \"from-failed\"`) whose run's\n * newest later continuation completed by stopping at a Preview review, so\n * continuing again would stop there too. `executionId` is that continuation;\n * `renderNodeIds` the Apply EDL renders and `reviewNodeIds` the Tighten Episode\n * nodes holding it; `next` the run that finishes them — send it first\n * (`client.workflows.run(workflowId, error.next)`), then continue. Absent only\n * when the server could not name it. For a single held render, `next` is that\n * render's `client.workflows.renderFinal`.\n */\nexport class ContinuationPreviewPendingError extends NodaroError {\n constructor(\n message: string,\n public readonly executionId: string,\n public readonly renderNodeIds: readonly string[],\n public readonly reviewNodeIds: readonly string[],\n public readonly next?: HeldFinalRun,\n ) {\n super(message, \"continuation_preview_pending\", 409)\n this.name = \"ContinuationPreviewPendingError\"\n }\n}\n\nconst stringList = (v: unknown): string[] => (Array.isArray(v) ? v.filter((id): id is string => typeof id === \"string\") : [])\n\n/** A `next` as the server sends it, or undefined for anything else. */\nfunction heldFinalRunOf(v: unknown): HeldFinalRun | undefined {\n if (!v || typeof v !== \"object\") return undefined\n const r = v as Record<string, unknown>\n if (typeof r.continueFromExecutionId !== \"string\" || !Array.isArray(r.nodeIds)) return undefined\n if (!r.inputOverrides || typeof r.inputOverrides !== \"object\" || Array.isArray(r.inputOverrides)) return undefined\n return {\n continueFromExecutionId: r.continueFromExecutionId,\n nodeIds: stringList(r.nodeIds),\n inputOverrides: r.inputOverrides as Record<string, Record<string, unknown>>,\n }\n}\n\n/**\n * HTTP 409 `already_running` that names the execution under way (a top-level\n * `executionId`): the run you asked to start or continue is still running —\n * follow `executionId` (`client.executions.get`) instead of starting it again.\n * Sent by the workflow run route and by an app run's Retry\n * (`client.apps.resume`). An `already_running` that names a job instead stays\n * {@link ContinuationRefusedError}; one that names nothing, a plain\n * `NodaroError`.\n */\nexport class AlreadyRunningError extends NodaroError {\n constructor(\n message: string,\n /** The execution under way. */\n public readonly executionId: string,\n ) {\n super(message, \"already_running\", 409)\n this.name = \"AlreadyRunningError\"\n }\n}\n\n/**\n * HTTP 409 `app_run_version_changed`: a Retry of a failed app run\n * (`client.apps.resume`) refused because the app is on another version than\n * the one the run ran — continuing would mix them. `runVersion` is the run's\n * version, `appVersion` the one you are on (the `version` you sent, else the\n * app's latest). Start the run over (`client.apps.run`) to run `appVersion`,\n * or send `{ version: runVersion }` to continue on the run's own version.\n * Nothing was written or billed. Selected by code; the two numbers are\n * `undefined` when the answer does not carry them.\n */\nexport class AppRunVersionChangedError extends NodaroError {\n constructor(\n message: string,\n public readonly runVersion?: number,\n public readonly appVersion?: number,\n ) {\n super(message, \"app_run_version_changed\", 409)\n this.name = \"AppRunVersionChangedError\"\n }\n}\n\n/**\n * HTTP 422 `job_blocked`. A job policy registered by this deployment refused\n * the generation **before it ran** — no job was created, nothing was reserved\n * and nothing was charged. `message` is the policy's user-safe text: show it\n * as-is. Do not retry the identical request; whether the same input would be\n * judged differently is the deployment's policy's business.\n *\n * Only occurs on deployments that register a job policy. Selected by `code`,\n * not by status, the same way `workflow_conflict` narrows a 409 above — any\n * other 422 stays a plain `NodaroError`.\n */\nexport class JobBlockedError extends NodaroError {\n constructor(message = \"Blocked by this deployment's content policy\") {\n super(message, \"job_blocked\", 422)\n this.name = \"JobBlockedError\"\n }\n}\n\n/**\n * A job reached a terminal `failed`/`cancelled` status while being awaited by\n * `nodes.runAndWait` / `nodes.runMany`. Not an HTTP-level error (the polls\n * themselves succeeded), so `status` is 0 — distinguish it by type/`code`.\n * Carries the job's own `error_message` (as the message) and `jobId`.\n */\nexport class JobFailedError extends NodaroError {\n constructor(\n message: string,\n public readonly jobId: string,\n /** The terminal status that triggered the failure (`failed` | `cancelled`). */\n public readonly jobStatus: \"failed\" | \"cancelled\" = \"failed\",\n ) {\n super(message, \"job_failed\", 0)\n this.name = \"JobFailedError\"\n }\n}\n\n/**\n * `nodes.runAndWait` polled past its `maxMs` deadline without the job reaching\n * a terminal status. Not an HTTP error — `status` is 0; catch by type/`code`.\n */\nexport class JobTimeoutError extends NodaroError {\n constructor(\n message: string,\n public readonly jobId: string,\n /** The wall-clock deadline (ms) that was exceeded. */\n public readonly timeoutMs: number,\n ) {\n super(message, \"job_timeout\", 0)\n this.name = \"JobTimeoutError\"\n }\n}\n\n/**\n * The caller's `AbortSignal` fired while `nodes.runAndWait` was polling (or it\n * was already aborted on entry). Polling stops and this rejects. Not an HTTP\n * error — `status` is 0; catch by type/`code`.\n */\nexport class JobAbortedError extends NodaroError {\n constructor(message = \"Aborted\", public readonly jobId?: string) {\n super(message, \"job_aborted\", 0)\n this.name = \"JobAbortedError\"\n }\n}\n\n/**\n * A batch preview was asked for and this deployment cannot give one, so\n * NOTHING was sent: the batch is still unapplied and the production untouched.\n *\n * A preview is two requests because the route's body is parsed in strip mode —\n * a deployment that predates the preview silently DROPS the flag and APPLIES\n * the batch. So the SDK asks with an EMPTY batch first and sends the real one\n * only when that answer carries the `dryRun` marker. This is what it throws\n * when the answer does not: whatever the older deployment made of an empty\n * batch, the caller's batch never left.\n *\n * The remedy is a deployment that serves the preview — there is nothing to\n * retry here. To apply the batch instead, send it without the flag.\n *\n * A deployment that REFUSES the empty batch outright throws its own error\n * instead of this one, which is the right way round: the route's message says\n * more than \"unavailable\" does.\n *\n * Not an HTTP error: the request itself succeeded and answered the older shape.\n * `status` is 0; catch by type/`code`.\n */\nexport class StudioPreviewUnavailable extends NodaroError {\n constructor(\n message = \"This deployment does not preview operation batches; nothing was sent\",\n ) {\n super(message, \"studio_preview_unavailable\", 0)\n this.name = \"StudioPreviewUnavailable\"\n }\n}\n\n/**\n * A batch preview was asked for and the batch was APPLIED instead. The\n * production is written; this is the opposite of {@link\n * StudioPreviewUnavailable}, where nothing was sent.\n *\n * How it happens: the preview's proving ping and the batch are two requests,\n * and a fleet mid-rollout can serve them from different deployments. The ping\n * answers the marker, the batch reaches a deployment that predates the preview,\n * parses in strip mode, drops the flag and writes. The SDK cannot recall that\n * request — by the time the answer comes back the change has landed — so it\n * refuses to call the result a preview, which is the only thing still in its\n * gift. `receipts` and `warnings` are on both shapes, so an unchecked reply\n * would have shown a person what ALREADY happened under the heading of what\n * would.\n *\n * `applied` is what the route answered: the ordinary apply reply, whose\n * `production` and `version` are now the truth. Adopt them the way a plain\n * apply's caller does — do NOT re-send the batch, and do not present it for\n * approval.\n *\n * Not an HTTP error: the request succeeded, at the wrong thing. `status` is 0.\n */\nexport class StudioPreviewAppliedError extends NodaroError {\n constructor(\n /**\n * The apply reply the route sent back, as it sent it. An answer this\n * package does not recognise arrives here unchanged rather than being\n * dressed up: it is what the deployment said about a batch it took.\n *\n * `undefined` when the answer carried no body at all — a 204, an empty\n * envelope. The refusal still fires, because a non-preview answer is never\n * handed back as a preview, but there is nothing to report and the SDK will\n * not invent it: whether the batch was applied is unknown from here, and\n * the caller settles it by re-reading the production.\n */\n public readonly applied: StudioOpsResponse | undefined,\n message = applied\n ? \"Asked for a preview and this deployment APPLIED the batch; the change is written — see `applied`\"\n : \"Asked for a preview and this deployment answered with neither one nor a body to read; the batch may have been applied — re-read the production before deciding anything\",\n ) {\n super(message, \"studio_preview_applied\", 0)\n this.name = \"StudioPreviewAppliedError\"\n }\n}\n\n/**\n * The awaited job entered `pending_review`: a job policy registered by this\n * deployment held its output for a human reviewer. `pending_review` is\n * IN-FLIGHT, not terminal, so `nodes.runAndWait` / `nodes.runMany` end the\n * poll on the first tick they observe it rather than burning `maxMs` on a\n * status that no longer moves on its own.\n *\n * This does NOT cancel the job — the output exists, a human is reviewing it,\n * and the credit reservation stays `reserved` for the whole hold. Do not\n * re-run the request (a duplicate would be held too): re-fetch with\n * `jobs.get(jobId)` later, or surface \"awaiting review\" to your user and poll\n * `jobs.getStatus()` yourself. It resolves to `completed` (approved), `failed`\n * (rejected, with `error_hint.kind === \"policy-block\"`) or `cancelled`.\n *\n * Not an HTTP error — `status` is 0; catch by type/`code`.\n */\nexport class JobHeldError extends NodaroError {\n constructor(\n message: string,\n public readonly jobId: string,\n ) {\n super(message, \"job_held\", 0)\n this.name = \"JobHeldError\"\n }\n}\n\n/** The `{ error: { code, message, … } }` envelope every current route sends. */\ninterface ApiErrorEnvelope {\n code?: string\n message?: string\n missingScope?: string\n required?: number\n available?: number\n limitBytes?: number\n opIndex?: number\n [key: string]: unknown\n}\n\ninterface ApiErrorBody {\n /** The envelope — or, on an older route, a bare string (see {@link readErrorBody}). */\n error?: ApiErrorEnvelope | string\n /** A top-level message: an older route's, a bare validation answer's, or the server framework's own. */\n message?: unknown\n /** OAuth's human text (RFC 6749 §5.2), beside a bare-string `error`. */\n error_description?: unknown\n /** A bare validation answer's per-field issues (`{ message, issues }`). */\n issues?: unknown\n /** A refusal that names another job (see {@link ContinuationRefusedError}). */\n jobId?: unknown\n /** `continuation_preview_pending`: the held continuation, what holds it, and the run that finishes it. */\n executionId?: unknown\n renderNodeIds?: unknown\n reviewNodeIds?: unknown\n next?: unknown\n /** The credit guard's 402 sends its figures beside the envelope: what the run needs… */\n required?: unknown\n /** …and what the caller has (withheld on a deployment-paid instance). */\n balance?: unknown\n /** A per-user allowance's 402: what the allowance has left. */\n remaining?: unknown\n /** `app_run_version_changed`: the version the run ran, and the one the caller is on. */\n runVersion?: unknown\n appVersion?: unknown\n}\n\nconst finite = (v: unknown): number | undefined => (typeof v === \"number\" && Number.isFinite(v) ? v : undefined)\n\n/** A machine code as an older route writes it: lower snake_case, never a sentence or a reason phrase. */\nconst BARE_CODE = /^[a-z][a-z0-9_]*$/\n\nconst nonEmpty = (v: unknown): string | undefined => (typeof v === \"string\" && v.length > 0 ? v : undefined)\n\n/**\n * Where a body keeps its code and its human message. Most routes send the\n * envelope `{ error: { code, message } }`; three other shapes reach the SDK\n * too, and each is read for what it says rather than collapsed into\n * `internal_error` / \"Request failed\":\n *\n * - an older route's bare string, `{ error: \"<code>\", message?, … }` (character\n * training, a few profile and billing routes), and OAuth's\n * `{ error: \"<code>\", error_description }`. A snake_case string is the code;\n * a sentence (`\"Profile not found\"`) is the message.\n * - a bare validation answer, `{ message, issues: [...] }`: `validation_error`.\n * - the server framework's own answer, `{ statusCode, error: \"<reason phrase>\",\n * message }` (a route it does not have): the reason phrase is neither, the\n * message is kept — so \"no such route\" stays distinguishable from \"no such\n * resource\".\n *\n * At HTTP 500 and above only the CODE is read from outside the envelope. Text\n * there can be whatever the server failed with: the framework's own answer to\n * an uncaught throw is `{ statusCode: 500, error: \"Internal Server Error\",\n * message: <the raw error> }`, and the server's sanitizer rewrites only the\n * `internal_error` envelope. The envelope's own message is a route's chosen\n * sentence and is read at every status, as before.\n *\n * `message` is undefined when the body carries no human text it may show, so a\n * typed class keeps its own default (\"Not found\").\n */\nfunction readErrorBody(status: number, body: ApiErrorBody): { code: string | undefined; message: string | undefined; envelope: ApiErrorEnvelope } {\n const raw = body.error\n const envelope: ApiErrorEnvelope = raw && typeof raw === \"object\" ? raw : {}\n const bare = typeof raw === \"string\" ? raw : undefined\n const bareCode = bare !== undefined && BARE_CODE.test(bare) ? bare : undefined\n // Words with a space between them are human text: an older route's sentence,\n // or the framework's reason phrase — which always arrives with a real\n // `message`, read first. A single capitalised word (\"Unauthorized\") is a\n // reason phrase alone and says nothing the status does not.\n const bareSentence = bare !== undefined && bareCode === undefined && /\\s/.test(bare.trim()) ? bare : undefined\n const code =\n nonEmpty(envelope.code) ??\n bareCode ??\n (status === 400 && raw === undefined && Array.isArray(body.issues) ? \"validation_error\" : undefined)\n const outside = status >= 500 ? undefined : (nonEmpty(body.message) ?? nonEmpty(body.error_description) ?? bareSentence)\n const message = nonEmpty(envelope.message) ?? outside\n return { code, message, envelope }\n}\n\n/** The envelope's fields other than `code` and `message` (see {@link NodaroError.details}). */\nfunction envelopeDetails(envelope: ApiErrorEnvelope): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(envelope)) {\n if (key !== \"code\" && key !== \"message\") out[key] = value\n }\n return out\n}\n\nexport function throwFromResponse(status: number, body: ApiErrorBody): never {\n try {\n selectError(status, body)\n } catch (err) {\n // Every class carries the envelope's other fields, whichever was chosen.\n if (err instanceof NodaroError) {\n const raw = body && typeof body === \"object\" ? body.error : undefined\n if (raw && typeof raw === \"object\") Object.defineProperty(err, \"details\", { value: envelopeDetails(raw), enumerable: true })\n }\n throw err\n }\n}\n\nfunction selectError(status: number, body: ApiErrorBody): never {\n // A body that is not an object (an empty answer, `null`, a bare string) still\n // throws by its status.\n const parsed: ApiErrorBody = body && typeof body === \"object\" ? body : {}\n const read = readErrorBody(status, parsed)\n const envelope = read.envelope\n const code = read.code ?? \"internal_error\"\n // A typed class falls back to its own default; a generic error to the code\n // it carries, which says more than \"Request failed\" does.\n const message = read.message ?? (read.code ? read.code : \"Request failed\")\n if (status === 401) throw new UnauthorizedError(read.message)\n if (status === 409 && (code === \"workflow_conflict\" || code === \"production_busy\")) {\n throw new WorkflowConflictError(\n read.message,\n envelope.currentUpdatedAt as string | undefined,\n envelope.currentVersion as number | undefined,\n envelope.currentRecord as Record<string, unknown> | undefined,\n code,\n )\n }\n // By shape, not by code — see StudioOpError. Only the studio operations route\n // sends an op index, so this cannot capture anyone else's 400.\n if (status >= 400 && status < 500 && typeof envelope.opIndex === \"number\") {\n throw new StudioOpError(message, code, status, envelope.opIndex)\n }\n if (status === 409 && CONTINUATION_REFUSAL_CODES.has(code) && typeof parsed.jobId === \"string\") {\n throw new ContinuationRefusedError(message, code, parsed.jobId)\n }\n if (status === 409 && code === \"continuation_preview_pending\" && typeof parsed.executionId === \"string\") {\n throw new ContinuationPreviewPendingError(\n message,\n parsed.executionId,\n stringList(parsed.renderNodeIds),\n stringList(parsed.reviewNodeIds),\n heldFinalRunOf(parsed.next),\n )\n }\n if (status === 409 && code === \"already_running\" && typeof parsed.executionId === \"string\") {\n throw new AlreadyRunningError(message, parsed.executionId)\n }\n if (status === 409 && code === \"app_run_version_changed\") {\n throw new AppRunVersionChangedError(message, finite(parsed.runVersion), finite(parsed.appVersion))\n }\n if (status === 422 && code === \"job_blocked\") throw new JobBlockedError(read.message)\n // The model, not the caller — before the scope line, so its own code is\n // kept (a plain ForbiddenError says \"forbidden\" whatever the server sent).\n const modelCode = read.code as ModelUnavailableCode | undefined\n if (status === 403 && modelCode !== undefined && MODEL_UNAVAILABLE_CODES.has(modelCode)) {\n throw new ModelUnavailableError(modelCode, read.message)\n }\n if (status === 403 && code === \"insufficient_scope\") {\n throw new ForbiddenError(read.message, envelope.missingScope)\n }\n if (status === 403) throw new ForbiddenError(read.message)\n // A 404 the framework answered itself (no route at that path) carries its\n // message at the top level, not under `error`; `readErrorBody` keeps it so\n // callers can tell \"no such route\" from \"no such resource\".\n if (status === 404) throw new NotFoundError(read.message)\n if (status === 429) throw new RateLimitedError(read.message)\n if (status === 402) {\n // The credit guard puts `required` / `balance` (an allowance: `remaining`)\n // beside the envelope; an envelope that carries them (`required` /\n // `available`) is read first.\n const required = finite(envelope.required) ?? finite(parsed.required)\n const available = finite(envelope.available) ?? finite(parsed.balance) ?? finite(parsed.remaining)\n const capCode = read.code as CreditCapCode | undefined\n if (capCode !== undefined && CREDIT_CAP_CODES.has(capCode)) {\n throw new CreditCapExceededError(capCode, read.message, required, available)\n }\n throw new InsufficientCreditsError(read.message, required, available, read.code ?? \"insufficient_credits\")\n }\n if (status === 413) throw new StorageExceededError(read.message, envelope.limitBytes)\n throw new NodaroError(message, code, status)\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkZ4B4SZ33_cjs = require('./chunk-Z4B4SZ33.cjs');
|
|
4
4
|
|
|
5
5
|
// src/resources/studio-productions.ts
|
|
6
6
|
function isStudioGenerateEstimate(result) {
|
|
@@ -104,11 +104,11 @@ var StudioProductionsResource = class {
|
|
|
104
104
|
this.path(productionId, "/ops"),
|
|
105
105
|
{ body: { ops: [], dryRun: true } }
|
|
106
106
|
);
|
|
107
|
-
if (ping?.data?.dryRun !== true) throw new
|
|
107
|
+
if (ping?.data?.dryRun !== true) throw new chunkZ4B4SZ33_cjs.StudioPreviewUnavailable();
|
|
108
108
|
const res = await this.client.request("POST", this.path(productionId, "/ops"), { body: input });
|
|
109
109
|
const data = res?.data;
|
|
110
110
|
if (data?.dryRun !== true) {
|
|
111
|
-
throw new
|
|
111
|
+
throw new chunkZ4B4SZ33_cjs.StudioPreviewAppliedError(data);
|
|
112
112
|
}
|
|
113
113
|
return data;
|
|
114
114
|
}
|
|
@@ -321,5 +321,5 @@ var StudioResource = class {
|
|
|
321
321
|
exports.StudioProductionsResource = StudioProductionsResource;
|
|
322
322
|
exports.StudioResource = StudioResource;
|
|
323
323
|
exports.isStudioGenerateEstimate = isStudioGenerateEstimate;
|
|
324
|
-
//# sourceMappingURL=chunk-
|
|
325
|
-
//# sourceMappingURL=chunk-
|
|
324
|
+
//# sourceMappingURL=chunk-4WOT5OAY.cjs.map
|
|
325
|
+
//# sourceMappingURL=chunk-4WOT5OAY.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resources/studio-productions.ts","../src/resources/studio.ts"],"names":["res","StudioPreviewUnavailable","StudioPreviewAppliedError"],"mappings":"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","file":"chunk-NKH2UFSD.cjs","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { StudioPreviewAppliedError, StudioPreviewUnavailable } from \"../errors.js\"\n\n/**\n * Studio productions — `/v1/studio/productions`.\n *\n * A production is a Nodaro workflow whose `settings.studio` holds the shots:\n * each shot a framed still, an optional animated clip, and the plan, looks,\n * cast bindings and voice that made them. These routes are the platform's own\n * reader and writer of that document, so an agent, a script and the studio app\n * are looking at ONE production rather than three opinions about one row.\n *\n * Two rules run through the whole surface:\n *\n * - **Every change is an OPERATION** ({@link StudioProductionsResource.ops}),\n * addressed by stable key — a shot id, a role slug, a result's job id or url\n * — and never by position. That is what lets two writers hold the same\n * production open: a batch composed against a slightly older version still\n * applies correctly to the newest one, and the response says whether it was\n * rebased.\n * - **Generation is run-then-poll.** A still or clip run returns job ids and\n * records a marker on the production; the results land when anyone — your\n * poll, the app, a later {@link StudioProductionsResource.reconcile} —\n * reports the finished job. Nothing waits minutes inside a request.\n *\n * Reads are `detail: \"summary\"` by default (counts and the active urls);\n * `detail: \"full\"` adds every result with the context that regenerates it.\n *\n * **The ENVELOPES are typed here; the production DOCUMENT is not.** A view, a\n * summary, a shot and an operation are open JSON on this surface\n * ({@link StudioProduction}, `ops: unknown[]`) — their field-level types ship\n * with the studio app, which is the one consumer that narrows them, and a\n * second spelling of that vocabulary in the SDK would drift from it the first\n * time either grew. Everything a caller branches on — `version`, `rebased`,\n * `receipts`, `warnings`, a quote's `credits`, a run's `jobIds` — is typed.\n *\n * Cloud edition only: these routes 404 on deployments that do not serve them.\n * Feature-detect once with `list()` — a deployment without them 404s that too,\n * where a deployment with them answers an empty page.\n */\n\n/**\n * A production, a summary, a shot, a receipt's target: open JSON.\n *\n * Deliberately not narrowed here — see the note at the top of this module.\n */\nexport type StudioProduction = Record<string, unknown>\n\n/** How much of a production a read returns. */\nexport type StudioProductionDetail = \"summary\" | \"full\"\n\n/** One thing wrong with a plan, addressed at the field that is wrong. */\nexport interface StudioPlanIssue {\n path: string\n message: string\n hint?: string\n}\n\n/** `GET …/skill` — the authoring skill, rendered at request time from what is live. */\nexport interface StudioSkillResponse {\n /** The authoring guide. */\n skill: string\n /** Every picker, model and enum, in full. */\n catalog: string\n /** The strict JSON Schema a plan is validated against. */\n schema: Record<string, unknown>\n /** The operating guide: the tool map, the loops, the rules. */\n operating: string\n /** The versions the three were rendered from — bare semver, no package names. */\n generatedFrom: { prompts: string; shared: string; codec: string }\n}\n\nexport interface StudioValidatePlanResponse {\n valid: boolean\n errors: StudioPlanIssue[]\n warnings: StudioPlanIssue[]\n summary?: {\n name?: string\n scenes: number\n shots: number\n cast: number\n /** Cast entries that matched a row in the caller's library. */\n bound: number\n }\n}\n\nexport interface StudioListProductionsResponse {\n data: StudioProduction[]\n nextCursor?: string\n}\n\n/** What a create or an import did, in the words a receipt would use. */\nexport interface StudioImportSummary {\n shotsAdded: number\n castEnrolled: number\n /** Cast entries that resolved to a row in the caller's library. */\n castBound: number\n}\n\nexport interface StudioProductionResponse {\n production: StudioProduction\n warnings?: StudioPlanIssue[]\n summary?: StudioImportSummary\n}\n\nexport interface StudioCreateProductionRequest {\n name?: string\n plan?: Record<string, unknown>\n}\n\n/** The caller's own retry token — 8–128 chars of `A-Za-z0-9_.:-`, never derived. */\nexport type StudioClientRequestId = string\n\n/**\n * A batch of operations, applied atomically.\n *\n * `ops` is `unknown[]`: the operation union is the studio app's vocabulary and\n * the route validates it, refusing the whole batch with the offending index.\n * The served operating guide is the runtime reference for what an operation\n * looks like.\n */\nexport interface StudioOpsRequest {\n /** Applied in order. At most 100 per request. */\n ops: unknown[]\n /**\n * The version the batch was composed against. INFORMATIONAL by default: the\n * operations address by stable KEY, so a batch built on a slightly older\n * document still applies exactly to the newest one, and the response says\n * `rebased: true`. Omitting it means \"apply to whatever is there\".\n */\n baseVersion?: number\n /**\n * Refuse to rebase. With `strict: true` a `baseVersion` older than the stored\n * one is a 409 `workflow_conflict` carrying the current production, instead\n * of a rebased apply — for the rare \"replace exactly what I read\" intent.\n */\n strict?: boolean\n /** Your own token for this batch, so a transport retry is not applied twice. */\n clientRequestId?: StudioClientRequestId\n}\n\n/**\n * What else an operation touched — the work that now has to follow it.\n *\n * Reported by the operations whose effect reaches past the thing they name: a\n * frame review re-opens every frame derived from it and every shot bound to\n * those, a sequence fork mints a whole parallel set. Both lists are always\n * present and either may be empty; ids, never counts, because the caller's job\n * is to go and refresh THOSE.\n */\nexport interface StudioOpsImpact {\n /** Planned frames the operation reaches, the named one first. */\n keyframeIds: string[]\n /** Shots bound to any of those frames. */\n shotIds: string[]\n}\n\n/**\n * A sentence as data: the id of the template a client words it from, and the\n * values that fill the template's slots.\n *\n * It travels beside the English wording, never instead of it. A client that\n * words the sentence in the person's language builds it from `template` and\n * `vars`, and shows the English wording whenever it has no wording for\n * `template` or `vars` does not fill it — so a template id it has never heard of\n * costs nothing. A template id is permanent: a change to its slots or its\n * meaning ships as a new id.\n */\nexport interface StudioOpsText {\n /** The template's id. */\n template: string\n /** What fills the template's slots, by slot name. */\n vars: Record<string, string | number>\n}\n\n/**\n * One line of what an operation did, in the words a change log would use.\n *\n * Past tense, the target named the way the user sees it, the side effect in a\n * trailing parenthetical: `Deleted take 2 of Shot 1 (in the bin).`\n */\nexport interface StudioOpsReceipt {\n /** The operation this line reports, by name. */\n op: string\n /** Past tense, naming the target the way a person would. */\n summary: string\n /**\n * `summary` as data, for a client that words receipts in the person's\n * language. `summary` is always present and always English; read `detail`\n * only when you have wording for its template, and show `summary` when you do\n * not. Absent when the studio service that answered predates it.\n */\n detail?: StudioOpsText\n /** Ids the operation MINTED — never ids the caller supplied. */\n ids?: string[]\n /**\n * The dependency scope, where the operation reports one — absent for the\n * many that touch only what they name. The route projects a receipt ONCE for\n * both answers, so this reads the same on an apply and on a preview.\n */\n impact?: StudioOpsImpact\n}\n\n/** What a batch produced. Adopt `production` whole; do not merge into it. */\nexport interface StudioOpsResponse {\n /** The canonical production AFTER the batch. */\n production: StudioProduction\n /** The version the batch produced. Carry it as the next `baseVersion`. */\n version: number\n /** True when the batch was applied to a newer document than it named. */\n rebased: boolean\n /** One per operation, in order. */\n receipts: StudioOpsReceipt[]\n /**\n * Things worth saying that are not failures — an operation that changed\n * nothing, a rename that rewrote four prompts. A warning never rejects a\n * batch; a refusal does.\n */\n warnings: string[]\n /**\n * `warnings` as data, by position: entry `i` words `warnings[i]`, and `null`\n * means that warning has no wording but the English one. The service sends it\n * only when it is exactly as long as `warnings`, so treat a list of any other\n * length as absent. Absent too when the studio service that answered predates\n * it.\n */\n warningDetails?: Array<StudioOpsText | null>\n}\n\n/**\n * An operation's confirmation class — the vocabulary's own four letters.\n *\n * `S` safe · `D` delete · `P` changes who can reach the work · `$` spends\n * credits. The table that assigns them ships with the production codec and is\n * pinned complete over the operation union there; this is the wire's spelling\n * of its values, not a second table.\n */\nexport type StudioOpClass = \"S\" | \"D\" | \"P\" | \"$\"\n\n/**\n * One line of what an operation WOULD do, for a person deciding whether to let\n * it. Everything {@link StudioOpsReceipt} says — the same summary, the same ids\n * and the same {@link StudioOpsImpact}, read in the conditional — plus the two\n * things the decision turns on and only a preview needs: which kind of change\n * it is, and whether it can be taken back.\n */\nexport interface StudioOpsDryRunReceipt extends StudioOpsReceipt {\n /**\n * The confirmation class, read out of the operation vocabulary's own table:\n * `S` safe, `D` deletes, `P` changes who can reach the work, `$` spends\n * credits. Narrow rather than open, because it is what a caller branches on\n * — a rule like \"never a `D` without asking\" is only writable if the\n * compiler knows the letters.\n */\n class: StudioOpClass\n /**\n * Present, and always `true`, when this operation put something in the bin\n * that can be brought back. ABSENT is the honest answer for everything else,\n * including a delete that destroys: there is no entry to name, so there is no\n * promise to make. Read it as `restorable ?? false`, never as `!restorable`\n * meaning \"kept\".\n */\n restorable?: true\n}\n\n/**\n * What a batch WOULD do. Nothing was written: there is no production here and\n * no new version, because none was produced.\n */\nexport interface StudioOpsDryRunResponse {\n /** Always present, and the marker the two-request protocol reads. */\n dryRun: true\n /** The version the preview was computed against. */\n version: number\n /** One per operation, in order. */\n receipts: StudioOpsDryRunReceipt[]\n /** The same things an apply would have said. */\n warnings: string[]\n /** The same data behind them an apply would have sent: see {@link StudioOpsResponse.warningDetails}. */\n warningDetails?: Array<StudioOpsText | null>\n}\n\n/** What landing the finished jobs did. */\nexport interface StudioReconcileResponse {\n /** Job ids whose media is now on the production. */\n landed: string[]\n /** Job ids still running — their markers stay; call again later. */\n pending: string[]\n /** Job ids that failed or were cancelled; their markers are cleared. */\n failed: string[]\n /** One line per landing that had something to say. */\n warnings: string[]\n /** The production after the landings. */\n production: StudioProduction\n /** Its version — unchanged when nothing landed. */\n version: number\n}\n\n/** `POST …/:id/describe` — a Director run that will land as scenes. */\nexport interface StudioDescribeRequest {\n brief: string\n llmModel: string\n /** `\"append\"` adds the drafted scenes; `\"replace\"` rewrites the film. */\n mode?: \"append\" | \"replace\"\n label?: string\n clientRequestId?: StudioClientRequestId\n}\n\n/**\n * `POST …/:id/generate` — one framing or directing run for one shot.\n *\n * `overrides` is what the CALL owns over what the shot's plan says: the model,\n * the prose, the aspect, the direction ids. Open JSON, because the request\n * builders' own option types are the contract and they ship with the studio.\n */\nexport interface StudioGenerateRequest {\n kind: \"still\" | \"clip\"\n shotId: string\n /** Candidates to fan out (stills); the builder clamps it to the catalog's range. */\n count?: number\n /**\n * The directing input mode for a clip; absent ⇒ derived from the scene's saved\n * inputs (a pinned end frame included). `start` sends ONLY the start frame;\n * `start-end` sends the start and the end frame.\n */\n mode?: \"start\" | \"start-end\" | \"references\"\n /** Price the run and return; nothing is submitted and nothing is written. */\n dryRun?: boolean\n clientRequestId?: StudioClientRequestId\n overrides?: Record<string, unknown>\n}\n\n/** Which video route a directing run went to — chosen from the inputs, never asked for. */\nexport type StudioVideoLane = \"generate-video\" | \"text-to-video\"\n\n/** `dryRun: true` — what this run would cost, and nothing else. */\nexport interface StudioGenerateEstimate {\n dryRun: true\n provider: string\n count: number\n /** `null` when the model is unpriced or the instance runs without credits. */\n credits: number | null\n lane?: StudioVideoLane\n}\n\n/**\n * A started (or already-started) run.\n *\n * `deduped` means the same `clientRequestId` came back and the job ids were\n * answered from the production's own markers — nothing was submitted and\n * nothing was charged, so `production` is absent.\n */\nexport interface StudioGenerateResponse {\n jobIds: string[]\n lane?: StudioVideoLane\n deduped?: true\n production?: StudioProduction\n receipts?: StudioOpsReceipt[]\n warnings?: string[]\n}\n\n/** `POST …/:id/frame` — a still pulled out of the shot's clip. */\nexport interface StudioFrameRequest {\n shotId: string\n mode?: \"first\" | \"last\" | \"timestamp\"\n /** Seconds, when `mode` is `\"timestamp\"`. */\n timestamp?: number\n /** Where the grabbed image lands. `\"new-shot\"` inserts a shot after this one. */\n target?: \"new-shot\" | \"start-frame\" | \"end-frame\" | \"still\"\n clientRequestId?: StudioClientRequestId\n}\n\n/** `POST …/:id/voice` — synthesize a shot's spoken line and record it. */\nexport interface StudioVoiceRequest {\n shotId: string\n text: string\n voiceId?: string\n voiceType?: \"premade\" | \"custom\" | \"library\"\n ttsProvider?: string\n /** The delivery levers; the text-to-speech route owns their bounds. */\n delivery?: Record<string, number>\n clientRequestId?: StudioClientRequestId\n}\n\n/** `POST …/:id/revoice` — recast the voices of the shot's active clip. */\nexport interface StudioRevoiceRequest {\n shotId: string\n /** The speaker-ordered recast plan, forwarded to the voice route verbatim. */\n plan: Record<string, unknown>\n clientRequestId?: StudioClientRequestId\n}\n\n/** `POST …/:id/music` — the film's soundtrack. */\nexport interface StudioMusicRequest {\n prompt: string\n duration?: number\n instrumental?: boolean\n vocalGender?: string\n model?: string\n clientRequestId?: StudioClientRequestId\n}\n\n/**\n * What a route that finished its work answers with: the production as it now\n * stands, plus whatever that route produced.\n *\n * `jobId` is present on the routes that only STARTED something (a revoice, a\n * soundtrack, a draft) — the result lands through its marker.\n */\nexport interface StudioMediaResponse {\n production: StudioProduction\n /** The grabbed frame's url, on the frame route. */\n url?: string\n jobId?: string\n receipts?: StudioOpsReceipt[]\n warnings?: string[]\n}\n\n/**\n * `GET …/:id/export-plan` — the ordered steps an export would run.\n *\n * The caller runs them with the verbs that already exist; a route that chained\n * three minutes-long jobs is the long-lived request every client times out on.\n */\nexport interface StudioExportPlanResponse {\n /** False when the production has fewer than two clips — nothing to stitch. */\n canExport: boolean\n steps: StudioExportStep[]\n /** The step whose output IS the film, or `null` when nothing can run. */\n resultStepId: string | null\n /** Total credits, or `null` when ANY step is unpriced (a partial sum understates). */\n estimate: number | null\n /** The credit models with no price, each named once, in step order. */\n unpriced: string[]\n}\n\nexport interface StudioExportStep {\n /** Stable within one plan and derived from the production, never minted. */\n id: string\n label: string\n /** The node this step runs — `merge-video-audio`, `combine-videos`, `video-upscale`. */\n node: string\n creditModel: string\n credits: number | null\n params: Record<string, unknown>\n}\n\n/** `POST …/:id/clone` — a copy, which always starts private and visible. */\nexport interface StudioCloneRequest {\n name?: string\n}\n\n/** Either arm of a generation reply: the quote, or the run that started. */\nexport type StudioGenerateResult = StudioGenerateEstimate | StudioGenerateResponse\n\n/** True when a generation reply is the `dryRun` QUOTE rather than a started run. */\nexport function isStudioGenerateEstimate(\n result: StudioGenerateResult,\n): result is StudioGenerateEstimate {\n return (result as StudioGenerateEstimate).dryRun === true\n}\n\n/** What a `generateStill` / `generateClip` call decides, beyond `kind` and the shot. */\nexport type StudioGenerateOptions = Omit<StudioGenerateRequest, \"kind\" | \"shotId\">\n\n/**\n * A route that only STARTED something — a draft, a revoice, a soundtrack. Its\n * `jobId` is always there, which is what makes `const { jobId } = await …` and\n * a poll the honest next line.\n *\n * `StudioMediaResponse` leaves `jobId` optional because the routes that FINISH\n * their work (a frame, a voiceover) share the shape and have no job to name.\n */\nexport type StudioJobStartedResponse = StudioMediaResponse & { jobId: string }\n\nexport interface ListStudioProductionsOptions {\n limit?: number\n /** From a previous page's `nextCursor`. */\n cursor?: string\n /** Include the rows the dashboard hides. Off by default. */\n includeArchived?: boolean\n}\n\nexport interface GetProductionOptions {\n detail?: StudioProductionDetail\n /** Read ONE shot — the cheap way to re-read after a generation. */\n shotId?: string\n}\n\nexport interface StudioExportPlanOptions {\n /** Plan the 4K finish too. Expensive, so it is always explicit. */\n upscale?: boolean\n}\n\n/** `client.studio.productions` — see the note at the top of this module. */\nexport class StudioProductionsResource {\n constructor(private client: NodaroClientCore) {}\n\n private path(productionId: string, suffix = \"\"): string {\n return `/v1/studio/productions/${encodeURIComponent(productionId)}${suffix}`\n }\n\n // ── reads ────────────────────────────────────────────────────────────────\n\n /**\n * The authoring guide, the full catalog, the plan's JSON Schema and the\n * operating guide — rendered server-side from the version that is live, so\n * they describe the platform you are actually talking to. Free.\n */\n async skill(): Promise<StudioSkillResponse> {\n const res = await this.client.request<{ data: StudioSkillResponse }>(\n \"GET\",\n \"/v1/studio/productions/skill\",\n )\n return res.data\n }\n\n /**\n * Check a plan before it becomes anything. Free, persists nothing, and\n * resolves cast names against YOUR library — loop on `errors` until\n * `valid: true`, then `create({ plan })`.\n */\n async validatePlan(plan: Record<string, unknown>): Promise<StudioValidatePlanResponse> {\n const res = await this.client.request<{ data: StudioValidatePlanResponse }>(\n \"POST\",\n \"/v1/studio/productions/validate\",\n { body: { plan } },\n )\n return res.data\n }\n\n /** Your productions, newest first. Archived rows are hidden unless asked for. */\n async list(opts: ListStudioProductionsOptions = {}): Promise<StudioListProductionsResponse> {\n const res = await this.client.request<{ data: StudioListProductionsResponse }>(\n \"GET\",\n \"/v1/studio/productions\",\n {\n query: {\n limit: opts.limit,\n cursor: opts.cursor,\n includeArchived: opts.includeArchived,\n },\n },\n )\n return res.data\n }\n\n /**\n * One production. A pure read — it never lands a finished job, so call\n * {@link reconcile} first if you are waiting on one.\n */\n async get(\n productionId: string,\n opts: GetProductionOptions = {},\n ): Promise<StudioProduction> {\n const res = await this.client.request<{ data: { production: StudioProduction } }>(\n \"GET\",\n this.path(productionId),\n { query: { detail: opts.detail, shot_id: opts.shotId } },\n )\n return res.data.production\n }\n\n /**\n * The ordered steps that assemble the film, with what they will cost. Run\n * them yourself with the ordinary verbs — nothing here blocks for minutes,\n * and nothing here spends.\n */\n async exportPlan(\n productionId: string,\n opts: StudioExportPlanOptions = {},\n ): Promise<StudioExportPlanResponse> {\n const res = await this.client.request<{ data: StudioExportPlanResponse }>(\n \"GET\",\n this.path(productionId, \"/export-plan\"),\n { query: { upscale: opts.upscale } },\n )\n return res.data\n }\n\n // ── writes ───────────────────────────────────────────────────────────────\n\n /** A new production, optionally landed from a plan in the same call. */\n async create(input: StudioCreateProductionRequest = {}): Promise<StudioProductionResponse> {\n const res = await this.client.request<{ data: StudioProductionResponse }>(\n \"POST\",\n \"/v1/studio/productions\",\n { body: input },\n )\n return res.data\n }\n\n /**\n * Apply a batch of operations. Atomic: one bad operation refuses the whole\n * batch with a `StudioOpError` naming its index, and nothing is written. On\n * success adopt `production` wholesale and carry `version` forward as the\n * next `baseVersion`.\n *\n * `dryRun: true` — the LITERAL, which is what selects the preview reply —\n * asks what the batch would do, so a person can approve an assistant's edits\n * before they land. Spell it in THIS call's own object literal: a flag passed\n * through a variable widens `true` to `boolean`, which selects the apply\n * overload while the runtime still takes the preview path.\n *\n * A preview is TWO requests, deliberately. The route's body is parsed in\n * strip mode, so a deployment that predates the preview drops the flag and\n * APPLIES the batch: a caller that sent its batch and read the answer\n * afterwards would already have written it. So the flag is proved on an EMPTY\n * batch first and the real batch goes only when that answer carries the\n * marker. An older deployment either answers the apply shape — this throws\n * `StudioPreviewUnavailable`, and the batch never leaves — or refuses the\n * empty batch with its own error, which is passed through as it stands.\n *\n * The ping proves the deployment that answered IT, and a fleet mid-rollout\n * can serve the second request from another one. So the second answer is\n * checked too: when the batch came back APPLIED, this throws\n * `StudioPreviewAppliedError`, which carries that write. The SDK cannot\n * un-send a request; what it can do is refuse to call the result a preview.\n *\n * An apply stays exactly one request.\n */\n ops(\n productionId: string,\n input: StudioOpsRequest & { dryRun: true },\n ): Promise<StudioOpsDryRunResponse>\n ops(productionId: string, input: StudioOpsRequest): Promise<StudioOpsResponse>\n async ops(\n productionId: string,\n input: StudioOpsRequest & { dryRun?: true },\n ): Promise<StudioOpsResponse | StudioOpsDryRunResponse> {\n if (input.dryRun !== true) {\n const res = await this.client.request<{ data: StudioOpsResponse }>(\n \"POST\",\n this.path(productionId, \"/ops\"),\n { body: input },\n )\n return res.data\n }\n\n // The ping carries nothing of the caller's batch, because an old deployment\n // takes whatever it is sent at face value; an empty batch with no\n // `clientRequestId` spends neither the caller's operations nor the retry\n // token that would make a real batch unrepeatable.\n const ping = await this.client.request<{ data?: { dryRun?: unknown } } | undefined>(\n \"POST\",\n this.path(productionId, \"/ops\"),\n { body: { ops: [], dryRun: true } },\n )\n // Read through: an older deployment can answer no envelope at all, or a 204\n // that `request` reads as `undefined`. Absent is a \"no\" like any other, and\n // the caller who catches `NodaroError` should not get a `TypeError`.\n if (ping?.data?.dryRun !== true) throw new StudioPreviewUnavailable()\n\n const res = await this.client.request<\n { data?: StudioOpsDryRunResponse | StudioOpsResponse } | undefined\n >(\"POST\", this.path(productionId, \"/ops\"), { body: input })\n // The answer that matters most: this request may have landed on a different\n // deployment from the ping, and an applied batch is not a preview.\n const data = res?.data\n if ((data as { dryRun?: unknown } | undefined)?.dryRun !== true) {\n throw new StudioPreviewAppliedError(data as StudioOpsResponse)\n }\n return data as StudioOpsDryRunResponse\n }\n\n /**\n * Land every generation that has finished since you last looked, and report\n * what is still running. The one call that turns finished jobs into results\n * without a browser open. It writes only when something actually landed.\n */\n async reconcile(productionId: string): Promise<StudioReconcileResponse> {\n const res = await this.client.request<{ data: StudioReconcileResponse }>(\n \"POST\",\n this.path(productionId, \"/reconcile\"),\n )\n return res.data\n }\n\n /** Add a plan's scenes to a production that already exists. */\n async importPlan(\n productionId: string,\n plan: Record<string, unknown>,\n opts: { mode?: \"append\" } = {},\n ): Promise<StudioProductionResponse> {\n const res = await this.client.request<{ data: StudioProductionResponse }>(\n \"POST\",\n this.path(productionId, \"/import\"),\n { body: { plan, mode: opts.mode ?? \"append\" } },\n )\n return res.data\n }\n\n /**\n * Turn a brief into scenes. The run is a platform job: poll it, and its\n * scenes land through {@link reconcile}. The production comes back with the\n * run recorded on it as a pending draft.\n */\n async describe(\n productionId: string,\n input: StudioDescribeRequest,\n ): Promise<StudioJobStartedResponse> {\n const res = await this.client.request<{ data: StudioJobStartedResponse }>(\n \"POST\",\n this.path(productionId, \"/describe\"),\n { body: input },\n )\n return res.data\n }\n\n // ── generation ───────────────────────────────────────────────────────────\n\n /**\n * Frame or animate one shot.\n *\n * The request is assembled server-side from the shot's own plan, looks and\n * bound references, so a scripted run and a press of the button in the app\n * produce the same media; `overrides` changes THIS run without changing the\n * shot. Prefer {@link generateStill} / {@link generateClip}, which say which\n * kind they mean.\n *\n * `dryRun: true` returns the quote and writes nothing — narrow the reply with\n * {@link isStudioGenerateEstimate}.\n */\n generate(\n productionId: string,\n input: StudioGenerateRequest & { dryRun: true },\n ): Promise<StudioGenerateEstimate>\n generate(\n productionId: string,\n input: StudioGenerateRequest,\n ): Promise<StudioGenerateResult>\n async generate(\n productionId: string,\n input: StudioGenerateRequest,\n ): Promise<StudioGenerateResult> {\n const res = await this.client.request<{ data: StudioGenerateResult }>(\n \"POST\",\n this.path(productionId, \"/generate\"),\n { body: input },\n )\n return res.data\n }\n\n /**\n * Frame a shot: submit `count` candidates and record a pending marker for\n * each. Results ACCUMULATE — a generate never replaces what is there.\n *\n * `clientRequestId` makes a retry safe: the same token answers with the jobs\n * the first call started (`deduped: true`) and submits nothing. Never retry a\n * spend without it.\n */\n generateStill(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions & { dryRun: true },\n ): Promise<StudioGenerateEstimate>\n generateStill(\n productionId: string,\n shotId: string,\n opts?: StudioGenerateOptions,\n ): Promise<StudioGenerateResult>\n generateStill(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions = {},\n ): Promise<StudioGenerateResult> {\n return this.generate(productionId, { ...opts, kind: \"still\", shotId })\n }\n\n /**\n * Animate a shot. The LANE is chosen from the shot's inputs (a start frame,\n * references, a prompt) — never passed in — and reported back as `lane`.\n */\n generateClip(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions & { dryRun: true },\n ): Promise<StudioGenerateEstimate>\n generateClip(\n productionId: string,\n shotId: string,\n opts?: StudioGenerateOptions,\n ): Promise<StudioGenerateResult>\n generateClip(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions = {},\n ): Promise<StudioGenerateResult> {\n return this.generate(productionId, { ...opts, kind: \"clip\", shotId })\n }\n\n // ── media on one shot ────────────────────────────────────────────────────\n\n /**\n * Extract a frame from a shot's active clip and put it where `target` says —\n * a new shot after this one (the default), this shot's sticky start or end\n * frame, or another still of the same shot. Seconds, not minutes: this one\n * waits for the job and answers with the changed production.\n */\n async frame(\n productionId: string,\n input: StudioFrameRequest,\n ): Promise<StudioMediaResponse> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/frame\"),\n { body: input },\n )\n return res.data\n }\n\n /** Synthesize a shot's spoken line and record it. Waits for the job. */\n async voice(\n productionId: string,\n input: StudioVoiceRequest,\n ): Promise<StudioMediaResponse> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/voice\"),\n { body: input },\n )\n return res.data\n }\n\n /**\n * Recast the voices of a shot's active clip. Minutes of work, so it answers\n * `jobId` and the new clip lands as a result through its own marker.\n */\n async revoice(\n productionId: string,\n input: StudioRevoiceRequest,\n ): Promise<StudioJobStartedResponse> {\n const res = await this.client.request<{ data: StudioJobStartedResponse }>(\n \"POST\",\n this.path(productionId, \"/revoice\"),\n { body: input },\n )\n return res.data\n }\n\n /** Score the film. The finished track lands through its pending marker. */\n async music(\n productionId: string,\n input: StudioMusicRequest,\n ): Promise<StudioJobStartedResponse> {\n const res = await this.client.request<{ data: StudioJobStartedResponse }>(\n \"POST\",\n this.path(productionId, \"/music\"),\n { body: input },\n )\n return res.data\n }\n\n // ── audience and copies ──────────────────────────────────────────────────\n\n /**\n * Open the share-by-link read. Deliberately its own route rather than an\n * operation: who may see the work is decided by the owner, never as a side\n * effect of a batch that was editing something else.\n */\n async share(productionId: string): Promise<StudioProduction> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/share\"),\n { body: { shared: true } },\n )\n return res.data.production\n }\n\n /** Close it again. Sharing is opt-in AND reversible. */\n async unshare(productionId: string): Promise<StudioProduction> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/unshare\"),\n )\n return res.data.production\n }\n\n /**\n * Copy a production you own or can see into your own Studio project. The\n * copy starts PRIVATE and visible — sharing and archiving never travel — and\n * it is copied through YOUR view of the source, so somebody else's bin does\n * not come with it.\n */\n async clone(\n productionId: string,\n input: StudioCloneRequest = {},\n ): Promise<StudioProduction> {\n const res = await this.client.request<{ data: { production: StudioProduction } }>(\n \"POST\",\n this.path(productionId, \"/clone\"),\n { body: input },\n )\n return res.data.production\n }\n}\n\n","import type { NodaroClientCore } from \"../core.js\"\nimport { StudioProductionsResource } from \"./studio-productions.js\"\nexport * from \"./studio-productions.js\"\n\n/** Public response/transport contracts only; document validation and planning\n * remain in the private Studio codec on the server. */\nexport type StudioDocumentJson = Record<string, unknown>\n\nexport interface StudioProductionCapabilities {\n planVersions: number[]\n operations: {\n readKeyframes: boolean\n saveEditorState?: boolean\n editableSharedCopies?: boolean\n revisionedSharing?: boolean\n cloneLinkedProductions?: boolean\n importPlannedBundles?: boolean\n importLinkedBundles?: boolean\n appendPlannedBundles?: boolean\n appendLinkedBundles?: boolean\n editKeyframes: boolean\n generateKeyframes: boolean\n acceptKeyframes: boolean\n rejectKeyframes?: boolean\n editSequencePlans?: boolean\n generateLinkedClips: boolean\n retakeLinkedClips?: boolean\n /** The host keeps a scene's empty media slots. */\n mediaSlots?: boolean\n /** The host keeps a clip's inputs on its clip slot. */\n clipSlotInputs?: boolean\n }\n sourceFrameReferences: boolean\n automaticAcceptance: false\n unattendedGeneration: false\n}\n\nexport interface StudioKeyframeRecord {\n id: string\n label: string\n revision: number\n nodeId: string\n parentKeyframeId?: string\n previewResultKey: string | null\n previewUrl: string | null\n acceptedResultKey: string | null\n acceptedUrl: string | null\n count: number\n pending: Array<{ jobId: string; startedAt: string }>\n /** Owner-only working state. Recorded acceptance is not an execution grant. */\n plan?: StudioDocumentJson\n acceptance?: StudioDocumentJson\n results?: StudioDocumentJson[]\n}\n\nexport interface StudioProductionRecord {\n id: string\n name: string\n version: number\n updatedAt: string\n thumbnailUrl: string | null\n shared: boolean\n archived: boolean\n requiredCapabilities?: string[]\n keyframes?: StudioKeyframeRecord[]\n sequences?: StudioDocumentJson[]\n shots: StudioDocumentJson[]\n pending: { stills: number; clips: number; keyframes?: number; music: boolean; draft: StudioDocumentJson | null }\n [field: string]: unknown\n}\n\nexport interface StudioProductionReply {\n production: StudioProductionRecord\n capabilities?: StudioProductionCapabilities\n warnings?: unknown[]\n [field: string]: unknown\n}\n\nexport interface StudioEditInput {\n ops: ReadonlyArray<{ op: string; [field: string]: unknown }>\n baseVersion?: number\n strict?: boolean\n clientRequestId?: string\n}\n\nexport interface StudioKeyframeGenerationInput {\n keyframeId: string\n expectedRevision: number\n clientRequestId?: string\n overrides?: StudioDocumentJson\n}\n\nexport interface StudioKeyframeAcceptanceInput {\n keyframeId: string\n expectedRevision: number\n resultKey: string\n expectedAcceptedResultKey: string | null\n requirementChecks: Array<{ requirementId: string; outcome: \"pass\" | \"waived\" }>\n waivedReason?: string\n}\n\nexport interface StudioShotGenerationInput {\n kind: \"still\" | \"clip\"\n shotId: string\n clientRequestId?: string\n count?: number\n mode?: \"start\" | \"start-end\" | \"references\"\n dryRun?: boolean\n /** Linked clips only: require the exact inputs returned by a reviewed quote. */\n expectedInputHash?: string\n /** Retake a native linked take using its original request and retained endpoints. */\n retakeResultKey?: string\n overrides?: StudioDocumentJson\n}\n\nexport type StudioGenerationReply = {\n jobIds: string[]\n production?: StudioProductionRecord\n deduped?: true\n lane?: string\n [field: string]: unknown\n} | {\n dryRun: true; provider: string; count: number; credits: number | null; lane?: string\n /** Linked-clip quotes include normalized settings and accepted endpoint pins. */\n inputHash?: string\n endpointPins?: StudioDocumentJson\n creditIdentifier?: string\n duration?: number\n resolution?: string\n aspectRatio?: string\n sound?: boolean\n}\n\nconst root = \"/v1/studio/productions\"\nconst path = (id: string) => `${root}/${encodeURIComponent(id)}`\n\n/** Cloud plugin routes. Check capabilities before exposing dependency controls.\n * Reads do not reconcile jobs, submit media or accept generated candidates. */\nexport class StudioResource {\n readonly productions: StudioProductionsResource\n\n constructor(private readonly client: NodaroClientCore) {\n this.productions = new StudioProductionsResource(client)\n }\n\n capabilities(): Promise<{ data: StudioProductionCapabilities }> {\n return this.client.request(\"GET\", `${root}/capabilities`)\n }\n\n skill(): Promise<{ data: StudioDocumentJson }> {\n return this.client.request(\"GET\", `${root}/skill`)\n }\n\n list(options: { limit?: number; cursor?: string; includeArchived?: boolean } = {}): Promise<{ data: {\n data: Array<{ id: string; name: string; version: number; updatedAt: string; thumbnailUrl: string | null; shared: boolean; archived: boolean; shotCount: number }>\n nextCursor?: string\n } }> {\n return this.client.request(\"GET\", root, { query: options })\n }\n\n get(id: string, options: { detail?: \"summary\" | \"full\"; shotId?: string } = {}): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"GET\", path(id), { query: { detail: options.detail, shot_id: options.shotId } })\n }\n\n validatePlan(plan: StudioDocumentJson): Promise<{ data: { valid: boolean; errors: StudioDocumentJson[]; warnings: StudioDocumentJson[]; summary?: StudioDocumentJson } }> {\n return this.client.request(\"POST\", `${root}/validate`, { body: { plan } })\n }\n\n create(input: { name?: string; plan?: StudioDocumentJson }): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", root, { body: input })\n }\n\n /** Import a portable document through the compatible server writer.\n * Retained frame media requires an authorized source; acceptance never transfers. */\n importBundle(input: { bundle: StudioDocumentJson; projectId?: string }): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", `${root}/import-bundle`, { body: input })\n }\n\n /** Append a bundle's scenes and frame closure under an exact destination revision. */\n appendBundle(id: string, input: { bundle: StudioDocumentJson; expectedVersion: number;\n afterShotId?: string; applyFilm?: boolean }): Promise<{ data: {\n production: StudioProductionRecord; importedShotIds: string[]; importedKeyframeIds: string[];\n } }> {\n return this.client.request(\"POST\", `${path(id)}/import-bundle`, { body: input })\n }\n\n /** Copy a saved production. Linked copies retain verified inputs, remap\n * dependencies and require fresh frame acceptance; they start no media jobs. */\n clone(id: string, input: { name?: string; projectId?: string; expectedVersion?: number } = {}): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", `${path(id)}/clone`, { body: input })\n }\n\n edit(id: string, input: StudioEditInput): Promise<{ data: StudioProductionReply & { version: number; rebased: boolean; receipts: StudioDocumentJson[] } }> {\n return this.client.request(\"POST\", `${path(id)}/ops`, { body: input })\n }\n\n /** Audience-authorized sharing; an expected revision prevents publication\n * of concurrent edits the caller has not reviewed. */\n setShared(id: string, input: { shared: boolean; allowEditableCopy?: boolean; expectedVersion?: number }): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", `${path(id)}/share`, { body: input })\n }\n\n /** Save ordinary editor fields against the loaded revision. Protected frame\n * and job state can only change through their dedicated semantic actions. */\n saveEditorState(id: string, input: { expectedVersion: number; graph: object; clientRequestId?: string }) {\n return this.edit(id, {\n baseVersion: input.expectedVersion, strict: true,\n ...(input.clientRequestId ? { clientRequestId: input.clientRequestId } : {}),\n ops: [{ op: \"save_editor_state\", expectedVersion: input.expectedVersion, graph: input.graph }],\n })\n }\n\n generateKeyframe(id: string, input: StudioKeyframeGenerationInput): Promise<{ data: Exclude<StudioGenerationReply, { dryRun: true }> }> {\n return this.client.request(\"POST\", `${path(id)}/generate`, { body: { ...input, kind: \"keyframe\" } })\n }\n\n generateShot(id: string, input: StudioShotGenerationInput): Promise<{ data: StudioGenerationReply }> {\n return this.client.request(\"POST\", `${path(id)}/generate`, { body: input })\n }\n\n /** A separate explicit review action; generation never calls this method. */\n acceptKeyframe(id: string, input: StudioKeyframeAcceptanceInput,\n concurrency: Pick<StudioEditInput, \"baseVersion\" | \"strict\" | \"clientRequestId\"> = {}) {\n return this.edit(id, { ...concurrency, ops: [{ ...input, op: \"accept_keyframe_result\" }] })\n }\n\n reconcile(id: string): Promise<{ data: StudioProductionReply & { landed: string[]; pending: string[]; failed: string[]; version: number } }> {\n return this.client.request(\"POST\", `${path(id)}/reconcile`, { body: {} })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/resources/studio-productions.ts","../src/resources/studio.ts"],"names":["res","StudioPreviewUnavailable","StudioPreviewAppliedError"],"mappings":"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","file":"chunk-4WOT5OAY.cjs","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { StudioPreviewAppliedError, StudioPreviewUnavailable } from \"../errors.js\"\n\n/**\n * Studio productions — `/v1/studio/productions`.\n *\n * A production is a Nodaro workflow whose `settings.studio` holds the shots:\n * each shot a framed still, an optional animated clip, and the plan, looks,\n * cast bindings and voice that made them. These routes are the platform's own\n * reader and writer of that document, so an agent, a script and the studio app\n * are looking at ONE production rather than three opinions about one row.\n *\n * Two rules run through the whole surface:\n *\n * - **Every change is an OPERATION** ({@link StudioProductionsResource.ops}),\n * addressed by stable key — a shot id, a role slug, a result's job id or url\n * — and never by position. That is what lets two writers hold the same\n * production open: a batch composed against a slightly older version still\n * applies correctly to the newest one, and the response says whether it was\n * rebased.\n * - **Generation is run-then-poll.** A still or clip run returns job ids and\n * records a marker on the production; the results land when anyone — your\n * poll, the app, a later {@link StudioProductionsResource.reconcile} —\n * reports the finished job. Nothing waits minutes inside a request.\n *\n * Reads are `detail: \"summary\"` by default (counts and the active urls);\n * `detail: \"full\"` adds every result with the context that regenerates it.\n *\n * **The ENVELOPES are typed here; the production DOCUMENT is not.** A view, a\n * summary, a shot and an operation are open JSON on this surface\n * ({@link StudioProduction}, `ops: unknown[]`) — their field-level types ship\n * with the studio app, which is the one consumer that narrows them, and a\n * second spelling of that vocabulary in the SDK would drift from it the first\n * time either grew. Everything a caller branches on — `version`, `rebased`,\n * `receipts`, `warnings`, a quote's `credits`, a run's `jobIds` — is typed.\n *\n * Cloud edition only: these routes 404 on deployments that do not serve them.\n * Feature-detect once with `list()` — a deployment without them 404s that too,\n * where a deployment with them answers an empty page.\n */\n\n/**\n * A production, a summary, a shot, a receipt's target: open JSON.\n *\n * Deliberately not narrowed here — see the note at the top of this module.\n */\nexport type StudioProduction = Record<string, unknown>\n\n/** How much of a production a read returns. */\nexport type StudioProductionDetail = \"summary\" | \"full\"\n\n/** One thing wrong with a plan, addressed at the field that is wrong. */\nexport interface StudioPlanIssue {\n path: string\n message: string\n hint?: string\n}\n\n/** `GET …/skill` — the authoring skill, rendered at request time from what is live. */\nexport interface StudioSkillResponse {\n /** The authoring guide. */\n skill: string\n /** Every picker, model and enum, in full. */\n catalog: string\n /** The strict JSON Schema a plan is validated against. */\n schema: Record<string, unknown>\n /** The operating guide: the tool map, the loops, the rules. */\n operating: string\n /** The versions the three were rendered from — bare semver, no package names. */\n generatedFrom: { prompts: string; shared: string; codec: string }\n}\n\nexport interface StudioValidatePlanResponse {\n valid: boolean\n errors: StudioPlanIssue[]\n warnings: StudioPlanIssue[]\n summary?: {\n name?: string\n scenes: number\n shots: number\n cast: number\n /** Cast entries that matched a row in the caller's library. */\n bound: number\n }\n}\n\nexport interface StudioListProductionsResponse {\n data: StudioProduction[]\n nextCursor?: string\n}\n\n/** What a create or an import did, in the words a receipt would use. */\nexport interface StudioImportSummary {\n shotsAdded: number\n castEnrolled: number\n /** Cast entries that resolved to a row in the caller's library. */\n castBound: number\n}\n\nexport interface StudioProductionResponse {\n production: StudioProduction\n warnings?: StudioPlanIssue[]\n summary?: StudioImportSummary\n}\n\nexport interface StudioCreateProductionRequest {\n name?: string\n plan?: Record<string, unknown>\n}\n\n/** The caller's own retry token — 8–128 chars of `A-Za-z0-9_.:-`, never derived. */\nexport type StudioClientRequestId = string\n\n/**\n * A batch of operations, applied atomically.\n *\n * `ops` is `unknown[]`: the operation union is the studio app's vocabulary and\n * the route validates it, refusing the whole batch with the offending index.\n * The served operating guide is the runtime reference for what an operation\n * looks like.\n */\nexport interface StudioOpsRequest {\n /** Applied in order. At most 100 per request. */\n ops: unknown[]\n /**\n * The version the batch was composed against. INFORMATIONAL by default: the\n * operations address by stable KEY, so a batch built on a slightly older\n * document still applies exactly to the newest one, and the response says\n * `rebased: true`. Omitting it means \"apply to whatever is there\".\n */\n baseVersion?: number\n /**\n * Refuse to rebase. With `strict: true` a `baseVersion` older than the stored\n * one is a 409 `workflow_conflict` carrying the current production, instead\n * of a rebased apply — for the rare \"replace exactly what I read\" intent.\n */\n strict?: boolean\n /** Your own token for this batch, so a transport retry is not applied twice. */\n clientRequestId?: StudioClientRequestId\n}\n\n/**\n * What else an operation touched — the work that now has to follow it.\n *\n * Reported by the operations whose effect reaches past the thing they name: a\n * frame review re-opens every frame derived from it and every shot bound to\n * those, a sequence fork mints a whole parallel set. Both lists are always\n * present and either may be empty; ids, never counts, because the caller's job\n * is to go and refresh THOSE.\n */\nexport interface StudioOpsImpact {\n /** Planned frames the operation reaches, the named one first. */\n keyframeIds: string[]\n /** Shots bound to any of those frames. */\n shotIds: string[]\n}\n\n/**\n * A sentence as data: the id of the template a client words it from, and the\n * values that fill the template's slots.\n *\n * It travels beside the English wording, never instead of it. A client that\n * words the sentence in the person's language builds it from `template` and\n * `vars`, and shows the English wording whenever it has no wording for\n * `template` or `vars` does not fill it — so a template id it has never heard of\n * costs nothing. A template id is permanent: a change to its slots or its\n * meaning ships as a new id.\n */\nexport interface StudioOpsText {\n /** The template's id. */\n template: string\n /** What fills the template's slots, by slot name. */\n vars: Record<string, string | number>\n}\n\n/**\n * One line of what an operation did, in the words a change log would use.\n *\n * Past tense, the target named the way the user sees it, the side effect in a\n * trailing parenthetical: `Deleted take 2 of Shot 1 (in the bin).`\n */\nexport interface StudioOpsReceipt {\n /** The operation this line reports, by name. */\n op: string\n /** Past tense, naming the target the way a person would. */\n summary: string\n /**\n * `summary` as data, for a client that words receipts in the person's\n * language. `summary` is always present and always English; read `detail`\n * only when you have wording for its template, and show `summary` when you do\n * not. Absent when the studio service that answered predates it.\n */\n detail?: StudioOpsText\n /** Ids the operation MINTED — never ids the caller supplied. */\n ids?: string[]\n /**\n * The dependency scope, where the operation reports one — absent for the\n * many that touch only what they name. The route projects a receipt ONCE for\n * both answers, so this reads the same on an apply and on a preview.\n */\n impact?: StudioOpsImpact\n}\n\n/** What a batch produced. Adopt `production` whole; do not merge into it. */\nexport interface StudioOpsResponse {\n /** The canonical production AFTER the batch. */\n production: StudioProduction\n /** The version the batch produced. Carry it as the next `baseVersion`. */\n version: number\n /** True when the batch was applied to a newer document than it named. */\n rebased: boolean\n /** One per operation, in order. */\n receipts: StudioOpsReceipt[]\n /**\n * Things worth saying that are not failures — an operation that changed\n * nothing, a rename that rewrote four prompts. A warning never rejects a\n * batch; a refusal does.\n */\n warnings: string[]\n /**\n * `warnings` as data, by position: entry `i` words `warnings[i]`, and `null`\n * means that warning has no wording but the English one. The service sends it\n * only when it is exactly as long as `warnings`, so treat a list of any other\n * length as absent. Absent too when the studio service that answered predates\n * it.\n */\n warningDetails?: Array<StudioOpsText | null>\n}\n\n/**\n * An operation's confirmation class — the vocabulary's own four letters.\n *\n * `S` safe · `D` delete · `P` changes who can reach the work · `$` spends\n * credits. The table that assigns them ships with the production codec and is\n * pinned complete over the operation union there; this is the wire's spelling\n * of its values, not a second table.\n */\nexport type StudioOpClass = \"S\" | \"D\" | \"P\" | \"$\"\n\n/**\n * One line of what an operation WOULD do, for a person deciding whether to let\n * it. Everything {@link StudioOpsReceipt} says — the same summary, the same ids\n * and the same {@link StudioOpsImpact}, read in the conditional — plus the two\n * things the decision turns on and only a preview needs: which kind of change\n * it is, and whether it can be taken back.\n */\nexport interface StudioOpsDryRunReceipt extends StudioOpsReceipt {\n /**\n * The confirmation class, read out of the operation vocabulary's own table:\n * `S` safe, `D` deletes, `P` changes who can reach the work, `$` spends\n * credits. Narrow rather than open, because it is what a caller branches on\n * — a rule like \"never a `D` without asking\" is only writable if the\n * compiler knows the letters.\n */\n class: StudioOpClass\n /**\n * Present, and always `true`, when this operation put something in the bin\n * that can be brought back. ABSENT is the honest answer for everything else,\n * including a delete that destroys: there is no entry to name, so there is no\n * promise to make. Read it as `restorable ?? false`, never as `!restorable`\n * meaning \"kept\".\n */\n restorable?: true\n}\n\n/**\n * What a batch WOULD do. Nothing was written: there is no production here and\n * no new version, because none was produced.\n */\nexport interface StudioOpsDryRunResponse {\n /** Always present, and the marker the two-request protocol reads. */\n dryRun: true\n /** The version the preview was computed against. */\n version: number\n /** One per operation, in order. */\n receipts: StudioOpsDryRunReceipt[]\n /** The same things an apply would have said. */\n warnings: string[]\n /** The same data behind them an apply would have sent: see {@link StudioOpsResponse.warningDetails}. */\n warningDetails?: Array<StudioOpsText | null>\n}\n\n/** What landing the finished jobs did. */\nexport interface StudioReconcileResponse {\n /** Job ids whose media is now on the production. */\n landed: string[]\n /** Job ids still running — their markers stay; call again later. */\n pending: string[]\n /** Job ids that failed or were cancelled; their markers are cleared. */\n failed: string[]\n /** One line per landing that had something to say. */\n warnings: string[]\n /** The production after the landings. */\n production: StudioProduction\n /** Its version — unchanged when nothing landed. */\n version: number\n}\n\n/** `POST …/:id/describe` — a Director run that will land as scenes. */\nexport interface StudioDescribeRequest {\n brief: string\n llmModel: string\n /** `\"append\"` adds the drafted scenes; `\"replace\"` rewrites the film. */\n mode?: \"append\" | \"replace\"\n label?: string\n clientRequestId?: StudioClientRequestId\n}\n\n/**\n * `POST …/:id/generate` — one framing or directing run for one shot.\n *\n * `overrides` is what the CALL owns over what the shot's plan says: the model,\n * the prose, the aspect, the direction ids. Open JSON, because the request\n * builders' own option types are the contract and they ship with the studio.\n */\nexport interface StudioGenerateRequest {\n kind: \"still\" | \"clip\"\n shotId: string\n /** Candidates to fan out (stills); the builder clamps it to the catalog's range. */\n count?: number\n /**\n * The directing input mode for a clip; absent ⇒ derived from the scene's saved\n * inputs (a pinned end frame included). `start` sends ONLY the start frame;\n * `start-end` sends the start and the end frame.\n */\n mode?: \"start\" | \"start-end\" | \"references\"\n /** Price the run and return; nothing is submitted and nothing is written. */\n dryRun?: boolean\n clientRequestId?: StudioClientRequestId\n overrides?: Record<string, unknown>\n}\n\n/** Which video route a directing run went to — chosen from the inputs, never asked for. */\nexport type StudioVideoLane = \"generate-video\" | \"text-to-video\"\n\n/** `dryRun: true` — what this run would cost, and nothing else. */\nexport interface StudioGenerateEstimate {\n dryRun: true\n provider: string\n count: number\n /** `null` when the model is unpriced or the instance runs without credits. */\n credits: number | null\n lane?: StudioVideoLane\n}\n\n/**\n * A started (or already-started) run.\n *\n * `deduped` means the same `clientRequestId` came back and the job ids were\n * answered from the production's own markers — nothing was submitted and\n * nothing was charged, so `production` is absent.\n */\nexport interface StudioGenerateResponse {\n jobIds: string[]\n lane?: StudioVideoLane\n deduped?: true\n production?: StudioProduction\n receipts?: StudioOpsReceipt[]\n warnings?: string[]\n}\n\n/** `POST …/:id/frame` — a still pulled out of the shot's clip. */\nexport interface StudioFrameRequest {\n shotId: string\n mode?: \"first\" | \"last\" | \"timestamp\"\n /** Seconds, when `mode` is `\"timestamp\"`. */\n timestamp?: number\n /** Where the grabbed image lands. `\"new-shot\"` inserts a shot after this one. */\n target?: \"new-shot\" | \"start-frame\" | \"end-frame\" | \"still\"\n clientRequestId?: StudioClientRequestId\n}\n\n/** `POST …/:id/voice` — synthesize a shot's spoken line and record it. */\nexport interface StudioVoiceRequest {\n shotId: string\n text: string\n voiceId?: string\n voiceType?: \"premade\" | \"custom\" | \"library\"\n ttsProvider?: string\n /** The delivery levers; the text-to-speech route owns their bounds. */\n delivery?: Record<string, number>\n clientRequestId?: StudioClientRequestId\n}\n\n/** `POST …/:id/revoice` — recast the voices of the shot's active clip. */\nexport interface StudioRevoiceRequest {\n shotId: string\n /** The speaker-ordered recast plan, forwarded to the voice route verbatim. */\n plan: Record<string, unknown>\n clientRequestId?: StudioClientRequestId\n}\n\n/** `POST …/:id/music` — the film's soundtrack. */\nexport interface StudioMusicRequest {\n prompt: string\n duration?: number\n instrumental?: boolean\n vocalGender?: string\n model?: string\n clientRequestId?: StudioClientRequestId\n}\n\n/**\n * What a route that finished its work answers with: the production as it now\n * stands, plus whatever that route produced.\n *\n * `jobId` is present on the routes that only STARTED something (a revoice, a\n * soundtrack, a draft) — the result lands through its marker.\n */\nexport interface StudioMediaResponse {\n production: StudioProduction\n /** The grabbed frame's url, on the frame route. */\n url?: string\n jobId?: string\n receipts?: StudioOpsReceipt[]\n warnings?: string[]\n}\n\n/**\n * `GET …/:id/export-plan` — the ordered steps an export would run.\n *\n * The caller runs them with the verbs that already exist; a route that chained\n * three minutes-long jobs is the long-lived request every client times out on.\n */\nexport interface StudioExportPlanResponse {\n /** False when the production has fewer than two clips — nothing to stitch. */\n canExport: boolean\n steps: StudioExportStep[]\n /** The step whose output IS the film, or `null` when nothing can run. */\n resultStepId: string | null\n /** Total credits, or `null` when ANY step is unpriced (a partial sum understates). */\n estimate: number | null\n /** The credit models with no price, each named once, in step order. */\n unpriced: string[]\n}\n\nexport interface StudioExportStep {\n /** Stable within one plan and derived from the production, never minted. */\n id: string\n label: string\n /** The node this step runs — `merge-video-audio`, `combine-videos`, `video-upscale`. */\n node: string\n creditModel: string\n credits: number | null\n params: Record<string, unknown>\n}\n\n/** `POST …/:id/clone` — a copy, which always starts private and visible. */\nexport interface StudioCloneRequest {\n name?: string\n}\n\n/** Either arm of a generation reply: the quote, or the run that started. */\nexport type StudioGenerateResult = StudioGenerateEstimate | StudioGenerateResponse\n\n/** True when a generation reply is the `dryRun` QUOTE rather than a started run. */\nexport function isStudioGenerateEstimate(\n result: StudioGenerateResult,\n): result is StudioGenerateEstimate {\n return (result as StudioGenerateEstimate).dryRun === true\n}\n\n/** What a `generateStill` / `generateClip` call decides, beyond `kind` and the shot. */\nexport type StudioGenerateOptions = Omit<StudioGenerateRequest, \"kind\" | \"shotId\">\n\n/**\n * A route that only STARTED something — a draft, a revoice, a soundtrack. Its\n * `jobId` is always there, which is what makes `const { jobId } = await …` and\n * a poll the honest next line.\n *\n * `StudioMediaResponse` leaves `jobId` optional because the routes that FINISH\n * their work (a frame, a voiceover) share the shape and have no job to name.\n */\nexport type StudioJobStartedResponse = StudioMediaResponse & { jobId: string }\n\nexport interface ListStudioProductionsOptions {\n limit?: number\n /** From a previous page's `nextCursor`. */\n cursor?: string\n /** Include the rows the dashboard hides. Off by default. */\n includeArchived?: boolean\n}\n\nexport interface GetProductionOptions {\n detail?: StudioProductionDetail\n /** Read ONE shot — the cheap way to re-read after a generation. */\n shotId?: string\n}\n\nexport interface StudioExportPlanOptions {\n /** Plan the 4K finish too. Expensive, so it is always explicit. */\n upscale?: boolean\n}\n\n/** `client.studio.productions` — see the note at the top of this module. */\nexport class StudioProductionsResource {\n constructor(private client: NodaroClientCore) {}\n\n private path(productionId: string, suffix = \"\"): string {\n return `/v1/studio/productions/${encodeURIComponent(productionId)}${suffix}`\n }\n\n // ── reads ────────────────────────────────────────────────────────────────\n\n /**\n * The authoring guide, the full catalog, the plan's JSON Schema and the\n * operating guide — rendered server-side from the version that is live, so\n * they describe the platform you are actually talking to. Free.\n */\n async skill(): Promise<StudioSkillResponse> {\n const res = await this.client.request<{ data: StudioSkillResponse }>(\n \"GET\",\n \"/v1/studio/productions/skill\",\n )\n return res.data\n }\n\n /**\n * Check a plan before it becomes anything. Free, persists nothing, and\n * resolves cast names against YOUR library — loop on `errors` until\n * `valid: true`, then `create({ plan })`.\n */\n async validatePlan(plan: Record<string, unknown>): Promise<StudioValidatePlanResponse> {\n const res = await this.client.request<{ data: StudioValidatePlanResponse }>(\n \"POST\",\n \"/v1/studio/productions/validate\",\n { body: { plan } },\n )\n return res.data\n }\n\n /** Your productions, newest first. Archived rows are hidden unless asked for. */\n async list(opts: ListStudioProductionsOptions = {}): Promise<StudioListProductionsResponse> {\n const res = await this.client.request<{ data: StudioListProductionsResponse }>(\n \"GET\",\n \"/v1/studio/productions\",\n {\n query: {\n limit: opts.limit,\n cursor: opts.cursor,\n includeArchived: opts.includeArchived,\n },\n },\n )\n return res.data\n }\n\n /**\n * One production. A pure read — it never lands a finished job, so call\n * {@link reconcile} first if you are waiting on one.\n */\n async get(\n productionId: string,\n opts: GetProductionOptions = {},\n ): Promise<StudioProduction> {\n const res = await this.client.request<{ data: { production: StudioProduction } }>(\n \"GET\",\n this.path(productionId),\n { query: { detail: opts.detail, shot_id: opts.shotId } },\n )\n return res.data.production\n }\n\n /**\n * The ordered steps that assemble the film, with what they will cost. Run\n * them yourself with the ordinary verbs — nothing here blocks for minutes,\n * and nothing here spends.\n */\n async exportPlan(\n productionId: string,\n opts: StudioExportPlanOptions = {},\n ): Promise<StudioExportPlanResponse> {\n const res = await this.client.request<{ data: StudioExportPlanResponse }>(\n \"GET\",\n this.path(productionId, \"/export-plan\"),\n { query: { upscale: opts.upscale } },\n )\n return res.data\n }\n\n // ── writes ───────────────────────────────────────────────────────────────\n\n /** A new production, optionally landed from a plan in the same call. */\n async create(input: StudioCreateProductionRequest = {}): Promise<StudioProductionResponse> {\n const res = await this.client.request<{ data: StudioProductionResponse }>(\n \"POST\",\n \"/v1/studio/productions\",\n { body: input },\n )\n return res.data\n }\n\n /**\n * Apply a batch of operations. Atomic: one bad operation refuses the whole\n * batch with a `StudioOpError` naming its index, and nothing is written. On\n * success adopt `production` wholesale and carry `version` forward as the\n * next `baseVersion`.\n *\n * `dryRun: true` — the LITERAL, which is what selects the preview reply —\n * asks what the batch would do, so a person can approve an assistant's edits\n * before they land. Spell it in THIS call's own object literal: a flag passed\n * through a variable widens `true` to `boolean`, which selects the apply\n * overload while the runtime still takes the preview path.\n *\n * A preview is TWO requests, deliberately. The route's body is parsed in\n * strip mode, so a deployment that predates the preview drops the flag and\n * APPLIES the batch: a caller that sent its batch and read the answer\n * afterwards would already have written it. So the flag is proved on an EMPTY\n * batch first and the real batch goes only when that answer carries the\n * marker. An older deployment either answers the apply shape — this throws\n * `StudioPreviewUnavailable`, and the batch never leaves — or refuses the\n * empty batch with its own error, which is passed through as it stands.\n *\n * The ping proves the deployment that answered IT, and a fleet mid-rollout\n * can serve the second request from another one. So the second answer is\n * checked too: when the batch came back APPLIED, this throws\n * `StudioPreviewAppliedError`, which carries that write. The SDK cannot\n * un-send a request; what it can do is refuse to call the result a preview.\n *\n * An apply stays exactly one request.\n */\n ops(\n productionId: string,\n input: StudioOpsRequest & { dryRun: true },\n ): Promise<StudioOpsDryRunResponse>\n ops(productionId: string, input: StudioOpsRequest): Promise<StudioOpsResponse>\n async ops(\n productionId: string,\n input: StudioOpsRequest & { dryRun?: true },\n ): Promise<StudioOpsResponse | StudioOpsDryRunResponse> {\n if (input.dryRun !== true) {\n const res = await this.client.request<{ data: StudioOpsResponse }>(\n \"POST\",\n this.path(productionId, \"/ops\"),\n { body: input },\n )\n return res.data\n }\n\n // The ping carries nothing of the caller's batch, because an old deployment\n // takes whatever it is sent at face value; an empty batch with no\n // `clientRequestId` spends neither the caller's operations nor the retry\n // token that would make a real batch unrepeatable.\n const ping = await this.client.request<{ data?: { dryRun?: unknown } } | undefined>(\n \"POST\",\n this.path(productionId, \"/ops\"),\n { body: { ops: [], dryRun: true } },\n )\n // Read through: an older deployment can answer no envelope at all, or a 204\n // that `request` reads as `undefined`. Absent is a \"no\" like any other, and\n // the caller who catches `NodaroError` should not get a `TypeError`.\n if (ping?.data?.dryRun !== true) throw new StudioPreviewUnavailable()\n\n const res = await this.client.request<\n { data?: StudioOpsDryRunResponse | StudioOpsResponse } | undefined\n >(\"POST\", this.path(productionId, \"/ops\"), { body: input })\n // The answer that matters most: this request may have landed on a different\n // deployment from the ping, and an applied batch is not a preview.\n const data = res?.data\n if ((data as { dryRun?: unknown } | undefined)?.dryRun !== true) {\n throw new StudioPreviewAppliedError(data as StudioOpsResponse)\n }\n return data as StudioOpsDryRunResponse\n }\n\n /**\n * Land every generation that has finished since you last looked, and report\n * what is still running. The one call that turns finished jobs into results\n * without a browser open. It writes only when something actually landed.\n */\n async reconcile(productionId: string): Promise<StudioReconcileResponse> {\n const res = await this.client.request<{ data: StudioReconcileResponse }>(\n \"POST\",\n this.path(productionId, \"/reconcile\"),\n )\n return res.data\n }\n\n /** Add a plan's scenes to a production that already exists. */\n async importPlan(\n productionId: string,\n plan: Record<string, unknown>,\n opts: { mode?: \"append\" } = {},\n ): Promise<StudioProductionResponse> {\n const res = await this.client.request<{ data: StudioProductionResponse }>(\n \"POST\",\n this.path(productionId, \"/import\"),\n { body: { plan, mode: opts.mode ?? \"append\" } },\n )\n return res.data\n }\n\n /**\n * Turn a brief into scenes. The run is a platform job: poll it, and its\n * scenes land through {@link reconcile}. The production comes back with the\n * run recorded on it as a pending draft.\n */\n async describe(\n productionId: string,\n input: StudioDescribeRequest,\n ): Promise<StudioJobStartedResponse> {\n const res = await this.client.request<{ data: StudioJobStartedResponse }>(\n \"POST\",\n this.path(productionId, \"/describe\"),\n { body: input },\n )\n return res.data\n }\n\n // ── generation ───────────────────────────────────────────────────────────\n\n /**\n * Frame or animate one shot.\n *\n * The request is assembled server-side from the shot's own plan, looks and\n * bound references, so a scripted run and a press of the button in the app\n * produce the same media; `overrides` changes THIS run without changing the\n * shot. Prefer {@link generateStill} / {@link generateClip}, which say which\n * kind they mean.\n *\n * `dryRun: true` returns the quote and writes nothing — narrow the reply with\n * {@link isStudioGenerateEstimate}.\n */\n generate(\n productionId: string,\n input: StudioGenerateRequest & { dryRun: true },\n ): Promise<StudioGenerateEstimate>\n generate(\n productionId: string,\n input: StudioGenerateRequest,\n ): Promise<StudioGenerateResult>\n async generate(\n productionId: string,\n input: StudioGenerateRequest,\n ): Promise<StudioGenerateResult> {\n const res = await this.client.request<{ data: StudioGenerateResult }>(\n \"POST\",\n this.path(productionId, \"/generate\"),\n { body: input },\n )\n return res.data\n }\n\n /**\n * Frame a shot: submit `count` candidates and record a pending marker for\n * each. Results ACCUMULATE — a generate never replaces what is there.\n *\n * `clientRequestId` makes a retry safe: the same token answers with the jobs\n * the first call started (`deduped: true`) and submits nothing. Never retry a\n * spend without it.\n */\n generateStill(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions & { dryRun: true },\n ): Promise<StudioGenerateEstimate>\n generateStill(\n productionId: string,\n shotId: string,\n opts?: StudioGenerateOptions,\n ): Promise<StudioGenerateResult>\n generateStill(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions = {},\n ): Promise<StudioGenerateResult> {\n return this.generate(productionId, { ...opts, kind: \"still\", shotId })\n }\n\n /**\n * Animate a shot. The LANE is chosen from the shot's inputs (a start frame,\n * references, a prompt) — never passed in — and reported back as `lane`.\n */\n generateClip(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions & { dryRun: true },\n ): Promise<StudioGenerateEstimate>\n generateClip(\n productionId: string,\n shotId: string,\n opts?: StudioGenerateOptions,\n ): Promise<StudioGenerateResult>\n generateClip(\n productionId: string,\n shotId: string,\n opts: StudioGenerateOptions = {},\n ): Promise<StudioGenerateResult> {\n return this.generate(productionId, { ...opts, kind: \"clip\", shotId })\n }\n\n // ── media on one shot ────────────────────────────────────────────────────\n\n /**\n * Extract a frame from a shot's active clip and put it where `target` says —\n * a new shot after this one (the default), this shot's sticky start or end\n * frame, or another still of the same shot. Seconds, not minutes: this one\n * waits for the job and answers with the changed production.\n */\n async frame(\n productionId: string,\n input: StudioFrameRequest,\n ): Promise<StudioMediaResponse> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/frame\"),\n { body: input },\n )\n return res.data\n }\n\n /** Synthesize a shot's spoken line and record it. Waits for the job. */\n async voice(\n productionId: string,\n input: StudioVoiceRequest,\n ): Promise<StudioMediaResponse> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/voice\"),\n { body: input },\n )\n return res.data\n }\n\n /**\n * Recast the voices of a shot's active clip. Minutes of work, so it answers\n * `jobId` and the new clip lands as a result through its own marker.\n */\n async revoice(\n productionId: string,\n input: StudioRevoiceRequest,\n ): Promise<StudioJobStartedResponse> {\n const res = await this.client.request<{ data: StudioJobStartedResponse }>(\n \"POST\",\n this.path(productionId, \"/revoice\"),\n { body: input },\n )\n return res.data\n }\n\n /** Score the film. The finished track lands through its pending marker. */\n async music(\n productionId: string,\n input: StudioMusicRequest,\n ): Promise<StudioJobStartedResponse> {\n const res = await this.client.request<{ data: StudioJobStartedResponse }>(\n \"POST\",\n this.path(productionId, \"/music\"),\n { body: input },\n )\n return res.data\n }\n\n // ── audience and copies ──────────────────────────────────────────────────\n\n /**\n * Open the share-by-link read. Deliberately its own route rather than an\n * operation: who may see the work is decided by the owner, never as a side\n * effect of a batch that was editing something else.\n */\n async share(productionId: string): Promise<StudioProduction> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/share\"),\n { body: { shared: true } },\n )\n return res.data.production\n }\n\n /** Close it again. Sharing is opt-in AND reversible. */\n async unshare(productionId: string): Promise<StudioProduction> {\n const res = await this.client.request<{ data: StudioMediaResponse }>(\n \"POST\",\n this.path(productionId, \"/unshare\"),\n )\n return res.data.production\n }\n\n /**\n * Copy a production you own or can see into your own Studio project. The\n * copy starts PRIVATE and visible — sharing and archiving never travel — and\n * it is copied through YOUR view of the source, so somebody else's bin does\n * not come with it.\n */\n async clone(\n productionId: string,\n input: StudioCloneRequest = {},\n ): Promise<StudioProduction> {\n const res = await this.client.request<{ data: { production: StudioProduction } }>(\n \"POST\",\n this.path(productionId, \"/clone\"),\n { body: input },\n )\n return res.data.production\n }\n}\n\n","import type { NodaroClientCore } from \"../core.js\"\nimport { StudioProductionsResource } from \"./studio-productions.js\"\nexport * from \"./studio-productions.js\"\n\n/** Public response/transport contracts only; document validation and planning\n * remain in the private Studio codec on the server. */\nexport type StudioDocumentJson = Record<string, unknown>\n\nexport interface StudioProductionCapabilities {\n planVersions: number[]\n operations: {\n readKeyframes: boolean\n saveEditorState?: boolean\n editableSharedCopies?: boolean\n revisionedSharing?: boolean\n cloneLinkedProductions?: boolean\n importPlannedBundles?: boolean\n importLinkedBundles?: boolean\n appendPlannedBundles?: boolean\n appendLinkedBundles?: boolean\n editKeyframes: boolean\n generateKeyframes: boolean\n acceptKeyframes: boolean\n rejectKeyframes?: boolean\n editSequencePlans?: boolean\n generateLinkedClips: boolean\n retakeLinkedClips?: boolean\n /** The host keeps a scene's empty media slots. */\n mediaSlots?: boolean\n /** The host keeps a clip's inputs on its clip slot. */\n clipSlotInputs?: boolean\n }\n sourceFrameReferences: boolean\n automaticAcceptance: false\n unattendedGeneration: false\n}\n\nexport interface StudioKeyframeRecord {\n id: string\n label: string\n revision: number\n nodeId: string\n parentKeyframeId?: string\n previewResultKey: string | null\n previewUrl: string | null\n acceptedResultKey: string | null\n acceptedUrl: string | null\n count: number\n pending: Array<{ jobId: string; startedAt: string }>\n /** Owner-only working state. Recorded acceptance is not an execution grant. */\n plan?: StudioDocumentJson\n acceptance?: StudioDocumentJson\n results?: StudioDocumentJson[]\n}\n\nexport interface StudioProductionRecord {\n id: string\n name: string\n version: number\n updatedAt: string\n thumbnailUrl: string | null\n shared: boolean\n archived: boolean\n requiredCapabilities?: string[]\n keyframes?: StudioKeyframeRecord[]\n sequences?: StudioDocumentJson[]\n shots: StudioDocumentJson[]\n pending: { stills: number; clips: number; keyframes?: number; music: boolean; draft: StudioDocumentJson | null }\n [field: string]: unknown\n}\n\nexport interface StudioProductionReply {\n production: StudioProductionRecord\n capabilities?: StudioProductionCapabilities\n warnings?: unknown[]\n [field: string]: unknown\n}\n\nexport interface StudioEditInput {\n ops: ReadonlyArray<{ op: string; [field: string]: unknown }>\n baseVersion?: number\n strict?: boolean\n clientRequestId?: string\n}\n\nexport interface StudioKeyframeGenerationInput {\n keyframeId: string\n expectedRevision: number\n clientRequestId?: string\n overrides?: StudioDocumentJson\n}\n\nexport interface StudioKeyframeAcceptanceInput {\n keyframeId: string\n expectedRevision: number\n resultKey: string\n expectedAcceptedResultKey: string | null\n requirementChecks: Array<{ requirementId: string; outcome: \"pass\" | \"waived\" }>\n waivedReason?: string\n}\n\nexport interface StudioShotGenerationInput {\n kind: \"still\" | \"clip\"\n shotId: string\n clientRequestId?: string\n count?: number\n mode?: \"start\" | \"start-end\" | \"references\"\n dryRun?: boolean\n /** Linked clips only: require the exact inputs returned by a reviewed quote. */\n expectedInputHash?: string\n /** Retake a native linked take using its original request and retained endpoints. */\n retakeResultKey?: string\n overrides?: StudioDocumentJson\n}\n\nexport type StudioGenerationReply = {\n jobIds: string[]\n production?: StudioProductionRecord\n deduped?: true\n lane?: string\n [field: string]: unknown\n} | {\n dryRun: true; provider: string; count: number; credits: number | null; lane?: string\n /** Linked-clip quotes include normalized settings and accepted endpoint pins. */\n inputHash?: string\n endpointPins?: StudioDocumentJson\n creditIdentifier?: string\n duration?: number\n resolution?: string\n aspectRatio?: string\n sound?: boolean\n}\n\nconst root = \"/v1/studio/productions\"\nconst path = (id: string) => `${root}/${encodeURIComponent(id)}`\n\n/** Cloud plugin routes. Check capabilities before exposing dependency controls.\n * Reads do not reconcile jobs, submit media or accept generated candidates. */\nexport class StudioResource {\n readonly productions: StudioProductionsResource\n\n constructor(private readonly client: NodaroClientCore) {\n this.productions = new StudioProductionsResource(client)\n }\n\n capabilities(): Promise<{ data: StudioProductionCapabilities }> {\n return this.client.request(\"GET\", `${root}/capabilities`)\n }\n\n skill(): Promise<{ data: StudioDocumentJson }> {\n return this.client.request(\"GET\", `${root}/skill`)\n }\n\n list(options: { limit?: number; cursor?: string; includeArchived?: boolean } = {}): Promise<{ data: {\n data: Array<{ id: string; name: string; version: number; updatedAt: string; thumbnailUrl: string | null; shared: boolean; archived: boolean; shotCount: number }>\n nextCursor?: string\n } }> {\n return this.client.request(\"GET\", root, { query: options })\n }\n\n get(id: string, options: { detail?: \"summary\" | \"full\"; shotId?: string } = {}): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"GET\", path(id), { query: { detail: options.detail, shot_id: options.shotId } })\n }\n\n validatePlan(plan: StudioDocumentJson): Promise<{ data: { valid: boolean; errors: StudioDocumentJson[]; warnings: StudioDocumentJson[]; summary?: StudioDocumentJson } }> {\n return this.client.request(\"POST\", `${root}/validate`, { body: { plan } })\n }\n\n create(input: { name?: string; plan?: StudioDocumentJson }): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", root, { body: input })\n }\n\n /** Import a portable document through the compatible server writer.\n * Retained frame media requires an authorized source; acceptance never transfers. */\n importBundle(input: { bundle: StudioDocumentJson; projectId?: string }): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", `${root}/import-bundle`, { body: input })\n }\n\n /** Append a bundle's scenes and frame closure under an exact destination revision. */\n appendBundle(id: string, input: { bundle: StudioDocumentJson; expectedVersion: number;\n afterShotId?: string; applyFilm?: boolean }): Promise<{ data: {\n production: StudioProductionRecord; importedShotIds: string[]; importedKeyframeIds: string[];\n } }> {\n return this.client.request(\"POST\", `${path(id)}/import-bundle`, { body: input })\n }\n\n /** Copy a saved production. Linked copies retain verified inputs, remap\n * dependencies and require fresh frame acceptance; they start no media jobs. */\n clone(id: string, input: { name?: string; projectId?: string; expectedVersion?: number } = {}): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", `${path(id)}/clone`, { body: input })\n }\n\n edit(id: string, input: StudioEditInput): Promise<{ data: StudioProductionReply & { version: number; rebased: boolean; receipts: StudioDocumentJson[] } }> {\n return this.client.request(\"POST\", `${path(id)}/ops`, { body: input })\n }\n\n /** Audience-authorized sharing; an expected revision prevents publication\n * of concurrent edits the caller has not reviewed. */\n setShared(id: string, input: { shared: boolean; allowEditableCopy?: boolean; expectedVersion?: number }): Promise<{ data: StudioProductionReply }> {\n return this.client.request(\"POST\", `${path(id)}/share`, { body: input })\n }\n\n /** Save ordinary editor fields against the loaded revision. Protected frame\n * and job state can only change through their dedicated semantic actions. */\n saveEditorState(id: string, input: { expectedVersion: number; graph: object; clientRequestId?: string }) {\n return this.edit(id, {\n baseVersion: input.expectedVersion, strict: true,\n ...(input.clientRequestId ? { clientRequestId: input.clientRequestId } : {}),\n ops: [{ op: \"save_editor_state\", expectedVersion: input.expectedVersion, graph: input.graph }],\n })\n }\n\n generateKeyframe(id: string, input: StudioKeyframeGenerationInput): Promise<{ data: Exclude<StudioGenerationReply, { dryRun: true }> }> {\n return this.client.request(\"POST\", `${path(id)}/generate`, { body: { ...input, kind: \"keyframe\" } })\n }\n\n generateShot(id: string, input: StudioShotGenerationInput): Promise<{ data: StudioGenerationReply }> {\n return this.client.request(\"POST\", `${path(id)}/generate`, { body: input })\n }\n\n /** A separate explicit review action; generation never calls this method. */\n acceptKeyframe(id: string, input: StudioKeyframeAcceptanceInput,\n concurrency: Pick<StudioEditInput, \"baseVersion\" | \"strict\" | \"clientRequestId\"> = {}) {\n return this.edit(id, { ...concurrency, ops: [{ ...input, op: \"accept_keyframe_result\" }] })\n }\n\n reconcile(id: string): Promise<{ data: StudioProductionReply & { landed: string[]; pending: string[]; failed: string[]; version: number } }> {\n return this.client.request(\"POST\", `${path(id)}/reconcile`, { body: {} })\n }\n}\n"]}
|
|
@@ -217,5 +217,5 @@ Object.defineProperty(exports, "OBJECT_ATTACH_COLUMNS", {
|
|
|
217
217
|
get: function () { return entities.OBJECT_ATTACH_COLUMNS; }
|
|
218
218
|
});
|
|
219
219
|
exports.ObjectsResource = ObjectsResource;
|
|
220
|
-
//# sourceMappingURL=chunk-
|
|
221
|
-
//# sourceMappingURL=chunk-
|
|
220
|
+
//# sourceMappingURL=chunk-57GANTLV.cjs.map
|
|
221
|
+
//# sourceMappingURL=chunk-57GANTLV.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/objects.ts"],"names":[],"mappings":"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","file":"chunk-57GANTLV.cjs","sourcesContent":["import type { ObjectAspectRatio, ObjectAssetType, ObjectAttachColumn } from \"@nodaro/shared/entities\"\nexport type { ObjectAssetType, ObjectAttachColumn, ObjectAspectRatio } from \"@nodaro/shared/entities\"\nexport { OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, OBJECT_ASPECT_OPTIONS, OBJECT_ASPECT_DEFAULTS } from \"@nodaro/shared/entities\"\nimport type { NodaroClientCore } from \"../core.js\"\nimport type { SetKeeperCatalogInput, SetKeeperCatalogResult } from \"./keepers.js\"\nimport type { GenerationSessionParams } from \"./nodes.js\"\n\n/**\n * Re-export the shared `ObjectAssetType` / `ObjectAttachColumn` unions and\n * their runtime tuples so SDK consumers don't have to add `@nodaro/shared` as\n * a second dependency just to typecheck the `assetType` / `attachToColumn`\n * fields. Single source of truth lives in `@nodaro/shared/entity-prompts`.\n *\n * `ObjectAspectRatio` is re-exported alongside them — `generateMotion`'s\n * `aspectRatio` field is the 5-value object enum (1:1 / 3:4 / 16:9 / 9:16 /\n * 4:3) from `@nodaro/shared/object-aspect-defaults`. Distinct from\n * `CharacterAspectRatio` because objects support an extra 4:3 framing for\n * product-showcase shots.\n */\n\n/**\n * Reference-photo kind discriminator — the mood-board roles a user can attach\n * to an object. Mirrors the `reference_photos.kind` field accepted by\n * `backend/src/routes/objects.ts` (the route accepts open strings; this SDK\n * type narrows to the 6 canonical roles surfaced by the Studio). `other` is\n * the free-form bucket.\n */\nexport type ObjectReferencePhotoKind =\n | \"front\"\n | \"side\"\n | \"detail\"\n | \"context\"\n | \"moodBoard\"\n | \"other\"\n\nexport interface ObjectReferencePhoto {\n url: string\n kind: ObjectReferencePhotoKind\n}\n\n/**\n * An object record returned by Nodaro's REST API. Mirrors the camelCase\n * shape produced by `backend/src/routes/objects.ts::toCamel()`.\n *\n * Asset buckets (`angles`, `materials`, `variations`, `motionClips`) are\n * independent JSONB arrays keyed by a human-readable variant name (e.g.\n * `\"front\"`, `\"wood\"`, `\"weathered\"`). Each entry's `url` points at an\n * R2-hosted asset.\n *\n * Identity-foundation fields:\n * - `referencePhotos` — caller-supplied mood-board refs (cap 20). Objects\n * do NOT carry a `piiConsentAt` field (location Phase 2 #7 only).\n * - `canonicalDescription` — ~80–120-word LLM-authored visual caption,\n * populated by `approveMainImage()` / `recaption()`. The wire still sends\n * `\"\"` on caption sub-failure (the breaking wire change is deferred to a\n * major bump), but `get()` normalizes `\"\"` → `null` so consumers see the\n * same `string | null` semantics as characters.\n * - `styleLock` — whether asset gens should anchor to the canonical style\n * captured at approval time. Defaults to `true` on new rows.\n *\n * `Object` shadows the JS global, which TypeScript handles cleanly via\n * local-scope resolution. Consumers who need both can alias as\n * `import type { Object as NodaroObject } from \"@nodaro/sdk\"`.\n */\nexport interface Object {\n id: string\n userId: string\n nodeId: string\n projectId: string | null\n name: string\n description: string | null\n category: string | null\n style: string | null\n sourceImageUrl: string | null\n /** MODEL_CATALOG image-model id the main image was generated with (or `null`).\n * Set on create + editable via the update route. */\n imageProvider: string | null\n angles: Array<{ name: string; url: string }>\n materials: Array<{ name: string; url: string }>\n variations: Array<{ name: string; url: string }>\n motionClips: Array<{ name: string; url: string }>\n /** Named Product Boards — dense reference sheets, one per variant/colorway\n * (the `generate-image/product-board` factory preset rendered from the\n * object's images). A first-class bucket: community publish snapshots it\n * and clone hands the consumer their own copy to extend. Defaults to `[]`.\n * `type` marks an image-collage `\"identity\"` sheet vs a plain `\"looks\"`\n * board; `sourceImages` are the R2 URLs it was collaged from. Both optional\n * + backward-compatible (legacy boards have neither). */\n boards?: Array<{ name: string; url: string; type?: \"looks\" | \"identity\"; sourceImages?: string[] }> | null\n referencePhotos: ObjectReferencePhoto[]\n /** `null` when no caption is set (or the LLM caption sub-failed) — the wire\n * sends `\"\"`, normalized to `null` in `get()` to match character semantics. */\n canonicalDescription: string | null\n styleLock: boolean\n /** The user's chosen DEFAULT asset take per variant (Studio version history).\n * OPAQUE map: key `\"<bucket>:<variant>\"` (e.g. `\"angles:front\"`) → the chosen\n * asset URL (one already present in that bucket). Stored verbatim — keys are\n * NOT normalized; soft-capped server-side at 200 keys / 2048-char values\n * (overflow dropped silently). Defaults to `{}`. */\n selectedAssetByVariant?: Record<string, string> | null\n /** Nodaro Keepers: whether this row is on the shared shelf (`client.keepers`).\n * Admin-set through `setCatalog`; `false` on everyone else's rows and on\n * every copy. Optional on the read surface for older servers. */\n catalog?: boolean\n /** The shelf order (lowest first); `0` when never set. */\n catalogSort?: number\n /** The shelf heading, or `null`. */\n catalogCategory?: string | null\n deletedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\n/**\n * GET /v1/objects/:id may append a `pendingJobs` bucket the studio uses to\n * rehydrate spinners after a reload. Optional on the SDK surface — it doesn't\n * appear on `list()` rows.\n */\nexport interface ObjectDetail extends Object {\n pendingJobs?: Array<{\n jobId: string\n assetType: string\n name: string\n status: string\n }>\n}\n\n/**\n * Body for `client.objects.create()`. Mirrors the INSERT branch of\n * `upsertObjectBody` in `backend/src/routes/objects.ts`. `name` + `nodeId`\n * are required on create.\n */\nexport interface CreateObjectInput {\n nodeId: string\n name: string\n description?: string\n category?: ObjectCategory\n style?: string\n workflowId?: string\n projectId?: string\n sourceImageUrl?: string\n /** Persistent image-model id (a MODEL_CATALOG image model). Validated\n * server-side — unknown / non-image / \"\" is stored as `null`. */\n imageProvider?: string | null\n referencePhotos?: ObjectReferencePhoto[]\n canonicalDescription?: string\n styleLock?: boolean\n /** The user's chosen DEFAULT asset take per variant. OPAQUE\n * `\"<bucket>:<variant>\"` → chosen-URL map; a write REPLACES the whole map.\n * Keys stored verbatim; soft-capped server-side at 200 keys / 2048-char values. */\n selectedAssetByVariant?: Record<string, string>\n}\n\n/**\n * The 10-value Object category enum. Mirrors the literal accepted by\n * `POST /v1/generate-object` and surfaced in the Object Studio category\n * picker. Distinct from location's geography-based set.\n */\nexport type ObjectCategory =\n | \"furniture\"\n | \"vehicle\"\n | \"weapon\"\n | \"food\"\n | \"clothing\"\n | \"electronics\"\n | \"nature\"\n | \"tool\"\n | \"animal\"\n | \"other\"\n\n/**\n * Body for `client.objects.update()`. Mirrors the UPDATE branch of\n * `upsertObjectBody` in `backend/src/routes/objects.ts`.\n *\n * Worker-owned asset buckets (`angles` / `materials` / `variations` /\n * `motionClips`) are deliberately omitted — the route drops them on UPDATE\n * so a Studio auto-save with a stale snapshot cannot clobber the worker's\n * atomic `append_object_asset()` writes.\n *\n * `expectedUpdatedAt` is the optimistic-concurrency token: when present, the\n * UPDATE only succeeds if the row's `updated_at` still matches; on mismatch\n * the route returns 409 so the studio can re-fetch + merge.\n */\nexport interface UpdateObjectInput {\n name?: string\n description?: string\n category?: ObjectCategory\n style?: string\n sourceImageUrl?: string\n /** Persistent image-model id (a MODEL_CATALOG image model). Validated\n * server-side — unknown / non-image / \"\" is stored as `null`. */\n imageProvider?: string | null\n referencePhotos?: ObjectReferencePhoto[]\n canonicalDescription?: string\n styleLock?: boolean\n /** The user's chosen DEFAULT asset take per variant. OPAQUE\n * `\"<bucket>:<variant>\"` → chosen-URL map; a write REPLACES the whole map\n * (omit to leave untouched). Keys stored verbatim; soft-capped server-side\n * at 200 keys / 2048-char values. */\n selectedAssetByVariant?: Record<string, string>\n /** Named Product Boards (see `Object.boards`) — whole-array replace,\n * USER-owned (unlike the worker-owned buckets it flows through UPDATE).\n * Server caps: 24 boards, 200-char names, 30 sourceImages per board. */\n boards?: Array<{ name: string; url: string; type?: \"looks\" | \"identity\"; sourceImages?: string[] }>\n expectedUpdatedAt?: string\n}\n\nexport interface UpdateObjectResult {\n id: string\n updatedAt: string\n}\n\n/**\n * Combined create + update body (parameter for both branches). Exported for\n * callers that want to drive a single `upsert` flow without picking between\n * `Create*` and `Update*`. Mirrors the `upsertObjectBody` Zod schema in\n * `backend/src/routes/objects.ts`. `nodeId` + `name` are required on INSERT;\n * `id` flips the route into UPDATE mode.\n */\nexport interface UpsertObjectInput extends CreateObjectInput {\n id?: string\n expectedUpdatedAt?: string\n}\n\nexport type UpsertObjectResult = { id: string } | UpdateObjectResult\n\nexport interface ListObjectsParams {\n /** When true, return archived objects instead of active ones. */\n archived?: boolean\n /** Optional project filter — server-scoped to the caller's user. */\n projectId?: string\n /**\n * Search words: only the objects whose name or description contains every\n * word (split on spaces, the first 5), in any order, ignoring case. Each\n * word is matched as written (`%`, `_` and `*` are not wildcards;\n * punctuation is kept); blank means no search; up to 200 characters.\n * Combines with the other filters and with `cursor` paging.\n */\n q?: string\n /**\n * Max rows to return (cap 500). OPT-IN: omitted, the server returns the\n * full legacy listing with no `nextCursor`; supplied, the response is one\n * page plus `nextCursor` — keep passing it back until it is `null`.\n */\n limit?: number\n /** Opaque cursor from a prior page's `nextCursor` (fetches the next page). */\n cursor?: string\n}\n\n/**\n * Input for `client.objects.generate()` — fires the\n * `POST /v1/generate-object` route. Produces 1–10 candidate\n * main images; each lands as one `jobs` row in `pending` state and is then\n * enqueued for the worker.\n *\n * When `attachToObjectId` is set AND `count === 1`, the worker writes the\n * resulting URL directly to `objects.source_image_url` on completion —\n * caller doesn't need a separate `approveMainImage` call. Multi-candidate\n * batches MUST go through explicit approval so the user picks the winner.\n *\n * `seedPromptHint` (Pass 7 F-77) flows the parameter-picker's prompt fragment\n * through to the worker so a catalog selection (e.g. \"antique brass lantern\")\n * gets appended to the generated prompt context.\n */\nexport interface GenerateObjectInput extends GenerationSessionParams {\n name: string\n description?: string\n userPrompt?: string\n category?: ObjectCategory\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n sourceImageUrl?: string\n provider?: string\n /** Number of candidate images to generate (1–10; server-validated). */\n count?: number\n /** Auto-attach the result to this object row (single-candidate only). */\n attachToObjectId?: string\n /** Parameter-picker prompt-fragment pass-through. */\n seedPromptHint?: string\n /** Optional name to set on the attached row alongside the main image. */\n attachName?: string\n /** Optimistic-concurrency token for the single-candidate auto-attach path. */\n expectedUpdatedAt?: string\n}\n\n/**\n * `generate()` response — `jobIds` is ALWAYS present (the harmonized contract,\n * matching characters). `jobId` is a deprecated back-compat alias populated only\n * on `count === 1`; prefer `jobIds`. (Will be removed on the next major.)\n */\nexport interface GenerateObjectResult {\n jobIds: string[]\n /** @deprecated count===1 back-compat alias — use `jobIds`. */\n jobId?: string\n}\n\n/**\n * Input for `client.objects.generateAsset()` — fires the\n * `POST /v1/generate-object-asset` route. Produces a single\n * angles / materials / variations / custom variant.\n *\n * When all three studio-path fields are set (`attachToObjectId` +\n * `attachToColumn` + `attachName`), the worker appends\n * `{ name: attachName, url: <result> }` to the named JSONB array column on\n * the user's object row on completion. `attachToColumn` is REQUIRED for\n * `assetType === \"custom\"` — the worker can't infer the bucket from the\n * asset type.\n */\nexport interface GenerateObjectAssetInput extends GenerationSessionParams {\n assetType: ObjectAssetType\n variant: string\n name: string\n description?: string\n userPrompt?: string\n category?: string\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n sourceImageUrl?: string\n provider?: string\n attachToObjectId?: string\n attachToColumn?: ObjectAttachColumn\n attachName?: string\n /** Parameter-picker prompt-fragment pass-through (Pass 7 F-77). */\n seedPromptHint?: string\n}\n\nexport interface GenerateObjectAssetResult {\n jobId: string\n}\n\n/**\n * Input for `client.objects.generateMotion()` — fires the\n * `POST /v1/generate-object-motion` route. Produces a single motion clip\n * (rotation, orbit, hover, drift, etc.) animated FROM a static product-shot\n * image.\n *\n * Mirrors `client.locations.generateMotion()` minus the location-specific\n * atmospheric fields. The route hardcodes the attach column to `motion_clips`\n * — callers supply `attachToObjectId` + `attachName` only.\n *\n * `sourceImageUrl` is REQUIRED — image-to-video needs a source frame and the\n * route has no fallback (no `source_image_url` column to pull from on the\n * objects row at this point in the flow; the studio path supplies the\n * canonical product-shot URL explicitly).\n *\n * Object-specific defaults vs location:\n * - `provider` defaults to `\"kling-turbo\"` (not location's `\"kling\"`)\n * - `aspectRatio` defaults to `\"1:1\"` server-side via\n * `resolveObjectAspectRatio({ assetType: \"motion\" })` — objects are\n * product-showcase framing, not cinematic establishing shots.\n *\n * When the studio path is set (`attachToObjectId` + `attachName`), the\n * worker appends `{ name: attachName, url: <result> }` to the object row's\n * `motion_clips` JSONB column on completion.\n */\nexport interface GenerateObjectMotionInput extends GenerationSessionParams {\n motionPrompt: string\n sourceImageUrl: string\n provider?: string\n name: string\n /** Source clip URL — when set, worker routes to video-to-video refine. */\n refineFromVideoUrl?: string\n category?: string\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n canonicalDescription?: string\n /** Parameter-picker prompt-fragment pass-through (Pass 7 F-77). */\n seedPromptHint?: string\n attachToObjectId?: string\n attachName?: string\n /**\n * Optional aspect ratio override. Defaults to 1:1 server-side. One of the\n * 5-value `ObjectAspectRatio` union (1:1 / 3:4 / 16:9 / 9:16 / 4:3) —\n * objects have their own enum (with 4:3 added) vs the character set.\n */\n aspectRatio?: ObjectAspectRatio\n /**\n * Optional clip duration in seconds. Validated server-side against the chosen\n * provider's allowed durations (e.g. kling 5/10, wan-i2v 5/10/15); omitted →\n * the model's own default (no behavior change). Mirrors generate-video's\n * per-model i2v duration lever.\n */\n duration?: number\n}\n\nexport interface GenerateObjectMotionResult {\n jobId: string\n}\n\nexport interface ApproveObjectMainImageResult {\n sourceImageUrl: string\n /**\n * LLM-authored caption. `null` when the LLM caption sub-failed — the wire\n * sends `\"\"`, normalized to `null` here so consumers see the same\n * `string | null` semantics as characters. The main image is still set; call\n * `recaption()` to retry.\n */\n canonicalDescription: string | null\n}\n\nexport interface RecaptionObjectResult {\n canonicalDescription: string\n}\n\nexport class ObjectsResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * List the caller's objects. By default returns active objects only;\n * pass `archived: true` to fetch soft-deleted rows for an \"archive\" view.\n * Optional `projectId` scopes the result to a single project; `q` keeps the\n * objects whose name or description contains it.\n */\n list(params: ListObjectsParams = {}): Promise<{ objects: Object[]; nextCursor?: string | null }> {\n const query: Record<string, string | undefined> = {}\n if (params.archived) query.archived = \"true\"\n if (params.projectId) query.projectId = params.projectId\n if (params.q) query.q = params.q\n if (params.limit !== undefined) query.limit = String(params.limit)\n if (params.cursor) query.cursor = params.cursor\n return this.client.request(\"GET\", \"/v1/objects\", { query })\n }\n\n /**\n * Convenience wrapper for `list({ archived: true })`. Returns soft-deleted\n * rows so callers can drive a UI \"Archived\" tab without re-encoding the\n * query param.\n *\n * `archived` is omitted from the param type — it's always set to `true` here.\n */\n listArchived(params: Omit<ListObjectsParams, \"archived\"> = {}): Promise<{ objects: Object[]; nextCursor?: string | null }> {\n return this.list({ ...params, archived: true })\n }\n\n /**\n * Fetch a single object including in-flight asset job state. Soft-deleted\n * (archived) rows are NOT returned by id — the route enforces\n * `deleted_at IS NULL` so archived objects 404 (uniform Pass 10 F-90b\n * \"not_found\" — does not leak the deleted vs non-existent distinction).\n */\n async get(id: string): Promise<ObjectDetail> {\n const res = await this.client.request<ObjectDetail>(\n \"GET\",\n `/v1/objects/${encodeURIComponent(id)}`,\n )\n // Normalize the wire `\"\"` caption (DB null / LLM sub-failure) → null so\n // consumers see the same `string | null` semantics as characters. New\n // object — never mutate the response.\n return { ...res, canonicalDescription: res.canonicalDescription || null }\n }\n\n /**\n * Create a new object. `name` + `nodeId` are required — the route 400s\n * otherwise. Returns the new row's id.\n *\n * Note: the underlying route is the same `POST /v1/objects` upsert that\n * powers `update()`. This convenience wrapper enforces the INSERT-required\n * fields at the type level and never sends an `id`.\n */\n create(data: CreateObjectInput): Promise<{ id: string }> {\n return this.client.request(\"POST\", \"/v1/objects\", { body: data })\n }\n\n /**\n * Update an object. Only the fields you pass are written — undefined keys\n * are NOT touched on the row. Worker-owned asset buckets are intentionally\n * not exposed on this surface (see `UpdateObjectInput` for the rationale).\n *\n * Optimistic-concurrency: pass `expectedUpdatedAt` to require the row's\n * `updated_at` still matches; on mismatch the route returns 409\n * `concurrent_modification` carrying the fresh `updatedAt`. The SDK\n * surfaces that as a generic `NodaroError` with the same code (per Phase\n * E1 calibration finding — error centralization in `throwApiError`).\n */\n update(id: string, data: UpdateObjectInput): Promise<UpdateObjectResult> {\n return this.client.request(\"POST\", \"/v1/objects\", {\n body: { id, ...data },\n })\n }\n\n /**\n * Soft-delete (archive) an object. The row is hidden from `list()` by\n * default but recoverable via `restore(id)` or visible under\n * `listArchived()`. Idempotent — repeating a delete on an already-archived\n * row is a no-op.\n */\n delete(id: string): Promise<{ success: true; archived: true }> {\n return this.client.request(\"DELETE\", `/v1/objects/${encodeURIComponent(id)}`)\n }\n\n /**\n * Hard-delete (permanent) an object — the row + every R2 asset it\n * references. Archived rows ONLY: active objects return 400 `not_archived`.\n * Call `delete()` first to archive, then `permanentDelete()` to destroy.\n *\n * Mirrors the `app_runs` permanent-delete pattern (archive-first) so a\n * stray SDK / curl caller cannot bypass the studio's archive-first UI\n * flow.\n */\n permanentDelete(id: string): Promise<{ success: true; permanent: true }> {\n return this.client.request(\"DELETE\", `/v1/objects/${encodeURIComponent(id)}`, {\n query: { permanent: \"true\" },\n })\n }\n\n /**\n * Un-archive an object. If the original name now collides (case-\n * insensitive) with an active row, the server auto-suffixes \"(restored)\"\n * and returns the effective name.\n */\n restore(id: string): Promise<{ id: string; name: string }> {\n return this.client.request(\"POST\", `/v1/objects/${encodeURIComponent(id)}/restore`)\n }\n\n /**\n * Admin only: put one of your own objects on the shared Nodaro Keepers\n * shelf (`client.keepers.catalog()`), or take it off. A first-party session\n * or your personal token; `forbidden` for anyone who is not a platform\n * admin, `not_found` for a row that is not yours.\n */\n setCatalog(id: string, input: SetKeeperCatalogInput): Promise<SetKeeperCatalogResult> {\n return this.client.request(\"PUT\", `/v1/objects/${encodeURIComponent(id)}/catalog`, { body: input })\n }\n\n /**\n * Fire `POST /v1/generate-object` to produce one or more candidate main\n * images. With `count > 1`, all jobs are reserved up-front before any\n * is enqueued — mid-batch failures roll back atomically.\n *\n * When `attachToObjectId` is set AND `count === 1`, the worker writes\n * the result directly to the row's `source_image_url`; otherwise you must\n * call `approveMainImage()` after picking a candidate.\n */\n async generate(data: GenerateObjectInput): Promise<GenerateObjectResult> {\n const res = await this.client.request<{ jobId?: string; jobIds?: string[] }>(\n \"POST\", \"/v1/generate-object\", { body: data },\n )\n // Tolerate the legacy `{ jobId }`-only shape (older server): synthesize jobIds.\n const jobIds = res.jobIds ?? (res.jobId ? [res.jobId] : [])\n return res.jobId ? { jobIds, jobId: res.jobId } : { jobIds }\n }\n\n /**\n * Fire `POST /v1/generate-object-asset` to produce a single variant.\n * When the studio path is set (`attachToObjectId` + `attachToColumn` +\n * `attachName`), the worker appends `{ name: attachName, url: <result> }`\n * to the named JSONB array column on completion.\n *\n * Note: `attachToColumn` is REQUIRED for `assetType === \"custom\"` — the\n * worker can't infer the bucket from the asset type. For canonical asset\n * types (`angles` / `materials` / `variations` / `motion`), the column is\n * derived automatically by the route.\n */\n generateAsset(\n data: GenerateObjectAssetInput,\n ): Promise<GenerateObjectAssetResult> {\n return this.client.request(\"POST\", \"/v1/generate-object-asset\", { body: data })\n }\n\n /**\n * Fire `POST /v1/generate-object-motion` to animate the object's main\n * image into a motion clip. Image-to-video, single clip per call; the\n * attach column is hardcoded to `motion_clips` server-side (objects have a\n * single motion bucket so the caller doesn't supply `attachToColumn`).\n * When the studio path is set (`attachToObjectId` + `attachName`), the\n * worker appends `{ name: attachName, url: <result> }` to the row's\n * `motion_clips` column on completion.\n *\n * Defaults: `provider` → `\"kling-turbo\"`, `aspectRatio` → `\"1:1\"` (set\n * server-side via `resolveObjectAspectRatio({ assetType: \"motion\" })`).\n */\n generateMotion(\n data: GenerateObjectMotionInput,\n ): Promise<GenerateObjectMotionResult> {\n return this.client.request(\"POST\", \"/v1/generate-object-motion\", { body: data })\n }\n\n /**\n * Approve a completed `generate-object` job as the object's main image.\n * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)\n * inline. Returns the new main-image URL plus the caption.\n *\n * Caption-failure semantics: the route still sends `\"\"` on LLM sub-failure,\n * but the SDK normalizes `\"\"` → `null` here so `canonicalDescription` carries\n * the same `string | null` semantics as characters. The main image is still\n * set; call `recaption()` to retry.\n *\n * Optimistic-concurrency: pass `expectedUpdatedAt` to gate the update on\n * the row's current `updated_at`; on mismatch the route returns 409\n * `concurrent_modification` carrying the fresh token.\n */\n async approveMainImage(\n id: string,\n candidateJobId: string,\n expectedUpdatedAt?: string,\n ): Promise<ApproveObjectMainImageResult> {\n const res = await this.client.request<{ sourceImageUrl: string; canonicalDescription: string | null }>(\n \"POST\",\n `/v1/objects/${encodeURIComponent(id)}/approve-main-image`,\n { body: { candidateJobId, expectedUpdatedAt } },\n )\n // Normalize the wire `\"\"` (LLM sub-failure) → null; build a new object\n // rather than mutating the response.\n return { sourceImageUrl: res.sourceImageUrl, canonicalDescription: res.canonicalDescription || null }\n }\n\n /**\n * Re-fire the LLM caption against the object's current main image. 502s\n * on LLM failure (unlike `approveMainImage` which preserves the side-effect\n * and returns \"\"); returns 400 `main_image_required` if no main image is\n * set yet.\n *\n * The route is a pure idempotent retry — it does NOT accept an\n * `expectedUpdatedAt` token (per Phase E1 calibration finding: backend\n * route is idempotent retry, not gated on optimistic-concurrency).\n */\n recaption(id: string): Promise<RecaptionObjectResult> {\n return this.client.request(\n \"POST\",\n `/v1/objects/${encodeURIComponent(id)}/llm-caption`,\n )\n }\n}\n"]}
|
|
@@ -214,5 +214,5 @@ Object.defineProperty(exports, "OBJECT_ASPECT_OPTIONS", {
|
|
|
214
214
|
});
|
|
215
215
|
exports.CREATURE_ASSET_TYPES = CREATURE_ASSET_TYPES;
|
|
216
216
|
exports.CreaturesResource = CreaturesResource;
|
|
217
|
-
//# sourceMappingURL=chunk-
|
|
218
|
-
//# sourceMappingURL=chunk-
|
|
217
|
+
//# sourceMappingURL=chunk-A3XA6UNM.cjs.map
|
|
218
|
+
//# sourceMappingURL=chunk-A3XA6UNM.cjs.map
|