diff --git a/README.md b/README.md index bad8a56..19100d3 100644 --- a/README.md +++ b/README.md @@ -198,8 +198,8 @@ Supported API command groups call only current `api.sume.com` API routes: - `GET /v1/balance` - `GET /v1/usage` -- `POST /v1/models/sume/avatar/v1.0/runs` -- `POST /v1/models/sume/avatar-video/v1.0/runs` +- `POST /v1/avatar-1.0/generate` +- `POST /v1/avatar-1.0/talking-video` - `GET /v1/avatars` - `GET /v1/avatars/:id` - `GET /v1/avatar-videos` @@ -226,11 +226,13 @@ Avatar and avatar-video submit commands support `--payload-json` or Avatar-video scripts are estimated locally and by the API; accepted target duration is 4-60 seconds inclusive. -`sume avatars create` defaults to `sume/avatar/v1.0`. `type` means the avatar -input kind (`prompt`, `photo`, or `props`). Launch-shaped requests use -`avatar_handle` plus an `input` union; the CLI exposes that as -`--avatar-handle` and type-specific fields. `--handle` remains a short alias for -`--avatar-handle`. +`sume avatars create` defaults to the primary `POST /v1/avatar-1.0/generate` +route. `type` means the avatar input kind (`prompt`, `photo`, or `props`). +Launch-shaped requests use `avatar_handle` plus an `input` union; the CLI +exposes that as `--avatar-handle` and type-specific fields. `--handle` remains +a short alias for `--avatar-handle`. Exact model-run ids such as +`sume/avatar-1.0/generate` are accepted for compatibility mode when `--model` +is supplied; older Avatar model ids remain explicit aliases. Photo avatar creation currently accepts a public image URL: diff --git a/docs/agent-workflows.md b/docs/agent-workflows.md index ef8d072..5a8da41 100644 --- a/docs/agent-workflows.md +++ b/docs/agent-workflows.md @@ -51,8 +51,10 @@ sume avatars list --handle presenter --agent --json sume avatars get --agent --json ``` -The create command submits `POST /v1/models/sume/avatar/v1.0/runs`. For exact -model-run payloads, use `--payload-json` or `--payload-file`. +The create command submits `POST /v1/avatar-1.0/generate` by default. For exact +model-run compatibility payloads, use `--payload-json` or `--payload-file`; +`--model sume/avatar-1.0/generate` and legacy aliases remain accepted when an +exact model-run path is needed. Photo avatar creation uses a public image URL: ```bash @@ -97,7 +99,7 @@ sume avatar-videos create \ --json ``` -The create command submits `POST /v1/models/sume/avatar-video/v1.0/runs`. +The create command submits `POST /v1/avatar-1.0/talking-video`. Use `--avatar-handle` with a ready avatar handle. Scripts are estimated locally and by the API; accepted target duration is 4-60 seconds inclusive. diff --git a/docs/architecture.md b/docs/architecture.md index 1f206df..4ba3f58 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -44,8 +44,8 @@ Current launch-supported paths are: - `GET /jobs/:id/result` - `GET /jobs/:id/events` - `POST /jobs/:id/cancel` -- `POST /models/sume/avatar/v1.0/runs` -- `POST /models/sume/avatar-video/v1.0/runs` +- `POST /avatar-1.0/generate` +- `POST /avatar-1.0/talking-video` - `GET /avatars` - `GET /avatars/:id` - `GET /avatar-videos` @@ -57,6 +57,10 @@ claim media generation has completed unless the API returns a completed job/result. Generic image/video routes and raw provider model ids are not part of the current public CLI surface. +Legacy model-run ids and routes remain explicit compatibility aliases, but +CLI defaults should prefer the primary Avatar 1.0 generate and talking-video +routes above. + CLI submit commands must require explicit confirmation before calling mutating routes. `--confirm-submit` is the generic write gate; `--confirm-paid` is the provider/credit-spend alias for generation submits. diff --git a/src/commands/avatar-videos.ts b/src/commands/avatar-videos.ts index 9b0b5f3..352b737 100644 --- a/src/commands/avatar-videos.ts +++ b/src/commands/avatar-videos.ts @@ -33,6 +33,7 @@ import { DEFAULT_AVATAR_VIDEO_QUALITY, readAvatarVideoQuality, } from "../lib/quality.js"; +import { AVATAR_PRIMARY_TALKING_VIDEO_ENDPOINT } from "../lib/models.js"; type AvatarVideoCreateOptions = SubmissionOptions & { avatarHandle?: string; @@ -158,7 +159,7 @@ export function registerAvatarVideosCommand(program: Command) { assertAvatarVideoScriptDuration(payload); requireSubmitConfirmation(options); - const endpoint = "/models/sume/avatar-video/v1.0/runs"; + const endpoint = AVATAR_PRIMARY_TALKING_VIDEO_ENDPOINT; const result = await createClient().post(endpoint, payload, { headers: idempotencyHeaders(options), }); diff --git a/src/commands/avatars.ts b/src/commands/avatars.ts index 29b337b..664b71e 100644 --- a/src/commands/avatars.ts +++ b/src/commands/avatars.ts @@ -12,7 +12,7 @@ import { CliError } from "../lib/errors.js"; import { renderResult } from "../lib/render.js"; import { AVATAR_MODEL_IDS, - avatarModelRunEndpoint, + avatarGenerateEndpoint, normalizeAvatarModelId, type AvatarModelId, } from "../lib/models.js"; @@ -157,7 +157,7 @@ export function registerAvatarsCommand(program: Command) { .option("--payload-file ", "Read exact API request body from a JSON file.") .option( "--model ", - `Public Avatar model id: ${AVATAR_MODEL_IDS.base}.`, + `Optional exact Avatar model-run id. Defaults to the primary ${AVATAR_MODEL_IDS.generate} route.`, ) .option("--type ", "Avatar request type: prompt, photo, or props.", "prompt") .option( @@ -205,7 +205,7 @@ export function registerAvatarsCommand(program: Command) { requireSubmitConfirmation(options); const modelId = readAvatarModelId(options); - const endpoint = avatarModelRunEndpoint(modelId); + const endpoint = avatarGenerateEndpoint(modelId); const result = await client.post(endpoint, payload, { headers: idempotencyHeaders(options), }); @@ -434,8 +434,8 @@ function readPropsEthnicity(value: string | undefined) { ); } -function readAvatarModelId(options: AvatarCreateOptions): AvatarModelId { - return normalizeAvatarModelId(options.model); +function readAvatarModelId(options: AvatarCreateOptions): AvatarModelId | undefined { + return options.model ? normalizeAvatarModelId(options.model) : undefined; } function readAvatarListStatus(options: AvatarListOptions) { diff --git a/src/lib/batch-workflows.ts b/src/lib/batch-workflows.ts index 6e90f9a..07d2bb2 100644 --- a/src/lib/batch-workflows.ts +++ b/src/lib/batch-workflows.ts @@ -9,6 +9,10 @@ import { DEFAULT_AVATAR_VIDEO_QUALITY, type AvatarVideoQuality, } from "./quality.js"; +import { + AVATAR_PRIMARY_GENERATE_ENDPOINT, + AVATAR_PRIMARY_TALKING_VIDEO_ENDPOINT, +} from "./models.js"; export type BatchKind = "avatar" | "avatar-video"; @@ -79,8 +83,8 @@ export async function submitBatch( const client = createClient(); const endpoint = plan.workflow === "avatar" - ? "/models/sume/avatar/v1.0/runs" - : "/models/sume/avatar-video/v1.0/runs"; + ? AVATAR_PRIMARY_GENERATE_ENDPOINT + : AVATAR_PRIMARY_TALKING_VIDEO_ENDPOINT; for (const planItem of plan.items) { const existing = state.items.find((item) => item.id === planItem.id); diff --git a/src/lib/models.ts b/src/lib/models.ts index a301785..1134235 100644 --- a/src/lib/models.ts +++ b/src/lib/models.ts @@ -1,7 +1,8 @@ import { CliError } from "./errors.js"; export const AVATAR_MODEL_IDS = { - base: "sume/avatar/v1.0", + generate: "sume/avatar-1.0/generate", + legacyBase: "sume/avatar/v1.0", } as const; export type AvatarModelId = @@ -12,20 +13,38 @@ export const AVATAR_MODEL_ID_VALUES = Object.values( ) as AvatarModelId[]; const AVATAR_MODEL_ALIASES = { - "sume/avatar-1.0": AVATAR_MODEL_IDS.base, - "sume/avatar/v1": AVATAR_MODEL_IDS.base, + "sume/avatar-1.0": AVATAR_MODEL_IDS.generate, + "sume/avatar/v1": AVATAR_MODEL_IDS.legacyBase, } as const satisfies Record; +export const AVATAR_PRIMARY_GENERATE_ENDPOINT = "/avatar-1.0/generate"; +export const AVATAR_PRIMARY_TALKING_VIDEO_ENDPOINT = "/avatar-1.0/talking-video"; + +export const AVATAR_VIDEO_MODEL_IDS = { + talkingVideo: "sume/avatar-1.0/talking-video", + legacyBase: "sume/avatar-video/v1.0", +} as const; + export function avatarModelRunEndpoint(modelId: AvatarModelId) { return `/models/${modelId}/runs`; } +export function avatarGenerateEndpoint(modelId?: AvatarModelId) { + return modelId + ? avatarModelRunEndpoint(modelId) + : AVATAR_PRIMARY_GENERATE_ENDPOINT; +} + +export function avatarTalkingVideoEndpoint() { + return AVATAR_PRIMARY_TALKING_VIDEO_ENDPOINT; +} + export function normalizeAvatarModelId( value: unknown, optionName = "model", ): AvatarModelId { if (value === undefined || value === null || value === "") { - return AVATAR_MODEL_IDS.base; + return AVATAR_MODEL_IDS.generate; } const candidate = String(value).trim(); @@ -36,7 +55,7 @@ export function normalizeAvatarModelId( if (canonical) return canonical; throw new CliError( - `${optionName} must be ${AVATAR_MODEL_IDS.base}.`, + `${optionName} must be ${AVATAR_MODEL_ID_VALUES.join(" or ")}.`, { code: "invalid_argument" }, ); } diff --git a/src/lib/tool-registry.ts b/src/lib/tool-registry.ts index a6f4f06..30e6c75 100644 --- a/src/lib/tool-registry.ts +++ b/src/lib/tool-registry.ts @@ -110,11 +110,18 @@ const submitConfirmation = { accepted_flags: ["confirm_submit", "confirm_paid"], required: true, }; +const avatarModelSchemaValues = [ + AVATAR_MODEL_IDS.generate, + AVATAR_MODEL_IDS.legacyBase, + "sume/avatar-1.0", + "sume/avatar/v1", +]; const avatarModelProperties = { model: { ...stringProperty, - enum: [AVATAR_MODEL_IDS.base], - description: "Public Avatar model id.", + enum: avatarModelSchemaValues, + description: + "Optional exact Avatar model-run id. Omit to use the primary Avatar 1.0 generate route.", }, }; const writeConfirmation = { @@ -166,8 +173,9 @@ const mcpAvatarCreateBaseProperties = { ...mcpPaidGenerationProperties, model: { ...stringProperty, - enum: [AVATAR_MODEL_IDS.base], - description: "Optional public Avatar model id. Omit for Avatar 1.0.", + enum: avatarModelSchemaValues, + description: + "Optional exact Avatar model-run id. Omit to use the primary Avatar 1.0 generate route.", }, avatar_handle: { ...stringProperty, @@ -1064,9 +1072,9 @@ const staticToolDefinitions: Record = { ...mcpPaidGenerationProperties, model: { ...stringProperty, - enum: [AVATAR_MODEL_IDS.base], + enum: avatarModelSchemaValues, description: - "Optional public Avatar model id. Omit for Avatar 1.0.", + "Optional exact Avatar model-run id. Omit to use the primary Avatar 1.0 generate route.", }, payload: { ...passthroughObjectSchema({}, []), @@ -1087,7 +1095,7 @@ const staticToolDefinitions: Record = { ], constraints: [ "payload_json and payload_file are exact-body escape hatches and are mutually exclusive.", - `model defaults to ${AVATAR_MODEL_IDS.base}.`, + `model defaults to the primary /v1/avatar-1.0/generate route; exact model mode accepts ${AVATAR_MODEL_IDS.generate}.`, "Flag-built requests submit avatar_handle plus an input union.", "type prompt requires avatar_handle plus prompt.", "type photo requires avatar_handle plus image_url.", @@ -1323,7 +1331,7 @@ const staticToolDefinitions: Record = { "avatar-videos.create": { command: "sume avatar-videos create --confirm-submit --json ...", description: - "Submit an Avatar Video 1.0 model run through /v1/models/sume/avatar-video/v1.0/runs.", + "Submit an Avatar Video 1.0 talking-video run through /v1/avatar-1.0/talking-video.", confirmation: submitConfirmation, input_schema: submitCliSchema( { @@ -1416,7 +1424,7 @@ const staticToolDefinitions: Record = { payload: { ...passthroughObjectSchema({}, []), description: - "Advanced exact /v1/models/sume/avatar-video/v1.0/runs request body. Prefer top-level friendly fields for agent use.", + "Advanced exact /v1/avatar-1.0/talking-video request body. Prefer top-level friendly fields for agent use.", }, }, ["idempotency_key", "max_spend_usd"], diff --git a/src/mcp/tools.ts b/src/mcp/tools.ts index d3b6b19..a488137 100644 --- a/src/mcp/tools.ts +++ b/src/mcp/tools.ts @@ -8,7 +8,9 @@ import { CliError } from "../lib/errors.js"; import { uploadLocalAsset } from "../lib/local-asset-upload.js"; import { AVATAR_MODEL_IDS, - avatarModelRunEndpoint, + AVATAR_VIDEO_MODEL_IDS, + avatarGenerateEndpoint, + avatarTalkingVideoEndpoint, normalizeAvatarModelId, } from "../lib/models.js"; import { validateAvatarVideoScriptDuration } from "../lib/avatar-video-duration.js"; @@ -52,8 +54,6 @@ export type McpToolFilterOptions = { toolsets?: McpToolset[]; }; -const AVATAR_VIDEO_MODEL_ID = "sume/avatar-video/v1.0"; - export const DEFAULT_MCP_TOOLSETS: McpToolset[] = [ "health", "account", @@ -170,7 +170,8 @@ const avatarVideoCreateInputSchema = z const avatarSubmissionInputSchema = paidSubmissionInputSchema.extend({ model: z .enum([ - AVATAR_MODEL_IDS.base, + AVATAR_MODEL_IDS.generate, + AVATAR_MODEL_IDS.legacyBase, "sume/avatar-1.0", "sume/avatar/v1", ]) @@ -189,7 +190,8 @@ const avatarCreateBaseInputSchema = z max_spend_usd: z.number().min(0), model: z .enum([ - AVATAR_MODEL_IDS.base, + AVATAR_MODEL_IDS.generate, + AVATAR_MODEL_IDS.legacyBase, "sume/avatar-1.0", "sume/avatar/v1", ]) @@ -539,7 +541,7 @@ async function submitAvatarGeneration({ return submitPaidGeneration({ client, decorateResult: (value) => addAvatarSummary(value, requestedAvatar), - endpoint: avatarModelRunEndpoint(modelId), + endpoint: avatarGenerateEndpoint(model ? modelId : undefined), idempotencyKey, maxSpendUsd, model: modelId, @@ -1248,10 +1250,10 @@ export const mcpTools: SumeMcpTool[] = [ assertAvatarVideoScriptDuration(payload); return submitPaidGeneration({ client, - endpoint: "/models/sume/avatar-video/v1.0/runs", + endpoint: avatarTalkingVideoEndpoint(), idempotencyKey: parsed.idempotency_key, maxSpendUsd: parsed.max_spend_usd, - model: AVATAR_VIDEO_MODEL_ID, + model: AVATAR_VIDEO_MODEL_IDS.talkingVideo, payload, dryRun: parsed.dry_run, toolName: "avatar-videos.create", diff --git a/test/cli.test.ts b/test/cli.test.ts index fc4cbf9..a500c25 100644 --- a/test/cli.test.ts +++ b/test/cli.test.ts @@ -641,7 +641,12 @@ describe("CLI", () => { input_schema: { properties: { model: expect.objectContaining({ - enum: ["sume/avatar/v1.0"], + enum: expect.arrayContaining([ + "sume/avatar-1.0/generate", + "sume/avatar/v1.0", + "sume/avatar-1.0", + "sume/avatar/v1", + ]), }), avatar_handle: expect.objectContaining({ type: "string" }), handle: expect.objectContaining({ type: "string" }), @@ -859,7 +864,12 @@ describe("CLI", () => { ]), properties: { model: expect.objectContaining({ - enum: ["sume/avatar/v1.0"], + enum: expect.arrayContaining([ + "sume/avatar-1.0/generate", + "sume/avatar/v1.0", + "sume/avatar-1.0", + "sume/avatar/v1", + ]), }), avatar_handle: expect.objectContaining({ type: "string" }), handle: expect.objectContaining({ type: "string" }), @@ -1460,7 +1470,7 @@ describe("CLI", () => { }); expect(requests[0]).toMatchObject({ method: "POST", - url: "/v1/models/sume/avatar/v1.0/runs", + url: "/v1/avatar-1.0/generate", body: { avatar_handle: "presenter", input: { @@ -1474,6 +1484,53 @@ describe("CLI", () => { ); }); + it("keeps exact Avatar model-run ids as explicit compatibility paths", async () => { + await withMockApi( + () => ({ + data: { + request_id: "job_avatar_exact", + job: { id: "job_avatar_exact", status: "queued" }, + }, + }), + async (baseUrl, requests) => { + await runCli( + [ + "--json", + "avatars", + "create", + "--confirm-submit", + "--model", + "sume/avatar-1.0/generate", + "--avatar-handle", + "presenter", + "--prompt", + "A friendly presenter", + ], + baseUrl, + ); + await runCli( + [ + "--json", + "avatars", + "create", + "--confirm-submit", + "--model", + "sume/avatar/v1.0", + "--avatar-handle", + "legacy_presenter", + "--prompt", + "A legacy compatible presenter", + ], + baseUrl, + ); + expect(requests.map((request) => request.url)).toEqual([ + "/v1/models/sume/avatar-1.0/generate/runs", + "/v1/models/sume/avatar/v1.0/runs", + ]); + }, + ); + }); + it("documents and submits launch-shaped Avatar 1.0 model runs without provider terms", async () => { const help = await execFileAsync(tsx, [ "src/index.ts", @@ -1490,15 +1547,15 @@ describe("CLI", () => { await withMockApi( (request) => { - if (request.url === "/v1/models/sume/avatar/v1.0/runs") { + if (request.url === "/v1/avatar-1.0/generate") { return { data: { request_id: "job_avatar_launch", - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", job: { id: "job_avatar_launch", status: "queued", - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", }, }, }; @@ -1530,9 +1587,9 @@ describe("CLI", () => { expect(JSON.parse(stdout)).toMatchObject({ data: { request_id: "job_avatar_launch", - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", job: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", status: "queued", }, }, @@ -1542,7 +1599,7 @@ describe("CLI", () => { ); expect(requests[0]).toMatchObject({ method: "POST", - url: "/v1/models/sume/avatar/v1.0/runs", + url: "/v1/avatar-1.0/generate", body: JSON.parse(payload), }); expect(requests[0]?.headers["idempotency-key"]).toBe("request-high-1"); @@ -1621,7 +1678,7 @@ describe("CLI", () => { it("submits avatar photo jobs from a public image URL", async () => { await withMockApi( (request) => { - if (request.url === "/v1/models/sume/avatar/v1.0/runs") { + if (request.url === "/v1/avatar-1.0/generate") { return { data: { request_id: "job_avatar_photo", @@ -1657,7 +1714,7 @@ describe("CLI", () => { }, }); expect(requests.map((request) => request.url)).toEqual([ - "/v1/models/sume/avatar/v1.0/runs", + "/v1/avatar-1.0/generate", ]); expect(requests[0]).toMatchObject({ method: "POST", @@ -2286,7 +2343,7 @@ describe("CLI", () => { it("plans and submits avatar batches with state and idempotency", async () => { await withMockApi( (request) => { - if (request.url === "/v1/models/sume/avatar/v1.0/runs") { + if (request.url === "/v1/avatar-1.0/generate") { return { data: { request_id: "job_avatar_1", @@ -2360,7 +2417,7 @@ describe("CLI", () => { }); expect(requests[0]).toMatchObject({ method: "POST", - url: "/v1/models/sume/avatar/v1.0/runs", + url: "/v1/avatar-1.0/generate", body: { avatar_handle: "presenter", input: { @@ -2445,7 +2502,7 @@ describe("CLI", () => { }); expect(requests[0]).toMatchObject({ method: "POST", - url: "/v1/models/sume/avatar-video/v1.0/runs", + url: "/v1/avatar-1.0/talking-video", body: { script: "Say hello.", product_image: "https://example.com/product.png", @@ -2497,7 +2554,7 @@ describe("CLI", () => { }); expect(requests[0]).toMatchObject({ method: "POST", - url: "/v1/models/sume/avatar-video/v1.0/runs", + url: "/v1/avatar-1.0/talking-video", body: { script: "Say hello.", quality: "plus", @@ -2564,7 +2621,7 @@ describe("CLI", () => { it("plans and submits avatar-video batches with selected avatar defaults", async () => { await withMockApi( (request) => { - if (request.url === "/v1/models/sume/avatar-video/v1.0/runs") { + if (request.url === "/v1/avatar-1.0/talking-video") { return { data: { request_id: "job_video_1", @@ -2619,7 +2676,7 @@ describe("CLI", () => { }); expect(requests[0]).toMatchObject({ method: "POST", - url: "/v1/models/sume/avatar-video/v1.0/runs", + url: "/v1/avatar-1.0/talking-video", body: { script: "Say hello.", quality: "plus", diff --git a/test/mcp.test.ts b/test/mcp.test.ts index ae6cb21..544b846 100644 --- a/test/mcp.test.ts +++ b/test/mcp.test.ts @@ -636,7 +636,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "presenter", input: { @@ -648,7 +648,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "presenter", input: { @@ -661,7 +661,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "presenter_two", input: { @@ -673,7 +673,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "presenter_two", input: { @@ -687,7 +687,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "prompt_presenter", input: { @@ -699,7 +699,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "prompt_presenter", input: { @@ -712,7 +712,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "profile_presenter", input: { @@ -726,7 +726,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "profile_presenter", input: { @@ -741,7 +741,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "photo_presenter", input: { @@ -761,7 +761,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar-video/v1.0", + model: "sume/avatar-1.0/talking-video", request: { script: "Hello", product_image: "https://example.com/product.png", @@ -771,7 +771,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar-video/v1.0/runs", + path: "/avatar-1.0/talking-video", body: { script: "Hello", product_image: "https://example.com/product.png", @@ -855,7 +855,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar: { type: "prompt", prompt: "Hello" } }, }, headers: undefined, @@ -909,7 +909,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "presenter", input: { type: "prompt", prompt: "Hello" }, @@ -918,7 +918,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "presenter", input: { type: "prompt", prompt: "Hello" }, @@ -1001,7 +1001,7 @@ describe("MCP tool registry", () => { ); expect(result).toMatchObject({ - model: "sume/avatar-video/v1.0", + model: "sume/avatar-1.0/talking-video", tool: "avatar-videos.create", would_submit: false, }); @@ -1009,7 +1009,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar-video/v1.0", + model: "sume/avatar-1.0/talking-video", request: { avatar_handle: "@david_im", mode: "async", @@ -1070,7 +1070,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar-video/v1.0", + model: "sume/avatar-1.0/talking-video", request: { avatar_handle: "avatar_123", product_image: "https://media.sume.com/product.png", @@ -1086,7 +1086,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar-video/v1.0/runs", + path: "/avatar-1.0/talking-video", body: { avatar_handle: "avatar_123", product_image: "https://media.sume.com/product.png", @@ -1150,7 +1150,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar-video/v1.0", + model: "sume/avatar-1.0/talking-video", request: { avatar_handle: "@david_im", product_image: "https://media.sume.com/product.png", @@ -1162,7 +1162,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar-video/v1.0/runs", + path: "/avatar-1.0/talking-video", body: { avatar_handle: "@david_im", product_image: "https://media.sume.com/product.png", @@ -1419,7 +1419,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "typed_avatar", input: { @@ -1431,7 +1431,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "typed_avatar", input: { @@ -1444,7 +1444,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "props_avatar", input: { @@ -1458,7 +1458,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "props_avatar", input: { @@ -1494,7 +1494,7 @@ describe("MCP tool registry", () => { }, }; } - if (path === "/models/sume/avatar/v1.0/runs") { + if (path === "/avatar-1.0/generate") { return { data: { job: { id: "job_photo" }, @@ -1523,7 +1523,7 @@ describe("MCP tool registry", () => { { path: "/generation/admission-preview", body: { - model: "sume/avatar/v1.0", + model: "sume/avatar-1.0/generate", request: { avatar_handle: "photo_avatar", input: { @@ -1535,7 +1535,7 @@ describe("MCP tool registry", () => { headers: undefined, }, { - path: "/models/sume/avatar/v1.0/runs", + path: "/avatar-1.0/generate", body: { avatar_handle: "photo_avatar", input: {