@docyrus/animaguru 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/animaguru.js +44 -2
- package/package.json +1 -1
- package/skills/animaguru/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,21 @@ Running `init` again refreshes an existing skill with the bundled version withou
|
|
|
72
72
|
|
|
73
73
|
The default server is https://animaguru.com. Use `--url http://localhost:5190` on the leaf command or `ANIMAGURU_URL` to override it. HTTP is allowed only for loopback development. Authentication is stored separately per server in `~/.config/animaguru/credentials.json`, with file permissions 0600. Set `ANIMAGURU_CONFIG_DIR` for an isolated configuration directory. Browser login uses a ten-minute, single-use device code and receives a seven-day revocable Better Auth session. `auth login --no-browser` prints the URL for manual use. `auth logout` revokes the token. `ANIMAGURU_TOKEN` supports secret injection by agent runners; do not put tokens in arguments or commit them.
|
|
74
74
|
|
|
75
|
+
## Personal and team projects
|
|
76
|
+
|
|
77
|
+
CLI 0.7.1 can select a cloud workspace for project listing, project creation, and credit balances:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
animaguru workspaces list
|
|
81
|
+
animaguru workspaces use team_0123456789abcdef0123456789abcdef
|
|
82
|
+
animaguru projects list
|
|
83
|
+
animaguru projects create --name "Shared cast" --style pixel
|
|
84
|
+
animaguru credits
|
|
85
|
+
animaguru workspaces use personal
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Use a team ID returned by `workspaces list`. The choice is saved per server in the existing credentials file. `workspaces list` also shows invitations; accept invitations in the web app before selecting that team. `projects get`, generation, jobs, and files use the project ID and work for any project you can access, regardless of the selected workspace. With `ANIMAGURU_TOKEN`, set `ANIMAGURU_WORKSPACE=personal` or a team ID instead of saving a selection. A cloud team is separate from the local `animaguru create workspace NAME` video folder.
|
|
89
|
+
|
|
75
90
|
## Agent workflow
|
|
76
91
|
|
|
77
92
|
```sh
|
package/dist/animaguru.js
CHANGED
|
@@ -542,7 +542,7 @@ var init_dist = __esm({
|
|
|
542
542
|
// cli/package.json
|
|
543
543
|
var package_default = {
|
|
544
544
|
name: "@docyrus/animaguru",
|
|
545
|
-
version: "0.7.
|
|
545
|
+
version: "0.7.1",
|
|
546
546
|
description: "Agent-friendly AnimaGuru CLI built with CrustJS",
|
|
547
547
|
type: "module",
|
|
548
548
|
bin: {
|
|
@@ -25871,6 +25871,22 @@ async function writeCredentials(credentials) {
|
|
|
25871
25871
|
await chmod2(temp, 384);
|
|
25872
25872
|
await rename2(temp, path);
|
|
25873
25873
|
}
|
|
25874
|
+
async function selectedWorkspace(origin) {
|
|
25875
|
+
const saved = process.env.ANIMAGURU_TOKEN ? void 0 : (await readCredentials())[origin]?.workspaceId;
|
|
25876
|
+
const value = process.env.ANIMAGURU_WORKSPACE ?? saved ?? "me";
|
|
25877
|
+
if (value === "personal" || value === "me") return "me";
|
|
25878
|
+
if (!/^team_[a-f0-9]{32}$/.test(value)) throw new Error("ANIMAGURU_WORKSPACE must be 'personal' or a team ID.");
|
|
25879
|
+
return value;
|
|
25880
|
+
}
|
|
25881
|
+
async function saveWorkspace(origin, workspaceId) {
|
|
25882
|
+
if (process.env.ANIMAGURU_TOKEN) throw new Error("With ANIMAGURU_TOKEN, set ANIMAGURU_WORKSPACE instead of saving a workspace.");
|
|
25883
|
+
if (process.env.ANIMAGURU_WORKSPACE) throw new Error("Unset ANIMAGURU_WORKSPACE before changing the saved workspace.");
|
|
25884
|
+
const credentials = await readCredentials();
|
|
25885
|
+
const saved = credentials[origin];
|
|
25886
|
+
if (!saved || saved.expiresAt <= Date.now()) throw new Error("Sign in with animaguru auth login first.");
|
|
25887
|
+
credentials[origin] = { ...saved, workspaceId };
|
|
25888
|
+
await writeCredentials(credentials);
|
|
25889
|
+
}
|
|
25874
25890
|
var ServiceError = class extends Error {
|
|
25875
25891
|
constructor(status, code, message) {
|
|
25876
25892
|
super(message);
|
|
@@ -27349,6 +27365,10 @@ var id = { name: "id", type: "string", required: true, description: "Project ID"
|
|
|
27349
27365
|
var out = (stdout, data) => stdout(JSON.stringify(data));
|
|
27350
27366
|
var actions = (text) => text ? text.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
27351
27367
|
var projectPath = (project) => `/api/v1/sprites/${encodeURIComponent(project)}`;
|
|
27368
|
+
var workspaceQuery = async (client) => {
|
|
27369
|
+
const selected = await selectedWorkspace(client.origin);
|
|
27370
|
+
return selected === "me" ? "" : `?workspace=${encodeURIComponent(selected)}`;
|
|
27371
|
+
};
|
|
27352
27372
|
async function openBrowser(url2) {
|
|
27353
27373
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "rundll32" : "xdg-open";
|
|
27354
27374
|
const args = process.platform === "win32" ? ["url.dll,FileProtocolHandler", url2] : [url2];
|
|
@@ -27419,7 +27439,29 @@ Confirm code: ${device.user_code}`);
|
|
|
27419
27439
|
delete credentials[client.origin];
|
|
27420
27440
|
await writeCredentials(credentials);
|
|
27421
27441
|
out(stdout, { authenticated: false });
|
|
27422
|
-
})))).
|
|
27442
|
+
})))).command("workspaces", (workspaces) => workspaces.add(defineCommand("list", { description: "List Personal, joined teams and pending invitations" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
|
|
27443
|
+
const client = new Client(flags.url, signal);
|
|
27444
|
+
const data = await client.request("/api/v1/workspaces");
|
|
27445
|
+
const selected = await selectedWorkspace(client.origin);
|
|
27446
|
+
out(stdout, { ...data, current: data.workspaces.find((item) => selected === "me" ? item.type === "user" : item.id === selected) ?? null });
|
|
27447
|
+
}))).add(defineCommand("use", { description: "Select Personal or a joined team for credits and project creation/listing" }, (command) => command.args({ name: "id", type: "string", required: true, description: "'personal' or a team ID from workspaces list" }).flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ args, flags, stdout, signal }) => {
|
|
27448
|
+
const client = new Client(flags.url, signal);
|
|
27449
|
+
const { workspaces: workspaces2 } = await client.request("/api/v1/workspaces");
|
|
27450
|
+
const chosen = args.id === "personal" || args.id === "me" ? workspaces2.find((item) => item.type === "user") : workspaces2.find((item) => item.type === "team" && item.id === args.id);
|
|
27451
|
+
if (!chosen) throw new Error("Workspace not found in your account. Run animaguru workspaces list.");
|
|
27452
|
+
await saveWorkspace(client.origin, chosen.type === "user" ? "me" : chosen.id);
|
|
27453
|
+
out(stdout, { current: chosen });
|
|
27454
|
+
})))).add(defineCommand("credits", { description: "Show the selected workspace's remaining credit balance" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
|
|
27455
|
+
const client = new Client(flags.url, signal);
|
|
27456
|
+
out(stdout, await client.request(`/api/v1/credits${await workspaceQuery(client)}`));
|
|
27457
|
+
}))).add(defineCommand("catalog", { description: "List styles, kinds, actions, asset types, models, video settings and speech voices" }, (command) => command.action(({ stdout }) => out(stdout, { styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, imageModels: SPRITE_IMAGE_MODEL_IDS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), elevenLabsVoices: ELEVENLABS_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS })))).command("projects", (projects) => projects.add(defineCommand("list", { description: "List projects in the selected workspace" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).action(async ({ flags, stdout, signal }) => {
|
|
27458
|
+
const client = new Client(flags.url, signal);
|
|
27459
|
+
out(stdout, await client.request(`/api/v1/projects${await workspaceQuery(client)}`));
|
|
27460
|
+
}))).add(defineCommand("create", { description: "Create an empty sprite project; generate artwork with jobs submit" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).flags(...modelFlags).flags({ name: "name", type: "string", required: true }, { name: "style", type: "string", required: true, choices: SPRITE_STYLES }).action(async ({ flags, stdout, signal }) => {
|
|
27461
|
+
const client = new Client(flags.url, signal);
|
|
27462
|
+
const selected = await selectedWorkspace(client.origin);
|
|
27463
|
+
out(stdout, await client.request("/api/v1/sprites", { method: "POST", body: { owner: selected, name: flags.name, style: flags.style, ...selectedModels(flags) } }));
|
|
27464
|
+
}))).add(defineCommand("get", { description: "Read project, subjects, animations, estimates and job state" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(projectPath(args.id)))))).add(defineCommand("rename", { description: "Rename a project" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).flags({ name: "name", type: "string", required: true }).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`/api/v1/projects/${encodeURIComponent(args.id)}`, { method: "PATCH", body: { name: flags.name } }))))).add(defineCommand("delete", { description: "Delete a project; requires --yes" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" }, description: "Server origin" }).args(id).flags({ name: "yes", type: "boolean", required: true }).action(async ({ args, flags, stdout, signal }) => {
|
|
27423
27465
|
if (!flags.yes) throw new Error("Pass --yes to delete this project.");
|
|
27424
27466
|
out(stdout, await new Client(flags.url, signal).request(`/api/v1/projects/${encodeURIComponent(args.id)}`, { method: "DELETE" }));
|
|
27425
27467
|
})))).command("assets", (assets) => assets.add(defineCommand("list", { description: "List saved assets, their blob hashes, and configured generation models" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/assets`))))).add(defineCommand("generate", { description: "Generate an image, video, music, speech or sound-effect asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ Before creative work in a multi-animation workspace, select or create the intend
|
|
|
16
16
|
Share the [animation-style gallery](https://animaguru.com/animation-styles), or open that URL in the internal browser when available, while asking the user to choose a style. Read the installed `animaguru.templates.json` for available styles and their skill names; `animaguru templates` lists the current CLI catalog. Offer the local catalog's choices so users select a skill actually installed in their workspace. Templates define appearance and motion; derive audience, message and story from the brief. Local scaffolding is separate from `projects create`, which creates a remote asset project. Never run `create` over an existing workspace.
|
|
17
17
|
|
|
18
18
|
- Run `animaguru schema` for the installed command structure and flags, and `animaguru catalog` for styles, subject kinds, actions, asset types, models, video settings, and speech voices. Use `--help` on a leaf command for details.
|
|
19
|
-
- Check `animaguru auth status` and `animaguru credits` before generation. If sign-in is needed, run `animaguru auth login --no-browser` and let the user approve the printed browser URL. Do not read or print stored credentials. Agent runners may inject `ANIMAGURU_TOKEN` as
|
|
19
|
+
- Check `animaguru auth status`, `animaguru workspaces list`, and `animaguru credits` before generation. If sign-in is needed, run `animaguru auth login --no-browser` and let the user approve the printed browser URL. Select the user's requested Personal or team workspace with `animaguru workspaces use personal|TEAM_ID` before listing or creating projects. Do not read or print stored credentials. Agent runners may inject `ANIMAGURU_TOKEN` and `ANIMAGURU_WORKSPACE` as secrets or configuration.
|
|
20
20
|
- The default service is `https://animaguru.com`. Respect an existing `ANIMAGURU_URL` or pass `--url` to the leaf command when the user chooses another service. HTTP is supported only for loopback development.
|
|
21
21
|
|
|
22
22
|
## Choose the project and submit work
|