@hypersoniclabs/helix-cli 0.1.25-helix3.465 → 0.1.25-helix3.467
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 +3 -3
- package/dist/api.d.ts +4 -0
- package/dist/api.js +39 -2
- package/dist/api.js.map +1 -1
- package/dist/assetGenerationDriver.d.ts +24 -1
- package/dist/assetGenerationDriver.js +43 -5
- package/dist/assetGenerationDriver.js.map +1 -1
- package/dist/authRefresh.d.ts +9 -0
- package/dist/authRefresh.js +61 -0
- package/dist/authRefresh.js.map +1 -0
- package/dist/character/stages/armBindFixRig.js +1 -1
- package/dist/character/stages/armBindFixRig.js.map +1 -1
- package/dist/character/stages/clothWeights.d.ts +61 -0
- package/dist/character/stages/clothWeights.js +265 -0
- package/dist/character/stages/clothWeights.js.map +1 -0
- package/dist/character/stages/hairWeights.d.ts +7 -0
- package/dist/character/stages/hairWeights.js +8 -3
- package/dist/character/stages/hairWeights.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +47 -9
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_stock_events.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/fmod_studio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/fsb5.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_ac.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_beamng.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_fixtures.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_sim_audio.cpython-312.pyc +0 -0
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ The token is stored in `~/.helix/credentials.json` (mode `600`). It's sent as
|
|
|
47
47
|
|---|---|
|
|
48
48
|
| `helix bridge detect\|inspect\|plan\|import\|validate\|doctor` | Universal plugin-driven intake for assets, characters, animations, scenes, and engine projects. Produces deterministic plans, HELIX-native outputs, and checksummed provenance. See [`docs/bridge.md`](docs/bridge.md). |
|
|
49
49
|
| `helix bridge plugins create\|test\|list\|inspect\|install\|remove` | Build and manage local/community Bridge Plugins using the versioned capability and permission contract. |
|
|
50
|
-
| `helix login [--api-url <url>] [--web-url <url>] [--token <t>] [--no-browser]` | Sign in via the browser (`/cli-login`), or `--token` for CI/headless. Stores the client token. |
|
|
50
|
+
| `helix login [--api-url <url>] [--web-url <url>] [--token <t> [--refresh-token <r>]] [--no-browser]` | Sign in via the browser (`/cli-login`), or `--token` for CI/headless. Stores the client token. `--refresh-token` (or `HELIX_REFRESH_TOKEN`) pairs a short-lived access token with its refresh token so a long command (`assets resume`) renews it when it expires. |
|
|
51
51
|
| `helix logout` | Remove the stored token. |
|
|
52
52
|
| `helix whoami` | Show current login status. |
|
|
53
53
|
| `helix init <dir> [--kind character\|multiplayer\|scene]` | Scaffold a complete, build-ready Vite + TypeScript world. `--kind scene` emits a multiplayer world whose ENVIRONMENT is a sealed HELIX Scene v2 document — the starter document is compiled offline into `public/scene/mall/`, pinned in `public/helix.json`'s `scene` field, kept out of the bundle by `public/.helixignore`, and lit by `public/helix.visuals.json` through the `scene` + `visual` system pins. |
|
|
@@ -86,8 +86,8 @@ The token is stored in `~/.helix/credentials.json` (mode `600`). It's sent as
|
|
|
86
86
|
| `helix assets start\|status\|generate\|resume` | Start or poll generation without duplicates. Props/characters use the Asset Generation job lane; standalone assets use the shared broker and report the auto-published `vaultAssetId`. `generate` and `resume` block waiting for the job (see `--timeout`/`--poll-interval` below). |
|
|
87
87
|
| `helix assets voices [--search <text>] [--category premade\|professional] [--page-size <n>] [--page-token <token>] [--json]` | Discover safe text-to-speech voices through the authenticated HELIX catalog, including language, labels, preview, default/recommended selection, and pagination. |
|
|
88
88
|
| `helix assets generate-image\|generate-material\|generate-audio\|generate-environment` | Run the supported standalone generation adapters. Material is a validated PBR bundle (1K default, explicit 2K); splats declare object/environment scope. Animation remains an explicit unavailable boundary. |
|
|
89
|
-
| `helix assets start character "<prompt>" [--title t] [--visibility v] [--max-lix n]` | Starts a character on the server-side Asset Generation job driver (`POST /api/v1/asset-generation/jobs`, `mode: deterministic`) and returns at once; stdout is the driver job JSON (`id`). `--visibility` is sent only when you pass it; the server owns the default and every other policy (reference review, redraws, retries, visual QA wait, WARN/BLOCK, refunds). |
|
|
90
|
-
| `helix assets resume <id> [--timeout <ms>] [--poll-interval <ms>]` (driver job) | Waits for `succeeded`, `held`, `failed` or `handoff` (default **80 min**, poll **3 s**), one progress line per change on stderr (stage, reference gate, scheduled retry, policy events, cost). Final stdout is the driver job JSON plus top-level `publishedItemId` (= `result.itemId`). Exit 0 for succeeded, held (the item exists but is not released; `result.qa` says why; `helix assets refund <id>` is offered) and handoff; exit 1 for `failed` (JSON on stdout, message with `escalate`/`retriable` on stderr) and for a client-side timeout (nothing on stdout). `--visibility` must match the job's (it is fixed at start) or the command exits 1. An id the driver does not know (props, older characters) resumes through the previous loop below. `helix assets generate character` is `start` + `resume`. |
|
|
89
|
+
| `helix assets start character "<prompt>" [--title t] [--visibility v] [--idempotency-key k] [--max-lix n]` | Starts a character on the server-side Asset Generation job driver (`POST /api/v1/asset-generation/jobs`, `mode: deterministic`) and returns at once; stdout is the driver job JSON (`id`). `--visibility` is sent only when you pass it; the server owns the default and every other policy (reference review, redraws, retries, visual QA wait, WARN/BLOCK, refunds). The create is retry-safe: the CLI picks one idempotency key (a UUID, or your `--idempotency-key`, 8-96 chars), sends the same key on every try (3 tries on a timeout, dropped connection or 5xx), and the backend returns the existing job for the same owner and key, so a timeout after the server created the job never duplicates or double charges. The key is printed on stderr and in the stdout JSON as `idempotencyKey`; if a run's answer was lost, re-run the same command with `--idempotency-key <key>`. |
|
|
90
|
+
| `helix assets resume <id> [--timeout <ms>] [--poll-interval <ms>]` (driver job) | Waits for `succeeded`, `held`, `failed` or `handoff` (default **80 min**, poll **3 s**), one progress line per change on stderr (stage, reference gate, scheduled retry, policy events, cost). Final stdout is the driver job JSON plus top-level `publishedItemId` (= `result.itemId`). Exit 0 for succeeded, held (the item exists but is not released; `result.qa` says why; `helix assets refund <id>` is offered) and handoff; exit 1 for `failed` (JSON on stdout, message with `escalate`/`retriable` on stderr) and for a client-side timeout (nothing on stdout). `--visibility` must match the job's (it is fixed at start) or the command exits 1. An access token that expires during the wait is renewed (see Login below: `helix login --token <access> --refresh-token <refresh>` or `HELIX_REFRESH_TOKEN`; otherwise another process's fresh `helix login` is picked up); a login that cannot be renewed ends the wait with `helix login` + `helix assets resume <id>`, and the job keeps running. An id the driver does not know (props, older characters) resumes through the previous loop below. `helix assets generate character` is `start` + `resume`. |
|
|
91
91
|
| `helix assets act <id> approve\|revise ["guidance"]`, `helix assets refund <id>`, `helix assets status <id> --pipeline driver` | Decide at the open reference gate, get the LIX back for a held avatar, or read the raw driver job. |
|
|
92
92
|
| `helix assets start-reference\|generate-reference` | Start or fully drive a character job from a local four-view PNG/JPEG/WebP. The backend validates and reuses the exact sheet; it skips image generation while preserving mesh, texture, rig, LOD, thumbnail, billing, and Vault publication. `generate-reference` blocks waiting for the job (see `--timeout`/`--poll-interval` below). |
|
|
93
93
|
| `helix assets generate\|generate-reference\|resume [--timeout <ms>] [--poll-interval <ms>]` | These three drive an Asset Generation prop/character job to completion (concept → mesh → texture → rig → publish) and block until it finishes. `--timeout` bounds how long the CLI process waits before giving up (default **1200000ms / 20min**, unchanged if omitted); `--poll-interval` sets how often it checks job status while waiting (default **2000ms**). A timeout is a CLIENT-SIDE giveup, not a job failure — the job keeps running server-side. The error prints the exact `helix assets resume <job-id>` command to check on or continue it; on a genuinely slow stage (e.g. mesh generation), rerun with a larger `--timeout`, or just poll separately with `helix assets status <job-id> --pipeline dreamer`. |
|
package/dist/api.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ export declare class HelixApi {
|
|
|
17
17
|
private token;
|
|
18
18
|
constructor(baseUrl: string, token?: string | null);
|
|
19
19
|
setToken(token: string): void;
|
|
20
|
+
private refresher;
|
|
21
|
+
private inflightRefresh;
|
|
22
|
+
setRefresher(refresher: (() => Promise<string | null>) | null): void;
|
|
23
|
+
private renewToken;
|
|
20
24
|
/**
|
|
21
25
|
* A stable, non-reversible scope for durable client state (for example the
|
|
22
26
|
* resumable large-upload checkpoint). It binds that state to this API origin
|
package/dist/api.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.HelixApi = exports.ApiError = exports.API_FETCH_TIMEOUT_MS = void 0;
|
|
4
4
|
exports.uploadToTicket = uploadToTicket;
|
|
5
5
|
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const authRefresh_1 = require("./authRefresh");
|
|
6
7
|
exports.API_FETCH_TIMEOUT_MS = 30_000;
|
|
7
8
|
function withTimeout(init, timeoutMs = exports.API_FETCH_TIMEOUT_MS) {
|
|
8
9
|
return { ...init, signal: AbortSignal.timeout(timeoutMs) };
|
|
@@ -42,6 +43,28 @@ class HelixApi {
|
|
|
42
43
|
setToken(token) {
|
|
43
44
|
this.token = token;
|
|
44
45
|
}
|
|
46
|
+
// Asked for a newer token after a 401; resolves to it or null. Installed by forCredentials.
|
|
47
|
+
refresher = null;
|
|
48
|
+
inflightRefresh = null;
|
|
49
|
+
setRefresher(refresher) {
|
|
50
|
+
this.refresher = refresher;
|
|
51
|
+
}
|
|
52
|
+
// One shared refresh for concurrent 401s.
|
|
53
|
+
async renewToken(staleToken) {
|
|
54
|
+
if (!this.refresher)
|
|
55
|
+
return false;
|
|
56
|
+
// Another call already renewed while this one was in flight.
|
|
57
|
+
if (this.token && this.token !== staleToken)
|
|
58
|
+
return true;
|
|
59
|
+
this.inflightRefresh ??= this.refresher().finally(() => {
|
|
60
|
+
this.inflightRefresh = null;
|
|
61
|
+
});
|
|
62
|
+
const next = await this.inflightRefresh;
|
|
63
|
+
if (!next)
|
|
64
|
+
return false;
|
|
65
|
+
this.token = next;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
45
68
|
/**
|
|
46
69
|
* A stable, non-reversible scope for durable client state (for example the
|
|
47
70
|
* resumable large-upload checkpoint). It binds that state to this API origin
|
|
@@ -63,7 +86,7 @@ class HelixApi {
|
|
|
63
86
|
.slice(0, 32);
|
|
64
87
|
}
|
|
65
88
|
async request(method, path, body) {
|
|
66
|
-
const
|
|
89
|
+
const send = () => fetch(`${this.baseUrl}${path}`, withTimeout({
|
|
67
90
|
method,
|
|
68
91
|
headers: {
|
|
69
92
|
'content-type': 'application/json',
|
|
@@ -71,6 +94,11 @@ class HelixApi {
|
|
|
71
94
|
},
|
|
72
95
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
73
96
|
}));
|
|
97
|
+
const sentWith = this.token;
|
|
98
|
+
let res = await send();
|
|
99
|
+
// A 401 means nothing was done: renew the token once and replay the identical request.
|
|
100
|
+
if (res.status === 401 && (await this.renewToken(sentWith)))
|
|
101
|
+
res = await send();
|
|
74
102
|
if (!res.ok) {
|
|
75
103
|
const problem = (await res.json().catch(() => ({})));
|
|
76
104
|
throw new ApiError(res.status, problem);
|
|
@@ -128,7 +156,16 @@ class HelixApi {
|
|
|
128
156
|
return (await res.json());
|
|
129
157
|
}
|
|
130
158
|
static forCredentials(creds) {
|
|
131
|
-
|
|
159
|
+
const api = new HelixApi(creds.apiUrl, creds.token);
|
|
160
|
+
let current = creds;
|
|
161
|
+
api.setRefresher(async () => {
|
|
162
|
+
const next = await (0, authRefresh_1.refreshCredentials)(current);
|
|
163
|
+
if (!next)
|
|
164
|
+
return null;
|
|
165
|
+
current = next;
|
|
166
|
+
return next.token;
|
|
167
|
+
});
|
|
168
|
+
return api;
|
|
132
169
|
}
|
|
133
170
|
}
|
|
134
171
|
exports.HelixApi = HelixApi;
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,8 +64,29 @@ export interface StartDriverAvatarInput {
|
|
|
64
64
|
title?: string;
|
|
65
65
|
/** Sent ONLY when the user chose one; the server owns the default. */
|
|
66
66
|
visibility?: DriverVisibility;
|
|
67
|
+
/** The caller's own key (8-96 chars). Default: a fresh UUID. */
|
|
68
|
+
idempotencyKey?: string;
|
|
67
69
|
}
|
|
68
|
-
export
|
|
70
|
+
export interface StartRetryOptions {
|
|
71
|
+
/** Total tries of the create call (default 3). Every try carries the SAME idempotency key. */
|
|
72
|
+
attempts?: number;
|
|
73
|
+
/** Backoff before try n+1 (default 1s, 3s). */
|
|
74
|
+
backoffMs?: (attempt: number) => number;
|
|
75
|
+
sleep?: (ms: number) => Promise<void>;
|
|
76
|
+
/** One human line per retry (the caller sends it to stderr). */
|
|
77
|
+
onRetry?: (line: string) => void;
|
|
78
|
+
}
|
|
79
|
+
/** A create that may have reached the server: no answer (timeout, dropped connection) or a gateway/server error. */
|
|
80
|
+
export declare function isAmbiguousCreateFailure(err: unknown): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Create the avatar job. The idempotency key is chosen ONCE and sent on every try, so a timeout after the server had
|
|
83
|
+
* already created the job re-attaches to that job on the next try (the backend returns the existing job for the same
|
|
84
|
+
* owner and key) instead of creating and charging a second one. The key is returned so a caller whose own process
|
|
85
|
+
* died can re-run the start with it.
|
|
86
|
+
*/
|
|
87
|
+
export declare function startDriverAvatarJob(api: DriverApi, input: StartDriverAvatarInput, newKey?: () => string, retry?: StartRetryOptions): Promise<DriverJobView & {
|
|
88
|
+
idempotencyKey: string;
|
|
89
|
+
}>;
|
|
69
90
|
/** The driver job, or null when the id is not a driver job (a legacy generation job id, a prop). */
|
|
70
91
|
export declare function getDriverJob(api: DriverApi, id: string): Promise<DriverJobView | null>;
|
|
71
92
|
export declare class DriverVisibilityError extends Error {
|
|
@@ -86,6 +107,8 @@ export interface ResumeDriverOptions {
|
|
|
86
107
|
progress?: (line: string) => void;
|
|
87
108
|
sleep?: (ms: number) => Promise<void>;
|
|
88
109
|
now?: () => number;
|
|
110
|
+
/** Echoed into the printed job JSON as `idempotencyKey`, so a `generate` run records the key its start used. */
|
|
111
|
+
idempotencyKey?: string;
|
|
89
112
|
}
|
|
90
113
|
/**
|
|
91
114
|
* Wait for a driver job to reach a terminal status. Returns null when `id` is not a driver job (the caller falls
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DriverTimeoutError = exports.DriverVisibilityError = exports.DRIVER_DEFAULT_POLL_MS = exports.DRIVER_DEFAULT_TIMEOUT_MS = exports.DRIVER_BASE = exports.DRIVER_TERMINAL = void 0;
|
|
4
|
+
exports.isAmbiguousCreateFailure = isAmbiguousCreateFailure;
|
|
4
5
|
exports.startDriverAvatarJob = startDriverAvatarJob;
|
|
5
6
|
exports.getDriverJob = getDriverJob;
|
|
6
7
|
exports.describeDriverEvent = describeDriverEvent;
|
|
@@ -27,15 +28,47 @@ exports.DRIVER_BASE = '/api/v1/asset-generation';
|
|
|
27
28
|
exports.DRIVER_DEFAULT_TIMEOUT_MS = 80 * 60_000;
|
|
28
29
|
exports.DRIVER_DEFAULT_POLL_MS = 3_000;
|
|
29
30
|
const MAX_CONSECUTIVE_POLL_ERRORS = 5;
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
/** A create that may have reached the server: no answer (timeout, dropped connection) or a gateway/server error. */
|
|
32
|
+
function isAmbiguousCreateFailure(err) {
|
|
33
|
+
if (err instanceof api_1.ApiError)
|
|
34
|
+
return [408, 425, 500, 502, 503, 504].includes(err.status);
|
|
35
|
+
if (err instanceof Error) {
|
|
36
|
+
// fetch() timeouts (AbortSignal.timeout -> TimeoutError / AbortError) and network failures (TypeError: fetch failed).
|
|
37
|
+
return err.name === 'TimeoutError' || err.name === 'AbortError' || err instanceof TypeError;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create the avatar job. The idempotency key is chosen ONCE and sent on every try, so a timeout after the server had
|
|
43
|
+
* already created the job re-attaches to that job on the next try (the backend returns the existing job for the same
|
|
44
|
+
* owner and key) instead of creating and charging a second one. The key is returned so a caller whose own process
|
|
45
|
+
* died can re-run the start with it.
|
|
46
|
+
*/
|
|
47
|
+
async function startDriverAvatarJob(api, input, newKey = node_crypto_1.randomUUID, retry = {}) {
|
|
48
|
+
const idempotencyKey = input.idempotencyKey ?? newKey();
|
|
49
|
+
const attempts = Math.max(1, retry.attempts ?? 3);
|
|
50
|
+
const backoff = retry.backoffMs ?? ((n) => (n === 1 ? 1_000 : 3_000));
|
|
51
|
+
const sleep = retry.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
52
|
+
const body = {
|
|
32
53
|
kind: 'avatar',
|
|
33
54
|
prompt: input.prompt,
|
|
34
55
|
...(input.title ? { title: input.title } : {}),
|
|
35
56
|
mode: 'deterministic',
|
|
36
57
|
...(input.visibility ? { visibility: input.visibility } : {}),
|
|
37
|
-
idempotencyKey
|
|
38
|
-
}
|
|
58
|
+
idempotencyKey,
|
|
59
|
+
};
|
|
60
|
+
for (let attempt = 1;; attempt++) {
|
|
61
|
+
try {
|
|
62
|
+
const job = await api.request('POST', `${exports.DRIVER_BASE}/jobs`, body);
|
|
63
|
+
return { ...job, idempotencyKey };
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (attempt >= attempts || !isAmbiguousCreateFailure(err))
|
|
67
|
+
throw err;
|
|
68
|
+
retry.onRetry?.(`create did not answer (${err instanceof Error ? err.message : String(err)}); retrying with the same idempotency key ${idempotencyKey} (try ${attempt + 1} of ${attempts})`);
|
|
69
|
+
await sleep(backoff(attempt));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
39
72
|
}
|
|
40
73
|
/** The driver job, or null when the id is not a driver job (a legacy generation job id, a prop). */
|
|
41
74
|
async function getDriverJob(api, id) {
|
|
@@ -157,6 +190,11 @@ async function waitForDriverJob(api, id, options = {}) {
|
|
|
157
190
|
errors = 0;
|
|
158
191
|
}
|
|
159
192
|
catch (err) {
|
|
193
|
+
// The session ended and could not be renewed (HelixApi already tried): retrying cannot help.
|
|
194
|
+
if (err instanceof api_1.ApiError && err.status === 401) {
|
|
195
|
+
throw new Error(`Your login expired and could not be renewed. The job ${id} keeps running on the server. ` +
|
|
196
|
+
`Run \`helix login\`, then \`helix assets resume ${id}\`.`);
|
|
197
|
+
}
|
|
160
198
|
// A transport blip on a poll is not a verdict about the job; a persistent one is real.
|
|
161
199
|
if (++errors >= MAX_CONSECUTIVE_POLL_ERRORS)
|
|
162
200
|
throw err;
|
|
@@ -197,7 +235,7 @@ async function runDriverResume(api, id, options, io) {
|
|
|
197
235
|
}
|
|
198
236
|
if (!job)
|
|
199
237
|
return null;
|
|
200
|
-
io.stdout(JSON.stringify(driverOutput(job), null, 2));
|
|
238
|
+
io.stdout(JSON.stringify(options.idempotencyKey ? { ...driverOutput(job), idempotencyKey: options.idempotencyKey } : driverOutput(job), null, 2));
|
|
201
239
|
if (job.status === 'failed') {
|
|
202
240
|
io.stderr(renderDriverFailure(job));
|
|
203
241
|
return 1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetGenerationDriver.js","sourceRoot":"","sources":["../src/assetGenerationDriver.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"assetGenerationDriver.js","sourceRoot":"","sources":["../src/assetGenerationDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type CliCredentials } from './config';
|
|
2
|
+
export interface RefreshDeps {
|
|
3
|
+
readStored?: () => CliCredentials | null;
|
|
4
|
+
save?: (creds: CliCredentials) => void;
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
now?: () => number;
|
|
7
|
+
}
|
|
8
|
+
/** A newer token for `current`, persisted when it was renewed here, or null when none can be had. */
|
|
9
|
+
export declare function refreshCredentials(current: CliCredentials, deps?: RefreshDeps): Promise<CliCredentials | null>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.refreshCredentials = refreshCredentials;
|
|
4
|
+
// The CLI's one token-renewal path. Every `HelixApi.forCredentials(creds)` client uses it: on a 401 the api asks
|
|
5
|
+
// `refreshCredentials` for a newer token and retries the request once, so a long command (`assets resume` waits up
|
|
6
|
+
// to 80 minutes; a 1 hour access token can expire inside it) survives expiry without a restart.
|
|
7
|
+
//
|
|
8
|
+
// Order of attempts:
|
|
9
|
+
// 1. Another process may already have renewed it (a concurrent `helix login`, or a parallel command that refreshed
|
|
10
|
+
// first). If credentials.json now holds a different, unexpired token for the SAME account and API, adopt it.
|
|
11
|
+
// 2. If the stored login carries a refresh token, exchange it at POST /auth/refresh and persist the new access token.
|
|
12
|
+
// 3. Otherwise there is nothing to renew with: return null and the caller surfaces the 401 ("run helix login").
|
|
13
|
+
//
|
|
14
|
+
// This is deliberately not the visual-QA bot login (visualQa/hosted.ts botLogin): that signs a *bot account* in with
|
|
15
|
+
// a password and is only meant for the hosted QA runner.
|
|
16
|
+
const config_1 = require("./config");
|
|
17
|
+
function unexpired(creds, now) {
|
|
18
|
+
return !creds.expiresAt || new Date(creds.expiresAt).getTime() > now;
|
|
19
|
+
}
|
|
20
|
+
/** A newer token for `current`, persisted when it was renewed here, or null when none can be had. */
|
|
21
|
+
async function refreshCredentials(current, deps = {}) {
|
|
22
|
+
const readStored = deps.readStored ?? config_1.readStoredCredentials;
|
|
23
|
+
const save = deps.save ?? config_1.saveCredentials;
|
|
24
|
+
const doFetch = deps.fetchImpl ?? fetch;
|
|
25
|
+
const now = (deps.now ?? Date.now)();
|
|
26
|
+
const stored = readStored();
|
|
27
|
+
const sameAccount = stored && stored.apiUrl === current.apiUrl && stored.username === current.username;
|
|
28
|
+
if (sameAccount && stored.token !== current.token && unexpired(stored, now))
|
|
29
|
+
return stored;
|
|
30
|
+
const refreshToken = (sameAccount ? stored.refreshToken : undefined) ?? current.refreshToken;
|
|
31
|
+
if (!refreshToken)
|
|
32
|
+
return null;
|
|
33
|
+
let res;
|
|
34
|
+
try {
|
|
35
|
+
res = await doFetch(`${current.apiUrl}/auth/refresh`, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'content-type': 'application/json' },
|
|
38
|
+
body: JSON.stringify({ refresh_token: refreshToken }),
|
|
39
|
+
signal: AbortSignal.timeout(30_000),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (!res.ok)
|
|
46
|
+
return null;
|
|
47
|
+
const body = (await res.json().catch(() => ({})));
|
|
48
|
+
if (typeof body.access_token !== 'string' || !body.access_token)
|
|
49
|
+
return null;
|
|
50
|
+
const expiresAt = (0, config_1.jwtExpiresAtIso)(body.access_token) ||
|
|
51
|
+
(typeof body.expires_in === 'number' ? new Date(now + body.expires_in * 1000).toISOString() : '');
|
|
52
|
+
const renewed = { ...current, token: body.access_token, expiresAt, refreshToken };
|
|
53
|
+
try {
|
|
54
|
+
save(renewed);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// A read-only home must not stop the running command; the new token still works in memory.
|
|
58
|
+
}
|
|
59
|
+
return renewed;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=authRefresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authRefresh.js","sourceRoot":"","sources":["../src/authRefresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,7 +47,7 @@ function describeFixRig(report) {
|
|
|
47
47
|
lines.push(`arm reach: ${r.skipped ? `skipped (${r.skipped})` : `${r.mode === 'report' ? 'would release' : 'released'} arm weight on ${r.released} vert(s) outside the arm (${r.weightMoved} weight moved to the body, LOD0)`}`);
|
|
48
48
|
const w = report.weights;
|
|
49
49
|
if (w !== null)
|
|
50
|
-
lines.push(`static weights: ${w.skipped ? `skipped (${w.skipped})` : `${w.mode === 'report' ? 'would re-weight' : 're-weighted'} ${w.offLimb} vert(s) carrying limb weight outside the limb (${w.loose} re-hung as hair/cloth/tail), ${w.hangingBack} hanging on the back or head-hung, ${w.feetSided ?? 0} shoe/foot vert(s) given back to their own foot (LOD0)`}`);
|
|
50
|
+
lines.push(`static weights: ${w.skipped ? `skipped (${w.skipped})` : `${w.mode === 'report' ? 'would re-weight' : 're-weighted'} ${w.offLimb} vert(s) carrying limb weight outside the limb (${w.loose} re-hung as hair/cloth/tail), ${w.hangingBack} hanging on the back or head-hung, ${w.feetSided ?? 0} shoe/foot vert(s) given back to their own foot, ${w.clothRelaxed ?? 0} hanging-cloth vert(s) (skirt, robe, cape tail) re-weighted so the stride does not tear them (LOD0)`}`);
|
|
51
51
|
const b = report.bind;
|
|
52
52
|
if (b !== null) {
|
|
53
53
|
if (b.skipped)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"armBindFixRig.js","sourceRoot":"","sources":["../../../src/character/stages/armBindFixRig.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"armBindFixRig.js","sourceRoot":"","sources":["../../../src/character/stages/armBindFixRig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type SkinModel, type VertexSet, type Weights } from './armBindSkin';
|
|
2
|
+
/**
|
|
3
|
+
* HANGING CLOTH — a skirt, robe, coat tail or cape skinned so it does not tear when the legs part.
|
|
4
|
+
*
|
|
5
|
+
* Generated characters (Dreamer: Tripo) come back auto-rigged by proximity to the bones. Cloth that hangs below the
|
|
6
|
+
* hips and is wider than the legs (a floor-length skirt, a robe, a cape's tail) is given, panel by panel, to whichever
|
|
7
|
+
* leg it is nearest to in the source pose: the left half of the hem follows the left leg, the right half the right
|
|
8
|
+
* leg, and a vertex a centimetre from the seam between them is 100 % one leg and its neighbour 100 % the other. At
|
|
9
|
+
* rest nothing shows. In a stride the legs part half a metre and every edge that crosses the seam is stretched
|
|
10
|
+
* 10-20x: the hem opens into spikes, the back of the garment into a flat blade behind the legs (2026-10-08, hosted
|
|
11
|
+
* critic, seven of the day's twelve avatars with long cloth: "the skirt tears into jagged shards", "coat-tail
|
|
12
|
+
* polygons stretch into spikes below the hem", "a thin flat triangular blade jutting behind the legs"). The gate's own
|
|
13
|
+
* `avatar.skin_intact` passed most of them because the torn cloth is a small share of the whole surface.
|
|
14
|
+
*
|
|
15
|
+
* What fixes it is not where the cloth hangs from but that the weights change SMOOTHLY: the legs part by the same
|
|
16
|
+
* distance, spread over many edges instead of one. So this stage finds the triangles a walk stride tears (an edge
|
|
17
|
+
* stretched over `tearRatio` x), takes the cloth around them (surface distance `reachM`), and relaxes that cloth's
|
|
18
|
+
* weights toward the average of its neighbours until the stride no longer tears it. Nothing else moves: a vertex
|
|
19
|
+
* outside that reach keeps its weights, and a model whose stride does not tear anything is not touched at all.
|
|
20
|
+
*
|
|
21
|
+
* The result is kept only when the stride stretch (share of the surface area with an edge over 3x) falls in the sum
|
|
22
|
+
* of the two opposite strides and rises in neither. Run per vertex set (per LOD), measured on that LOD's own mesh,
|
|
23
|
+
* after the other static-weight rules. Only JOINTS_n / WEIGHTS_n change.
|
|
24
|
+
*/
|
|
25
|
+
export interface HangingClothOptions {
|
|
26
|
+
/** An edge stretched past this ratio in a stride marks the cloth around it for relaxing (default 2). */
|
|
27
|
+
tearRatio?: number;
|
|
28
|
+
/** Surface distance around a torn triangle that is relaxed, at 1.70 m (default 0.2 m). */
|
|
29
|
+
reachM?: number;
|
|
30
|
+
/** Relaxation rounds (each `iterationsPerRound` weighted-average sweeps) before giving up (default 30). */
|
|
31
|
+
rounds?: number;
|
|
32
|
+
iterationsPerRound?: number;
|
|
33
|
+
/** Cloth is only relaxed this far above the pelvis joint, at 1.70 m (default 0.05 m): a skirt, robe or tail hangs below the hips. */
|
|
34
|
+
aboveHipM?: number;
|
|
35
|
+
/** Stride half-angle of the gate, degrees (default 50: a run's, wider than the walk's 35). */
|
|
36
|
+
strideDeg?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Cloth more than `legMarginM` from every leg axis (a cape's tail, a skirt's flare, a coat tail) is not leg skin: up to
|
|
39
|
+
* this share of its leg weight is handed to the pelvis, so it hangs from the hips instead of swinging with a leg
|
|
40
|
+
* (default 0.6; 0 skips). Faded in over `pullFadeM`.
|
|
41
|
+
*/
|
|
42
|
+
freeHangShare?: number;
|
|
43
|
+
legMarginM?: number;
|
|
44
|
+
pullFadeM?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface HangingClothReport {
|
|
47
|
+
/** Vertices whose weights were relaxed (0 when nothing tore, or the result was not an improvement). */
|
|
48
|
+
vertices: number;
|
|
49
|
+
/** Stride stretch (% of surface area with an edge over 3x), the two strides, before and after. */
|
|
50
|
+
before: [number, number];
|
|
51
|
+
after: [number, number];
|
|
52
|
+
/** Vertices (welded nodes) whose leg weight was partly handed to the pelvis because the cloth hangs free of the legs. */
|
|
53
|
+
pulled?: number;
|
|
54
|
+
/** Why nothing was changed, when so. */
|
|
55
|
+
skipped?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Relax the weights of the cloth a stride tears. `w` is changed in place when (and only when) the result is an
|
|
59
|
+
* improvement; the caller writes it back.
|
|
60
|
+
*/
|
|
61
|
+
export declare function relaxHangingCloth(model: SkinModel, set: VertexSet, w: Weights, options?: HangingClothOptions): HangingClothReport;
|