@reactor-team/js-sdk 1.0.2 → 1.0.4
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/bin/create-reactor-app.ts +140 -0
- package/dist/bin/create-reactor-app.mjs +137 -0
- package/dist/index.d.mts +151 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.js +1000 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +971 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +9 -2
- package/tsconfig.json +1 -1
- package/tsup.config.ts +28 -11
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import simpleGit from "simple-git";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
|
|
9
|
+
const REPO = "https://github.com/reactor-team/js-sdk.git";
|
|
10
|
+
const EXAMPLES_PATH = "examples";
|
|
11
|
+
|
|
12
|
+
async function getTemplates(): Promise<string[]> {
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetch(
|
|
15
|
+
`https://api.github.com/repos/reactor-team/js-sdk/contents/${EXAMPLES_PATH}`
|
|
16
|
+
);
|
|
17
|
+
const data = (await res.json()) as { name: string; type: string }[];
|
|
18
|
+
return data.filter((item) => item.type === "dir").map((item) => item.name);
|
|
19
|
+
} catch {
|
|
20
|
+
console.log(
|
|
21
|
+
chalk.yellow("⚠️ Could not fetch from GitHub, using fallback templates.")
|
|
22
|
+
);
|
|
23
|
+
return ["longlive", "matrix-2"];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function showUsage(): void {
|
|
28
|
+
console.log(chalk.cyan("\n🧩 Create Reactor App\n"));
|
|
29
|
+
console.log(chalk.white("Usage:"));
|
|
30
|
+
console.log(chalk.white(" create-reactor-app [project-name] [template]\n"));
|
|
31
|
+
console.log(chalk.white("Arguments:"));
|
|
32
|
+
console.log(chalk.white(" project-name Name of the project to create"));
|
|
33
|
+
console.log(
|
|
34
|
+
chalk.white(
|
|
35
|
+
" template Template to use (longlive, matrix-2, mk64, etc.)\n"
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
console.log(
|
|
39
|
+
chalk.white(
|
|
40
|
+
"If arguments are not provided, you will be prompted interactively.\n"
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function main(): Promise<void> {
|
|
46
|
+
const args = process.argv.slice(2);
|
|
47
|
+
|
|
48
|
+
// Show help if requested
|
|
49
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
50
|
+
showUsage();
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log(chalk.cyan("\n🧩 Create Reactor App\n"));
|
|
55
|
+
|
|
56
|
+
const templates = await getTemplates();
|
|
57
|
+
|
|
58
|
+
// Parse command line arguments
|
|
59
|
+
const [argProjectName, argTemplate] = args;
|
|
60
|
+
|
|
61
|
+
// Validate template argument if provided
|
|
62
|
+
if (argTemplate && !templates.includes(argTemplate)) {
|
|
63
|
+
console.error(chalk.red(`Template "${argTemplate}" is not available.`));
|
|
64
|
+
console.log(chalk.white("Available templates:"), templates.join(", "));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Prepare prompts, skipping those with provided arguments
|
|
69
|
+
const prompts: any[] = [];
|
|
70
|
+
|
|
71
|
+
if (!argProjectName) {
|
|
72
|
+
prompts.push({
|
|
73
|
+
type: "input",
|
|
74
|
+
name: "projectName",
|
|
75
|
+
message: "Enter your project name:",
|
|
76
|
+
validate: (input: string) =>
|
|
77
|
+
input ? true : "Project name cannot be empty.",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!argTemplate) {
|
|
82
|
+
prompts.push({
|
|
83
|
+
type: "list",
|
|
84
|
+
name: "template",
|
|
85
|
+
message: "Select a template:",
|
|
86
|
+
choices: templates,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Get answers from prompts (if any are needed)
|
|
91
|
+
const answers = prompts.length > 0 ? await inquirer.prompt(prompts) : {};
|
|
92
|
+
|
|
93
|
+
// Use provided arguments or prompted answers
|
|
94
|
+
const projectName = argProjectName || answers.projectName;
|
|
95
|
+
const template = argTemplate || answers.template;
|
|
96
|
+
const dest = path.resolve(process.cwd(), projectName);
|
|
97
|
+
|
|
98
|
+
if (fs.existsSync(dest)) {
|
|
99
|
+
console.error(chalk.red(`Folder "${projectName}" already exists.`));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(chalk.green(`\nCloning template "${template}"...\n`));
|
|
104
|
+
|
|
105
|
+
const git = simpleGit();
|
|
106
|
+
await git.clone(REPO, projectName, ["--depth", "1"]);
|
|
107
|
+
|
|
108
|
+
const examplesDir = path.join(dest, EXAMPLES_PATH);
|
|
109
|
+
const templateDir = path.join(examplesDir, template);
|
|
110
|
+
|
|
111
|
+
if (!fs.existsSync(templateDir)) {
|
|
112
|
+
console.error(chalk.red(`Template "${template}" not found.`));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Move files up
|
|
117
|
+
for (const file of fs.readdirSync(templateDir)) {
|
|
118
|
+
fs.renameSync(path.join(templateDir, file), path.join(dest, file));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fs.rmSync(examplesDir, { recursive: true, force: true });
|
|
122
|
+
fs.rmSync(path.join(dest, ".git"), { recursive: true, force: true });
|
|
123
|
+
|
|
124
|
+
console.log(chalk.yellow("\nInstalling dependencies...\n"));
|
|
125
|
+
execSync("pnpm install", { cwd: dest, stdio: "inherit" });
|
|
126
|
+
|
|
127
|
+
console.log(
|
|
128
|
+
chalk.green(
|
|
129
|
+
`\n✅ Project "${projectName}" created successfully using "${template}" template!\n`
|
|
130
|
+
)
|
|
131
|
+
);
|
|
132
|
+
console.log(chalk.cyan("Next steps:"));
|
|
133
|
+
console.log(chalk.white(` cd ${projectName}`));
|
|
134
|
+
console.log(chalk.white(` pnpm dev\n`));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
main().catch((err) => {
|
|
138
|
+
console.error(chalk.red("Error:"), err);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __async = (__this, __arguments, generator) => {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
var fulfilled = (value) => {
|
|
5
|
+
try {
|
|
6
|
+
step(generator.next(value));
|
|
7
|
+
} catch (e) {
|
|
8
|
+
reject(e);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var rejected = (value) => {
|
|
12
|
+
try {
|
|
13
|
+
step(generator.throw(value));
|
|
14
|
+
} catch (e) {
|
|
15
|
+
reject(e);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
19
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
import inquirer from "inquirer";
|
|
23
|
+
import { execSync } from "child_process";
|
|
24
|
+
import simpleGit from "simple-git";
|
|
25
|
+
import fs from "fs";
|
|
26
|
+
import path from "path";
|
|
27
|
+
import chalk from "chalk";
|
|
28
|
+
const REPO = "https://github.com/reactor-team/js-sdk.git";
|
|
29
|
+
const EXAMPLES_PATH = "examples";
|
|
30
|
+
function getTemplates() {
|
|
31
|
+
return __async(this, null, function* () {
|
|
32
|
+
try {
|
|
33
|
+
const res = yield fetch(
|
|
34
|
+
`https://api.github.com/repos/reactor-team/js-sdk/contents/${EXAMPLES_PATH}`
|
|
35
|
+
);
|
|
36
|
+
const data = yield res.json();
|
|
37
|
+
return data.filter((item) => item.type === "dir").map((item) => item.name);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.log(
|
|
40
|
+
chalk.yellow("\u26A0\uFE0F Could not fetch from GitHub, using fallback templates.")
|
|
41
|
+
);
|
|
42
|
+
return ["longlive", "matrix-2"];
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function showUsage() {
|
|
47
|
+
console.log(chalk.cyan("\n\u{1F9E9} Create Reactor App\n"));
|
|
48
|
+
console.log(chalk.white("Usage:"));
|
|
49
|
+
console.log(chalk.white(" create-reactor-app [project-name] [template]\n"));
|
|
50
|
+
console.log(chalk.white("Arguments:"));
|
|
51
|
+
console.log(chalk.white(" project-name Name of the project to create"));
|
|
52
|
+
console.log(
|
|
53
|
+
chalk.white(
|
|
54
|
+
" template Template to use (longlive, matrix-2, mk64, etc.)\n"
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
console.log(
|
|
58
|
+
chalk.white(
|
|
59
|
+
"If arguments are not provided, you will be prompted interactively.\n"
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
function main() {
|
|
64
|
+
return __async(this, null, function* () {
|
|
65
|
+
const args = process.argv.slice(2);
|
|
66
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
67
|
+
showUsage();
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
console.log(chalk.cyan("\n\u{1F9E9} Create Reactor App\n"));
|
|
71
|
+
const templates = yield getTemplates();
|
|
72
|
+
const [argProjectName, argTemplate] = args;
|
|
73
|
+
if (argTemplate && !templates.includes(argTemplate)) {
|
|
74
|
+
console.error(chalk.red(`Template "${argTemplate}" is not available.`));
|
|
75
|
+
console.log(chalk.white("Available templates:"), templates.join(", "));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
const prompts = [];
|
|
79
|
+
if (!argProjectName) {
|
|
80
|
+
prompts.push({
|
|
81
|
+
type: "input",
|
|
82
|
+
name: "projectName",
|
|
83
|
+
message: "Enter your project name:",
|
|
84
|
+
validate: (input) => input ? true : "Project name cannot be empty."
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (!argTemplate) {
|
|
88
|
+
prompts.push({
|
|
89
|
+
type: "list",
|
|
90
|
+
name: "template",
|
|
91
|
+
message: "Select a template:",
|
|
92
|
+
choices: templates
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const answers = prompts.length > 0 ? yield inquirer.prompt(prompts) : {};
|
|
96
|
+
const projectName = argProjectName || answers.projectName;
|
|
97
|
+
const template = argTemplate || answers.template;
|
|
98
|
+
const dest = path.resolve(process.cwd(), projectName);
|
|
99
|
+
if (fs.existsSync(dest)) {
|
|
100
|
+
console.error(chalk.red(`Folder "${projectName}" already exists.`));
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
console.log(chalk.green(`
|
|
104
|
+
Cloning template "${template}"...
|
|
105
|
+
`));
|
|
106
|
+
const git = simpleGit();
|
|
107
|
+
yield git.clone(REPO, projectName, ["--depth", "1"]);
|
|
108
|
+
const examplesDir = path.join(dest, EXAMPLES_PATH);
|
|
109
|
+
const templateDir = path.join(examplesDir, template);
|
|
110
|
+
if (!fs.existsSync(templateDir)) {
|
|
111
|
+
console.error(chalk.red(`Template "${template}" not found.`));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
for (const file of fs.readdirSync(templateDir)) {
|
|
115
|
+
fs.renameSync(path.join(templateDir, file), path.join(dest, file));
|
|
116
|
+
}
|
|
117
|
+
fs.rmSync(examplesDir, { recursive: true, force: true });
|
|
118
|
+
fs.rmSync(path.join(dest, ".git"), { recursive: true, force: true });
|
|
119
|
+
console.log(chalk.yellow("\nInstalling dependencies...\n"));
|
|
120
|
+
execSync("pnpm install", { cwd: dest, stdio: "inherit" });
|
|
121
|
+
console.log(
|
|
122
|
+
chalk.green(
|
|
123
|
+
`
|
|
124
|
+
\u2705 Project "${projectName}" created successfully using "${template}" template!
|
|
125
|
+
`
|
|
126
|
+
)
|
|
127
|
+
);
|
|
128
|
+
console.log(chalk.cyan("Next steps:"));
|
|
129
|
+
console.log(chalk.white(` cd ${projectName}`));
|
|
130
|
+
console.log(chalk.white(` pnpm dev
|
|
131
|
+
`));
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
main().catch((err) => {
|
|
135
|
+
console.error(chalk.red("Error:"), err);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import react, { ReactNode } from 'react';
|
|
4
|
+
import { RemoteVideoTrack } from 'livekit-client';
|
|
5
|
+
|
|
6
|
+
type ReactorStatus = "disconnected" | "connecting" | "waiting" | "ready";
|
|
7
|
+
interface ReactorWaitingInfo {
|
|
8
|
+
position?: number;
|
|
9
|
+
estimatedWaitTime?: number;
|
|
10
|
+
averageWaitTime?: number;
|
|
11
|
+
}
|
|
12
|
+
interface ReactorError {
|
|
13
|
+
code: string;
|
|
14
|
+
message: string;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
recoverable: boolean;
|
|
17
|
+
component: "coordinator" | "gpu" | "livekit";
|
|
18
|
+
retryAfter?: number;
|
|
19
|
+
}
|
|
20
|
+
interface ReactorState$1 {
|
|
21
|
+
status: ReactorStatus;
|
|
22
|
+
waitingInfo?: ReactorWaitingInfo;
|
|
23
|
+
lastError?: ReactorError;
|
|
24
|
+
}
|
|
25
|
+
type ReactorEvent = "statusChanged" | "waitingInfoChanged" | "newMessage" | "fps" | "streamChanged" | "error";
|
|
26
|
+
|
|
27
|
+
declare const OptionsSchema: z.ZodObject<{
|
|
28
|
+
directConnection: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
livekitJwtToken: z.ZodString;
|
|
30
|
+
livekitWsUrl: z.ZodString;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
insecureApiKey: z.ZodOptional<z.ZodString>;
|
|
33
|
+
jwtToken: z.ZodOptional<z.ZodString>;
|
|
34
|
+
coordinatorUrl: z.ZodDefault<z.ZodString>;
|
|
35
|
+
modelName: z.ZodString;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
type Options = z.input<typeof OptionsSchema>;
|
|
38
|
+
type EventHandler = (...args: any[]) => void;
|
|
39
|
+
declare class Reactor {
|
|
40
|
+
private coordinatorClient;
|
|
41
|
+
private machineClient;
|
|
42
|
+
private status;
|
|
43
|
+
private coordinatorUrl;
|
|
44
|
+
private lastError?;
|
|
45
|
+
private waitingInfo?;
|
|
46
|
+
private jwtToken?;
|
|
47
|
+
private insecureApiKey?;
|
|
48
|
+
private directConnection?;
|
|
49
|
+
private modelName;
|
|
50
|
+
private modelVersion;
|
|
51
|
+
constructor(options: Options);
|
|
52
|
+
private eventListeners;
|
|
53
|
+
on(event: ReactorEvent, handler: EventHandler): void;
|
|
54
|
+
off(event: ReactorEvent, handler: EventHandler): void;
|
|
55
|
+
emit(event: ReactorEvent, ...args: any[]): void;
|
|
56
|
+
/**
|
|
57
|
+
* Public method to send a message to the machine.
|
|
58
|
+
* Automatically wraps the message in an application message.
|
|
59
|
+
* @param message The message to send to the machine.
|
|
60
|
+
* @throws Error if not in ready state
|
|
61
|
+
*/
|
|
62
|
+
sendMessage(message: any): void;
|
|
63
|
+
/**
|
|
64
|
+
* Connects to the machine via LiveKit and waits for the gpu machine to be ready.
|
|
65
|
+
* Once the machine is ready, the Reactor will establish the LiveKit connection.
|
|
66
|
+
* @param livekitJwtToken The JWT token for LiveKit authentication
|
|
67
|
+
* @param livekitWsUrl The WebSocket URL for LiveKit connection
|
|
68
|
+
*/
|
|
69
|
+
private connectToGPUMachine;
|
|
70
|
+
/**
|
|
71
|
+
* Connects to the coordinator and waits for a GPU to be assigned.
|
|
72
|
+
* Once a GPU is assigned, the Reactor will connect to the gpu machine via LiveKit.
|
|
73
|
+
*/
|
|
74
|
+
connect(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Disconnects from the coordinator and the gpu machine.
|
|
77
|
+
* Ensures cleanup completes even if individual disconnections fail.
|
|
78
|
+
*/
|
|
79
|
+
disconnect(): Promise<void>;
|
|
80
|
+
private setStatus;
|
|
81
|
+
private setWaitingInfo;
|
|
82
|
+
getStatus(): ReactorStatus;
|
|
83
|
+
/**
|
|
84
|
+
* Get the current state including status, error, and waiting info
|
|
85
|
+
*/
|
|
86
|
+
getState(): ReactorState$1;
|
|
87
|
+
/**
|
|
88
|
+
* Get waiting information when status is 'waiting'
|
|
89
|
+
*/
|
|
90
|
+
getWaitingInfo(): ReactorWaitingInfo | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Get the last error that occurred
|
|
93
|
+
*/
|
|
94
|
+
getLastError(): ReactorError | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Create and store an error
|
|
97
|
+
*/
|
|
98
|
+
private createError;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface ReactorState {
|
|
102
|
+
status: ReactorStatus;
|
|
103
|
+
videoTrack: RemoteVideoTrack | null;
|
|
104
|
+
fps?: number;
|
|
105
|
+
waitingInfo?: ReactorWaitingInfo;
|
|
106
|
+
lastError?: ReactorError;
|
|
107
|
+
}
|
|
108
|
+
interface ReactorActions {
|
|
109
|
+
sendMessage(message: any): void;
|
|
110
|
+
connect(): Promise<void>;
|
|
111
|
+
disconnect(): Promise<void>;
|
|
112
|
+
}
|
|
113
|
+
interface ReactorInternalState {
|
|
114
|
+
reactor: Reactor;
|
|
115
|
+
}
|
|
116
|
+
type ReactorStore = ReactorState & ReactorActions & {
|
|
117
|
+
internal: ReactorInternalState;
|
|
118
|
+
};
|
|
119
|
+
interface ReactorInitializationProps extends Options {
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface ReactorProviderProps extends ReactorInitializationProps {
|
|
123
|
+
autoConnect?: boolean;
|
|
124
|
+
children: ReactNode;
|
|
125
|
+
}
|
|
126
|
+
declare function ReactorProvider({ children, autoConnect, ...props }: ReactorProviderProps): react_jsx_runtime.JSX.Element;
|
|
127
|
+
declare function useReactorStore<T = ReactorStore>(selector: (state: ReactorStore) => T): T;
|
|
128
|
+
|
|
129
|
+
interface ReactorViewProps {
|
|
130
|
+
width?: number;
|
|
131
|
+
height?: number;
|
|
132
|
+
className?: string;
|
|
133
|
+
style?: react.CSSProperties;
|
|
134
|
+
}
|
|
135
|
+
declare function ReactorView({ width, height, className, style, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Generic hook for accessing selected parts of the Reactor store.
|
|
139
|
+
*
|
|
140
|
+
* @param selector - A function that selects part of the store state.
|
|
141
|
+
* @returns The selected slice from the store.
|
|
142
|
+
*/
|
|
143
|
+
declare function useReactor<T>(selector: (state: ReactorStore) => T): T;
|
|
144
|
+
/**
|
|
145
|
+
* Hook for handling message subscriptions with proper React lifecycle management.
|
|
146
|
+
*
|
|
147
|
+
* @param handler - The message handler function
|
|
148
|
+
*/
|
|
149
|
+
declare function useReactorMessage(handler: (message: any) => void): void;
|
|
150
|
+
|
|
151
|
+
export { type Options, Reactor, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type ReactorWaitingInfo, useReactor, useReactorMessage, useReactorStore };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import react, { ReactNode } from 'react';
|
|
4
|
+
import { RemoteVideoTrack } from 'livekit-client';
|
|
5
|
+
|
|
6
|
+
type ReactorStatus = "disconnected" | "connecting" | "waiting" | "ready";
|
|
7
|
+
interface ReactorWaitingInfo {
|
|
8
|
+
position?: number;
|
|
9
|
+
estimatedWaitTime?: number;
|
|
10
|
+
averageWaitTime?: number;
|
|
11
|
+
}
|
|
12
|
+
interface ReactorError {
|
|
13
|
+
code: string;
|
|
14
|
+
message: string;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
recoverable: boolean;
|
|
17
|
+
component: "coordinator" | "gpu" | "livekit";
|
|
18
|
+
retryAfter?: number;
|
|
19
|
+
}
|
|
20
|
+
interface ReactorState$1 {
|
|
21
|
+
status: ReactorStatus;
|
|
22
|
+
waitingInfo?: ReactorWaitingInfo;
|
|
23
|
+
lastError?: ReactorError;
|
|
24
|
+
}
|
|
25
|
+
type ReactorEvent = "statusChanged" | "waitingInfoChanged" | "newMessage" | "fps" | "streamChanged" | "error";
|
|
26
|
+
|
|
27
|
+
declare const OptionsSchema: z.ZodObject<{
|
|
28
|
+
directConnection: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
livekitJwtToken: z.ZodString;
|
|
30
|
+
livekitWsUrl: z.ZodString;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
insecureApiKey: z.ZodOptional<z.ZodString>;
|
|
33
|
+
jwtToken: z.ZodOptional<z.ZodString>;
|
|
34
|
+
coordinatorUrl: z.ZodDefault<z.ZodString>;
|
|
35
|
+
modelName: z.ZodString;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
type Options = z.input<typeof OptionsSchema>;
|
|
38
|
+
type EventHandler = (...args: any[]) => void;
|
|
39
|
+
declare class Reactor {
|
|
40
|
+
private coordinatorClient;
|
|
41
|
+
private machineClient;
|
|
42
|
+
private status;
|
|
43
|
+
private coordinatorUrl;
|
|
44
|
+
private lastError?;
|
|
45
|
+
private waitingInfo?;
|
|
46
|
+
private jwtToken?;
|
|
47
|
+
private insecureApiKey?;
|
|
48
|
+
private directConnection?;
|
|
49
|
+
private modelName;
|
|
50
|
+
private modelVersion;
|
|
51
|
+
constructor(options: Options);
|
|
52
|
+
private eventListeners;
|
|
53
|
+
on(event: ReactorEvent, handler: EventHandler): void;
|
|
54
|
+
off(event: ReactorEvent, handler: EventHandler): void;
|
|
55
|
+
emit(event: ReactorEvent, ...args: any[]): void;
|
|
56
|
+
/**
|
|
57
|
+
* Public method to send a message to the machine.
|
|
58
|
+
* Automatically wraps the message in an application message.
|
|
59
|
+
* @param message The message to send to the machine.
|
|
60
|
+
* @throws Error if not in ready state
|
|
61
|
+
*/
|
|
62
|
+
sendMessage(message: any): void;
|
|
63
|
+
/**
|
|
64
|
+
* Connects to the machine via LiveKit and waits for the gpu machine to be ready.
|
|
65
|
+
* Once the machine is ready, the Reactor will establish the LiveKit connection.
|
|
66
|
+
* @param livekitJwtToken The JWT token for LiveKit authentication
|
|
67
|
+
* @param livekitWsUrl The WebSocket URL for LiveKit connection
|
|
68
|
+
*/
|
|
69
|
+
private connectToGPUMachine;
|
|
70
|
+
/**
|
|
71
|
+
* Connects to the coordinator and waits for a GPU to be assigned.
|
|
72
|
+
* Once a GPU is assigned, the Reactor will connect to the gpu machine via LiveKit.
|
|
73
|
+
*/
|
|
74
|
+
connect(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Disconnects from the coordinator and the gpu machine.
|
|
77
|
+
* Ensures cleanup completes even if individual disconnections fail.
|
|
78
|
+
*/
|
|
79
|
+
disconnect(): Promise<void>;
|
|
80
|
+
private setStatus;
|
|
81
|
+
private setWaitingInfo;
|
|
82
|
+
getStatus(): ReactorStatus;
|
|
83
|
+
/**
|
|
84
|
+
* Get the current state including status, error, and waiting info
|
|
85
|
+
*/
|
|
86
|
+
getState(): ReactorState$1;
|
|
87
|
+
/**
|
|
88
|
+
* Get waiting information when status is 'waiting'
|
|
89
|
+
*/
|
|
90
|
+
getWaitingInfo(): ReactorWaitingInfo | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Get the last error that occurred
|
|
93
|
+
*/
|
|
94
|
+
getLastError(): ReactorError | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Create and store an error
|
|
97
|
+
*/
|
|
98
|
+
private createError;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface ReactorState {
|
|
102
|
+
status: ReactorStatus;
|
|
103
|
+
videoTrack: RemoteVideoTrack | null;
|
|
104
|
+
fps?: number;
|
|
105
|
+
waitingInfo?: ReactorWaitingInfo;
|
|
106
|
+
lastError?: ReactorError;
|
|
107
|
+
}
|
|
108
|
+
interface ReactorActions {
|
|
109
|
+
sendMessage(message: any): void;
|
|
110
|
+
connect(): Promise<void>;
|
|
111
|
+
disconnect(): Promise<void>;
|
|
112
|
+
}
|
|
113
|
+
interface ReactorInternalState {
|
|
114
|
+
reactor: Reactor;
|
|
115
|
+
}
|
|
116
|
+
type ReactorStore = ReactorState & ReactorActions & {
|
|
117
|
+
internal: ReactorInternalState;
|
|
118
|
+
};
|
|
119
|
+
interface ReactorInitializationProps extends Options {
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface ReactorProviderProps extends ReactorInitializationProps {
|
|
123
|
+
autoConnect?: boolean;
|
|
124
|
+
children: ReactNode;
|
|
125
|
+
}
|
|
126
|
+
declare function ReactorProvider({ children, autoConnect, ...props }: ReactorProviderProps): react_jsx_runtime.JSX.Element;
|
|
127
|
+
declare function useReactorStore<T = ReactorStore>(selector: (state: ReactorStore) => T): T;
|
|
128
|
+
|
|
129
|
+
interface ReactorViewProps {
|
|
130
|
+
width?: number;
|
|
131
|
+
height?: number;
|
|
132
|
+
className?: string;
|
|
133
|
+
style?: react.CSSProperties;
|
|
134
|
+
}
|
|
135
|
+
declare function ReactorView({ width, height, className, style, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Generic hook for accessing selected parts of the Reactor store.
|
|
139
|
+
*
|
|
140
|
+
* @param selector - A function that selects part of the store state.
|
|
141
|
+
* @returns The selected slice from the store.
|
|
142
|
+
*/
|
|
143
|
+
declare function useReactor<T>(selector: (state: ReactorStore) => T): T;
|
|
144
|
+
/**
|
|
145
|
+
* Hook for handling message subscriptions with proper React lifecycle management.
|
|
146
|
+
*
|
|
147
|
+
* @param handler - The message handler function
|
|
148
|
+
*/
|
|
149
|
+
declare function useReactorMessage(handler: (message: any) => void): void;
|
|
150
|
+
|
|
151
|
+
export { type Options, Reactor, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type ReactorWaitingInfo, useReactor, useReactorMessage, useReactorStore };
|