@kvell007/embed-labs-local-bridge 0.1.0-alpha.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 +130 -0
- package/dist/adapters/debug.d.ts +2 -0
- package/dist/adapters/debug.js +124 -0
- package/dist/adapters/debug.js.map +1 -0
- package/dist/adapters/deploy.d.ts +5 -0
- package/dist/adapters/deploy.js +132 -0
- package/dist/adapters/deploy.js.map +1 -0
- package/dist/adapters/flash.d.ts +3 -0
- package/dist/adapters/flash.js +169 -0
- package/dist/adapters/flash.js.map +1 -0
- package/dist/adapters/network.d.ts +22 -0
- package/dist/adapters/network.js +64 -0
- package/dist/adapters/network.js.map +1 -0
- package/dist/adapters/serial.d.ts +3 -0
- package/dist/adapters/serial.js +133 -0
- package/dist/adapters/serial.js.map +1 -0
- package/dist/adapters/uf2.d.ts +1 -0
- package/dist/adapters/uf2.js +53 -0
- package/dist/adapters/uf2.js.map +1 -0
- package/dist/adapters/usb.d.ts +3 -0
- package/dist/adapters/usb.js +102 -0
- package/dist/adapters/usb.js.map +1 -0
- package/dist/hardware.d.ts +17 -0
- package/dist/hardware.js +310 -0
- package/dist/hardware.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +4 -0
- package/dist/jobs.js +125 -0
- package/dist/jobs.js.map +1 -0
- package/dist/process.d.ts +13 -0
- package/dist/process.js +77 -0
- package/dist/process.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +242 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +3 -0
- package/dist/tools.js +228 -0
- package/dist/tools.js.map +1 -0
- package/package.json +26 -0
package/dist/hardware.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access, stat } from "node:fs/promises";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
import { deployTaishanPiArtifact } from "./adapters/deploy.js";
|
|
5
|
+
import { probeTcp, probeTcpWithEvidence } from "./adapters/network.js";
|
|
6
|
+
import { listSerialPorts } from "./adapters/serial.js";
|
|
7
|
+
import { findUf2Volumes } from "./adapters/uf2.js";
|
|
8
|
+
import { isRockchipUsb, scanUsbDevices } from "./adapters/usb.js";
|
|
9
|
+
export { buildFlashPlan, executeRp2350Uf2Flash } from "./adapters/flash.js";
|
|
10
|
+
export { scanDebugTools } from "./adapters/debug.js";
|
|
11
|
+
export { captureSerial, listSerialPorts } from "./adapters/serial.js";
|
|
12
|
+
export { runBoundedSsh } from "./adapters/network.js";
|
|
13
|
+
export { scanUsbDevices } from "./adapters/usb.js";
|
|
14
|
+
const TAISHANPI_DEFAULT_HOST = "198.19.77.2";
|
|
15
|
+
const DEFAULT_PROBE_TIMEOUT_MS = 1000;
|
|
16
|
+
const MIN_PROBE_TIMEOUT_MS = 100;
|
|
17
|
+
const MAX_PROBE_TIMEOUT_MS = 5000;
|
|
18
|
+
const MAX_PROBE_PORTS = 16;
|
|
19
|
+
const MAX_SERIAL_PATHS = 16;
|
|
20
|
+
const DEFAULT_TAISHANPI_REMOTE_DIR = "/userdata/embed-labs/apps";
|
|
21
|
+
const SAFE_REMOTE_DEPLOY_PREFIXES = [`${DEFAULT_TAISHANPI_REMOTE_DIR}/`, "/tmp/embed-labs/"];
|
|
22
|
+
export async function scanHardware() {
|
|
23
|
+
const observedAt = new Date().toISOString();
|
|
24
|
+
const warnings = [];
|
|
25
|
+
const usb = await scanUsbDevices(warnings);
|
|
26
|
+
const serial = await listSerialPorts(warnings);
|
|
27
|
+
const devices = [];
|
|
28
|
+
for (const volumePath of await findUf2Volumes()) {
|
|
29
|
+
devices.push({
|
|
30
|
+
device_id: `rp2350-uf2-${safeId(basename(volumePath))}`,
|
|
31
|
+
board_id: "rp2350",
|
|
32
|
+
display_name: `RP2350 UF2 boot volume (${basename(volumePath)})`,
|
|
33
|
+
status: "bootloader",
|
|
34
|
+
locators: [{ transport: "uf2-volume", volume_path: volumePath }],
|
|
35
|
+
observed_at: observedAt,
|
|
36
|
+
summary_for_user: `Detected RP2350-compatible UF2 boot volume at ${volumePath}.`
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const taishanPiUsb = usb.find((item) => isRockchipUsb(item));
|
|
40
|
+
if (taishanPiUsb) {
|
|
41
|
+
const mode = /maskrom/i.test(taishanPiUsb.product_name ?? "")
|
|
42
|
+
? "bootloader"
|
|
43
|
+
: /loader|rockchip/i.test(taishanPiUsb.product_name ?? "")
|
|
44
|
+
? "bootloader"
|
|
45
|
+
: "unknown";
|
|
46
|
+
devices.push({
|
|
47
|
+
device_id: `taishanpi-rockusb-${safeId(taishanPiUsb.serial_number ?? taishanPiUsb.location_id ?? "device")}`,
|
|
48
|
+
board_id: "taishanpi",
|
|
49
|
+
display_name: taishanPiUsb.product_name ?? "TaishanPi Rockchip USB device",
|
|
50
|
+
status: mode,
|
|
51
|
+
locators: [{ transport: "rockusb" }],
|
|
52
|
+
usb: taishanPiUsb,
|
|
53
|
+
observed_at: observedAt,
|
|
54
|
+
summary_for_user: "Detected a Rockchip USB device that may be TaishanPi Loader/Maskrom."
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const taishanRuntime = await probeTcp(TAISHANPI_DEFAULT_HOST, 22, 800);
|
|
58
|
+
const taishanControl = await probeTcp(TAISHANPI_DEFAULT_HOST, 15301, 800);
|
|
59
|
+
if (taishanRuntime || taishanControl) {
|
|
60
|
+
const evidence = [{
|
|
61
|
+
evidence_id: `evidence_${Date.now()}_taishanpi_tcp`,
|
|
62
|
+
board_id: "taishanpi",
|
|
63
|
+
method: "probe",
|
|
64
|
+
summary: `USB ECM probe host=${TAISHANPI_DEFAULT_HOST} ssh=${taishanRuntime} control=${taishanControl}`,
|
|
65
|
+
observed_at: observedAt,
|
|
66
|
+
verdict: taishanRuntime || taishanControl ? "pass" : "inconclusive"
|
|
67
|
+
}];
|
|
68
|
+
devices.push({
|
|
69
|
+
device_id: `taishanpi-usbecm-${TAISHANPI_DEFAULT_HOST.replace(/\./g, "")}`,
|
|
70
|
+
board_id: "taishanpi",
|
|
71
|
+
display_name: "TaishanPi USB ECM runtime",
|
|
72
|
+
status: "connected",
|
|
73
|
+
locators: [
|
|
74
|
+
{ transport: "usbecm", host: TAISHANPI_DEFAULT_HOST },
|
|
75
|
+
{ transport: "ssh", host: TAISHANPI_DEFAULT_HOST, port: 22 }
|
|
76
|
+
],
|
|
77
|
+
observed_at: observedAt,
|
|
78
|
+
summary_for_user: `Detected TaishanPi runtime link at ${TAISHANPI_DEFAULT_HOST}.`,
|
|
79
|
+
evidence
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
for (const port of serial) {
|
|
83
|
+
devices.push({
|
|
84
|
+
device_id: `serial-${safeId(port.path)}`,
|
|
85
|
+
display_name: port.display_name ?? `Serial port ${port.path}`,
|
|
86
|
+
status: port.available ? "connected" : "not_ready",
|
|
87
|
+
locators: [{ transport: "serial", path: port.path }],
|
|
88
|
+
serial: port,
|
|
89
|
+
observed_at: observedAt,
|
|
90
|
+
summary_for_user: `Detected serial port ${port.path}.`
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return { devices, usb, serial, observed_at: observedAt, warnings };
|
|
94
|
+
}
|
|
95
|
+
export async function probeDevices(request) {
|
|
96
|
+
const observedAt = new Date().toISOString();
|
|
97
|
+
const timeoutMs = clampProbeTimeout(request.timeout_ms);
|
|
98
|
+
const warnings = buildProbeWarnings(request);
|
|
99
|
+
const host = request.host?.trim();
|
|
100
|
+
const ports = normalizeProbePorts(request.ports ?? []);
|
|
101
|
+
const serialPaths = normalizeSerialPaths(request.serial_paths ?? []);
|
|
102
|
+
const knownSerialPorts = process.platform === "win32" && serialPaths.length > 0
|
|
103
|
+
? await listSerialPorts(warnings)
|
|
104
|
+
: undefined;
|
|
105
|
+
const [tcp, serialPathResults] = await Promise.all([
|
|
106
|
+
host
|
|
107
|
+
? Promise.all(ports.map((port) => probeTcpWithEvidence(host, port, timeoutMs, observedAt)))
|
|
108
|
+
: Promise.resolve([]),
|
|
109
|
+
Promise.all(serialPaths.map((path) => probeSerialPath(path, observedAt, knownSerialPorts)))
|
|
110
|
+
]);
|
|
111
|
+
const reachablePorts = tcp.filter((item) => item.reachable).length;
|
|
112
|
+
const existingSerialPaths = serialPathResults.filter((item) => item.exists).length;
|
|
113
|
+
return {
|
|
114
|
+
observed_at: observedAt,
|
|
115
|
+
timeout_ms: timeoutMs,
|
|
116
|
+
tcp,
|
|
117
|
+
serial_paths: serialPathResults,
|
|
118
|
+
summary_for_user: `Probe finished: ${reachablePorts}/${tcp.length} TCP ports reachable, ${existingSerialPaths}/${serialPathResults.length} serial paths exist.`,
|
|
119
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export async function deployTaishanPiApplication(request) {
|
|
123
|
+
return await deployTaishanPiArtifact(request);
|
|
124
|
+
}
|
|
125
|
+
export function validateTaishanPiDeployRequest(input) {
|
|
126
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
127
|
+
return { error: "Request body must be a JSON object." };
|
|
128
|
+
}
|
|
129
|
+
const request = input;
|
|
130
|
+
const unknownFields = Object.keys(request).filter((field) => ![
|
|
131
|
+
"board_id",
|
|
132
|
+
"host",
|
|
133
|
+
"user",
|
|
134
|
+
"artifact_path",
|
|
135
|
+
"remote_path",
|
|
136
|
+
"run",
|
|
137
|
+
"timeout_seconds",
|
|
138
|
+
"approved"
|
|
139
|
+
].includes(field));
|
|
140
|
+
if (unknownFields.length > 0) {
|
|
141
|
+
return { error: `Unsupported field(s): ${unknownFields.join(", ")}.` };
|
|
142
|
+
}
|
|
143
|
+
if (request.board_id !== undefined && request.board_id !== "taishanpi") {
|
|
144
|
+
return { error: "board_id must be taishanpi when provided." };
|
|
145
|
+
}
|
|
146
|
+
if (typeof request.host !== "string" || !isValidDeployHost(request.host.trim())) {
|
|
147
|
+
return { error: "host must be a hostname or IP address without schemes, paths, spaces, or credentials." };
|
|
148
|
+
}
|
|
149
|
+
if (request.user !== undefined && (typeof request.user !== "string" || !/^[a-z_][a-z0-9_-]{0,31}$/i.test(request.user.trim()))) {
|
|
150
|
+
return { error: "user must be a safe SSH user name when provided." };
|
|
151
|
+
}
|
|
152
|
+
if (typeof request.artifact_path !== "string" || !request.artifact_path.trim()) {
|
|
153
|
+
return { error: "artifact_path is required." };
|
|
154
|
+
}
|
|
155
|
+
if (request.remote_path !== undefined && (typeof request.remote_path !== "string" || !isSafeRemoteDeployPath(request.remote_path.trim()))) {
|
|
156
|
+
return { error: `remote_path must be under ${SAFE_REMOTE_DEPLOY_PREFIXES.join(" or ")} and contain only safe path characters.` };
|
|
157
|
+
}
|
|
158
|
+
if (request.run !== undefined && typeof request.run !== "boolean") {
|
|
159
|
+
return { error: "run must be a boolean when provided." };
|
|
160
|
+
}
|
|
161
|
+
if (request.timeout_seconds !== undefined && (typeof request.timeout_seconds !== "number" || !Number.isFinite(request.timeout_seconds) || request.timeout_seconds <= 0)) {
|
|
162
|
+
return { error: "timeout_seconds must be a positive number when provided." };
|
|
163
|
+
}
|
|
164
|
+
if (request.approved !== undefined && typeof request.approved !== "boolean") {
|
|
165
|
+
return { error: "approved must be a boolean when provided." };
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
request: {
|
|
169
|
+
board_id: "taishanpi",
|
|
170
|
+
host: request.host.trim(),
|
|
171
|
+
user: typeof request.user === "string" ? request.user.trim() : undefined,
|
|
172
|
+
artifact_path: request.artifact_path.trim(),
|
|
173
|
+
remote_path: typeof request.remote_path === "string" ? request.remote_path.trim() : undefined,
|
|
174
|
+
run: typeof request.run === "boolean" ? request.run : undefined,
|
|
175
|
+
timeout_seconds: typeof request.timeout_seconds === "number" ? request.timeout_seconds : undefined,
|
|
176
|
+
approved: typeof request.approved === "boolean" ? request.approved : undefined
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function probeSerialPath(path, observedAt, knownSerialPorts) {
|
|
181
|
+
const knownPort = knownSerialPorts?.find((port) => port.path.toLowerCase() === path.toLowerCase());
|
|
182
|
+
if (knownPort) {
|
|
183
|
+
return {
|
|
184
|
+
transport: "serial-path",
|
|
185
|
+
path,
|
|
186
|
+
exists: true,
|
|
187
|
+
path_type: "unknown",
|
|
188
|
+
readable: knownPort.available,
|
|
189
|
+
writable: knownPort.available,
|
|
190
|
+
observed_at: observedAt
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const pathStat = await stat(path);
|
|
195
|
+
const [readable, writable] = await Promise.all([
|
|
196
|
+
canAccess(path, constants.R_OK),
|
|
197
|
+
canAccess(path, constants.W_OK)
|
|
198
|
+
]);
|
|
199
|
+
return {
|
|
200
|
+
transport: "serial-path",
|
|
201
|
+
path,
|
|
202
|
+
exists: true,
|
|
203
|
+
path_type: pathStat.isCharacterDevice()
|
|
204
|
+
? "character_device"
|
|
205
|
+
: pathStat.isFile()
|
|
206
|
+
? "file"
|
|
207
|
+
: pathStat.isDirectory()
|
|
208
|
+
? "directory"
|
|
209
|
+
: "other",
|
|
210
|
+
readable,
|
|
211
|
+
writable,
|
|
212
|
+
observed_at: observedAt
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
const typed = error;
|
|
217
|
+
return {
|
|
218
|
+
transport: "serial-path",
|
|
219
|
+
path,
|
|
220
|
+
exists: false,
|
|
221
|
+
path_type: "unknown",
|
|
222
|
+
observed_at: observedAt,
|
|
223
|
+
error_code: typed.code,
|
|
224
|
+
error_message: typed.message
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
async function canAccess(path, mode) {
|
|
229
|
+
try {
|
|
230
|
+
await access(path, mode);
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function clampProbeTimeout(timeoutMs) {
|
|
238
|
+
const timeout = Number.isFinite(timeoutMs) ? Number(timeoutMs) : DEFAULT_PROBE_TIMEOUT_MS;
|
|
239
|
+
return Math.max(MIN_PROBE_TIMEOUT_MS, Math.min(Math.trunc(timeout), MAX_PROBE_TIMEOUT_MS));
|
|
240
|
+
}
|
|
241
|
+
function normalizeProbePorts(ports) {
|
|
242
|
+
const normalized = ports
|
|
243
|
+
.map((port) => Math.trunc(Number(port)))
|
|
244
|
+
.filter((port) => Number.isInteger(port) && port > 0 && port <= 65_535);
|
|
245
|
+
return [...new Set(normalized)].slice(0, MAX_PROBE_PORTS);
|
|
246
|
+
}
|
|
247
|
+
function normalizeSerialPaths(paths) {
|
|
248
|
+
const normalized = paths
|
|
249
|
+
.map((path) => path.trim())
|
|
250
|
+
.filter(Boolean);
|
|
251
|
+
return [...new Set(normalized)].slice(0, MAX_SERIAL_PATHS);
|
|
252
|
+
}
|
|
253
|
+
function buildProbeWarnings(request) {
|
|
254
|
+
const warnings = [];
|
|
255
|
+
if (request.host && (request.ports?.length ?? 0) === 0) {
|
|
256
|
+
warnings.push({
|
|
257
|
+
code: "probe_host_without_ports",
|
|
258
|
+
message: "Host was provided without TCP ports, so no TCP probe was performed."
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (request.timeout_ms !== undefined && (request.timeout_ms < MIN_PROBE_TIMEOUT_MS || request.timeout_ms > MAX_PROBE_TIMEOUT_MS)) {
|
|
262
|
+
warnings.push({
|
|
263
|
+
code: "probe_timeout_clamped",
|
|
264
|
+
message: `Probe timeout was clamped to ${MIN_PROBE_TIMEOUT_MS}-${MAX_PROBE_TIMEOUT_MS}ms.`
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
if (countUniqueProbePorts(request.ports ?? []) > MAX_PROBE_PORTS) {
|
|
268
|
+
warnings.push({
|
|
269
|
+
code: "probe_ports_truncated",
|
|
270
|
+
message: `Only the first ${MAX_PROBE_PORTS} unique valid ports were probed.`
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
if (countUniqueSerialPaths(request.serial_paths ?? []) > MAX_SERIAL_PATHS) {
|
|
274
|
+
warnings.push({
|
|
275
|
+
code: "probe_serial_paths_truncated",
|
|
276
|
+
message: `Only the first ${MAX_SERIAL_PATHS} unique serial paths were probed.`
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return warnings;
|
|
280
|
+
}
|
|
281
|
+
function countUniqueProbePorts(ports) {
|
|
282
|
+
return new Set(ports
|
|
283
|
+
.map((port) => Math.trunc(Number(port)))
|
|
284
|
+
.filter((port) => Number.isInteger(port) && port > 0 && port <= 65_535)).size;
|
|
285
|
+
}
|
|
286
|
+
function countUniqueSerialPaths(paths) {
|
|
287
|
+
return new Set(paths.map((path) => path.trim()).filter(Boolean)).size;
|
|
288
|
+
}
|
|
289
|
+
function safeId(input) {
|
|
290
|
+
return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "unknown";
|
|
291
|
+
}
|
|
292
|
+
function isValidDeployHost(host) {
|
|
293
|
+
if (!host || host.length > 253 || /[\s\x00-\x1f\x7f]/.test(host)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
if (host.includes("://") || host.includes("/") || host.includes("\\") || host.includes("@")) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
return /^[a-zA-Z0-9.-]+$/.test(host);
|
|
300
|
+
}
|
|
301
|
+
function isSafeRemoteDeployPath(remotePath) {
|
|
302
|
+
if (!SAFE_REMOTE_DEPLOY_PREFIXES.some((prefix) => remotePath.startsWith(prefix))) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
if (remotePath.includes("..") || /[\s\x00-\x1f\x7f'"`$;&|<>()[\]{}]/.test(remotePath)) {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
return /^\/[A-Za-z0-9._/-]+$/.test(remotePath) && !remotePath.endsWith("/");
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=hardware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardware.js","sourceRoot":"","sources":["../src/hardware.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { startServer } from "./server.js";
|
|
5
|
+
export { startServer } from "./server.js";
|
|
6
|
+
if (isDirectRun()) {
|
|
7
|
+
startServer();
|
|
8
|
+
}
|
|
9
|
+
function isDirectRun() {
|
|
10
|
+
if (!process.argv[1]) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,IAAI,WAAW,EAAE,EAAE,CAAC;IAClB,WAAW,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,WAAW;IAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/jobs.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BridgeJob, FlashRunRequest } from "@embed-labs/protocol";
|
|
2
|
+
export declare function listJobs(): BridgeJob[];
|
|
3
|
+
export declare function getJob(localJobId: string): BridgeJob | undefined;
|
|
4
|
+
export declare function startFlashJob(request: FlashRunRequest): Promise<BridgeJob>;
|
package/dist/jobs.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { buildFlashPlan, executeRp2350Uf2Flash } from "./hardware.js";
|
|
2
|
+
import { tailLines } from "./process.js";
|
|
3
|
+
const jobs = new Map();
|
|
4
|
+
export function listJobs() {
|
|
5
|
+
return [...jobs.values()].sort((a, b) => a.created_at.localeCompare(b.created_at));
|
|
6
|
+
}
|
|
7
|
+
export function getJob(localJobId) {
|
|
8
|
+
return jobs.get(localJobId);
|
|
9
|
+
}
|
|
10
|
+
export async function startFlashJob(request) {
|
|
11
|
+
const now = new Date().toISOString();
|
|
12
|
+
const localJobId = `local_job_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
|
13
|
+
const job = {
|
|
14
|
+
local_job_id: localJobId,
|
|
15
|
+
state: "queued",
|
|
16
|
+
kind: "flash.device",
|
|
17
|
+
progress_stage: "queued",
|
|
18
|
+
progress_text: "Flash job queued.",
|
|
19
|
+
progress_percent: 0,
|
|
20
|
+
output_tail: [],
|
|
21
|
+
created_at: now,
|
|
22
|
+
updated_at: now
|
|
23
|
+
};
|
|
24
|
+
jobs.set(localJobId, job);
|
|
25
|
+
void runFlashJob(localJobId, request);
|
|
26
|
+
return job;
|
|
27
|
+
}
|
|
28
|
+
async function runFlashJob(localJobId, request) {
|
|
29
|
+
updateJob(localJobId, {
|
|
30
|
+
state: "planning",
|
|
31
|
+
progress_stage: "plan",
|
|
32
|
+
progress_text: "Building flash plan.",
|
|
33
|
+
progress_percent: 5
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
const plan = await buildFlashPlan(request);
|
|
37
|
+
if (!plan.ready) {
|
|
38
|
+
updateJob(localJobId, {
|
|
39
|
+
state: "blocked",
|
|
40
|
+
progress_stage: "not_ready",
|
|
41
|
+
progress_text: plan.summary,
|
|
42
|
+
progress_percent: 10,
|
|
43
|
+
result: { plan },
|
|
44
|
+
error: {
|
|
45
|
+
code: "flash_plan_not_ready",
|
|
46
|
+
message: plan.summary,
|
|
47
|
+
retryable: true,
|
|
48
|
+
details: { missing_files: plan.missing_files, missing_tools: plan.missing_tools }
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!request.approved) {
|
|
54
|
+
updateJob(localJobId, {
|
|
55
|
+
state: "awaiting_approval",
|
|
56
|
+
progress_stage: "awaiting_approval",
|
|
57
|
+
progress_text: "Flash plan requires explicit approval.",
|
|
58
|
+
progress_percent: 15,
|
|
59
|
+
result: { plan },
|
|
60
|
+
error: {
|
|
61
|
+
code: "approval_required",
|
|
62
|
+
message: "Re-run with approved=true after the user approves the destructive flash plan.",
|
|
63
|
+
retryable: true
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
updateJob(localJobId, {
|
|
69
|
+
state: "running",
|
|
70
|
+
progress_stage: "flash",
|
|
71
|
+
progress_text: "Executing local flash profile.",
|
|
72
|
+
progress_percent: 30,
|
|
73
|
+
result: { plan }
|
|
74
|
+
});
|
|
75
|
+
if (request.board_id === "rp2350") {
|
|
76
|
+
const result = await executeRp2350Uf2Flash(plan);
|
|
77
|
+
updateJob(localJobId, {
|
|
78
|
+
state: "succeeded",
|
|
79
|
+
progress_stage: "finished",
|
|
80
|
+
progress_text: "RP2350 UF2 copy finished.",
|
|
81
|
+
progress_percent: 100,
|
|
82
|
+
output_tail: tailLines(JSON.stringify(result, null, 2)),
|
|
83
|
+
result: { plan, flash_result: result }
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
updateJob(localJobId, {
|
|
88
|
+
state: "blocked",
|
|
89
|
+
progress_stage: "blocked_by_profile_review",
|
|
90
|
+
progress_text: "Real flashing for this board is blocked until the Board Pack command profile is accepted.",
|
|
91
|
+
progress_percent: 40,
|
|
92
|
+
result: { plan },
|
|
93
|
+
error: {
|
|
94
|
+
code: "flash_profile_not_accepted",
|
|
95
|
+
message: "This board has a planner, but its destructive command template is not accepted yet.",
|
|
96
|
+
retryable: false,
|
|
97
|
+
remediation: "Complete EL-010/EL-011 flash profile review before enabling this real flash path."
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
updateJob(localJobId, {
|
|
103
|
+
state: "failed",
|
|
104
|
+
progress_stage: "failed",
|
|
105
|
+
progress_text: "Flash job failed.",
|
|
106
|
+
error: {
|
|
107
|
+
code: "flash_job_failed",
|
|
108
|
+
message: error instanceof Error ? error.message : String(error),
|
|
109
|
+
retryable: true
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function updateJob(localJobId, patch) {
|
|
115
|
+
const existing = jobs.get(localJobId);
|
|
116
|
+
if (!existing) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
jobs.set(localJobId, {
|
|
120
|
+
...existing,
|
|
121
|
+
...patch,
|
|
122
|
+
updated_at: new Date().toISOString()
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=jobs.js.map
|
package/dist/jobs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CommandResult {
|
|
2
|
+
command: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
exit_code: number | null;
|
|
5
|
+
stdout: string;
|
|
6
|
+
stderr: string;
|
|
7
|
+
timed_out: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function commandExists(command: string): Promise<boolean>;
|
|
10
|
+
export declare function resolveCommand(command: string): Promise<string | undefined>;
|
|
11
|
+
export declare function stripControl(input: string): string;
|
|
12
|
+
export declare function runCommand(command: string, args: string[], timeoutMs?: number, stdin?: string | Buffer): Promise<CommandResult>;
|
|
13
|
+
export declare function tailLines(text: string, maxLines?: number): string[];
|
package/dist/process.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
export async function commandExists(command) {
|
|
6
|
+
return (await resolveCommand(command)) !== undefined;
|
|
7
|
+
}
|
|
8
|
+
export async function resolveCommand(command) {
|
|
9
|
+
const pathParts = (process.env.PATH ?? "").split(process.platform === "win32" ? ";" : ":");
|
|
10
|
+
const suffixes = process.platform === "win32" ? ["", ".exe", ".cmd", ".bat"] : [""];
|
|
11
|
+
for (const dir of pathParts) {
|
|
12
|
+
for (const suffix of suffixes) {
|
|
13
|
+
const candidate = dir ? join(dir, `${command}${suffix}`) : `${command}${suffix}`;
|
|
14
|
+
try {
|
|
15
|
+
await access(candidate, constants.X_OK);
|
|
16
|
+
return candidate;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Keep looking.
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
export function stripControl(input) {
|
|
26
|
+
return input
|
|
27
|
+
.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "")
|
|
28
|
+
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, "");
|
|
29
|
+
}
|
|
30
|
+
export async function runCommand(command, args, timeoutMs = 10_000, stdin) {
|
|
31
|
+
return new Promise((resolve) => {
|
|
32
|
+
const child = spawn(command, args, { stdio: [stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"] });
|
|
33
|
+
let stdout = "";
|
|
34
|
+
let stderr = "";
|
|
35
|
+
let timedOut = false;
|
|
36
|
+
const timer = setTimeout(() => {
|
|
37
|
+
timedOut = true;
|
|
38
|
+
child.kill("SIGTERM");
|
|
39
|
+
setTimeout(() => child.kill("SIGKILL"), 1000).unref();
|
|
40
|
+
}, timeoutMs);
|
|
41
|
+
child.stdout?.on("data", (chunk) => {
|
|
42
|
+
stdout += chunk.toString("utf8");
|
|
43
|
+
});
|
|
44
|
+
child.stderr?.on("data", (chunk) => {
|
|
45
|
+
stderr += chunk.toString("utf8");
|
|
46
|
+
});
|
|
47
|
+
if (stdin !== undefined && child.stdin) {
|
|
48
|
+
child.stdin.end(stdin);
|
|
49
|
+
}
|
|
50
|
+
child.on("error", (error) => {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
resolve({
|
|
53
|
+
command,
|
|
54
|
+
args,
|
|
55
|
+
exit_code: null,
|
|
56
|
+
stdout: "",
|
|
57
|
+
stderr: error.message,
|
|
58
|
+
timed_out: timedOut
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
child.on("close", (code) => {
|
|
62
|
+
clearTimeout(timer);
|
|
63
|
+
resolve({
|
|
64
|
+
command,
|
|
65
|
+
args,
|
|
66
|
+
exit_code: code,
|
|
67
|
+
stdout: stripControl(stdout),
|
|
68
|
+
stderr: stripControl(stderr),
|
|
69
|
+
timed_out: timedOut
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export function tailLines(text, maxLines = 40) {
|
|
75
|
+
return text.split(/\r?\n/).filter(Boolean).slice(-maxLines);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"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"}
|