@kvell007/embed-labs-local-bridge 0.1.0-alpha.73 → 0.1.0-alpha.74
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/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 +220 -0
- package/dist/adapters/serial.js.map +1 -0
- package/dist/adapters/taishanpi-live.d.ts +163 -0
- package/dist/adapters/taishanpi-live.js +349 -0
- package/dist/adapters/taishanpi-live.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 +18 -0
- package/dist/hardware.js +412 -0
- package/dist/hardware.js.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +4 -130
- 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 +624 -0
- package/dist/tools.js.map +1 -0
- package/package.json +4 -9
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { resolveCommand, runCommand, tailLines } from "../process.js";
|
|
2
|
+
const VERSION_TIMEOUT_MS = 2500;
|
|
3
|
+
const DEBUG_TOOLS = [
|
|
4
|
+
{
|
|
5
|
+
tool_id: "openocd",
|
|
6
|
+
display_name: "OpenOCD",
|
|
7
|
+
command: "openocd",
|
|
8
|
+
version_args: ["--version"]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
tool_id: "probe-rs",
|
|
12
|
+
display_name: "probe-rs",
|
|
13
|
+
command: "probe-rs",
|
|
14
|
+
version_args: ["--version"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
tool_id: "pyocd",
|
|
18
|
+
display_name: "pyOCD",
|
|
19
|
+
command: "pyocd",
|
|
20
|
+
version_args: ["--version"]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
tool_id: "jlink-commander",
|
|
24
|
+
display_name: "SEGGER J-Link Commander",
|
|
25
|
+
command: "JLinkExe",
|
|
26
|
+
version_args: ["-?"]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
tool_id: "jlink-gdb-server",
|
|
30
|
+
display_name: "SEGGER J-Link GDB Server",
|
|
31
|
+
command: "JLinkGDBServerCLExe",
|
|
32
|
+
version_args: ["-?"]
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
export async function scanDebugTools() {
|
|
36
|
+
const observedAt = new Date().toISOString();
|
|
37
|
+
const tools = await Promise.all(DEBUG_TOOLS.map((tool) => scanDebugTool(tool, observedAt)));
|
|
38
|
+
const availableCount = tools.filter((tool) => tool.available).length;
|
|
39
|
+
return {
|
|
40
|
+
tools,
|
|
41
|
+
observed_at: observedAt,
|
|
42
|
+
summary_for_user: `Debug tool scan finished: ${availableCount}/${tools.length} tools available. No debug sessions or probe connections were opened.`
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function scanDebugTool(spec, observedAt) {
|
|
46
|
+
const evidence = [];
|
|
47
|
+
const resolvedPath = await resolveCommand(spec.command);
|
|
48
|
+
evidence.push({
|
|
49
|
+
evidence_id: evidenceId(spec.tool_id, "path", observedAt),
|
|
50
|
+
tool_id: spec.tool_id,
|
|
51
|
+
kind: "path_lookup",
|
|
52
|
+
command: spec.command,
|
|
53
|
+
observed_at: observedAt,
|
|
54
|
+
available: resolvedPath !== undefined,
|
|
55
|
+
resolved_path: resolvedPath,
|
|
56
|
+
summary: resolvedPath
|
|
57
|
+
? `Found ${spec.command} on PATH.`
|
|
58
|
+
: `${spec.command} was not found on PATH.`
|
|
59
|
+
});
|
|
60
|
+
if (!resolvedPath) {
|
|
61
|
+
return {
|
|
62
|
+
tool_id: spec.tool_id,
|
|
63
|
+
display_name: spec.display_name,
|
|
64
|
+
command: spec.command,
|
|
65
|
+
available: false,
|
|
66
|
+
evidence,
|
|
67
|
+
summary_for_user: `${spec.display_name} is not available on PATH.`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const versionResult = await runCommand(resolvedPath, spec.version_args, VERSION_TIMEOUT_MS);
|
|
71
|
+
const stdoutTail = tailLines(versionResult.stdout, 8);
|
|
72
|
+
const stderrTail = tailLines(versionResult.stderr, 8);
|
|
73
|
+
const version = extractVersionLine(`${versionResult.stdout}\n${versionResult.stderr}`);
|
|
74
|
+
evidence.push({
|
|
75
|
+
evidence_id: evidenceId(spec.tool_id, "version", observedAt),
|
|
76
|
+
tool_id: spec.tool_id,
|
|
77
|
+
kind: "version_command",
|
|
78
|
+
command: spec.command,
|
|
79
|
+
args: spec.version_args,
|
|
80
|
+
observed_at: observedAt,
|
|
81
|
+
exit_code: versionResult.exit_code,
|
|
82
|
+
timed_out: versionResult.timed_out,
|
|
83
|
+
stdout_tail: stdoutTail.length > 0 ? stdoutTail : undefined,
|
|
84
|
+
stderr_tail: stderrTail.length > 0 ? stderrTail : undefined,
|
|
85
|
+
error_code: versionResult.timed_out
|
|
86
|
+
? "version_command_timeout"
|
|
87
|
+
: versionResult.exit_code === 0
|
|
88
|
+
? undefined
|
|
89
|
+
: "version_command_nonzero",
|
|
90
|
+
error_message: versionResult.timed_out
|
|
91
|
+
? `Version/help command exceeded ${VERSION_TIMEOUT_MS}ms.`
|
|
92
|
+
: versionResult.exit_code === 0
|
|
93
|
+
? undefined
|
|
94
|
+
: `Version/help command exited with code ${versionResult.exit_code ?? "unknown"}.`,
|
|
95
|
+
summary: versionResult.timed_out
|
|
96
|
+
? `${spec.command} was found, but the bounded version/help command timed out.`
|
|
97
|
+
: versionResult.exit_code === 0
|
|
98
|
+
? `${spec.command} version/help command completed.`
|
|
99
|
+
: `${spec.command} was found, but its version/help command exited non-zero.`
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
tool_id: spec.tool_id,
|
|
103
|
+
display_name: spec.display_name,
|
|
104
|
+
command: spec.command,
|
|
105
|
+
available: true,
|
|
106
|
+
version,
|
|
107
|
+
evidence,
|
|
108
|
+
summary_for_user: version
|
|
109
|
+
? `${spec.display_name} is available (${version}).`
|
|
110
|
+
: `${spec.display_name} is available; version output was not recognized.`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function extractVersionLine(output) {
|
|
114
|
+
return output
|
|
115
|
+
.split(/\r?\n/)
|
|
116
|
+
.map((line) => line.trim())
|
|
117
|
+
.find((line) => line.length > 0)
|
|
118
|
+
?.slice(0, 160);
|
|
119
|
+
}
|
|
120
|
+
function evidenceId(toolId, kind, observedAt) {
|
|
121
|
+
const stableTime = observedAt.replace(/[^0-9]/g, "");
|
|
122
|
+
return `debug_${toolId}_${kind}_${stableTime}`;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/adapters/debug.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { posix } from "node:path";
|
|
3
|
+
import { commandExists, runCommand, tailLines } from "../process.js";
|
|
4
|
+
const DEFAULT_REMOTE_PATH = "/userdata/embed-labs/apps/app";
|
|
5
|
+
const REMOTE_ROOT = "/userdata/embed-labs/apps";
|
|
6
|
+
const MAX_ARTIFACT_BYTES = 16 * 1024 * 1024;
|
|
7
|
+
export async function deployTaishanPiArtifact(request) {
|
|
8
|
+
const observedAt = new Date().toISOString();
|
|
9
|
+
if (request.board_id !== "taishanpi") {
|
|
10
|
+
return failDeploy("unsupported_board", `board_id must be taishanpi, got ${request.board_id}.`);
|
|
11
|
+
}
|
|
12
|
+
const host = request.host.trim();
|
|
13
|
+
const user = request.user?.trim() || "root";
|
|
14
|
+
const remotePath = normalizeRemotePath(request.remote_path ?? DEFAULT_REMOTE_PATH);
|
|
15
|
+
const timeoutSeconds = clampTimeoutSeconds(request.timeout_seconds);
|
|
16
|
+
if (!remotePath) {
|
|
17
|
+
return failDeploy("invalid_remote_path", `remote_path must stay under ${REMOTE_ROOT} and contain only safe path characters.`);
|
|
18
|
+
}
|
|
19
|
+
if (!/^[A-Za-z0-9._-]{1,64}$/.test(user)) {
|
|
20
|
+
return failDeploy("invalid_user", "SSH user must contain only letters, numbers, dots, underscores, or hyphens.");
|
|
21
|
+
}
|
|
22
|
+
if (!await commandExists("ssh")) {
|
|
23
|
+
return failDeploy("ssh_not_found", "ssh binary was not found on PATH.", "Install OpenSSH client or add ssh to PATH.");
|
|
24
|
+
}
|
|
25
|
+
const artifactStat = await stat(request.artifact_path).catch(() => undefined);
|
|
26
|
+
if (!artifactStat?.isFile()) {
|
|
27
|
+
return failDeploy("artifact_file_not_found", `Local artifact file is not available: ${request.artifact_path}`);
|
|
28
|
+
}
|
|
29
|
+
if (artifactStat.size > MAX_ARTIFACT_BYTES) {
|
|
30
|
+
return failDeploy("artifact_file_too_large", `Local Bridge deploy currently accepts artifacts up to ${MAX_ARTIFACT_BYTES} bytes on the SSH/base64 MVP path.`);
|
|
31
|
+
}
|
|
32
|
+
const artifactBytes = await readFile(request.artifact_path);
|
|
33
|
+
const remoteDir = posix.dirname(remotePath);
|
|
34
|
+
const tmpPath = `${remotePath}.tmp.${Date.now()}`;
|
|
35
|
+
const logPath = `${remotePath}.log`;
|
|
36
|
+
const pidPath = `${remotePath}.pid`;
|
|
37
|
+
const upload = await ssh(host, user, [
|
|
38
|
+
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
39
|
+
"umask 077",
|
|
40
|
+
`base64 -d > ${shellQuote(tmpPath)}`,
|
|
41
|
+
`chmod 0755 ${shellQuote(tmpPath)}`,
|
|
42
|
+
`mv -f ${shellQuote(tmpPath)} ${shellQuote(remotePath)}`
|
|
43
|
+
].join(" && "), timeoutSeconds, artifactBytes.toString("base64"));
|
|
44
|
+
if (upload.exit_code !== 0) {
|
|
45
|
+
return commandFailure(upload.timed_out ? "artifact_upload_timeout" : "artifact_upload_failed", "Failed to upload the artifact to the board over SSH/base64.", upload);
|
|
46
|
+
}
|
|
47
|
+
let runResult;
|
|
48
|
+
if (request.run === true) {
|
|
49
|
+
runResult = await ssh(host, user, [
|
|
50
|
+
`cd ${shellQuote(remoteDir)}`,
|
|
51
|
+
`(nohup ${shellQuote(remotePath)} > ${shellQuote(logPath)} 2>&1 < /dev/null & printf '%s' "$!" > ${shellQuote(pidPath)})`,
|
|
52
|
+
"sleep 1",
|
|
53
|
+
"printf 'pid='",
|
|
54
|
+
`cat ${shellQuote(pidPath)}`,
|
|
55
|
+
"printf '\\n'",
|
|
56
|
+
`tail -n 40 ${shellQuote(logPath)} 2>/dev/null || true`
|
|
57
|
+
].join(" && "), timeoutSeconds);
|
|
58
|
+
if (runResult.exit_code !== 0) {
|
|
59
|
+
return commandFailure(runResult.timed_out ? "artifact_run_timeout" : "artifact_run_failed", "The artifact was deployed, but the start/log command failed.", runResult);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
board_id: "taishanpi",
|
|
64
|
+
host,
|
|
65
|
+
user,
|
|
66
|
+
artifact_path: request.artifact_path,
|
|
67
|
+
artifact_size_bytes: artifactStat.size,
|
|
68
|
+
remote_path: remotePath,
|
|
69
|
+
deployed: true,
|
|
70
|
+
ran: request.run === true && runResult?.exit_code === 0,
|
|
71
|
+
remote_pid: runResult ? extractPid(runResult.stdout) : undefined,
|
|
72
|
+
log_path: logPath,
|
|
73
|
+
exit_code: runResult?.exit_code,
|
|
74
|
+
stdout: runResult?.stdout,
|
|
75
|
+
stderr: runResult?.stderr,
|
|
76
|
+
output_tail: runResult ? tailLines(`${runResult.stdout}\n${runResult.stderr}`) : tailLines(`${upload.stdout}\n${upload.stderr}`),
|
|
77
|
+
observed_at: observedAt
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function ssh(host, user, command, timeoutSeconds, stdin) {
|
|
81
|
+
return runCommand("ssh", [
|
|
82
|
+
"-o", "BatchMode=yes",
|
|
83
|
+
"-o", "UserKnownHostsFile=/dev/null",
|
|
84
|
+
"-o", "StrictHostKeyChecking=no",
|
|
85
|
+
"-o", `ConnectTimeout=${Math.max(1, Math.min(timeoutSeconds, 30))}`,
|
|
86
|
+
`${user}@${host}`,
|
|
87
|
+
command
|
|
88
|
+
], timeoutSeconds * 1000 + 1000, stdin);
|
|
89
|
+
}
|
|
90
|
+
function normalizeRemotePath(input) {
|
|
91
|
+
if (!input.startsWith("/") || /[\u0000-\u001f\u007f]/.test(input)) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const normalized = posix.normalize(input);
|
|
95
|
+
if (normalized === REMOTE_ROOT || !normalized.startsWith(`${REMOTE_ROOT}/`)) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (!/^\/[A-Za-z0-9._/-]+$/.test(normalized) || normalized.endsWith("/")) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return normalized;
|
|
102
|
+
}
|
|
103
|
+
function clampTimeoutSeconds(value) {
|
|
104
|
+
const timeout = Number.isFinite(value) ? Number(value) : 30;
|
|
105
|
+
return Math.max(5, Math.min(Math.trunc(timeout), 120));
|
|
106
|
+
}
|
|
107
|
+
function failDeploy(code, message, remediation) {
|
|
108
|
+
return { ok: false, error: { code, message, remediation } };
|
|
109
|
+
}
|
|
110
|
+
function commandFailure(code, message, result) {
|
|
111
|
+
return {
|
|
112
|
+
ok: false,
|
|
113
|
+
error: {
|
|
114
|
+
code,
|
|
115
|
+
message,
|
|
116
|
+
details: {
|
|
117
|
+
exit_code: result.exit_code,
|
|
118
|
+
stdout: result.stdout,
|
|
119
|
+
stderr: result.stderr,
|
|
120
|
+
timed_out: result.timed_out
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function shellQuote(value) {
|
|
126
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
127
|
+
}
|
|
128
|
+
function extractPid(stdout) {
|
|
129
|
+
const match = stdout.match(/^pid=(\d+)/m);
|
|
130
|
+
return match?.[1];
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/adapters/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { copyFile, stat } from "node:fs/promises";
|
|
4
|
+
import { basename, join } from "node:path";
|
|
5
|
+
import { commandExists } from "../process.js";
|
|
6
|
+
import { findUf2Volumes } from "./uf2.js";
|
|
7
|
+
export async function buildFlashPlan(request) {
|
|
8
|
+
if (request.board_id === "rp2350") {
|
|
9
|
+
return buildRp2350FlashPlan(request);
|
|
10
|
+
}
|
|
11
|
+
if (request.board_id === "taishanpi") {
|
|
12
|
+
return buildTaishanPiFlashPlan(request);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
plan_id: `plan_${Date.now()}`,
|
|
16
|
+
board_id: request.board_id,
|
|
17
|
+
profile_id: request.profile_id ?? "unknown",
|
|
18
|
+
destructive: true,
|
|
19
|
+
approval_required: true,
|
|
20
|
+
ready: false,
|
|
21
|
+
summary: `No flash planner is available for board_id=${request.board_id}.`,
|
|
22
|
+
warnings: [{
|
|
23
|
+
code: "board_not_supported",
|
|
24
|
+
message: `No local bridge flash planner is available for ${request.board_id}.`
|
|
25
|
+
}]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export async function executeRp2350Uf2Flash(plan) {
|
|
29
|
+
if (!plan.artifact_path || !plan.target_volume_path) {
|
|
30
|
+
throw new Error("RP2350 UF2 flash requires artifact_path and target_volume_path.");
|
|
31
|
+
}
|
|
32
|
+
const target = join(plan.target_volume_path, basename(plan.artifact_path));
|
|
33
|
+
await copyFile(plan.artifact_path, target);
|
|
34
|
+
return {
|
|
35
|
+
copied_to: target,
|
|
36
|
+
summary_for_user: `Copied UF2 artifact to ${plan.target_volume_path}. The board should reboot automatically if the UF2 volume accepted the file.`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function buildRp2350FlashPlan(request) {
|
|
40
|
+
const missingFiles = [];
|
|
41
|
+
const artifactPath = request.artifact_path;
|
|
42
|
+
if (!artifactPath) {
|
|
43
|
+
missingFiles.push("artifact_path");
|
|
44
|
+
}
|
|
45
|
+
else if (!artifactPath.endsWith(".uf2")) {
|
|
46
|
+
missingFiles.push(`${artifactPath} must be a .uf2 artifact`);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
try {
|
|
50
|
+
await stat(artifactPath);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
missingFiles.push(artifactPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const volumes = request.target_volume_path ? [request.target_volume_path] : await findUf2Volumes();
|
|
57
|
+
const targetVolumePath = volumes[0];
|
|
58
|
+
if (!targetVolumePath) {
|
|
59
|
+
missingFiles.push("RP2350 UF2 boot volume");
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
plan_id: `plan_${Date.now()}_rp2350`,
|
|
63
|
+
board_id: "rp2350",
|
|
64
|
+
variant_id: request.variant_id,
|
|
65
|
+
profile_id: request.profile_id ?? "uf2-flash-local",
|
|
66
|
+
destructive: true,
|
|
67
|
+
approval_required: true,
|
|
68
|
+
ready: missingFiles.length === 0,
|
|
69
|
+
summary: missingFiles.length === 0
|
|
70
|
+
? `Ready to copy ${artifactPath} to RP2350 UF2 volume ${targetVolumePath}.`
|
|
71
|
+
: "RP2350 UF2 flash is not ready.",
|
|
72
|
+
artifact_path: artifactPath,
|
|
73
|
+
target_volume_path: targetVolumePath,
|
|
74
|
+
missing_files: missingFiles,
|
|
75
|
+
warnings: missingFiles.length > 0 ? [{
|
|
76
|
+
code: "flash_plan_not_ready",
|
|
77
|
+
message: "RP2350 UF2 flash requires a .uf2 artifact and a mounted BOOTSEL/UF2 volume."
|
|
78
|
+
}] : undefined
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async function buildTaishanPiFlashPlan(request) {
|
|
82
|
+
const imageDir = request.image_dir;
|
|
83
|
+
const missingFiles = [];
|
|
84
|
+
const required = [
|
|
85
|
+
"MiniLoaderAll.bin",
|
|
86
|
+
"parameter.txt",
|
|
87
|
+
"uboot.img",
|
|
88
|
+
"boot.img",
|
|
89
|
+
"rootfs.img",
|
|
90
|
+
"userdata.img"
|
|
91
|
+
];
|
|
92
|
+
const optional = ["misc.img", "recovery.img", "oem.img"];
|
|
93
|
+
const partitions = [];
|
|
94
|
+
if (!imageDir) {
|
|
95
|
+
missingFiles.push("image_dir");
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
for (const name of required) {
|
|
99
|
+
const path = join(imageDir, name);
|
|
100
|
+
try {
|
|
101
|
+
const fileStat = await stat(path);
|
|
102
|
+
partitions.push({
|
|
103
|
+
partition: partitionName(name),
|
|
104
|
+
image_path: path,
|
|
105
|
+
required: true,
|
|
106
|
+
size_bytes: fileStat.size,
|
|
107
|
+
sha256: await sha256(path)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
missingFiles.push(path);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const name of optional) {
|
|
115
|
+
const path = join(imageDir, name);
|
|
116
|
+
try {
|
|
117
|
+
const fileStat = await stat(path);
|
|
118
|
+
partitions.push({
|
|
119
|
+
partition: partitionName(name),
|
|
120
|
+
image_path: path,
|
|
121
|
+
required: false,
|
|
122
|
+
size_bytes: fileStat.size,
|
|
123
|
+
sha256: await sha256(path)
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Optional image.
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const missingTools = [];
|
|
132
|
+
if (!await commandExists("rkdeveloptool")) {
|
|
133
|
+
missingTools.push("rkdeveloptool");
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
plan_id: `plan_${Date.now()}_taishanpi`,
|
|
137
|
+
board_id: "taishanpi",
|
|
138
|
+
variant_id: request.variant_id,
|
|
139
|
+
hardware_profile_id: request.hardware_profile_id,
|
|
140
|
+
profile_id: request.profile_id ?? "rk356x-full-image-local",
|
|
141
|
+
destructive: true,
|
|
142
|
+
approval_required: true,
|
|
143
|
+
ready: missingFiles.length === 0 && missingTools.length === 0,
|
|
144
|
+
summary: missingFiles.length === 0 && missingTools.length === 0
|
|
145
|
+
? `TaishanPi image set is complete. Destructive flash still requires explicit approval.`
|
|
146
|
+
: "TaishanPi flash plan is not ready; missing images or local tools.",
|
|
147
|
+
partitions,
|
|
148
|
+
required_tools: ["rkdeveloptool"],
|
|
149
|
+
missing_tools: missingTools,
|
|
150
|
+
missing_files: missingFiles,
|
|
151
|
+
warnings: [{
|
|
152
|
+
code: "taishanpi_flash_guardrail",
|
|
153
|
+
message: "TaishanPi real flashing is intentionally blocked until exact hardware_profile and Board Pack command templates are accepted.",
|
|
154
|
+
remediation: "Use this plan as validation evidence. Enable real TaishanPi flash only after EL-010 profile commands are reviewed."
|
|
155
|
+
}]
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function partitionName(fileName) {
|
|
159
|
+
return fileName.replace(/\.img$|\.bin$|\.txt$/g, "").replace("MiniLoaderAll", "loader");
|
|
160
|
+
}
|
|
161
|
+
async function sha256(path) {
|
|
162
|
+
const hash = createHash("sha256");
|
|
163
|
+
const stream = createReadStream(path);
|
|
164
|
+
for await (const chunk of stream) {
|
|
165
|
+
hash.update(chunk);
|
|
166
|
+
}
|
|
167
|
+
return hash.digest("hex");
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=flash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flash.js","sourceRoot":"","sources":["../../src/adapters/flash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAM3C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAyB;IAC5D,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QACrC,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO;QACL,OAAO,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,EAAE;QAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;QAC3C,WAAW,EAAE,IAAI;QACjB,iBAAiB,EAAE,IAAI;QACvB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,8CAA8C,OAAO,CAAC,QAAQ,GAAG;QAC1E,QAAQ,EAAE,CAAC;gBACT,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,kDAAkD,OAAO,CAAC,QAAQ,GAAG;aAC/E,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAe;IACzD,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IAC3E,MAAM,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC3C,OAAO;QACL,SAAS,EAAE,MAAM;QACjB,gBAAgB,EAAE,0BAA0B,IAAI,CAAC,kBAAkB,8EAA8E;KAClJ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,OAAyB;IAC3D,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAC3C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,YAAY,CAAC,IAAI,CAAC,GAAG,YAAY,0BAA0B,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,EAAE,CAAC;IACnG,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,OAAO,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,SAAS;QACpC,QAAQ,EAAE,QAAQ;QAClB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,iBAAiB;QACnD,WAAW,EAAE,IAAI;QACjB,iBAAiB,EAAE,IAAI;QACvB,KAAK,EAAE,YAAY,CAAC,MAAM,KAAK,CAAC;QAChC,OAAO,EAAE,YAAY,CAAC,MAAM,KAAK,CAAC;YAChC,CAAC,CAAC,iBAAiB,YAAY,yBAAyB,gBAAgB,GAAG;YAC3E,CAAC,CAAC,gCAAgC;QACpC,aAAa,EAAE,YAAY;QAC3B,kBAAkB,EAAE,gBAAgB;QACpC,aAAa,EAAE,YAAY;QAC3B,QAAQ,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnC,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,6EAA6E;aACvF,CAAC,CAAC,CAAC,CAAC,SAAS;KACf,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,OAAyB;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IACnC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,UAAU;QACV,YAAY;QACZ,cAAc;KACf,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC;IAEzD,MAAM,UAAU,GAAyB,EAAE,CAAC;IAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,UAAU,CAAC,IAAI,CAAC;oBACd,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC;oBAC9B,UAAU,EAAE,IAAI;oBAChB,QAAQ,EAAE,IAAI;oBACd,UAAU,EAAE,QAAQ,CAAC,IAAI;oBACzB,MAAM,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC;iBAC3B,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,UAAU,CAAC,IAAI,CAAC;oBACd,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC;oBAC9B,UAAU,EAAE,IAAI;oBAChB,QAAQ,EAAE,KAAK;oBACf,UAAU,EAAE,QAAQ,CAAC,IAAI;oBACzB,MAAM,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC;iBAC3B,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,kBAAkB;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,aAAa,CAAC,eAAe,CAAC,EAAE,CAAC;QAC1C,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IAED,OAAO;QACL,OAAO,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,YAAY;QACvC,QAAQ,EAAE,WAAW;QACrB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,yBAAyB;QAC3D,WAAW,EAAE,IAAI;QACjB,iBAAiB,EAAE,IAAI;QACvB,KAAK,EAAE,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAC7D,OAAO,EAAE,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAC7D,CAAC,CAAC,sFAAsF;YACxF,CAAC,CAAC,mEAAmE;QACvE,UAAU;QACV,cAAc,EAAE,CAAC,eAAe,CAAC;QACjC,aAAa,EAAE,YAAY;QAC3B,aAAa,EAAE,YAAY;QAC3B,QAAQ,EAAE,CAAC;gBACT,IAAI,EAAE,2BAA2B;gBACjC,OAAO,EAAE,8HAA8H;gBACvI,WAAW,EAAE,oHAAoH;aAClI,CAAC;KACH,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,OAAO,QAAQ,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAC1F,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAY;IAChC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,KAAe,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TcpProbeEvidence } from "@embed-labs/protocol";
|
|
2
|
+
export declare function probeTcp(host: string, port: number, timeoutMs: number): Promise<boolean>;
|
|
3
|
+
export declare function probeTcpWithEvidence(host: string, port: number, timeoutMs: number, observedAt: string): Promise<TcpProbeEvidence>;
|
|
4
|
+
export declare function runBoundedSsh(host: string, user: string, command: string, timeoutSeconds?: number): Promise<{
|
|
5
|
+
readonly ok: false;
|
|
6
|
+
readonly error: {
|
|
7
|
+
readonly code: "ssh_not_found";
|
|
8
|
+
readonly message: "ssh binary was not found on PATH.";
|
|
9
|
+
readonly remediation: "Install OpenSSH client or add ssh to PATH.";
|
|
10
|
+
};
|
|
11
|
+
exit_code?: undefined;
|
|
12
|
+
stdout?: undefined;
|
|
13
|
+
stderr?: undefined;
|
|
14
|
+
output_tail?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
exit_code: number | null;
|
|
18
|
+
stdout: string;
|
|
19
|
+
stderr: string;
|
|
20
|
+
output_tail: string[];
|
|
21
|
+
readonly error?: undefined;
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
import { commandExists, runCommand, tailLines } from "../process.js";
|
|
3
|
+
export async function probeTcp(host, port, timeoutMs) {
|
|
4
|
+
const evidence = await probeTcpWithEvidence(host, port, timeoutMs, new Date().toISOString());
|
|
5
|
+
return evidence.reachable;
|
|
6
|
+
}
|
|
7
|
+
export async function probeTcpWithEvidence(host, port, timeoutMs, observedAt) {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
const startedAt = Date.now();
|
|
10
|
+
const socket = new net.Socket();
|
|
11
|
+
let settled = false;
|
|
12
|
+
const done = (value, error) => {
|
|
13
|
+
if (settled) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
settled = true;
|
|
17
|
+
socket.destroy();
|
|
18
|
+
resolve({
|
|
19
|
+
transport: "tcp",
|
|
20
|
+
host,
|
|
21
|
+
port,
|
|
22
|
+
reachable: value,
|
|
23
|
+
duration_ms: Date.now() - startedAt,
|
|
24
|
+
observed_at: observedAt,
|
|
25
|
+
error_code: error?.code,
|
|
26
|
+
error_message: error?.message
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
socket.setTimeout(timeoutMs);
|
|
30
|
+
socket.once("connect", () => done(true));
|
|
31
|
+
socket.once("timeout", () => done(false, Object.assign(new Error(`Timed out after ${timeoutMs}ms.`), { code: "timeout" })));
|
|
32
|
+
socket.once("error", (error) => done(false, error));
|
|
33
|
+
socket.connect(port, host);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export async function runBoundedSsh(host, user, command, timeoutSeconds = 15) {
|
|
37
|
+
const sshExists = await commandExists("ssh");
|
|
38
|
+
if (!sshExists) {
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
error: {
|
|
42
|
+
code: "ssh_not_found",
|
|
43
|
+
message: "ssh binary was not found on PATH.",
|
|
44
|
+
remediation: "Install OpenSSH client or add ssh to PATH."
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const result = await runCommand("ssh", [
|
|
49
|
+
"-o", "BatchMode=yes",
|
|
50
|
+
"-o", "UserKnownHostsFile=/dev/null",
|
|
51
|
+
"-o", "StrictHostKeyChecking=no",
|
|
52
|
+
"-o", `ConnectTimeout=${Math.max(1, Math.min(timeoutSeconds, 30))}`,
|
|
53
|
+
`${user}@${host}`,
|
|
54
|
+
command
|
|
55
|
+
], timeoutSeconds * 1000 + 1000);
|
|
56
|
+
return {
|
|
57
|
+
ok: result.exit_code === 0,
|
|
58
|
+
exit_code: result.exit_code,
|
|
59
|
+
stdout: result.stdout,
|
|
60
|
+
stderr: result.stderr,
|
|
61
|
+
output_tail: tailLines(`${result.stdout}\n${result.stderr}`)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/adapters/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ErrorEnvelope, SerialPortInfo } from "@embed-labs/protocol";
|
|
2
|
+
export declare function listSerialPorts(warnings?: ErrorEnvelope[]): Promise<SerialPortInfo[]>;
|
|
3
|
+
export declare function captureSerial(path: string, baudRate?: number, durationSeconds?: number): Promise<unknown>;
|