@koda-sl/baker-cli 0.306.0-dev.bb28562ac → 0.306.2-dev.bb28562ac
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/cli.js +30 -9
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2957,8 +2957,14 @@ Read one avatar: status, `sheetUrl` for `--reference`, and the `subjectDescripti
|
|
|
2957
2957
|
```bash
|
|
2958
2958
|
baker avatars get marta
|
|
2959
2959
|
baker avatars get marta --full --output md
|
|
2960
|
+
baker avatars get marta --wait # returns the moment the sheet settles (≤90s)
|
|
2960
2961
|
```
|
|
2961
2962
|
|
|
2963
|
+
`--wait` returns immediately, rather than blocking, when the avatar is waiting for its
|
|
2964
|
+
face (`needsFace: true`). That state is `generating` with nothing rendering — the casting
|
|
2965
|
+
portraits are in front of the user and the build starts when they choose — so there is
|
|
2966
|
+
nothing for the deadline to wait out.
|
|
2967
|
+
|
|
2962
2968
|
#### `baker avatars create`
|
|
2963
2969
|
|
|
2964
2970
|
Cast a new presenter. `--name` and `--subject` are required; `--subject` describes one person plainly (age, build, hair, skin, face) with no scene, lighting, camera, or wardrobe.
|
|
@@ -2976,6 +2982,12 @@ baker avatars create --name "Marta" --subject "…" \
|
|
|
2976
2982
|
|
|
2977
2983
|
Optional: `--handle`, `--speech`, `--motion`, `--setting`, `--accent`. Returns `{ avatarId, handle, likeness, status }`.
|
|
2978
2984
|
|
|
2985
|
+
The handle is slugged from `--name` when you do not pass one, and a taken slug is numbered
|
|
2986
|
+
rather than refused — a second Marta becomes `marta-2`, so a retired avatar never blocks the
|
|
2987
|
+
next one that shares her name. A `--handle` you pass yourself still conflicts: that one is a
|
|
2988
|
+
decision, and moving it quietly would point `@marta` at somebody else. The returned `handle`
|
|
2989
|
+
is the one the avatar actually got.
|
|
2990
|
+
|
|
2979
2991
|
#### `baker avatars update <handle>`
|
|
2980
2992
|
|
|
2981
2993
|
Edit an avatar. Profile flags are merged over the stored profile, so `--persona` alone keeps the subject description intact; an empty value clears the field it names (except `--subject`, which can only be replaced). Changing `--subject` requires `--regenerate-sheet` in the same call — otherwise the sheet still shows the person described before.
|
|
@@ -2990,6 +3002,9 @@ baker avatars update marta --new-handle marta-founder --accent "Spanish from Spa
|
|
|
2990
3002
|
|
|
2991
3003
|
Remove an avatar. `--archive` retires it — it leaves the roster but past work and `@handle` mentions keep resolving. Without `--archive` it is deleted for good.
|
|
2992
3004
|
|
|
3005
|
+
Refused, either way, while the user is choosing that avatar's face: removing it would leave
|
|
3006
|
+
the casting question on their screen with nothing behind it.
|
|
3007
|
+
|
|
2993
3008
|
```bash
|
|
2994
3009
|
baker avatars delete marta --archive --dry-run
|
|
2995
3010
|
baker avatars delete marta --archive
|
package/dist/cli.js
CHANGED
|
@@ -4470,6 +4470,15 @@ var avatarSummarySchema = z10.object({
|
|
|
4470
4470
|
sheetUrl: z10.string().optional(),
|
|
4471
4471
|
coverUrl: z10.string().optional(),
|
|
4472
4472
|
errorMessage: z10.string().optional(),
|
|
4473
|
+
/**
|
|
4474
|
+
* The build is parked on a face nobody has picked yet.
|
|
4475
|
+
*
|
|
4476
|
+
* `generating` otherwise means a render is running. This is the one case where it
|
|
4477
|
+
* does not, and it is the difference between "come back in thirty seconds" and
|
|
4478
|
+
* "the user is looking at four portraits right now" — so anything that waits on an
|
|
4479
|
+
* avatar has to read it, or it waits out its whole deadline on nothing.
|
|
4480
|
+
*/
|
|
4481
|
+
needsFace: z10.boolean().optional(),
|
|
4473
4482
|
/**
|
|
4474
4483
|
* The chat this avatar was created in, when it was created in one.
|
|
4475
4484
|
*
|
|
@@ -30332,6 +30341,11 @@ var CAST_FLAG_RULE = "Cast with `--avatar <handle>` on `baker studio generate`,
|
|
|
30332
30341
|
var VERBATIM_RULE = "When you do write the description yourself \u2014 a hand-built canvas node, a landing image, anywhere `--avatar` does not exist \u2014 copy `subjectDescription` VERBATIM, word for word. Re-phrasing it per generation is the other reason a face drifts across a set.";
|
|
30333
30342
|
var VIDEO_ROUTING = "In video, a photoreal presenter renders on `google/veo-3.1` (or `google/veo-3.1-fast`), never `bytedance/seedance-2.0` \u2014 it refuses photoreal human faces, AI-generated ones included. Scaffolding a video creative: `baker canvas scaffold-video \u2026 --real-face`.";
|
|
30334
30343
|
function castingHints(avatar) {
|
|
30344
|
+
if (avatar.status === "generating" && avatar.needsFace) {
|
|
30345
|
+
return [
|
|
30346
|
+
`The user is picking @${avatar.handle}'s face right now \u2014 portraits are on their screen and nothing renders until they answer. There is NOTHING to wait for and nothing to check: do not poll, do not block on it, do not ask about the face in a question of your own, and do not delete or recreate this avatar. Whatever you do next simply runs after they have chosen.`
|
|
30347
|
+
];
|
|
30348
|
+
}
|
|
30335
30349
|
if (avatar.status === "generating") {
|
|
30336
30350
|
return [
|
|
30337
30351
|
`Still building \u2014 a ~30s render that settles on its own, and this avatar is castable only once it reads \`ready\`. If the next thing you do needs it (a clip, a still, anything with --avatar), block on it: \`baker avatars get ${avatar.handle} --wait\` returns the moment it is ready. Otherwise do other work first and read it back with \`baker avatars get ${avatar.handle}\`. Never write your own sleep or poll loop, and never end the turn waiting \u2014 the user would have to come back and tell you it is ready.`
|
|
@@ -30492,13 +30506,19 @@ function failValidation2(message, fix) {
|
|
|
30492
30506
|
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message, ...fix ? { fix } : {} } });
|
|
30493
30507
|
process.exit(1);
|
|
30494
30508
|
}
|
|
30495
|
-
function avatarFailureFix(err, handle) {
|
|
30509
|
+
function avatarFailureFix(err, handle, context = {}) {
|
|
30496
30510
|
if (err.code === "NOT_FOUND") {
|
|
30497
30511
|
return {
|
|
30498
30512
|
action: "list_avatars",
|
|
30499
30513
|
explanation: `Run \`baker avatars list\` to see which avatars this company has${handle ? ` \u2014 "${handle}" is not one of them` : ""}. Handles are lowercase letters, numbers and dashes ("maria-founder", not "Maria Founder"). If the roster is empty, create the avatar first with \`baker avatars create\`. Do not abandon the wider job over this \u2014 carry on without the avatar and say so.`
|
|
30500
30514
|
};
|
|
30501
30515
|
}
|
|
30516
|
+
if (err.code === "CONFLICT" && context.operation === "remove") {
|
|
30517
|
+
return {
|
|
30518
|
+
action: "wait_for_the_user",
|
|
30519
|
+
explanation: `Do not remove or recreate${handle ? ` @${handle}` : " this avatar"} \u2014 wait. The portraits are on the user's screen and the turn continues once they answer. If you think the faces are wrong, say so in your reply and let them turn all four down; that recasts the same avatar from what they tell you was missing, and keeps everything already pointing at it.`
|
|
30520
|
+
};
|
|
30521
|
+
}
|
|
30502
30522
|
if (err.code === "CONFLICT" && handle) {
|
|
30503
30523
|
return {
|
|
30504
30524
|
action: "use_the_existing_avatar",
|
|
@@ -30507,9 +30527,9 @@ function avatarFailureFix(err, handle) {
|
|
|
30507
30527
|
}
|
|
30508
30528
|
return void 0;
|
|
30509
30529
|
}
|
|
30510
|
-
function failAvatarApi(err, handle) {
|
|
30530
|
+
function failAvatarApi(err, handle, context = {}) {
|
|
30511
30531
|
if (err instanceof ApiError) {
|
|
30512
|
-
const fix = avatarFailureFix(err, handle);
|
|
30532
|
+
const fix = avatarFailureFix(err, handle, context);
|
|
30513
30533
|
writeJson({ ok: false, error: { code: err.code, message: err.message, ...fix ? { fix } : {} } });
|
|
30514
30534
|
process.exit(1);
|
|
30515
30535
|
}
|
|
@@ -30800,7 +30820,7 @@ var deleteCommand = defineCommand97({
|
|
|
30800
30820
|
});
|
|
30801
30821
|
writeJson({ ok: true, data, hints: removalHints({ handle: data.handle, archived: data.archived }) });
|
|
30802
30822
|
} catch (err) {
|
|
30803
|
-
failAvatarApi(err, handle);
|
|
30823
|
+
failAvatarApi(err, handle, { operation: "remove" });
|
|
30804
30824
|
}
|
|
30805
30825
|
}
|
|
30806
30826
|
});
|
|
@@ -30811,17 +30831,18 @@ import { defineCommand as defineCommand98 } from "citty";
|
|
|
30811
30831
|
// src/commands/avatars/wait.ts
|
|
30812
30832
|
var WAIT_TIMEOUT_MS = 9e4;
|
|
30813
30833
|
var WAIT_INTERVAL_MS = 3e3;
|
|
30814
|
-
function shouldKeepWaiting(
|
|
30815
|
-
if (status === "ready") return { done: true, reason: "ready" };
|
|
30816
|
-
if (status === "error" || status === "archived") return { done: true, reason: "settled" };
|
|
30834
|
+
function shouldKeepWaiting(avatar, elapsedMs) {
|
|
30835
|
+
if (avatar.status === "ready") return { done: true, reason: "ready" };
|
|
30836
|
+
if (avatar.status === "error" || avatar.status === "archived") return { done: true, reason: "settled" };
|
|
30837
|
+
if (avatar.needsFace) return { done: true, reason: "needs-face" };
|
|
30817
30838
|
if (elapsedMs >= WAIT_TIMEOUT_MS) return { done: false, reason: "expired" };
|
|
30818
30839
|
return { done: false, reason: "building" };
|
|
30819
30840
|
}
|
|
30820
30841
|
async function waitForSheet(first, read, sleep4 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms))) {
|
|
30821
30842
|
const startedAt = Date.now();
|
|
30822
30843
|
let latest = first;
|
|
30823
|
-
while (!shouldKeepWaiting(latest
|
|
30824
|
-
if (shouldKeepWaiting(latest
|
|
30844
|
+
while (!shouldKeepWaiting(latest, Date.now() - startedAt).done) {
|
|
30845
|
+
if (shouldKeepWaiting(latest, Date.now() - startedAt).reason === "expired") return latest;
|
|
30825
30846
|
await sleep4(WAIT_INTERVAL_MS);
|
|
30826
30847
|
latest = await read();
|
|
30827
30848
|
}
|