@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/dist/server.js ADDED
@@ -0,0 +1,242 @@
1
+ import http from "node:http";
2
+ import net from "node:net";
3
+ import { URL } from "node:url";
4
+ import { fail, ok } from "@embed-labs/protocol";
5
+ import { buildFlashPlan, captureSerial, deployTaishanPiApplication, probeDevices, runBoundedSsh, scanDebugTools, scanHardware, validateTaishanPiDeployRequest } from "./hardware.js";
6
+ import { getJob, listJobs, startFlashJob } from "./jobs.js";
7
+ import { invokeToolCapability, listToolCapabilities } from "./tools.js";
8
+ const MAX_JSON_BODY_BYTES = 64 * 1024;
9
+ const PROBE_REQUEST_FIELDS = new Set(["host", "ports", "serial_paths", "timeout_ms"]);
10
+ class HttpRequestError extends Error {
11
+ status;
12
+ code;
13
+ constructor(status, code, message) {
14
+ super(message);
15
+ this.status = status;
16
+ this.code = code;
17
+ }
18
+ }
19
+ export function startServer(options = {}) {
20
+ const host = options.host ?? process.env.EMBED_BRIDGE_HOST ?? "127.0.0.1";
21
+ const port = options.port ?? Number(process.env.EMBED_BRIDGE_PORT ?? "18083");
22
+ const server = http.createServer((request, response) => {
23
+ void route(request, response);
24
+ });
25
+ server.listen(port, host, () => {
26
+ console.log(`embed-local-bridge listening on http://${host}:${port}`);
27
+ });
28
+ return server;
29
+ }
30
+ async function route(request, response) {
31
+ const url = new URL(request.url ?? "/", "http://127.0.0.1");
32
+ const method = request.method ?? "GET";
33
+ try {
34
+ if (method === "GET" && url.pathname === "/healthz") {
35
+ return send(response, ok({
36
+ service: "embed-local-bridge",
37
+ status: "ok",
38
+ version: "0.1.0",
39
+ platform: process.platform,
40
+ arch: process.arch,
41
+ time: new Date().toISOString()
42
+ }));
43
+ }
44
+ if (method === "GET" && url.pathname === "/v1/devices") {
45
+ return send(response, ok(await scanHardware()));
46
+ }
47
+ if (method === "GET" && url.pathname === "/v1/debug/tools") {
48
+ return send(response, ok(await scanDebugTools()));
49
+ }
50
+ if (method === "GET" && url.pathname === "/v1/tools/capabilities") {
51
+ return send(response, ok(listToolCapabilities()));
52
+ }
53
+ if (method === "POST" && url.pathname === "/v1/tools/invoke") {
54
+ const body = await readJson(request);
55
+ const invoked = await invokeToolCapability(body);
56
+ return send(response, invoked, invoked.ok ? 200 : toolInvokeStatus(invoked.error.code));
57
+ }
58
+ if (method === "POST" && url.pathname === "/v1/devices/probe") {
59
+ const body = await readJson(request);
60
+ const parsed = parseProbeRequest(body);
61
+ if ("error" in parsed) {
62
+ return send(response, fail("invalid_request", parsed.error), 400);
63
+ }
64
+ return send(response, ok(await probeDevices(parsed.request)));
65
+ }
66
+ if (method === "GET" && url.pathname === "/v1/serial/ports") {
67
+ const scan = await scanHardware();
68
+ return send(response, ok({ serial: scan.serial, observed_at: scan.observed_at, warnings: scan.warnings }));
69
+ }
70
+ if (method === "POST" && url.pathname === "/v1/serial/capture") {
71
+ const body = await readJson(request);
72
+ if (!body.path) {
73
+ return send(response, fail("invalid_request", "path is required."), 400);
74
+ }
75
+ return send(response, ok(await captureSerial(body.path, body.baud_rate, body.duration_seconds)));
76
+ }
77
+ if (method === "POST" && url.pathname === "/v1/ssh/run") {
78
+ const body = await readJson(request);
79
+ if (!body.host || !body.user || !body.command) {
80
+ return send(response, fail("invalid_request", "host, user, and command are required."), 400);
81
+ }
82
+ return send(response, ok(await runBoundedSsh(body.host, body.user, body.command, body.timeout_seconds)));
83
+ }
84
+ if (method === "POST" && url.pathname === "/v1/board/taishanpi/deploy") {
85
+ const body = await readJson(request);
86
+ const parsed = validateTaishanPiDeployRequest(body);
87
+ if ("error" in parsed) {
88
+ return send(response, fail("invalid_request", parsed.error), 400);
89
+ }
90
+ if (parsed.request.approved !== true) {
91
+ return send(response, fail("approval_required", "TaishanPi deploy writes to a board over SSH. Re-run with approved=true after the user approves the action."), 403);
92
+ }
93
+ const deployed = await deployTaishanPiApplication(parsed.request);
94
+ if ("ok" in deployed && deployed.ok === false) {
95
+ return send(response, deployed, 400);
96
+ }
97
+ return send(response, ok(deployed));
98
+ }
99
+ if (method === "POST" && url.pathname === "/v1/flash/plan") {
100
+ const body = await readJson(request);
101
+ return send(response, ok(await buildFlashPlan(body)));
102
+ }
103
+ if (method === "POST" && url.pathname === "/v1/flash/run") {
104
+ const body = await readJson(request);
105
+ return send(response, ok(await startFlashJob(body)));
106
+ }
107
+ if (method === "GET" && url.pathname === "/v1/jobs") {
108
+ return send(response, ok({ jobs: listJobs() }));
109
+ }
110
+ const jobMatch = url.pathname.match(/^\/v1\/jobs\/([^/]+)$/);
111
+ if (method === "GET" && jobMatch) {
112
+ const job = getJob(decodeURIComponent(jobMatch[1]));
113
+ if (!job) {
114
+ return send(response, fail("job_not_found", `No local job found for ${jobMatch[1]}.`), 404);
115
+ }
116
+ return send(response, ok(job));
117
+ }
118
+ return send(response, fail("not_found", `${method} ${url.pathname} is not available.`), 404);
119
+ }
120
+ catch (error) {
121
+ if (error instanceof HttpRequestError) {
122
+ return send(response, fail(error.code, error.message), error.status);
123
+ }
124
+ return send(response, fail("internal_error", error instanceof Error ? error.message : String(error)), 500);
125
+ }
126
+ }
127
+ async function readJson(request) {
128
+ const chunks = [];
129
+ let totalBytes = 0;
130
+ for await (const chunk of request) {
131
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
132
+ totalBytes += buffer.length;
133
+ if (totalBytes > MAX_JSON_BODY_BYTES) {
134
+ throw new HttpRequestError(413, "request_too_large", `JSON body must be ${MAX_JSON_BODY_BYTES} bytes or smaller.`);
135
+ }
136
+ chunks.push(buffer);
137
+ }
138
+ const text = Buffer.concat(chunks).toString("utf8").trim();
139
+ if (!text) {
140
+ return {};
141
+ }
142
+ try {
143
+ return JSON.parse(text);
144
+ }
145
+ catch {
146
+ throw new HttpRequestError(400, "invalid_json", "Request body must be valid JSON.");
147
+ }
148
+ }
149
+ function send(response, payload, status = payload.ok ? 200 : 500) {
150
+ response.statusCode = status;
151
+ response.setHeader("content-type", "application/json; charset=utf-8");
152
+ response.end(JSON.stringify(payload, null, 2));
153
+ }
154
+ function toolInvokeStatus(code) {
155
+ if (code === "tool_capability_not_found") {
156
+ return 404;
157
+ }
158
+ if (code === "approval_required") {
159
+ return 403;
160
+ }
161
+ return 400;
162
+ }
163
+ function parseProbeRequest(body) {
164
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
165
+ return { error: "Request body must be a JSON object." };
166
+ }
167
+ const request = body;
168
+ const unknownFields = Object.keys(request).filter((field) => !PROBE_REQUEST_FIELDS.has(field));
169
+ if (unknownFields.length > 0) {
170
+ return { error: `Unsupported field(s): ${unknownFields.join(", ")}.` };
171
+ }
172
+ let host;
173
+ if (request.host !== undefined) {
174
+ if (typeof request.host !== "string") {
175
+ return { error: "host must be a hostname or IP address string." };
176
+ }
177
+ host = request.host.trim();
178
+ if (!isValidProbeHost(host)) {
179
+ return { error: "host must be a hostname or IP address without schemes, paths, spaces, or credentials." };
180
+ }
181
+ }
182
+ let ports;
183
+ if (request.ports !== undefined) {
184
+ if (!Array.isArray(request.ports)) {
185
+ return { error: "ports must be an array." };
186
+ }
187
+ const invalidPort = request.ports.find((port) => typeof port !== "number" || !Number.isInteger(port) || port < 1 || port > 65_535);
188
+ if (invalidPort !== undefined) {
189
+ return { error: `Invalid TCP port: ${String(invalidPort)}.` };
190
+ }
191
+ ports = [...request.ports];
192
+ }
193
+ let serialPaths;
194
+ if (request.serial_paths !== undefined) {
195
+ if (!Array.isArray(request.serial_paths)) {
196
+ return { error: "serial_paths must be an array." };
197
+ }
198
+ const invalidPath = request.serial_paths.find((path) => typeof path !== "string" || !path.trim());
199
+ if (invalidPath !== undefined) {
200
+ return { error: "serial_paths must contain non-empty strings." };
201
+ }
202
+ serialPaths = request.serial_paths.map((path) => path.trim());
203
+ }
204
+ if (request.timeout_ms !== undefined && (typeof request.timeout_ms !== "number" || !Number.isFinite(request.timeout_ms) || request.timeout_ms <= 0)) {
205
+ return { error: "timeout_ms must be a positive number." };
206
+ }
207
+ const hasPorts = (ports?.length ?? 0) > 0;
208
+ const hasSerialPaths = (serialPaths?.length ?? 0) > 0;
209
+ if (!hasPorts && !hasSerialPaths) {
210
+ return { error: "At least one TCP port or serial path is required." };
211
+ }
212
+ if (hasPorts && !host) {
213
+ return { error: "host is required when ports are provided." };
214
+ }
215
+ const parsed = {};
216
+ if (host !== undefined) {
217
+ parsed.host = host;
218
+ }
219
+ if (ports !== undefined) {
220
+ parsed.ports = ports;
221
+ }
222
+ if (serialPaths !== undefined) {
223
+ parsed.serial_paths = serialPaths;
224
+ }
225
+ if (request.timeout_ms !== undefined) {
226
+ parsed.timeout_ms = request.timeout_ms;
227
+ }
228
+ return { request: parsed };
229
+ }
230
+ function isValidProbeHost(host) {
231
+ if (!host || host.length > 253 || /[\s\x00-\x1f\x7f]/.test(host)) {
232
+ return false;
233
+ }
234
+ if (host.includes("://") || host.includes("/") || host.includes("\\") || host.includes("@")) {
235
+ return false;
236
+ }
237
+ if (net.isIP(host) !== 0) {
238
+ return true;
239
+ }
240
+ return host.split(".").every((label) => /^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(label));
241
+ }
242
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type ApiResponse, type ToolCapabilityList, type ToolInvokeResult } from "@embed-labs/protocol";
2
+ export declare function listToolCapabilities(): ToolCapabilityList;
3
+ export declare function invokeToolCapability(input: unknown): Promise<ApiResponse<ToolInvokeResult>>;
package/dist/tools.js ADDED
@@ -0,0 +1,228 @@
1
+ import net from "node:net";
2
+ import { fail, ok } from "@embed-labs/protocol";
3
+ import { deployTaishanPiApplication, probeDevices, scanDebugTools, scanHardware, validateTaishanPiDeployRequest } from "./hardware.js";
4
+ const PROBE_REQUEST_FIELDS = new Set(["host", "ports", "serial_paths", "timeout_ms"]);
5
+ export function listToolCapabilities() {
6
+ return {
7
+ observed_at: new Date().toISOString(),
8
+ capabilities: [
9
+ {
10
+ capability_id: "debug.tools.scan",
11
+ display_name: "Debug Tool Scan",
12
+ description: "Scan OpenOCD, probe-rs, pyOCD, and J-Link command availability without opening a debug session.",
13
+ runtime: "local_bridge",
14
+ category: "debug",
15
+ destructive: false,
16
+ requires_approval: false,
17
+ input_schema: {
18
+ type: "object",
19
+ additionalProperties: false,
20
+ properties: {}
21
+ }
22
+ },
23
+ {
24
+ capability_id: "device.scan",
25
+ display_name: "Device Scan",
26
+ description: "Detect USB, serial, UF2, Rockchip, and TaishanPi USB ECM devices visible to the local machine.",
27
+ runtime: "local_bridge",
28
+ category: "device",
29
+ destructive: false,
30
+ requires_approval: false,
31
+ input_schema: {
32
+ type: "object",
33
+ additionalProperties: false,
34
+ properties: {}
35
+ }
36
+ },
37
+ {
38
+ capability_id: "device.probe",
39
+ display_name: "Device Probe",
40
+ description: "Probe selected TCP ports and serial paths with bounded timeouts.",
41
+ runtime: "local_bridge",
42
+ category: "device",
43
+ destructive: false,
44
+ requires_approval: false,
45
+ input_schema: {
46
+ type: "object",
47
+ additionalProperties: false,
48
+ properties: {
49
+ host: { type: "string" },
50
+ ports: { type: "array", items: { type: "integer", minimum: 1, maximum: 65535 } },
51
+ serial_paths: { type: "array", items: { type: "string" } },
52
+ timeout_ms: { type: "number", minimum: 100, maximum: 5000 }
53
+ }
54
+ }
55
+ },
56
+ {
57
+ capability_id: "taishanpi.deploy",
58
+ display_name: "TaishanPi Deploy",
59
+ description: "Copy a local artifact to a TaishanPi runtime over SSH and optionally start it.",
60
+ runtime: "local_bridge",
61
+ category: "board",
62
+ destructive: false,
63
+ requires_approval: true,
64
+ input_schema: {
65
+ type: "object",
66
+ additionalProperties: false,
67
+ required: ["host", "artifact_path"],
68
+ properties: {
69
+ board_id: { const: "taishanpi" },
70
+ host: { type: "string" },
71
+ user: { type: "string" },
72
+ artifact_path: { type: "string" },
73
+ remote_path: { type: "string" },
74
+ run: { type: "boolean" },
75
+ timeout_seconds: { type: "number", minimum: 1 }
76
+ }
77
+ }
78
+ }
79
+ ]
80
+ };
81
+ }
82
+ export async function invokeToolCapability(input) {
83
+ const parsed = parseToolInvokeRequest(input);
84
+ if (!parsed.ok) {
85
+ return parsed;
86
+ }
87
+ const observedAt = new Date().toISOString();
88
+ if (parsed.data.capability_id === "debug.tools.scan") {
89
+ const inputError = emptyInputError(parsed.data.input, parsed.data.capability_id);
90
+ if (inputError) {
91
+ return fail("invalid_request", inputError);
92
+ }
93
+ return ok({ capability_id: parsed.data.capability_id, result: await scanDebugTools(), observed_at: observedAt });
94
+ }
95
+ if (parsed.data.capability_id === "device.scan") {
96
+ const inputError = emptyInputError(parsed.data.input, parsed.data.capability_id);
97
+ if (inputError) {
98
+ return fail("invalid_request", inputError);
99
+ }
100
+ return ok({ capability_id: parsed.data.capability_id, result: await scanHardware(), observed_at: observedAt });
101
+ }
102
+ if (parsed.data.capability_id === "device.probe") {
103
+ const probe = parseDeviceProbeInput(parsed.data.input ?? {});
104
+ if ("error" in probe) {
105
+ return fail("invalid_request", probe.error);
106
+ }
107
+ return ok({ capability_id: parsed.data.capability_id, result: await probeDevices(probe.request), observed_at: observedAt });
108
+ }
109
+ if (parsed.data.capability_id === "taishanpi.deploy") {
110
+ if (parsed.data.approved !== true) {
111
+ return fail("approval_required", "taishanpi.deploy requires approved=true because it writes to a board over SSH.");
112
+ }
113
+ const deploy = validateTaishanPiDeployRequest(parsed.data.input ?? {});
114
+ if ("error" in deploy) {
115
+ return fail("invalid_request", deploy.error);
116
+ }
117
+ const deployed = await deployTaishanPiApplication(deploy.request);
118
+ if ("ok" in deployed && deployed.ok === false) {
119
+ return deployed;
120
+ }
121
+ return ok({ capability_id: parsed.data.capability_id, result: deployed, observed_at: observedAt });
122
+ }
123
+ return fail("tool_capability_not_found", `No local tool capability found for ${parsed.data.capability_id}.`);
124
+ }
125
+ function emptyInputError(input, capabilityId) {
126
+ if (input === undefined || Object.keys(input).length === 0) {
127
+ return undefined;
128
+ }
129
+ return `${capabilityId} does not accept input fields: ${Object.keys(input).join(", ")}.`;
130
+ }
131
+ function parseToolInvokeRequest(input) {
132
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
133
+ return fail("invalid_request", "Request body must be a JSON object.");
134
+ }
135
+ const body = input;
136
+ const unknownFields = Object.keys(body).filter((field) => !["capability_id", "input", "approved"].includes(field));
137
+ if (unknownFields.length > 0) {
138
+ return fail("invalid_request", `Unsupported field(s): ${unknownFields.join(", ")}.`);
139
+ }
140
+ if (typeof body.capability_id !== "string" || !body.capability_id.trim()) {
141
+ return fail("invalid_request", "capability_id is required.");
142
+ }
143
+ if (body.input !== undefined && (!body.input || typeof body.input !== "object" || Array.isArray(body.input))) {
144
+ return fail("invalid_request", "input must be a JSON object when provided.");
145
+ }
146
+ if (body.approved !== undefined && typeof body.approved !== "boolean") {
147
+ return fail("invalid_request", "approved must be a boolean when provided.");
148
+ }
149
+ return ok({
150
+ capability_id: body.capability_id.trim(),
151
+ input: body.input,
152
+ approved: body.approved
153
+ });
154
+ }
155
+ function parseDeviceProbeInput(input) {
156
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
157
+ return { error: "input must be a JSON object." };
158
+ }
159
+ const request = input;
160
+ const unknownFields = Object.keys(request).filter((field) => !PROBE_REQUEST_FIELDS.has(field));
161
+ if (unknownFields.length > 0) {
162
+ return { error: `Unsupported field(s): ${unknownFields.join(", ")}.` };
163
+ }
164
+ let host;
165
+ if (request.host !== undefined) {
166
+ if (typeof request.host !== "string") {
167
+ return { error: "host must be a hostname or IP address string." };
168
+ }
169
+ host = request.host.trim();
170
+ if (!isValidProbeHost(host)) {
171
+ return { error: "host must be a hostname or IP address without schemes, paths, spaces, or credentials." };
172
+ }
173
+ }
174
+ let ports;
175
+ if (request.ports !== undefined) {
176
+ if (!Array.isArray(request.ports)) {
177
+ return { error: "ports must be an array." };
178
+ }
179
+ const invalidPort = request.ports.find((port) => typeof port !== "number" || !Number.isInteger(port) || port < 1 || port > 65_535);
180
+ if (invalidPort !== undefined) {
181
+ return { error: `Invalid TCP port: ${String(invalidPort)}.` };
182
+ }
183
+ ports = [...request.ports];
184
+ }
185
+ let serialPaths;
186
+ if (request.serial_paths !== undefined) {
187
+ if (!Array.isArray(request.serial_paths)) {
188
+ return { error: "serial_paths must be an array." };
189
+ }
190
+ const invalidPath = request.serial_paths.find((path) => typeof path !== "string" || !path.trim());
191
+ if (invalidPath !== undefined) {
192
+ return { error: "serial_paths must contain non-empty strings." };
193
+ }
194
+ serialPaths = request.serial_paths.map((path) => path.trim());
195
+ }
196
+ if (request.timeout_ms !== undefined && (typeof request.timeout_ms !== "number" || !Number.isFinite(request.timeout_ms) || request.timeout_ms <= 0)) {
197
+ return { error: "timeout_ms must be a positive number." };
198
+ }
199
+ const hasPorts = (ports?.length ?? 0) > 0;
200
+ const hasSerialPaths = (serialPaths?.length ?? 0) > 0;
201
+ if (!hasPorts && !hasSerialPaths) {
202
+ return { error: "At least one TCP port or serial path is required." };
203
+ }
204
+ if (hasPorts && !host) {
205
+ return { error: "host is required when ports are provided." };
206
+ }
207
+ return {
208
+ request: {
209
+ host,
210
+ ports,
211
+ serial_paths: serialPaths,
212
+ timeout_ms: typeof request.timeout_ms === "number" ? request.timeout_ms : undefined
213
+ }
214
+ };
215
+ }
216
+ function isValidProbeHost(host) {
217
+ if (!host || host.length > 253 || /[\s\x00-\x1f\x7f]/.test(host)) {
218
+ return false;
219
+ }
220
+ if (host.includes("://") || host.includes("/") || host.includes("\\") || host.includes("@")) {
221
+ return false;
222
+ }
223
+ if (net.isIP(host) !== 0) {
224
+ return true;
225
+ }
226
+ return host.split(".").every((label) => /^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(label));
227
+ }
228
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@kvell007/embed-labs-local-bridge",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Local hardware bridge service for Embed Labs Cloud. Experimental npm publish.",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "bin": {
17
+ "embed-local-bridge": "dist/index.js"
18
+ },
19
+ "dependencies": {
20
+ "@embed-labs/protocol": "npm:@kvell007/embed-labs-protocol@0.1.0-alpha.0"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public",
24
+ "registry": "https://registry.npmjs.org/"
25
+ }
26
+ }