@bitmagic/asset-core 0.1.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.
Files changed (53) hide show
  1. package/dist/forger-client.d.ts +42 -0
  2. package/dist/forger-client.d.ts.map +1 -0
  3. package/dist/forger-client.js +135 -0
  4. package/dist/forger-client.js.map +1 -0
  5. package/dist/generators/animation.d.ts +102 -0
  6. package/dist/generators/animation.d.ts.map +1 -0
  7. package/dist/generators/animation.js +234 -0
  8. package/dist/generators/animation.js.map +1 -0
  9. package/dist/generators/character.d.ts +40 -0
  10. package/dist/generators/character.d.ts.map +1 -0
  11. package/dist/generators/character.js +134 -0
  12. package/dist/generators/character.js.map +1 -0
  13. package/dist/generators/image.d.ts +43 -0
  14. package/dist/generators/image.d.ts.map +1 -0
  15. package/dist/generators/image.js +74 -0
  16. package/dist/generators/image.js.map +1 -0
  17. package/dist/generators/skybox.d.ts +18 -0
  18. package/dist/generators/skybox.d.ts.map +1 -0
  19. package/dist/generators/skybox.js +57 -0
  20. package/dist/generators/skybox.js.map +1 -0
  21. package/dist/generators/sound-effect.d.ts +31 -0
  22. package/dist/generators/sound-effect.d.ts.map +1 -0
  23. package/dist/generators/sound-effect.js +73 -0
  24. package/dist/generators/sound-effect.js.map +1 -0
  25. package/dist/http.d.ts +13 -0
  26. package/dist/http.d.ts.map +1 -0
  27. package/dist/http.js +29 -0
  28. package/dist/http.js.map +1 -0
  29. package/dist/index.d.ts +19 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +15 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/result.d.ts +6 -0
  34. package/dist/result.d.ts.map +1 -0
  35. package/dist/result.js +9 -0
  36. package/dist/result.js.map +1 -0
  37. package/dist/terminal-failure.d.ts +152 -0
  38. package/dist/terminal-failure.d.ts.map +1 -0
  39. package/dist/terminal-failure.js +203 -0
  40. package/dist/terminal-failure.js.map +1 -0
  41. package/dist/types.d.ts +89 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/dist/validation.d.ts +9 -0
  46. package/dist/validation.d.ts.map +1 -0
  47. package/dist/validation.js +12 -0
  48. package/dist/validation.js.map +1 -0
  49. package/dist/world-patch.d.ts +25 -0
  50. package/dist/world-patch.d.ts.map +1 -0
  51. package/dist/world-patch.js +59 -0
  52. package/dist/world-patch.js.map +1 -0
  53. package/package.json +71 -0
@@ -0,0 +1,42 @@
1
+ import type { CoreLogger, ForgerClient } from './types.js';
2
+ /**
3
+ * Asset Forger API client for authentication and request handling.
4
+ *
5
+ * Moved verbatim from game-play-agent; the only change is that the logger is
6
+ * injected so this package stays free of any host's logging stack.
7
+ */
8
+ export interface AssetForgerCredentials {
9
+ username: string;
10
+ password: string;
11
+ }
12
+ export declare class AssetForgerClient implements ForgerClient {
13
+ private readonly baseUrl;
14
+ private readonly credentials;
15
+ private readonly log;
16
+ constructor(logger: CoreLogger);
17
+ hasCredentials(): boolean;
18
+ getMissingCredentialsMessage(): string;
19
+ private authHeader;
20
+ private postJson;
21
+ /**
22
+ * Make a POST request to an Asset Forger endpoint
23
+ *
24
+ * @param endpoint - API endpoint path (e.g., '/ai/v1/generate-image-as-webp-url')
25
+ * @param payload - Request payload (object or pre-serialized JSON string)
26
+ * @param loggerName - Name for logging (e.g., 'SkyboxImageGenerator')
27
+ * @returns Response JSON
28
+ */
29
+ post<T = unknown>(endpoint: string, payload: unknown, loggerName: string): Promise<T>;
30
+ /**
31
+ * Submit an async job and poll until it reaches a terminal state.
32
+ *
33
+ * POSTs `payload` to `jobsEndpoint` (expects 202 with `{jobId, statusUrl}`),
34
+ * then GETs `<baseUrl><statusUrl>` every ~5s with jitter until status is
35
+ * `succeeded` (returns `result.data`) or `failed` (throws). Transient poll
36
+ * failures (network errors, non-ok responses, JSON parse errors) are retried
37
+ * up to a small limit; the 404 race with the initial status-blob write in
38
+ * GCS just after job acceptance is covered by this retry path.
39
+ */
40
+ postJobAndWait<T = unknown>(jobsEndpoint: string, payload: unknown, loggerName: string): Promise<T>;
41
+ }
42
+ //# sourceMappingURL=forger-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forger-client.d.ts","sourceRoot":"","sources":["../src/forger-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;GAKG;AAEH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiF;IACzG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgC;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;gBAErB,MAAM,EAAE,UAAU;IAgBvB,cAAc,IAAI,OAAO;IAIzB,4BAA4B,IAAI,MAAM;IAI7C,OAAO,CAAC,UAAU;YAMJ,QAAQ;IAgCtB;;;;;;;OAOG;IACU,IAAI,CAAC,CAAC,GAAG,OAAO,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC;IAMb;;;;;;;;;OASG;IACU,cAAc,CAAC,CAAC,GAAG,OAAO,EACrC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC;CA+Ed"}
@@ -0,0 +1,135 @@
1
+ export class AssetForgerClient {
2
+ constructor(logger) {
3
+ this.baseUrl = process.env.ASSET_FORGER_URL || 'https://asset-forger.staging.bitmagic.cloud';
4
+ this.log = logger;
5
+ const username = process.env.ASSET_FORGER_USER;
6
+ const password = process.env.ASSET_FORGER_PASSWORD;
7
+ this.log.info(`Initializing AssetForgerClient with URL: ${this.baseUrl}`);
8
+ if (username && password) {
9
+ this.credentials = { username, password };
10
+ this.log.info('Asset Forger credentials configured');
11
+ }
12
+ else {
13
+ this.credentials = null;
14
+ this.log.warn('Asset Forger credentials not found in environment variables');
15
+ }
16
+ }
17
+ hasCredentials() {
18
+ return this.credentials !== null;
19
+ }
20
+ getMissingCredentialsMessage() {
21
+ return 'Asset Forger credentials not found in environment variables. Please set ASSET_FORGER_USER and ASSET_FORGER_PASSWORD.';
22
+ }
23
+ authHeader() {
24
+ // Callers must check hasCredentials() first.
25
+ const { username, password } = this.credentials;
26
+ return `Basic ${btoa(`${username}:${password}`)}`;
27
+ }
28
+ async postJson(endpoint, payload, loggerName) {
29
+ if (!this.credentials) {
30
+ throw new Error('Asset Forger credentials not configured');
31
+ }
32
+ const url = `${this.baseUrl}${endpoint}`;
33
+ this.log.info(`[${loggerName}] POST ${url}`);
34
+ const response = await fetch(url, {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ 'Authorization': this.authHeader(),
39
+ },
40
+ body: typeof payload === 'string' ? payload : JSON.stringify(payload),
41
+ });
42
+ this.log.info(`[${loggerName}] API Response Status: ${response.status} ${response.statusText}`);
43
+ if (!response.ok) {
44
+ const errorText = await response.text();
45
+ this.log.error(`[${loggerName}] API Error Response:`, errorText);
46
+ throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
47
+ }
48
+ return await response.json();
49
+ }
50
+ /**
51
+ * Make a POST request to an Asset Forger endpoint
52
+ *
53
+ * @param endpoint - API endpoint path (e.g., '/ai/v1/generate-image-as-webp-url')
54
+ * @param payload - Request payload (object or pre-serialized JSON string)
55
+ * @param loggerName - Name for logging (e.g., 'SkyboxImageGenerator')
56
+ * @returns Response JSON
57
+ */
58
+ async post(endpoint, payload, loggerName) {
59
+ const json = await this.postJson(endpoint, payload, loggerName);
60
+ this.log.info(`[${loggerName}] Received response:`, json);
61
+ return json;
62
+ }
63
+ /**
64
+ * Submit an async job and poll until it reaches a terminal state.
65
+ *
66
+ * POSTs `payload` to `jobsEndpoint` (expects 202 with `{jobId, statusUrl}`),
67
+ * then GETs `<baseUrl><statusUrl>` every ~5s with jitter until status is
68
+ * `succeeded` (returns `result.data`) or `failed` (throws). Transient poll
69
+ * failures (network errors, non-ok responses, JSON parse errors) are retried
70
+ * up to a small limit; the 404 race with the initial status-blob write in
71
+ * GCS just after job acceptance is covered by this retry path.
72
+ */
73
+ async postJobAndWait(jobsEndpoint, payload, loggerName) {
74
+ const submitJson = await this.postJson(jobsEndpoint, payload, loggerName);
75
+ const { jobId, statusUrl } = submitJson;
76
+ if (!jobId || !statusUrl) {
77
+ throw new Error(`Job submission returned invalid response: ${JSON.stringify(submitJson)}`);
78
+ }
79
+ this.log.info(`[${loggerName}] Job ${jobId} accepted, polling ${statusUrl}...`);
80
+ const statusFullUrl = `${this.baseUrl}${statusUrl}`;
81
+ // Upstream's Python wrapper retries once after a per-attempt 300s timeout,
82
+ // so legitimate slow successes can take ~380s. Must exceed that ceiling.
83
+ const overallTimeoutMs = 8 * 60 * 1000;
84
+ const basePollMs = 5000;
85
+ const minPollMs = 2000;
86
+ const maxConsecutivePollErrors = 5;
87
+ const startTime = Date.now();
88
+ let consecutivePollErrors = 0;
89
+ for (;;) {
90
+ if (Date.now() - startTime > overallTimeoutMs) {
91
+ throw new Error(`Job ${jobId} exceeded client timeout of ${overallTimeoutMs}ms`);
92
+ }
93
+ // 5s ± 20% jitter, floored at 2s
94
+ const waitMs = Math.max(minPollMs, Math.round(basePollMs * (0.8 + Math.random() * 0.4)));
95
+ await new Promise(resolve => setTimeout(resolve, waitMs));
96
+ let statusJson;
97
+ try {
98
+ const statusResponse = await fetch(statusFullUrl, {
99
+ method: 'GET',
100
+ headers: { 'Authorization': this.authHeader() },
101
+ });
102
+ if (!statusResponse.ok) {
103
+ const errorText = await statusResponse.text().catch(() => '');
104
+ throw new Error(`non-ok ${statusResponse.status}: ${errorText}`);
105
+ }
106
+ statusJson = await statusResponse.json();
107
+ consecutivePollErrors = 0;
108
+ }
109
+ catch (err) {
110
+ consecutivePollErrors += 1;
111
+ const errMsg = err instanceof Error ? err.message : String(err);
112
+ if (consecutivePollErrors >= maxConsecutivePollErrors) {
113
+ throw new Error(`Job ${jobId} polling failed: ${consecutivePollErrors} consecutive errors. Last: ${errMsg}`);
114
+ }
115
+ this.log.warn(`[${loggerName}] Status poll error (${consecutivePollErrors}/${maxConsecutivePollErrors}), will retry: ${errMsg}`);
116
+ continue;
117
+ }
118
+ if (statusJson.status === 'succeeded') {
119
+ this.log.info(`[${loggerName}] Job ${jobId} succeeded`);
120
+ if (!statusJson.result) {
121
+ throw new Error(`Job ${jobId} succeeded but has no result`);
122
+ }
123
+ return statusJson.result;
124
+ }
125
+ if (statusJson.status === 'failed') {
126
+ const errStr = typeof statusJson.error === 'string'
127
+ ? statusJson.error
128
+ : JSON.stringify(statusJson.error ?? 'unknown error');
129
+ const httpPart = statusJson.httpStatus ? ` (httpStatus=${statusJson.httpStatus})` : '';
130
+ throw new Error(`Job ${jobId} failed${httpPart}: ${errStr}`);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ //# sourceMappingURL=forger-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forger-client.js","sourceRoot":"","sources":["../src/forger-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { z } from 'zod';
2
+ import type { AssetResultBase, GenerateDeps } from '../types.js';
3
+ /**
4
+ * `process.env.ANIMATION_MODEL` is the one env read this package gains beyond
5
+ * `forger-client.ts`'s existing `ASSET_FORGER_*` reads. It is not a violation
6
+ * of "no module globals": it configures the upstream call itself (which
7
+ * animation model asset-forger receives), exactly like the Forger URL and
8
+ * credentials env reads in `forger-client.ts`. It is read once per generation
9
+ * call, not cached at module load, so it stays test- and CLI-friendly.
10
+ */
11
+ /**
12
+ * The text-to-motion-3.0 model constrains animation length to 4-8 seconds;
13
+ * out-of-range values are clamped in buildRequest below.
14
+ */
15
+ export declare const ANIMATION_MODEL_TEXT_TO_MOTION_3 = "text-to-motion-3.0";
16
+ /** The older, faster model — also the fallback when text-to-motion-3.0 fails. */
17
+ export declare const ANIMATION_MODEL_TEXT_TO_MOTION_2 = "text-to-motion-2.0";
18
+ /**
19
+ * UI/request sentinel meaning "the older, faster model" (text-to-motion-2.0).
20
+ * Distinct from an absent override, which inherits the ANIMATION_MODEL env
21
+ * default. Used by the generate-animation tool's per-request override.
22
+ */
23
+ export declare const ANIMATION_MODEL_OLDER = "older";
24
+ /**
25
+ * Model for the asset-forger animation generator. Defaults to
26
+ * text-to-motion-3.0 when `ANIMATION_MODEL` is unset. Set `ANIMATION_MODEL`
27
+ * to another model id (or `older` for text-to-motion-2.0) to override.
28
+ */
29
+ export declare function getConfiguredAnimationModel(): string;
30
+ export declare const animationParamsSchema: z.ZodObject<{
31
+ description: z.ZodString;
32
+ cfgScale: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
33
+ length: z.ZodOptional<z.ZodNumber>;
34
+ seed: z.ZodOptional<z.ZodNumber>;
35
+ footIk: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
36
+ inPlace: z.ZodOptional<z.ZodBoolean>;
37
+ loop: z.ZodOptional<z.ZodBoolean>;
38
+ assetId: z.ZodOptional<z.ZodString>;
39
+ /**
40
+ * Explicit per-request model override, e.g. from the game-play-agent
41
+ * runtimeContext's `animationModel`. `undefined` inherits the
42
+ * ANIMATION_MODEL-configured default. Not part of the LLM-facing tool
43
+ * schema — the adapter resolves this from its own session state and passes
44
+ * it through.
45
+ */
46
+ model: z.ZodOptional<z.ZodString>;
47
+ }, "strict", z.ZodTypeAny, {
48
+ description: string;
49
+ cfgScale: number;
50
+ footIk: boolean;
51
+ length?: number | undefined;
52
+ loop?: boolean | undefined;
53
+ assetId?: string | undefined;
54
+ seed?: number | undefined;
55
+ inPlace?: boolean | undefined;
56
+ model?: string | undefined;
57
+ }, {
58
+ description: string;
59
+ length?: number | undefined;
60
+ loop?: boolean | undefined;
61
+ assetId?: string | undefined;
62
+ cfgScale?: number | undefined;
63
+ seed?: number | undefined;
64
+ footIk?: boolean | undefined;
65
+ inPlace?: boolean | undefined;
66
+ model?: string | undefined;
67
+ }>;
68
+ /**
69
+ * The schema's INPUT type — callers may omit the defaulted fields. The
70
+ * generator parses on entry and works with the output type internally, which
71
+ * is what lets it own its own defaults instead of each host patching them in.
72
+ */
73
+ export type AnimationParams = z.input<typeof animationParamsSchema>;
74
+ export type AnimationResult = AssetResultBase & {
75
+ animationUrl?: string;
76
+ /** The id the animation was stored under: `assetId` when supplied, else the generator's own motionId. */
77
+ motionId?: string;
78
+ /**
79
+ * Resolved animation length in seconds actually sent to asset-forger for the
80
+ * attempt that succeeded (after defaults and text-to-motion-3.0 clamping).
81
+ * The adapter passes this as `units` to `reportToolExecution` for
82
+ * per-second billing — it must reflect the duration actually generated.
83
+ */
84
+ lengthSeconds?: number;
85
+ /**
86
+ * Model actually used by the successful attempt (absent on total failure,
87
+ * since no attempt succeeded). The adapter passes this as `model` to
88
+ * `reportToolExecution`, which resolves the per-second rate via
89
+ * `cost_per_second_by_model[model] ?? cost_per_second`.
90
+ */
91
+ model?: string;
92
+ /**
93
+ * True once a response with a resolvable animation URL was received.
94
+ * Left unset on any failure — including "the Forger responded but with no
95
+ * URL" — matching the original tool, which never billed a fully-failed
96
+ * generation (unlike the job-based character/skybox generators, this
97
+ * endpoint answers synchronously with no separate "job accepted" moment).
98
+ */
99
+ billable?: boolean;
100
+ };
101
+ export declare function generateAnimationAsset(params: AnimationParams, deps: GenerateDeps): Promise<AnimationResult>;
102
+ //# sourceMappingURL=animation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation.d.ts","sourceRoot":"","sources":["../../src/generators/animation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAA4B,YAAY,EAAc,MAAM,aAAa,CAAC;AAIvG;;;;;;;GAOG;AAEH;;;GAGG;AACH,eAAO,MAAM,gCAAgC,uBAAuB,CAAC;AAIrE,iFAAiF;AACjF,eAAO,MAAM,gCAAgC,uBAAuB,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAe7C;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAMpD;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;IAiBhC;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;EAGM,CAAC;AAEZ;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAwIF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,eAAe,CAAC,CAwF1B"}
@@ -0,0 +1,234 @@
1
+ import { z } from 'zod';
2
+ import { fail, ok } from '../result.js';
3
+ import { formatZodIssues } from '../validation.js';
4
+ /**
5
+ * `process.env.ANIMATION_MODEL` is the one env read this package gains beyond
6
+ * `forger-client.ts`'s existing `ASSET_FORGER_*` reads. It is not a violation
7
+ * of "no module globals": it configures the upstream call itself (which
8
+ * animation model asset-forger receives), exactly like the Forger URL and
9
+ * credentials env reads in `forger-client.ts`. It is read once per generation
10
+ * call, not cached at module load, so it stays test- and CLI-friendly.
11
+ */
12
+ /**
13
+ * The text-to-motion-3.0 model constrains animation length to 4-8 seconds;
14
+ * out-of-range values are clamped in buildRequest below.
15
+ */
16
+ export const ANIMATION_MODEL_TEXT_TO_MOTION_3 = 'text-to-motion-3.0';
17
+ const TEXT_TO_MOTION_3_MIN_LENGTH = 4;
18
+ const TEXT_TO_MOTION_3_MAX_LENGTH = 8;
19
+ /** The older, faster model — also the fallback when text-to-motion-3.0 fails. */
20
+ export const ANIMATION_MODEL_TEXT_TO_MOTION_2 = 'text-to-motion-2.0';
21
+ /**
22
+ * UI/request sentinel meaning "the older, faster model" (text-to-motion-2.0).
23
+ * Distinct from an absent override, which inherits the ANIMATION_MODEL env
24
+ * default. Used by the generate-animation tool's per-request override.
25
+ */
26
+ export const ANIMATION_MODEL_OLDER = 'older';
27
+ const DEFAULT_LENGTH_SECONDS = 3;
28
+ const FIXED_STEPS = 100;
29
+ // Per-attempt timeouts. text-to-motion-3.0 clips can take ~2.5min+ server-side
30
+ // (and retry internally in asset-forger), so it gets a generous 10min; the
31
+ // text-to-motion-2.0 fallback is faster, so 3min. Legacy non-T2M3 path stays at 6min.
32
+ const T2M3_TIMEOUT_MS = 600000; // 10 minutes
33
+ const FALLBACK_TIMEOUT_MS = 180000; // 3 minutes
34
+ const LEGACY_TIMEOUT_MS = 360000; // 6 minutes
35
+ const RETRY_DELAY_MS = 2000;
36
+ const ENDPOINT = '/ai/v1/generate-animation-as-glb-url';
37
+ /**
38
+ * Model for the asset-forger animation generator. Defaults to
39
+ * text-to-motion-3.0 when `ANIMATION_MODEL` is unset. Set `ANIMATION_MODEL`
40
+ * to another model id (or `older` for text-to-motion-2.0) to override.
41
+ */
42
+ export function getConfiguredAnimationModel() {
43
+ const configured = process.env.ANIMATION_MODEL;
44
+ if (configured === ANIMATION_MODEL_OLDER) {
45
+ return ANIMATION_MODEL_TEXT_TO_MOTION_2;
46
+ }
47
+ return configured || ANIMATION_MODEL_TEXT_TO_MOTION_3;
48
+ }
49
+ export const animationParamsSchema = z.object({
50
+ description: z.string().min(1)
51
+ .describe('Simple action phrase describing the animation (e.g., "A person swimming slowly")'),
52
+ cfgScale: z.number().optional().default(6.0)
53
+ .describe('Classifier-free guidance scale (higher = more prompt adherence). Defaults to 6.0.'),
54
+ length: z.number().optional()
55
+ .describe('Animation length in seconds. Defaults to 3.0. Note: the text-to-motion-3.0 model only supports 4–8s (out-of-range values are clamped).'),
56
+ seed: z.number().optional()
57
+ .describe('Random seed for reproducibility. Omit for random results.'),
58
+ footIk: z.boolean().optional().default(true)
59
+ .describe('Enable foot IK (inverse kinematics) for grounded animations. Defaults to true. Set to false for airborne animations like jumping.'),
60
+ inPlace: z.boolean().optional()
61
+ .describe('Generate animation where the character stays in place (e.g., idle animations). Defaults to false.'),
62
+ loop: z.boolean().optional()
63
+ .describe('Whether the animation should loop continuously. Set to true for idle animations. Defaults to false.'),
64
+ assetId: z.string().optional()
65
+ .describe('Pre-generated asset id from the manifest. When provided, the animation is stored under this exact id (used as its motionId for playCustomAnimation) so code that references it resolves. If omitted, the generator motionId is used.'),
66
+ /**
67
+ * Explicit per-request model override, e.g. from the game-play-agent
68
+ * runtimeContext's `animationModel`. `undefined` inherits the
69
+ * ANIMATION_MODEL-configured default. Not part of the LLM-facing tool
70
+ * schema — the adapter resolves this from its own session state and passes
71
+ * it through.
72
+ */
73
+ model: z.string().optional()
74
+ .describe('Explicit model override for this call. Omit to use the configured ANIMATION_MODEL default.'),
75
+ }).strict();
76
+ /**
77
+ * Resolve which model this call should start with: an explicit per-request
78
+ * `model` override wins (`text-to-motion-3.0` names that model directly,
79
+ * `older` forces text-to-motion-2.0 even over an ANIMATION_MODEL=3.0 env
80
+ * default); any other value (including absent) inherits the configured
81
+ * default. An unrecognized override string is not treated as an explicit
82
+ * model id — it falls through to the env default, matching the original
83
+ * tool's behaviour.
84
+ */
85
+ function resolveEffectiveModel(modelOverride) {
86
+ if (modelOverride === ANIMATION_MODEL_TEXT_TO_MOTION_3) {
87
+ return ANIMATION_MODEL_TEXT_TO_MOTION_3;
88
+ }
89
+ if (modelOverride === ANIMATION_MODEL_OLDER) {
90
+ return ANIMATION_MODEL_TEXT_TO_MOTION_2;
91
+ }
92
+ return getConfiguredAnimationModel();
93
+ }
94
+ /**
95
+ * Attempt plan for a resolved starting model. text-to-motion-3.0 retries
96
+ * internally in asset-forger, so we NEVER retry it client-side; instead, on
97
+ * failure we fall back to text-to-motion-2.0 for a single attempt. Any other
98
+ * configured model keeps the legacy 2-attempt retry (same model twice).
99
+ */
100
+ function buildAttemptPlan(effectiveModel) {
101
+ if (effectiveModel === ANIMATION_MODEL_TEXT_TO_MOTION_3) {
102
+ return [
103
+ { model: ANIMATION_MODEL_TEXT_TO_MOTION_3, label: ANIMATION_MODEL_TEXT_TO_MOTION_3, timeoutMs: T2M3_TIMEOUT_MS },
104
+ { model: ANIMATION_MODEL_TEXT_TO_MOTION_2, label: `${ANIMATION_MODEL_TEXT_TO_MOTION_2}-fallback`, timeoutMs: FALLBACK_TIMEOUT_MS },
105
+ ];
106
+ }
107
+ return [
108
+ { model: effectiveModel, label: effectiveModel, timeoutMs: LEGACY_TIMEOUT_MS },
109
+ { model: effectiveModel, label: `${effectiveModel}-retry`, timeoutMs: LEGACY_TIMEOUT_MS },
110
+ ];
111
+ }
112
+ /**
113
+ * Builds the resolved asset-forger request for one attempt (applies the
114
+ * text-to-motion-3.0 length clamp). Returning the object (rather than only a
115
+ * JSON string) lets the caller read the resolved length/model back for
116
+ * per-second billing without re-parsing what was sent.
117
+ */
118
+ function buildRequest(input, model, logger) {
119
+ const payload = {
120
+ prompt: input.description,
121
+ format: 'glb',
122
+ model,
123
+ bucmd: true,
124
+ footIk: input.footIk,
125
+ length: input.length ?? DEFAULT_LENGTH_SECONDS,
126
+ cfgScale: input.cfgScale,
127
+ steps: FIXED_STEPS,
128
+ ...(input.seed !== undefined && { seed: input.seed }),
129
+ ...(input.inPlace !== undefined && { inPlace: input.inPlace }),
130
+ };
131
+ // text-to-motion-3.0 only accepts 4-8s clips. Clamp the resolved length into
132
+ // range; other models (including the text-to-motion-2.0 fallback) send it
133
+ // as-is.
134
+ if (model === ANIMATION_MODEL_TEXT_TO_MOTION_3) {
135
+ const clamped = Math.min(TEXT_TO_MOTION_3_MAX_LENGTH, Math.max(TEXT_TO_MOTION_3_MIN_LENGTH, payload.length));
136
+ if (clamped !== payload.length) {
137
+ logger.info(`[animation] Clamped length ${payload.length}s -> ${clamped}s for ${model} (allowed ${TEXT_TO_MOTION_3_MIN_LENGTH}-${TEXT_TO_MOTION_3_MAX_LENGTH}s)`);
138
+ payload.length = clamped;
139
+ }
140
+ }
141
+ return payload;
142
+ }
143
+ function withTimeout(promise, timeoutMs) {
144
+ let timer;
145
+ const timeout = new Promise((_, reject) => {
146
+ timer = setTimeout(() => reject(new Error(`Animation generation timed out after ${timeoutMs / 60000} minutes`)), timeoutMs);
147
+ });
148
+ // Clearing the loser's timer matters beyond tidiness: an un-cleared 10-minute
149
+ // timeout keeps the process (and a test runner's event loop) alive long after
150
+ // every real attempt has already settled.
151
+ return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
152
+ }
153
+ function sleep(ms) {
154
+ return new Promise((resolve) => setTimeout(resolve, ms));
155
+ }
156
+ async function requestAnimation(forger, requestPayload, logger) {
157
+ logger.info({ payload: requestPayload }, '[animation] Request payload');
158
+ const response = await forger.post(ENDPOINT, JSON.stringify(requestPayload), 'AnimationGenerator');
159
+ if (!response.animationUrl) {
160
+ throw new Error('No animation URL found in API response');
161
+ }
162
+ return { animationUrl: response.animationUrl, motionId: response.motionId };
163
+ }
164
+ export async function generateAnimationAsset(params, deps) {
165
+ const { forger, logger, onProgress } = deps;
166
+ const parsed = animationParamsSchema.safeParse(params);
167
+ if (!parsed.success) {
168
+ logger.warn({ err: parsed.error }, '[animation] Invalid parameters');
169
+ return fail(formatZodIssues(parsed.error));
170
+ }
171
+ const input = parsed.data;
172
+ if (!forger.hasCredentials()) {
173
+ logger.error('[animation] Missing Asset Forger credentials');
174
+ return fail(forger.getMissingCredentialsMessage());
175
+ }
176
+ onProgress(`Generating animation: "${input.description}"`);
177
+ logger.info(`[animation] Starting generation for: "${input.description}"`);
178
+ const effectiveModel = resolveEffectiveModel(input.model);
179
+ const usingTextToMotion3 = effectiveModel === ANIMATION_MODEL_TEXT_TO_MOTION_3;
180
+ const attempts = buildAttemptPlan(effectiveModel);
181
+ let lastError = null;
182
+ for (let attempt = 0; attempt < attempts.length; attempt++) {
183
+ const { model, label, timeoutMs } = attempts[attempt];
184
+ const requestPayload = buildRequest(input, model, logger);
185
+ try {
186
+ const { animationUrl, motionId } = await withTimeout(requestAnimation(forger, requestPayload, logger), timeoutMs);
187
+ logger.info(`[animation] Successfully generated animation GLB URL: ${animationUrl}`);
188
+ logger.info(`[animation] Motion ID: ${motionId}`);
189
+ // The engine derives motionId from the asset id (see mergeGameData in
190
+ // game/src/types/game.ts) and loads the clip by URL, so honoring a
191
+ // pre-generated id from the manifest makes code that references it (via
192
+ // playCustomAnimation("<id>")) resolve. Falls back to the generator's
193
+ // own motionId when no id was pre-minted.
194
+ const finalMotionId = input.assetId ?? motionId;
195
+ const patch = {
196
+ type: 'pushRoot',
197
+ path: ['assets'],
198
+ value: {
199
+ id: finalMotionId,
200
+ name: input.description,
201
+ url: animationUrl,
202
+ type: 'animation',
203
+ prompt: input.description,
204
+ source: 'generated',
205
+ size: 0,
206
+ ...(input.loop !== undefined && { loop: input.loop }),
207
+ },
208
+ };
209
+ return ok(`Animation generated: ${animationUrl}`, [patch], {
210
+ animationUrl,
211
+ motionId: finalMotionId,
212
+ lengthSeconds: requestPayload.length,
213
+ model,
214
+ billable: true,
215
+ });
216
+ }
217
+ catch (error) {
218
+ lastError = error instanceof Error ? error : new Error('Unknown error occurred');
219
+ logger.error({ err: lastError }, `[animation] ${label} attempt failed`);
220
+ }
221
+ if (attempt < attempts.length - 1) {
222
+ const next = attempts[attempt + 1];
223
+ const reason = usingTextToMotion3
224
+ ? `${label} failed, falling back to ${next.label}`
225
+ : `attempt ${attempt + 1} failed, retrying`;
226
+ logger.warn(`[animation] ${reason} in ${RETRY_DELAY_MS}ms...`);
227
+ await sleep(RETRY_DELAY_MS);
228
+ }
229
+ }
230
+ const message = lastError?.message ?? 'Failed to generate animation';
231
+ logger.error({ err: lastError }, `[animation] Generation failed after ${attempts.length} attempts`);
232
+ return fail(message);
233
+ }
234
+ //# sourceMappingURL=animation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation.js","sourceRoot":"","sources":["../../src/generators/animation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ import type { AssetResultBase, GenerateDeps } from '../types.js';
3
+ export declare const characterParamsSchema: z.ZodObject<{
4
+ name: z.ZodString;
5
+ prompt: z.ZodString;
6
+ applyToPlayer: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
7
+ headScale: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
8
+ assetId: z.ZodOptional<z.ZodString>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ prompt: string;
11
+ name: string;
12
+ applyToPlayer: boolean;
13
+ headScale: number;
14
+ assetId?: string | undefined;
15
+ }, {
16
+ prompt: string;
17
+ name: string;
18
+ assetId?: string | undefined;
19
+ applyToPlayer?: boolean | undefined;
20
+ headScale?: number | undefined;
21
+ }>;
22
+ /**
23
+ * The schema's INPUT type — callers may omit the defaulted fields. The
24
+ * generator parses on entry and works with the output type internally, which
25
+ * is what lets it own its own defaults instead of each host patching them in.
26
+ */
27
+ export type CharacterParams = z.input<typeof characterParamsSchema>;
28
+ export type CharacterResult = AssetResultBase & {
29
+ assetId?: string;
30
+ characterUrl?: string;
31
+ /**
32
+ * True once the Asset Forger has accepted the rigged-character job — the
33
+ * vendor bills on acceptance, so a downstream failure (no resolvable URL)
34
+ * still costs. Left unset when the job submission itself threw, which is
35
+ * how the tool has always billed.
36
+ */
37
+ billable?: boolean;
38
+ };
39
+ export declare function generateCharacter(params: CharacterParams, deps: GenerateDeps): Promise<CharacterResult>;
40
+ //# sourceMappingURL=character.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character.d.ts","sourceRoot":"","sources":["../../src/generators/character.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAI7E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;EAqBvB,CAAC;AAEZ;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAWF,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,eAAe,CAAC,CA6H1B"}