@kvell007/embed-labs-cli 0.1.0-alpha.89 → 0.1.0-alpha.90
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/embed-labs-mcp-bridge.mjs +64 -12
- package/package.json +3 -3
|
@@ -12,7 +12,7 @@ const DEFAULT_HOST = "198.19.77.2";
|
|
|
12
12
|
const DEFAULT_PORTS = "22,15301";
|
|
13
13
|
const DEFAULT_STATUS_PORTS = "22";
|
|
14
14
|
const TOOL_INTEGRITY_RELOGIN_MESSAGE = "工具完整性校验失败,请在当前电脑重新执行 embedlabs auth login --token <key>";
|
|
15
|
-
const MCP_SERVER_VERSION = "0.2.
|
|
15
|
+
const MCP_SERVER_VERSION = "0.2.41";
|
|
16
16
|
const MCP_ICON_FILES = [
|
|
17
17
|
{ fileName: "embed-labs-icon-dark.png", theme: "dark" },
|
|
18
18
|
{ fileName: "embed-labs-icon-light.png", theme: "light" }
|
|
@@ -150,8 +150,8 @@ const tools = [
|
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
name: "dbt_rp2350_uart_write",
|
|
153
|
-
description: "Send text or HEX data over
|
|
154
|
-
inputSchema: { type: "object", properties: { id: { type: "number" }, instance: { type: "number" }, tx: { type: "number" }, rx: { type: "number" }, baud: { type: "number" }, text: { type: "string" }, hex: { type: "string" }, data_hex: { type: "string" }, line_ending: { type: "string" }, approved: { type: "boolean" }, approve: { type: "boolean" }, transport: { type: "string" }, local_device_id: { type: "string" }, monitor_bridge_url: { type: "string" }, serial_path: { type: "string" }, tcp: { type: "string" }, tcp_endpoint: { type: "string" }, host: { type: "string" }, port: { type: "number" }, timeout_ms: { type: "number" } } }
|
|
153
|
+
description: "Send text or HEX data over a configurable RP2350 UART channel, with optional tx/rx/baud override. Accepts uart_id such as uart1 and data/data_format aliases. Requires approved=true.",
|
|
154
|
+
inputSchema: { type: "object", properties: { id: { type: "number" }, instance: { type: "number" }, uart_id: { type: "string", description: "Alias such as uart0 or uart1; normalized to instance." }, tx: { type: "number" }, rx: { type: "number" }, baud: { type: "number" }, text: { type: "string" }, hex: { type: "string" }, data: { type: "string", description: "Text or hex payload depending on data_format." }, data_format: { type: "string", description: "hex, text, string, utf8, or ascii." }, data_hex: { type: "string" }, line_ending: { type: "string" }, approved: { type: "boolean" }, approve: { type: "boolean" }, transport: { type: "string" }, local_device_id: { type: "string" }, monitor_bridge_url: { type: "string" }, serial_path: { type: "string" }, tcp: { type: "string" }, tcp_endpoint: { type: "string" }, host: { type: "string" }, port: { type: "number" }, timeout_ms: { type: "number" } } }
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
157
|
name: "dbt_rp2350_i2c_transfer",
|
|
@@ -163,7 +163,6 @@ const tools = [
|
|
|
163
163
|
description: "Capture a compact RP2350-Monitor logic-analyzer JSONL file and optionally generate UART/SPI/I2C stimulus in the same operation. Requires approved=true because it arms local hardware. For closed-loop validation, do not call uart/spi write separately; pass stimulus here. UART/SPI/I2C/GPIO/logic functions may be combined freely when their GPIO sets do not overlap; only overlapping pins conflict. Example UART loopback: UART1 GP8/GP9 wired to logic GP16/GP17. Supports USB serial or board LAN IP/TCP transport.",
|
|
164
164
|
inputSchema: {
|
|
165
165
|
type: "object",
|
|
166
|
-
required: ["pin_base", "pin_count"],
|
|
167
166
|
properties: {
|
|
168
167
|
transport: { type: "string" },
|
|
169
168
|
local_device_id: { type: "string" },
|
|
@@ -173,10 +172,14 @@ const tools = [
|
|
|
173
172
|
tcp_endpoint: { type: "string" },
|
|
174
173
|
host: { type: "string", description: "Board LAN IP/hostname for network mode. Defaults to RP2350 Monitor TCP port 4242." },
|
|
175
174
|
port: { type: "number", description: "Network-mode RP2350 Monitor TCP port. Defaults to 4242." },
|
|
176
|
-
pin_base: { type: "number" },
|
|
177
|
-
pin_count: { type: "number" },
|
|
175
|
+
pin_base: { type: "number", description: "First contiguous analyzer GPIO. Optional when channels/pins is provided." },
|
|
176
|
+
pin_count: { type: "number", description: "Number of contiguous analyzer GPIOs. Optional when channels/pins is provided." },
|
|
177
|
+
channels: { type: "array", items: { anyOf: [{ type: "number" }, { type: "string" }] }, description: "Analyzer GPIO aliases such as [\"gpio8\",\"gpio9\"]. The bridge derives pin_base/pin_count when possible." },
|
|
178
|
+
pins: { type: "array", items: { anyOf: [{ type: "number" }, { type: "string" }] }, description: "Alias for channels." },
|
|
178
179
|
sample_rate: { type: "number" },
|
|
180
|
+
sample_rate_hz: { type: "number", description: "Alias for sample_rate." },
|
|
179
181
|
samples: { type: "number" },
|
|
182
|
+
duration_ms: { type: "number", description: "Alias that computes samples from sample_rate/sample_rate_hz." },
|
|
180
183
|
output_path: { type: "string" },
|
|
181
184
|
decoder: { type: "string", description: "Optional decoder hint such as uart, spi, summary, or structure. If provided with decode=true/default, the bridge decodes the generated capture file." },
|
|
182
185
|
decode: { type: "boolean" },
|
|
@@ -210,14 +213,14 @@ const tools = [
|
|
|
210
213
|
description: "Decode a local RP2350-Monitor logic JSONL capture without touching hardware. Supported decoders: summary, bursts, edges, uart, spi, and structure/auto/unknown. The result includes summary_for_user, decoded_preview, protocol_data, and analysis so the AI can report actual sampled data; use structure/unknown when the protocol is not known.",
|
|
211
214
|
inputSchema: {
|
|
212
215
|
type: "object",
|
|
213
|
-
required: ["input_path"],
|
|
214
216
|
properties: {
|
|
215
217
|
local_device_id: { type: "string" },
|
|
216
|
-
input_path: { type: "string" },
|
|
218
|
+
input_path: { type: "string", description: "Preferred capture file path from logic-capture output_path." },
|
|
219
|
+
capture_id: { type: "number", description: "Optional capture id; when input_path is omitted, the bridge searches the default capture directory." },
|
|
217
220
|
decoder: { type: "string", description: "summary, bursts, edges, uart, spi, structure, auto, or unknown." },
|
|
218
221
|
output_path: { type: "string" },
|
|
219
222
|
preview_limit: { type: "number" },
|
|
220
|
-
pins: { type: "array", items: { type: "number" } },
|
|
223
|
+
pins: { type: "array", items: { anyOf: [{ type: "number" }, { type: "string" }] }, description: "GPIO aliases such as [\"gpio8\",\"gpio9\"]." },
|
|
221
224
|
rx_pin: { type: "number" },
|
|
222
225
|
baud: { type: "number" },
|
|
223
226
|
data_bits: { type: "number" },
|
|
@@ -1549,8 +1552,24 @@ async function boardControl(args) {
|
|
|
1549
1552
|
|
|
1550
1553
|
function normalizeRp2350Input(args) {
|
|
1551
1554
|
const input = compactObject({ ...args });
|
|
1555
|
+
if (input.local_device_id == null && input.device_id != null) {
|
|
1556
|
+
input.local_device_id = input.device_id;
|
|
1557
|
+
}
|
|
1558
|
+
if (input.sample_rate == null && input.sample_rate_hz != null) {
|
|
1559
|
+
input.sample_rate = input.sample_rate_hz;
|
|
1560
|
+
}
|
|
1561
|
+
if (input.hex == null && input.data != null && ["hex", "data_hex", ""].includes(asString(input.data_format).toLowerCase())) {
|
|
1562
|
+
input.hex = input.data;
|
|
1563
|
+
} else if (input.text == null && input.data != null && ["text", "string", "utf8", "ascii"].includes(asString(input.data_format).toLowerCase())) {
|
|
1564
|
+
input.text = input.data;
|
|
1565
|
+
}
|
|
1566
|
+
if (input.instance == null && typeof input.uart_id === "string") {
|
|
1567
|
+
const match = input.uart_id.match(/\d+/);
|
|
1568
|
+
if (match) input.instance = Number(match[0]);
|
|
1569
|
+
}
|
|
1570
|
+
normalizeRp2350LogicChannels(input);
|
|
1552
1571
|
for (const key of [
|
|
1553
|
-
"port", "baud", "timeout_ms", "pin_base", "pin_count", "sample_rate", "samples",
|
|
1572
|
+
"port", "baud", "timeout_ms", "duration_ms", "sample_rate_hz", "pin_base", "pin_count", "sample_rate", "samples",
|
|
1554
1573
|
"wait_timeout_ms", "read_timeout_ms", "pre_samples", "post_samples", "search_samples",
|
|
1555
1574
|
"burst_count", "trigger_pin", "trigger_mask", "trigger_value", "capture_id",
|
|
1556
1575
|
"start_sample", "end_sample", "preview_limit", "rx_pin", "data_bits", "sck_pin", "mosi_pin",
|
|
@@ -1564,14 +1583,22 @@ function normalizeRp2350Input(args) {
|
|
|
1564
1583
|
input[key] = Number(value);
|
|
1565
1584
|
}
|
|
1566
1585
|
}
|
|
1567
|
-
for (const key of ["include_caps", "release", "trigger_level", "invert", "cs_active_high", "level", "save", "use_current_channel", "decode", "strict_pins"]) {
|
|
1586
|
+
for (const key of ["include_caps", "release", "release_after", "trigger_level", "invert", "cs_active_high", "level", "save", "use_current_channel", "decode", "strict_pins"]) {
|
|
1568
1587
|
if (typeof input[key] === "string") {
|
|
1569
1588
|
input[key] = boolValue(input[key]);
|
|
1570
1589
|
}
|
|
1571
1590
|
}
|
|
1572
1591
|
if (typeof input.pins === "string") {
|
|
1573
|
-
input.pins = input.pins
|
|
1592
|
+
input.pins = parseGPIOList(input.pins);
|
|
1593
|
+
}
|
|
1594
|
+
normalizeRp2350LogicChannels(input);
|
|
1595
|
+
if (input.samples == null && Number.isFinite(input.duration_ms) && Number.isFinite(input.sample_rate)) {
|
|
1596
|
+
input.samples = Math.max(1, Math.round(input.sample_rate * input.duration_ms / 1000));
|
|
1574
1597
|
}
|
|
1598
|
+
delete input.sample_rate_hz;
|
|
1599
|
+
delete input.data;
|
|
1600
|
+
delete input.data_format;
|
|
1601
|
+
delete input.uart_id;
|
|
1575
1602
|
for (const key of ["channel_names", "pin_pulls", "stimulus", "params"]) {
|
|
1576
1603
|
const parsed = objectValue(input[key]);
|
|
1577
1604
|
if (parsed) input[key] = parsed;
|
|
@@ -1580,6 +1607,31 @@ function normalizeRp2350Input(args) {
|
|
|
1580
1607
|
return input;
|
|
1581
1608
|
}
|
|
1582
1609
|
|
|
1610
|
+
function normalizeRp2350LogicChannels(input) {
|
|
1611
|
+
const pins = parseGPIOList(input.channels ?? input.channel ?? input.pins);
|
|
1612
|
+
if (pins.length === 0) return;
|
|
1613
|
+
input.pins = pins;
|
|
1614
|
+
if (input.pin_base == null || input.pin_count == null) {
|
|
1615
|
+
const min = Math.min(...pins);
|
|
1616
|
+
const max = Math.max(...pins);
|
|
1617
|
+
input.pin_base = min;
|
|
1618
|
+
input.pin_count = max - min + 1;
|
|
1619
|
+
input.channel_names ??= Object.fromEntries(pins.map((pin) => [String(pin), `gpio${pin}`]));
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
function parseGPIOList(value) {
|
|
1624
|
+
if (value == null) return [];
|
|
1625
|
+
const raw = Array.isArray(value) ? value : String(value).split(/[,\s]+/g);
|
|
1626
|
+
return raw
|
|
1627
|
+
.map((item) => {
|
|
1628
|
+
if (typeof item === "number") return item;
|
|
1629
|
+
const match = String(item).trim().toLowerCase().match(/^(?:gp|gpio|pin)?\s*(\d+)$/);
|
|
1630
|
+
return match ? Number(match[1]) : Number.NaN;
|
|
1631
|
+
})
|
|
1632
|
+
.filter((item) => Number.isInteger(item) && item >= 0 && item <= 47);
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1583
1635
|
async function rp2350MonitorStatus(args) {
|
|
1584
1636
|
return await rp2350MonitorTool("dbt_rp2350_monitor_status", "rp2350.monitor.status", args);
|
|
1585
1637
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kvell007/embed-labs-cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.90",
|
|
4
4
|
"description": "Command-line interface for Embed Labs Cloud. Experimental npm publish.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"embedlabs": "dist/index.js"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@embed-labs/local-bridge": "npm:@kvell007/embed-labs-local-bridge@0.1.0-alpha.
|
|
22
|
-
"@embed-labs/protocol": "npm:@kvell007/embed-labs-protocol@0.1.0-alpha.
|
|
21
|
+
"@embed-labs/local-bridge": "npm:@kvell007/embed-labs-local-bridge@0.1.0-alpha.90",
|
|
22
|
+
"@embed-labs/protocol": "npm:@kvell007/embed-labs-protocol@0.1.0-alpha.90",
|
|
23
23
|
"qrcode-terminal": "^0.12.0"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|