robopark 3.1.2 → 3.3.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 +66 -95
- package/bin/robopark.js +9 -2
- package/conversation/elevenlabs_agent.py +1617 -1617
- package/conversation/supervisor_store.py +189 -189
- package/dist/{kernel/config-schema.js → config-schema.js} +1 -0
- package/dist/config-schema.js.map +1 -0
- package/dist/robopark/add-robot.js +1 -0
- package/dist/robopark/add-robot.js.map +1 -0
- package/dist/robopark/agent-ctl.js +1 -0
- package/dist/robopark/agent-ctl.js.map +1 -0
- package/dist/robopark/auto-start.js +51 -73
- package/dist/robopark/auto-start.js.map +1 -0
- package/dist/robopark/conversation.js +1 -0
- package/dist/robopark/conversation.js.map +1 -0
- package/dist/robopark/discovery.js +1 -0
- package/dist/robopark/discovery.js.map +1 -0
- package/dist/robopark/doctor.js +1 -0
- package/dist/robopark/doctor.js.map +1 -0
- package/dist/robopark/enroll.js +1 -0
- package/dist/robopark/enroll.js.map +1 -0
- package/dist/robopark/llm-set.js +1 -0
- package/dist/robopark/llm-set.js.map +1 -0
- package/dist/robopark/motor-control.js +1 -0
- package/dist/robopark/motor-control.js.map +1 -0
- package/dist/robopark/preview-agent-launcher.js +1 -0
- package/dist/robopark/preview-agent-launcher.js.map +1 -0
- package/dist/robopark/probe.js +16 -15
- package/dist/robopark/probe.js.map +1 -0
- package/dist/robopark/profile.js +1 -0
- package/dist/robopark/profile.js.map +1 -0
- package/dist/robopark/python-env.js +1 -7
- package/dist/robopark/python-env.js.map +1 -0
- package/dist/robopark/robot-runtime.js +1 -0
- package/dist/robopark/robot-runtime.js.map +1 -0
- package/dist/robopark/scan.js +1 -0
- package/dist/robopark/scan.js.map +1 -0
- package/dist/robopark/screen-control.js +1 -0
- package/dist/robopark/screen-control.js.map +1 -0
- package/dist/robopark/secrets.js +1 -0
- package/dist/robopark/secrets.js.map +1 -0
- package/dist/robopark/serve.js +4 -6
- package/dist/robopark/serve.js.map +1 -0
- package/dist/robopark/server-add.js +1 -0
- package/dist/robopark/server-add.js.map +1 -0
- package/dist/robopark/setup-livekit.js +53 -52
- package/dist/robopark/setup-livekit.js.map +1 -0
- package/dist/robopark/setup.js +1 -0
- package/dist/robopark/setup.js.map +1 -0
- package/dist/robopark/stop-all.js +1 -0
- package/dist/robopark/stop-all.js.map +1 -0
- package/dist/robopark/verify.js +1 -0
- package/dist/robopark/verify.js.map +1 -0
- package/dist/robopark/vision-agent-launcher.js +1 -0
- package/dist/robopark/vision-agent-launcher.js.map +1 -0
- package/dist/robopark/vision-control.js +1 -0
- package/dist/robopark/vision-control.js.map +1 -0
- package/dist/robopark-cli.js +7 -125
- package/dist/robopark-cli.js.map +1 -0
- package/package.json +16 -25
- package/pi-client/_install_steps.sh +29 -29
- package/pi-client/client.py +76 -76
- package/pi-client/install.sh +40 -40
- package/pi-client/join_convo.sh +54 -54
- package/pi-client/livekit_bridge.py +24 -24
- package/pi-client/motor_bridge.py +10 -10
- package/scheduler/__pycache__/main.cpython-312.pyc +0 -0
- package/scheduler/main.py +196 -17
- package/scheduler/media_lock.py +57 -57
- package/scheduler/preview_agent.py +1122 -1122
- package/scheduler/production_config.json +73 -113
- package/scheduler/scripts/install-robot-supervisor-linux.sh +33 -33
- package/{static → scheduler/static}/vendor/elevenlabs-client.iife.js +24199 -24199
- package/scheduler/static/voice-join.html +177 -0
- package/screen/screen_runtime.py +75 -75
- package/vision/app_pi_clean.py +297 -297
- package/vision/audio_server_pi.py +24 -24
- package/vision/install.sh +34 -34
- package/vision/motor_server.py +275 -275
- package/vision/requirements_camera.txt +6 -6
- package/vision/requirements_motor.txt +4 -4
- package/vision/requirements_pi_unified.txt +2 -2
- package/vision/requirements_vision_agent.txt +19 -19
- package/vision/run.sh +244 -244
- package/vision/services/services.sh +12 -12
- package/dist/kernel/types.js +0 -7
- package/dist/robopark/access.js +0 -99
- package/dist/robopark/control-center-html.js +0 -9191
- package/dist/robopark/control-server.js +0 -148
- package/dist/robopark/deployment-commands.js +0 -47
- package/dist/robopark/standalone.js +0 -562
- package/dist/robopark/voice-join-html.js +0 -57
- package/scripts/windows-shim-fix.cjs +0 -58
- package/static/robopark/barracuda.png +0 -0
- package/static/robopark/bmw.png +0 -0
- package/static/robopark/jaguar.png +0 -0
- package/static/robopark/magnus.jpg +0 -0
- package/static/robopark/panda.png +0 -0
- package/static/robopark/tesla.png +0 -0
- package/static/robopark/titan.jpg +0 -0
- package/static/robopark/volt.png +0 -0
- package/static/vendor/elevenlabs-client.LICENSE +0 -21
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { createServer, request as httpRequest } from 'node:http';
|
|
2
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
-
import { dirname, extname, join } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { createRequire } from 'node:module';
|
|
6
|
-
import { ROBOPARK_CONTROL_HTML } from './control-center-html.js';
|
|
7
|
-
import { ROBOPARK_VOICE_JOIN_HTML } from './voice-join-html.js';
|
|
8
|
-
function packageRoot() {
|
|
9
|
-
return dirname(dirname(dirname(fileURLToPath(import.meta.url))));
|
|
10
|
-
}
|
|
11
|
-
function contentType(path) {
|
|
12
|
-
const ext = extname(path).toLowerCase();
|
|
13
|
-
if (ext === '.png')
|
|
14
|
-
return 'image/png';
|
|
15
|
-
if (ext === '.jpg' || ext === '.jpeg')
|
|
16
|
-
return 'image/jpeg';
|
|
17
|
-
if (ext === '.js')
|
|
18
|
-
return 'application/javascript; charset=utf-8';
|
|
19
|
-
return 'application/octet-stream';
|
|
20
|
-
}
|
|
21
|
-
function proxy(req, res, schedulerUrl) {
|
|
22
|
-
const incoming = new URL(req.url ?? '/', 'http://robopark.local');
|
|
23
|
-
const upstreamBase = new URL(schedulerUrl);
|
|
24
|
-
const path = incoming.pathname.replace(/^\/robopark/, '') || '/';
|
|
25
|
-
const upstream = httpRequest({
|
|
26
|
-
protocol: upstreamBase.protocol,
|
|
27
|
-
hostname: upstreamBase.hostname,
|
|
28
|
-
port: upstreamBase.port,
|
|
29
|
-
method: req.method,
|
|
30
|
-
path: `${path}${incoming.search}`,
|
|
31
|
-
headers: { ...req.headers, host: upstreamBase.host },
|
|
32
|
-
}, response => {
|
|
33
|
-
res.writeHead(response.statusCode ?? 502, response.headers);
|
|
34
|
-
response.pipe(res);
|
|
35
|
-
});
|
|
36
|
-
upstream.on('error', error => {
|
|
37
|
-
if (!res.headersSent)
|
|
38
|
-
res.writeHead(502, { 'content-type': 'application/json' });
|
|
39
|
-
res.end(JSON.stringify({ ok: false, error: `scheduler unavailable: ${error.message}` }));
|
|
40
|
-
});
|
|
41
|
-
req.pipe(upstream);
|
|
42
|
-
}
|
|
43
|
-
async function fleetStatus(schedulerUrl) {
|
|
44
|
-
const [devices, robots] = await Promise.all([
|
|
45
|
-
fetch(`${schedulerUrl}/api/devices`).then(r => r.ok ? r.json() : []),
|
|
46
|
-
fetch(`${schedulerUrl}/api/robots`).then(r => r.ok ? r.json() : []),
|
|
47
|
-
]);
|
|
48
|
-
const nodes = devices.map(device => ({
|
|
49
|
-
nodeId: device.id,
|
|
50
|
-
displayName: device.name,
|
|
51
|
-
role: 'robot',
|
|
52
|
-
connected: device.status === 'online',
|
|
53
|
-
hardware: device.device_inventory ?? {},
|
|
54
|
-
characterId: device.character_id,
|
|
55
|
-
tailscaleIp: device.tailscale_ip,
|
|
56
|
-
lanIp: device.lan_ip,
|
|
57
|
-
}));
|
|
58
|
-
return {
|
|
59
|
-
product: 'robopark',
|
|
60
|
-
nodes,
|
|
61
|
-
robots,
|
|
62
|
-
control: { schedulerLinked: true, schedulerUrl },
|
|
63
|
-
generatedAt: new Date().toISOString(),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
export async function startControlServer(opts) {
|
|
67
|
-
const root = packageRoot();
|
|
68
|
-
const server = createServer((req, res) => {
|
|
69
|
-
const url = new URL(req.url ?? '/', 'http://robopark.local');
|
|
70
|
-
const path = url.pathname;
|
|
71
|
-
if (req.method === 'GET' && (path === '/' || path === '/ui' || path === '/dashboard' || path === '/robopark-control.html')) {
|
|
72
|
-
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-store' });
|
|
73
|
-
res.end(ROBOPARK_CONTROL_HTML);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
if (req.method === 'GET' && path === '/fed/ui-build') {
|
|
77
|
-
const build = ROBOPARK_CONTROL_HTML.match(/<meta name="robopark-ui-build" content="([^"]+)">/)?.[1] ?? 'standalone';
|
|
78
|
-
res.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' });
|
|
79
|
-
res.end(JSON.stringify({ build, owner: 'robopark' }));
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (req.method === 'GET' && path === '/voice-join.html') {
|
|
83
|
-
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-store', 'referrer-policy': 'strict-origin' });
|
|
84
|
-
res.end(ROBOPARK_VOICE_JOIN_HTML);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (req.method === 'GET' && path === '/fed/status') {
|
|
88
|
-
void fleetStatus(opts.schedulerUrl).then(status => {
|
|
89
|
-
res.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' });
|
|
90
|
-
res.end(JSON.stringify(status));
|
|
91
|
-
}).catch(error => {
|
|
92
|
-
res.writeHead(503, { 'content-type': 'application/json' });
|
|
93
|
-
res.end(JSON.stringify({ ok: false, error: error instanceof Error ? error.message : String(error) }));
|
|
94
|
-
});
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (req.method === 'GET' && path === '/fed/stream') {
|
|
98
|
-
res.writeHead(200, { 'content-type': 'text/event-stream', 'cache-control': 'no-store', connection: 'keep-alive' });
|
|
99
|
-
res.write('retry: 3000\n\n');
|
|
100
|
-
const timer = setInterval(() => res.write(': robopark heartbeat\n\n'), 10_000);
|
|
101
|
-
req.on('close', () => clearInterval(timer));
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (req.method === 'GET' && path.startsWith('/static/')) {
|
|
105
|
-
const relative = path.slice(8).replace(/\.\./g, '');
|
|
106
|
-
const file = join(root, 'static', relative);
|
|
107
|
-
if (!existsSync(file)) {
|
|
108
|
-
res.writeHead(404).end('asset not found');
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
res.writeHead(200, { 'content-type': contentType(file), 'cache-control': 'public,max-age=86400' });
|
|
112
|
-
res.end(readFileSync(file));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
if (req.method === 'GET' && path === '/vendor/livekit-client.umd.js') {
|
|
116
|
-
try {
|
|
117
|
-
const file = createRequire(import.meta.url).resolve('livekit-client');
|
|
118
|
-
res.writeHead(200, { 'content-type': 'application/javascript; charset=utf-8', 'cache-control': 'public,max-age=86400' });
|
|
119
|
-
res.end(readFileSync(file));
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
res.writeHead(404).end('livekit-client not installed');
|
|
123
|
-
}
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
if (req.method === 'GET' && path === '/vendor/elevenlabs-client.iife.js') {
|
|
127
|
-
const file = join(root, 'static', 'vendor', 'elevenlabs-client.iife.js');
|
|
128
|
-
if (!existsSync(file)) {
|
|
129
|
-
res.writeHead(404).end('ElevenLabs client not installed');
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
res.writeHead(200, { 'content-type': 'application/javascript; charset=utf-8', 'cache-control': 'public,max-age=86400' });
|
|
133
|
-
res.end(readFileSync(file));
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
if (path.startsWith('/robopark/')) {
|
|
137
|
-
proxy(req, res, opts.schedulerUrl);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
res.writeHead(404, { 'content-type': 'application/json' });
|
|
141
|
-
res.end(JSON.stringify({ ok: false, error: 'not found' }));
|
|
142
|
-
});
|
|
143
|
-
await new Promise((resolve, reject) => {
|
|
144
|
-
server.once('error', reject);
|
|
145
|
-
server.listen(opts.port, opts.host, () => resolve());
|
|
146
|
-
});
|
|
147
|
-
return server;
|
|
148
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
function loadProductionConfig() {
|
|
5
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
const candidates = [
|
|
7
|
-
join(here, '..', '..', 'scheduler', 'production_config.json'),
|
|
8
|
-
join(here, '..', '..', '..', 'packages', 'robopark', 'scheduler', 'production_config.json'),
|
|
9
|
-
];
|
|
10
|
-
for (const path of candidates) {
|
|
11
|
-
try {
|
|
12
|
-
return JSON.parse(readFileSync(path, 'utf8'));
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
// Try the source-tree or installed-package layout next.
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
throw new Error('packaged production character configuration was not found');
|
|
19
|
-
}
|
|
20
|
-
export function productionCharacters() {
|
|
21
|
-
return loadProductionConfig().characters
|
|
22
|
-
.filter(character => character.default_engine === 'elevenlabs' && character.elevenlabs_agent_id)
|
|
23
|
-
.sort((a, b) => a.id.localeCompare(b.id));
|
|
24
|
-
}
|
|
25
|
-
export function deploymentCommandSheet(options) {
|
|
26
|
-
const install = `npm install -g robopark@${options.version}`;
|
|
27
|
-
const token = options.token?.trim() || 'rp1_<token-from-gateway>';
|
|
28
|
-
const publicUrl = options.publicUrl?.trim() || 'https://<gateway-tailnet-or-domain>';
|
|
29
|
-
const characters = productionCharacters();
|
|
30
|
-
const lines = [
|
|
31
|
-
'ROBOPARK DEPLOYMENT COMMANDS',
|
|
32
|
-
'',
|
|
33
|
-
'GATEWAY DEVICE',
|
|
34
|
-
install,
|
|
35
|
-
`robopark --password '<activation-password>' gateway start --public-url ${publicUrl}`,
|
|
36
|
-
'',
|
|
37
|
-
'EACH ROBOT DEVICE (run install/connect once, then its start command)',
|
|
38
|
-
install,
|
|
39
|
-
`robopark connect ${token}`,
|
|
40
|
-
'',
|
|
41
|
-
];
|
|
42
|
-
for (const character of characters) {
|
|
43
|
-
lines.push(`${character.name}: robopark start --voice --video --character ${character.id}`);
|
|
44
|
-
}
|
|
45
|
-
lines.push('', 'OPERATIONS', 'robopark status', 'robopark gateway start', '', `${characters.length} verified character commands - production config revision ${loadProductionConfig().revision}`);
|
|
46
|
-
return lines.join('\n');
|
|
47
|
-
}
|