@vivipilot/cli 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.
- package/README.md +57 -0
- package/dist/api.d.ts +86 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +77 -0
- package/dist/api.js.map +1 -0
- package/dist/args.d.ts +11 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +53 -0
- package/dist/args.js.map +1 -0
- package/dist/browser.d.ts +31 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +162 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +536 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +12 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +40 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +90 -0
- package/dist/manifest.js.map +1 -0
- package/dist/mcp.d.ts +13 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +392 -0
- package/dist/mcp.js.map +1 -0
- package/dist/render.d.ts +21 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +369 -0
- package/dist/render.js.map +1 -0
- package/package.json +42 -0
- package/src/api.ts +163 -0
- package/src/args.test.ts +21 -0
- package/src/args.ts +64 -0
- package/src/browser.test.ts +103 -0
- package/src/browser.ts +174 -0
- package/src/cli.ts +656 -0
- package/src/config.test.ts +30 -0
- package/src/config.ts +71 -0
- package/src/errors.ts +14 -0
- package/src/index.ts +25 -0
- package/src/manifest.test.ts +105 -0
- package/src/manifest.ts +126 -0
- package/src/mcp.test.ts +48 -0
- package/src/mcp.ts +438 -0
- package/src/render.ts +424 -0
- package/tsconfig.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @vivipilot/cli
|
|
2
|
+
|
|
3
|
+
Paid-only Vivipilot CLI scaffold for developer/API and MCP workflows.
|
|
4
|
+
|
|
5
|
+
The CLI is the user-facing shell around the manifest-minting architecture:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
vivipilot login --api-key vvp_live_...
|
|
9
|
+
vivipilot balance
|
|
10
|
+
vivipilot estimate --prompt "animated pricing comparison"
|
|
11
|
+
vivipilot generate --prompt "animated pricing comparison" --out scene.vivi.json
|
|
12
|
+
vivipilot verify scene.vivi.json
|
|
13
|
+
vivipilot render scene.vivi.json --out video.mp4
|
|
14
|
+
vivipilot mcp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Current status:
|
|
18
|
+
|
|
19
|
+
- API key/config handling is implemented.
|
|
20
|
+
- Paid-only generation checks are enforced client-side before cloud calls.
|
|
21
|
+
- Estimate/generate/status calls are wired to future `/api/v1` cloud endpoints.
|
|
22
|
+
- Manifest verification uses `@vivipilot/render-manifest`.
|
|
23
|
+
- `vivipilot mcp` starts a stdio MCP server with paid-only Vivipilot tools.
|
|
24
|
+
- Browser-shell rendering is intentionally stubbed for the next implementation slice.
|
|
25
|
+
|
|
26
|
+
Environment variables:
|
|
27
|
+
|
|
28
|
+
- `VIVIPILOT_API_KEY`: API key for non-interactive agent/CI use.
|
|
29
|
+
- `VIVIPILOT_API_URL`: Cloud API base URL. Defaults to `https://vivipilot.com`.
|
|
30
|
+
- `VIVIPILOT_CONFIG`: Override config file path.
|
|
31
|
+
- `VIVIPILOT_MANIFEST_PUBLIC_KEYS`: JSON object mapping `keyId` to public key.
|
|
32
|
+
- `VIVIPILOT_MANIFEST_PUBLIC_KEY_ID` and `VIVIPILOT_MANIFEST_PUBLIC_KEY`: Single public key pair.
|
|
33
|
+
|
|
34
|
+
MCP config example:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"vivipilot": {
|
|
40
|
+
"command": "vivipilot",
|
|
41
|
+
"args": ["mcp"],
|
|
42
|
+
"env": {
|
|
43
|
+
"VIVIPILOT_API_KEY": "vvp_live_..."
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Exposed MCP tools:
|
|
51
|
+
|
|
52
|
+
- `vivipilot_get_balance`
|
|
53
|
+
- `vivipilot_estimate_motion_layout`
|
|
54
|
+
- `vivipilot_generate_motion_layout`
|
|
55
|
+
- `vivipilot_verify_manifest`
|
|
56
|
+
- `vivipilot_render_video`
|
|
57
|
+
- `vivipilot_get_generation_status`
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type CliConfig, type Env } from "./config.js";
|
|
2
|
+
export type ApiClientOptions = {
|
|
3
|
+
config: CliConfig;
|
|
4
|
+
env?: Env;
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
};
|
|
7
|
+
export type BalanceResponse = {
|
|
8
|
+
balance: number;
|
|
9
|
+
paidBalance?: number;
|
|
10
|
+
currency?: "credits";
|
|
11
|
+
topupUrl?: string;
|
|
12
|
+
};
|
|
13
|
+
export type EstimateRequest = {
|
|
14
|
+
prompt: string;
|
|
15
|
+
canvas?: {
|
|
16
|
+
width?: number;
|
|
17
|
+
height?: number;
|
|
18
|
+
fps?: number;
|
|
19
|
+
};
|
|
20
|
+
durationSeconds?: number;
|
|
21
|
+
enginePreference?: "pixi" | "three" | "auto";
|
|
22
|
+
};
|
|
23
|
+
export type EstimateResponse = {
|
|
24
|
+
estimatedCredits: number;
|
|
25
|
+
engine: string;
|
|
26
|
+
paidOnly: true;
|
|
27
|
+
warnings?: string[];
|
|
28
|
+
};
|
|
29
|
+
export type GenerateRequest = EstimateRequest & {
|
|
30
|
+
outputFormat?: "manifest";
|
|
31
|
+
};
|
|
32
|
+
export type GenerateResponse = {
|
|
33
|
+
generationId: string;
|
|
34
|
+
manifest: unknown;
|
|
35
|
+
creditsCharged?: number;
|
|
36
|
+
};
|
|
37
|
+
export type StartGenerateResponse = {
|
|
38
|
+
generationId: string;
|
|
39
|
+
status: string;
|
|
40
|
+
estimatedCredits: number;
|
|
41
|
+
engine: string;
|
|
42
|
+
paidOnly: true;
|
|
43
|
+
idempotentReplay?: boolean;
|
|
44
|
+
};
|
|
45
|
+
export type ProgressResponse = {
|
|
46
|
+
generationId: string;
|
|
47
|
+
status: "pending" | "running" | "completed" | "failed" | "refunded";
|
|
48
|
+
workflowStatus: string | null;
|
|
49
|
+
workflowStage: string | null;
|
|
50
|
+
progressMessage: string | null;
|
|
51
|
+
creditsCharged: number | null;
|
|
52
|
+
estimatedCredits: number | null;
|
|
53
|
+
engine: string | null;
|
|
54
|
+
manifest: {
|
|
55
|
+
manifestId: string;
|
|
56
|
+
manifestHash: string;
|
|
57
|
+
} | null;
|
|
58
|
+
manifestData: unknown;
|
|
59
|
+
error: string | null;
|
|
60
|
+
};
|
|
61
|
+
export type StatusResponse = {
|
|
62
|
+
generationId: string;
|
|
63
|
+
status: "pending" | "running" | "completed" | "failed";
|
|
64
|
+
manifest?: unknown;
|
|
65
|
+
error?: string;
|
|
66
|
+
};
|
|
67
|
+
export declare class VivipilotApiClient {
|
|
68
|
+
private readonly config;
|
|
69
|
+
private readonly env;
|
|
70
|
+
private readonly fetchImpl;
|
|
71
|
+
constructor(options: ApiClientOptions);
|
|
72
|
+
private apiUrl;
|
|
73
|
+
private apiKey;
|
|
74
|
+
private requestJson;
|
|
75
|
+
whoami(): Promise<unknown>;
|
|
76
|
+
balance(): Promise<BalanceResponse>;
|
|
77
|
+
estimate(request: EstimateRequest): Promise<EstimateResponse>;
|
|
78
|
+
/** Original synchronous generate — blocks until completion */
|
|
79
|
+
generate(request: GenerateRequest, idempotencyKey: string): Promise<GenerateResponse>;
|
|
80
|
+
/** Start generation asynchronously — returns immediately with generationId */
|
|
81
|
+
startGenerate(request: GenerateRequest, idempotencyKey: string): Promise<StartGenerateResponse>;
|
|
82
|
+
/** Poll generation status with workflow progress info */
|
|
83
|
+
generationProgress(generationId: string): Promise<ProgressResponse>;
|
|
84
|
+
generationStatus(generationId: string): Promise<StatusResponse>;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAgC,MAAM,aAAa,CAAC;AAErF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,IAAI,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;IACpE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,GAAG,IAAI,CAAC;IACT,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,OAAO,EAAE,gBAAgB;IAMrC,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,MAAM;YAQA,WAAW;IAsBnB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAInC,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAOnE,8DAA8D;IACxD,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQ3F,8EAA8E;IACxE,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQrG,yDAAyD;IACnD,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAMnE,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAGtE"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { CliError } from "./errors.js";
|
|
2
|
+
import { resolveApiKey, resolveApiUrl } from "./config.js";
|
|
3
|
+
export class VivipilotApiClient {
|
|
4
|
+
config;
|
|
5
|
+
env;
|
|
6
|
+
fetchImpl;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.config = options.config;
|
|
9
|
+
this.env = options.env ?? process.env;
|
|
10
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
11
|
+
}
|
|
12
|
+
apiUrl() {
|
|
13
|
+
return resolveApiUrl(this.config, this.env);
|
|
14
|
+
}
|
|
15
|
+
apiKey() {
|
|
16
|
+
const apiKey = resolveApiKey(this.config, this.env);
|
|
17
|
+
if (!apiKey) {
|
|
18
|
+
throw new CliError("Vivipilot CLI/MCP generation is paid-only. Set VIVIPILOT_API_KEY or run `vivipilot login --api-key <key>`.", 2);
|
|
19
|
+
}
|
|
20
|
+
return apiKey;
|
|
21
|
+
}
|
|
22
|
+
async requestJson(path, init = {}) {
|
|
23
|
+
const headers = new Headers(init.headers);
|
|
24
|
+
headers.set("accept", "application/json");
|
|
25
|
+
headers.set("authorization", `Bearer ${this.apiKey()}`);
|
|
26
|
+
headers.set("x-vivipilot-client", "@vivipilot/cli");
|
|
27
|
+
if (init.body && !headers.has("content-type"))
|
|
28
|
+
headers.set("content-type", "application/json");
|
|
29
|
+
const response = await this.fetchImpl(`${this.apiUrl()}${path}`, { ...init, headers });
|
|
30
|
+
const text = await response.text();
|
|
31
|
+
const payload = text.length > 0 ? JSON.parse(text) : {};
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
const message = payload && typeof payload === "object" && "error" in payload
|
|
34
|
+
? String(payload.error)
|
|
35
|
+
: `Vivipilot API request failed with status ${response.status}`;
|
|
36
|
+
const suffix = response.status === 402 ? " Run `vivipilot topup` to buy credits." : "";
|
|
37
|
+
throw new CliError(`${message}${suffix}`, response.status === 401 ? 2 : 1);
|
|
38
|
+
}
|
|
39
|
+
return payload;
|
|
40
|
+
}
|
|
41
|
+
async whoami() {
|
|
42
|
+
return this.requestJson("/api/v1/me");
|
|
43
|
+
}
|
|
44
|
+
async balance() {
|
|
45
|
+
return this.requestJson("/api/v1/credits/balance");
|
|
46
|
+
}
|
|
47
|
+
async estimate(request) {
|
|
48
|
+
return this.requestJson("/api/v1/layouts/estimate", {
|
|
49
|
+
method: "POST",
|
|
50
|
+
body: JSON.stringify(request),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Original synchronous generate — blocks until completion */
|
|
54
|
+
async generate(request, idempotencyKey) {
|
|
55
|
+
return this.requestJson("/api/v1/layouts/generate", {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: { "idempotency-key": idempotencyKey },
|
|
58
|
+
body: JSON.stringify({ ...request, outputFormat: "manifest" }),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** Start generation asynchronously — returns immediately with generationId */
|
|
62
|
+
async startGenerate(request, idempotencyKey) {
|
|
63
|
+
return this.requestJson("/api/v1/layouts/generate/start", {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "idempotency-key": idempotencyKey },
|
|
66
|
+
body: JSON.stringify({ ...request, outputFormat: "manifest" }),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Poll generation status with workflow progress info */
|
|
70
|
+
async generationProgress(generationId) {
|
|
71
|
+
return this.requestJson(`/api/v1/layouts/${encodeURIComponent(generationId)}?progress=true`);
|
|
72
|
+
}
|
|
73
|
+
async generationStatus(generationId) {
|
|
74
|
+
return this.requestJson(`/api/v1/layouts/${encodeURIComponent(generationId)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type FlagValue = string | boolean;
|
|
2
|
+
export type ParsedArgs = {
|
|
3
|
+
command: string | undefined;
|
|
4
|
+
flags: Record<string, FlagValue>;
|
|
5
|
+
positionals: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare function parseArgv(argv: readonly string[]): ParsedArgs;
|
|
8
|
+
export declare function flagString(parsed: ParsedArgs, names: readonly string[]): string | undefined;
|
|
9
|
+
export declare function flagBoolean(parsed: ParsedArgs, names: readonly string[]): boolean;
|
|
10
|
+
export declare function flagNumber(parsed: ParsedArgs, names: readonly string[]): number | undefined;
|
|
11
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAMF,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CA+B7D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAM3F;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAEjF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAK3F"}
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function normalizeFlagName(value) {
|
|
2
|
+
return value.replace(/^-+/, "").trim();
|
|
3
|
+
}
|
|
4
|
+
export function parseArgv(argv) {
|
|
5
|
+
const [command, ...tokens] = argv;
|
|
6
|
+
const flags = {};
|
|
7
|
+
const positionals = [];
|
|
8
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
9
|
+
const token = tokens[index];
|
|
10
|
+
if (token === "--") {
|
|
11
|
+
positionals.push(...tokens.slice(index + 1));
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
if (token.startsWith("--")) {
|
|
15
|
+
const equalsIndex = token.indexOf("=");
|
|
16
|
+
if (equalsIndex > -1) {
|
|
17
|
+
flags[normalizeFlagName(token.slice(0, equalsIndex))] = token.slice(equalsIndex + 1);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const name = normalizeFlagName(token);
|
|
21
|
+
const next = tokens[index + 1];
|
|
22
|
+
if (next && !next.startsWith("-")) {
|
|
23
|
+
flags[name] = next;
|
|
24
|
+
index++;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
flags[name] = true;
|
|
28
|
+
}
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
positionals.push(token);
|
|
32
|
+
}
|
|
33
|
+
return { command, flags, positionals };
|
|
34
|
+
}
|
|
35
|
+
export function flagString(parsed, names) {
|
|
36
|
+
for (const name of names) {
|
|
37
|
+
const value = parsed.flags[name];
|
|
38
|
+
if (typeof value === "string" && value.length > 0)
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
export function flagBoolean(parsed, names) {
|
|
44
|
+
return names.some((name) => parsed.flags[name] === true || parsed.flags[name] === "true");
|
|
45
|
+
}
|
|
46
|
+
export function flagNumber(parsed, names) {
|
|
47
|
+
const value = flagString(parsed, names);
|
|
48
|
+
if (value === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
const parsedNumber = Number(value);
|
|
51
|
+
return Number.isFinite(parsedNumber) ? parsedNumber : undefined;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type BrowserResolution = {
|
|
2
|
+
executablePath: string;
|
|
3
|
+
source: "env" | "chrome-headless-shell" | "system-chrome" | "system-chromium";
|
|
4
|
+
};
|
|
5
|
+
export declare class BrowserNotFoundError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a browser binary for headless rendering.
|
|
10
|
+
*
|
|
11
|
+
* Priority:
|
|
12
|
+
* 1. `VIVIPILOT_HEADLESS_BROWSER` env var (explicit override)
|
|
13
|
+
* 2. `chrome-headless-shell` in PATH or common install locations
|
|
14
|
+
* 3. System Chrome / Chromium in common install locations
|
|
15
|
+
*
|
|
16
|
+
* Returns the path + source. Throws `BrowserNotFoundError` when no browser is found.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveHeadlessBrowser(env?: NodeJS.ProcessEnv): Promise<BrowserResolution>;
|
|
19
|
+
/**
|
|
20
|
+
* Build the Chrome/Chromium CLI flags for headless rendering with WebGL/WebGPU support.
|
|
21
|
+
* These flags ensure the GPU is available (or SwiftShader fallback) so Pixi v8 can
|
|
22
|
+
* initialise its renderer inside a headless browser.
|
|
23
|
+
*/
|
|
24
|
+
export declare function headlessBrowserArgs(renderUrl: string, options?: {
|
|
25
|
+
windowSize?: {
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
};
|
|
29
|
+
extraArgs?: string[];
|
|
30
|
+
}): string[];
|
|
31
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,iBAAiB,GAAG;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,KAAK,GAAG,uBAAuB,GAAG,eAAe,GAAG,iBAAiB,CAAC;CAC9E,CAAC;AAEF,qBAAa,oBAAqB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkB7G;AAyFD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAChE,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG,MAAM,EAAE,CA+BX"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { access, constants } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
export class BrowserNotFoundError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "BrowserNotFoundError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a browser binary for headless rendering.
|
|
13
|
+
*
|
|
14
|
+
* Priority:
|
|
15
|
+
* 1. `VIVIPILOT_HEADLESS_BROWSER` env var (explicit override)
|
|
16
|
+
* 2. `chrome-headless-shell` in PATH or common install locations
|
|
17
|
+
* 3. System Chrome / Chromium in common install locations
|
|
18
|
+
*
|
|
19
|
+
* Returns the path + source. Throws `BrowserNotFoundError` when no browser is found.
|
|
20
|
+
*/
|
|
21
|
+
export async function resolveHeadlessBrowser(env = process.env) {
|
|
22
|
+
const envPath = env.VIVIPILOT_HEADLESS_BROWSER;
|
|
23
|
+
if (envPath && await isExecutable(envPath)) {
|
|
24
|
+
return { executablePath: envPath, source: "env" };
|
|
25
|
+
}
|
|
26
|
+
const shell = await findChromeHeadlessShell();
|
|
27
|
+
if (shell)
|
|
28
|
+
return { executablePath: shell, source: "chrome-headless-shell" };
|
|
29
|
+
const chrome = await findSystemChrome();
|
|
30
|
+
if (chrome)
|
|
31
|
+
return { executablePath: chrome, source: "system-chrome" };
|
|
32
|
+
const chromium = await findSystemChromium();
|
|
33
|
+
if (chromium)
|
|
34
|
+
return { executablePath: chromium, source: "system-chromium" };
|
|
35
|
+
throw new BrowserNotFoundError("No headless browser found. Install chrome-headless-shell or Chrome/Chromium, or set VIVIPILOT_HEADLESS_BROWSER to the binary path.");
|
|
36
|
+
}
|
|
37
|
+
async function isExecutable(path) {
|
|
38
|
+
try {
|
|
39
|
+
await access(path, constants.X_OK);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function findChromeHeadlessShell() {
|
|
47
|
+
const candidates = [
|
|
48
|
+
process.env.PUPPETEER_EXECUTABLE_PATH,
|
|
49
|
+
join(homedir(), ".cache", "puppeteer", "chrome-headless-shell"),
|
|
50
|
+
"/usr/bin/chrome-headless-shell",
|
|
51
|
+
"/usr/local/bin/chrome-headless-shell",
|
|
52
|
+
"/snap/bin/chrome-headless-shell",
|
|
53
|
+
join(homedir(), ".local", "share", "chrome-headless-shell", "chrome-headless-shell"),
|
|
54
|
+
"/opt/chrome-headless-shell/chrome-headless-shell",
|
|
55
|
+
// macOS
|
|
56
|
+
"/Applications/Google Chrome Headless Shell.app/Contents/MacOS/Google Chrome Headless Shell",
|
|
57
|
+
// Windows
|
|
58
|
+
join(homedir(), "AppData", "Local", "chrome-headless-shell", "chrome-headless-shell.exe"),
|
|
59
|
+
];
|
|
60
|
+
for (const candidate of candidates) {
|
|
61
|
+
if (!candidate)
|
|
62
|
+
continue;
|
|
63
|
+
if (await isExecutable(candidate))
|
|
64
|
+
return candidate;
|
|
65
|
+
// Some install dirs contain a versioned subfolder
|
|
66
|
+
if (existsSync(candidate) && !candidate.endsWith("chrome-headless-shell") && !candidate.endsWith(".exe")) {
|
|
67
|
+
// Search for the binary inside versioned subdirs
|
|
68
|
+
const { readdirSync } = await import("node:fs");
|
|
69
|
+
try {
|
|
70
|
+
const entries = readdirSync(candidate, { withFileTypes: true });
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
if (!entry.isDirectory())
|
|
73
|
+
continue;
|
|
74
|
+
const inner = join(candidate, entry.name, "chrome-headless-shell");
|
|
75
|
+
if (await isExecutable(inner))
|
|
76
|
+
return inner;
|
|
77
|
+
const innerExe = join(candidate, entry.name, "chrome-headless-shell.exe");
|
|
78
|
+
if (await isExecutable(innerExe))
|
|
79
|
+
return innerExe;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch { /* ignore */ }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
async function findSystemChrome() {
|
|
88
|
+
const candidates = [
|
|
89
|
+
"/usr/bin/google-chrome",
|
|
90
|
+
"/usr/bin/google-chrome-stable",
|
|
91
|
+
"/usr/bin/google-chrome-unstable",
|
|
92
|
+
"/usr/local/bin/google-chrome",
|
|
93
|
+
"/opt/google/chrome/chrome",
|
|
94
|
+
"/snap/bin/google-chrome",
|
|
95
|
+
// macOS
|
|
96
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
97
|
+
// Windows
|
|
98
|
+
join(homedir(), "AppData", "Local", "Google", "Chrome", "Application", "chrome.exe"),
|
|
99
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
100
|
+
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
|
101
|
+
];
|
|
102
|
+
for (const candidate of candidates) {
|
|
103
|
+
if (await isExecutable(candidate))
|
|
104
|
+
return candidate;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
async function findSystemChromium() {
|
|
109
|
+
const candidates = [
|
|
110
|
+
"/usr/bin/chromium",
|
|
111
|
+
"/usr/bin/chromium-browser",
|
|
112
|
+
"/usr/local/bin/chromium",
|
|
113
|
+
"/snap/bin/chromium",
|
|
114
|
+
"/usr/bin/brave-browser",
|
|
115
|
+
"/usr/bin/brave",
|
|
116
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
117
|
+
join(homedir(), "AppData", "Local", "Chromium", "Application", "chromium.exe"),
|
|
118
|
+
"C:\\Program Files\\Chromium\\Application\\chromium.exe",
|
|
119
|
+
];
|
|
120
|
+
for (const candidate of candidates) {
|
|
121
|
+
if (await isExecutable(candidate))
|
|
122
|
+
return candidate;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build the Chrome/Chromium CLI flags for headless rendering with WebGL/WebGPU support.
|
|
128
|
+
* These flags ensure the GPU is available (or SwiftShader fallback) so Pixi v8 can
|
|
129
|
+
* initialise its renderer inside a headless browser.
|
|
130
|
+
*/
|
|
131
|
+
export function headlessBrowserArgs(renderUrl, options) {
|
|
132
|
+
const width = options?.windowSize?.width ?? 1920;
|
|
133
|
+
const height = options?.windowSize?.height ?? 1080;
|
|
134
|
+
return [
|
|
135
|
+
"--headless=new",
|
|
136
|
+
"--no-sandbox",
|
|
137
|
+
"--disable-gpu-sandbox",
|
|
138
|
+
"--disable-dev-shm-usage",
|
|
139
|
+
"--disable-extensions",
|
|
140
|
+
"--disable-background-networking",
|
|
141
|
+
"--disable-sync",
|
|
142
|
+
"--disable-translate",
|
|
143
|
+
"--disable-default-apps",
|
|
144
|
+
"--disable-popup-blocking",
|
|
145
|
+
"--disable-component-update",
|
|
146
|
+
"--disable-metrics",
|
|
147
|
+
"--no-first-run",
|
|
148
|
+
"--mute-audio",
|
|
149
|
+
"--enable-logging=stderr",
|
|
150
|
+
"--log-level=0",
|
|
151
|
+
"--v=1",
|
|
152
|
+
`--window-size=${width},${height}`,
|
|
153
|
+
"--enable-features=Vulkan",
|
|
154
|
+
"--use-gl=angle",
|
|
155
|
+
"--use-angle=swiftshader",
|
|
156
|
+
"--enable-unsafe-swiftshader",
|
|
157
|
+
"--ignore-gpu-blocklist",
|
|
158
|
+
...(options?.extraArgs ?? []),
|
|
159
|
+
renderUrl,
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type Env } from "./config.js";
|
|
3
|
+
type WritableLike = {
|
|
4
|
+
write(chunk: string): void;
|
|
5
|
+
};
|
|
6
|
+
type CliIo = {
|
|
7
|
+
stdout: WritableLike;
|
|
8
|
+
stderr: WritableLike;
|
|
9
|
+
};
|
|
10
|
+
export declare function runCli(argv?: string[], env?: Env, io?: CliIo): Promise<void>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAMA,OAAO,EAQL,KAAK,GAAG,EACT,MAAM,aAAa,CAAC;AAMrB,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB,CAAC;AAojBF,wBAAsB,MAAM,CAAC,IAAI,WAAwB,EAAE,GAAG,GAAE,GAAiB,EAAE,EAAE,GAAE,KAA0D,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDhK"}
|