@kvell007/embed-labs-cli 0.1.0-alpha.3 → 0.1.0-alpha.4

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/index.js CHANGED
@@ -9,7 +9,7 @@ import { basename, delimiter, dirname, join, resolve } from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { startServer } from "@embed-labs/local-bridge";
11
11
  import { composeBootLogoPackage } from "./image-compose.js";
12
- import { buildTaishanPiQtSmoke, compileTaishanPiSingleFile, validateLocalToolchain } from "./local-toolchain.js";
12
+ import { buildTaishanPiQtSmoke, compileTaishanPiSingleFile, currentLocalToolchain, installLocalToolchain, latestLocalToolchain, validateLocalToolchain } from "./local-toolchain.js";
13
13
  import { fail, ok } from "@embed-labs/protocol";
14
14
  const require = createRequire(import.meta.url);
15
15
  const CLI_MODULE_DIR = dirname(fileURLToPath(import.meta.url));
@@ -81,6 +81,9 @@ const BUILD_IMAGE_BOOT_LOGO_USAGE = "Usage: embed build image boot-logo --logo <
81
81
  const IMAGE_BOOT_LOGO_COMPOSE_USAGE = "Usage: embed image boot-logo compose --package <boot-logo-package.json> --base-image <boot.img|image.img> --output <image> [--manifest <manifest.json>] [--force] [--json]";
82
82
  const BUILD_IMAGE_DTB_USAGE = "Usage: embed build image dtb --dtb <local.dtb|local.dts> [--input-format auto|dtb|dts] [--account <account_id>] [--project <project_id>] [--board taishanpi] [--variant 1M-RK3566] [--output <package.json>] [--json]";
83
83
  const IMAGE_DTB_COMPOSE_USAGE = "Usage: embed image dtb compose --package <dtb-package.json> --base-image <boot.img|image.img> --output <image> [--manifest <manifest.json>] [--force] [--json]";
84
+ const LOCAL_TOOLCHAIN_LATEST_USAGE = "Usage: embed local toolchain latest [--board taishanpi-1m-rk3566] [--channel stable] [--metadata-root <path>] [--json]";
85
+ const LOCAL_TOOLCHAIN_CURRENT_USAGE = "Usage: embed local toolchain current [--install-root <path>] [--json]";
86
+ const LOCAL_TOOLCHAIN_INSTALL_USAGE = "Usage: embed local toolchain install [--board taishanpi-1m-rk3566] [--channel stable] [--metadata-root <path>] [--source-url <tar.gz-url>|--source-release-root <path>] [--install-root <path>] [--force] [--json]";
84
87
  const LOCAL_TOOLCHAIN_VALIDATE_USAGE = "Usage: embed local toolchain validate [--release-root <path>] [--json]";
85
88
  const LOCAL_COMPILE_TAISHANPI_USAGE = "Usage: embed local compile taishanpi --source <main.c|main.cpp> --output <artifact> [--release-root <path>] [--account <account_id>] [--json]";
86
89
  const LOCAL_BUILD_QT_SMOKE_USAGE = "Usage: embed local build qt-smoke --build-dir <dir> [--source <qt-smoke-dir>] [--release-root <path>] [--account <account_id>] [--json]";
@@ -503,6 +506,27 @@ async function main(argv) {
503
506
  return output(parsed, fail("invalid_args", [IMAGE_BOOT_LOGO_COMPOSE_USAGE, IMAGE_DTB_COMPOSE_USAGE].join("\n")), undefined, 2);
504
507
  }
505
508
  if (area === "local") {
509
+ if (action === "toolchain" && parsed.command[2] === "latest") {
510
+ const request = localToolchainLatestRequest(parsed);
511
+ if (typeof request === "string") {
512
+ return output(parsed, fail("invalid_args", request), undefined, 2);
513
+ }
514
+ return output(parsed, ok(await latestLocalToolchain(request)), renderLocalToolchainLatest);
515
+ }
516
+ if (action === "toolchain" && parsed.command[2] === "current") {
517
+ const request = localToolchainCurrentRequest(parsed);
518
+ if (typeof request === "string") {
519
+ return output(parsed, fail("invalid_args", request), undefined, 2);
520
+ }
521
+ return output(parsed, ok(await currentLocalToolchain(request.installRoot)), renderLocalToolchainCurrent);
522
+ }
523
+ if (action === "toolchain" && parsed.command[2] === "install") {
524
+ const request = localToolchainInstallRequest(parsed);
525
+ if (typeof request === "string") {
526
+ return output(parsed, fail("invalid_args", request), undefined, 2);
527
+ }
528
+ return output(parsed, ok(await installLocalToolchain(request)), renderLocalToolchainInstall);
529
+ }
506
530
  if (action === "toolchain" && parsed.command[2] === "validate") {
507
531
  const request = localToolchainValidateRequest(parsed);
508
532
  if (typeof request === "string") {
@@ -525,6 +549,9 @@ async function main(argv) {
525
549
  return output(parsed, ok(await buildTaishanPiQtSmoke(request)), renderLocalCompileResult);
526
550
  }
527
551
  return output(parsed, fail("invalid_args", [
552
+ LOCAL_TOOLCHAIN_LATEST_USAGE,
553
+ LOCAL_TOOLCHAIN_CURRENT_USAGE,
554
+ LOCAL_TOOLCHAIN_INSTALL_USAGE,
528
555
  LOCAL_TOOLCHAIN_VALIDATE_USAGE,
529
556
  LOCAL_COMPILE_TAISHANPI_USAGE,
530
557
  LOCAL_BUILD_QT_SMOKE_USAGE
@@ -4024,6 +4051,80 @@ function billingSnapshotListRequest(parsed) {
4024
4051
  }
4025
4052
  return { path: `/v1/accounts/${encodeURIComponent(accountResult.value)}/billing/snapshots` };
4026
4053
  }
4054
+ function localToolchainLatestRequest(parsed) {
4055
+ const unknownFlag = firstUnknownFlag(parsed, ["json", "board", "board-id", "channel", "metadata-root"]);
4056
+ if (unknownFlag) {
4057
+ return `Unknown flag --${unknownFlag}. ${LOCAL_TOOLCHAIN_LATEST_USAGE}`;
4058
+ }
4059
+ const extra = parsed.command.slice(3);
4060
+ if (extra.length > 0) {
4061
+ return `Unexpected argument: ${extra[0]}. ${LOCAL_TOOLCHAIN_LATEST_USAGE}`;
4062
+ }
4063
+ const board = optionalTrimmedStringAliasFlag(parsed, ["board", "board-id"], "board or board-id");
4064
+ if (board.error)
4065
+ return board.error;
4066
+ const channel = optionalTrimmedStringFlag(parsed, "channel");
4067
+ if (channel.error)
4068
+ return channel.error;
4069
+ const metadataRoot = optionalTrimmedStringFlag(parsed, "metadata-root");
4070
+ if (metadataRoot.error)
4071
+ return metadataRoot.error;
4072
+ return { boardId: board.value, channel: channel.value, metadataRoot: metadataRoot.value };
4073
+ }
4074
+ function localToolchainCurrentRequest(parsed) {
4075
+ const unknownFlag = firstUnknownFlag(parsed, ["json", "install-root"]);
4076
+ if (unknownFlag) {
4077
+ return `Unknown flag --${unknownFlag}. ${LOCAL_TOOLCHAIN_CURRENT_USAGE}`;
4078
+ }
4079
+ const extra = parsed.command.slice(3);
4080
+ if (extra.length > 0) {
4081
+ return `Unexpected argument: ${extra[0]}. ${LOCAL_TOOLCHAIN_CURRENT_USAGE}`;
4082
+ }
4083
+ const installRoot = optionalTrimmedStringFlag(parsed, "install-root");
4084
+ if (installRoot.error)
4085
+ return installRoot.error;
4086
+ return { installRoot: installRoot.value };
4087
+ }
4088
+ function localToolchainInstallRequest(parsed) {
4089
+ const unknownFlag = firstUnknownFlag(parsed, ["json", "board", "board-id", "channel", "metadata-root", "source-url", "source-release-root", "install-root", "force"]);
4090
+ if (unknownFlag) {
4091
+ return `Unknown flag --${unknownFlag}. ${LOCAL_TOOLCHAIN_INSTALL_USAGE}`;
4092
+ }
4093
+ const extra = parsed.command.slice(3);
4094
+ if (extra.length > 0) {
4095
+ return `Unexpected argument: ${extra[0]}. ${LOCAL_TOOLCHAIN_INSTALL_USAGE}`;
4096
+ }
4097
+ const board = optionalTrimmedStringAliasFlag(parsed, ["board", "board-id"], "board or board-id");
4098
+ if (board.error)
4099
+ return board.error;
4100
+ const channel = optionalTrimmedStringFlag(parsed, "channel");
4101
+ if (channel.error)
4102
+ return channel.error;
4103
+ const metadataRoot = optionalTrimmedStringFlag(parsed, "metadata-root");
4104
+ if (metadataRoot.error)
4105
+ return metadataRoot.error;
4106
+ const sourceUrl = optionalTrimmedStringFlag(parsed, "source-url");
4107
+ if (sourceUrl.error)
4108
+ return sourceUrl.error;
4109
+ const sourceReleaseRoot = optionalTrimmedStringFlag(parsed, "source-release-root");
4110
+ if (sourceReleaseRoot.error)
4111
+ return sourceReleaseRoot.error;
4112
+ if (sourceUrl.value && sourceReleaseRoot.value) {
4113
+ return "Use only one of --source-url or --source-release-root.";
4114
+ }
4115
+ const installRoot = optionalTrimmedStringFlag(parsed, "install-root");
4116
+ if (installRoot.error)
4117
+ return installRoot.error;
4118
+ return {
4119
+ boardId: board.value,
4120
+ channel: channel.value,
4121
+ metadataRoot: metadataRoot.value,
4122
+ sourceUrl: sourceUrl.value,
4123
+ sourceReleaseRoot: sourceReleaseRoot.value,
4124
+ installRoot: installRoot.value,
4125
+ force: booleanFlag(parsed, "force")
4126
+ };
4127
+ }
4027
4128
  function localToolchainValidateRequest(parsed) {
4028
4129
  const unknownFlag = firstUnknownFlag(parsed, ["json", "release-root"]);
4029
4130
  if (unknownFlag) {
@@ -5159,6 +5260,69 @@ function renderBuildWorkspaceSourcePatch(result) {
5159
5260
  }
5160
5261
  return lines.join("\n");
5161
5262
  }
5263
+ function renderLocalToolchainLatest(result) {
5264
+ const lines = [
5265
+ `board=${result.board_id}`,
5266
+ `channel=${result.channel}`,
5267
+ `version=${result.version}`,
5268
+ `host=${result.host}`,
5269
+ result.metadata_root ? `metadata_root=${result.metadata_root}` : "metadata=built-in"
5270
+ ];
5271
+ if (result.packages.length > 0) {
5272
+ lines.push("packages:");
5273
+ for (const pkg of result.packages) {
5274
+ lines.push(` ${pkg.id}@${pkg.version}`);
5275
+ }
5276
+ }
5277
+ return lines.join("\n");
5278
+ }
5279
+ function renderLocalToolchainCurrent(result) {
5280
+ if (!result.installed) {
5281
+ return [
5282
+ "No local toolchain installed.",
5283
+ `board=${result.board_id}`,
5284
+ `install_root=${result.install_root}`,
5285
+ `registry=${result.registry_path}`
5286
+ ].join("\n");
5287
+ }
5288
+ return [
5289
+ "Local toolchain installed.",
5290
+ `board=${result.board_id}`,
5291
+ result.version ? `version=${result.version}` : "",
5292
+ result.channel ? `channel=${result.channel}` : "",
5293
+ result.release_root ? `release_root=${result.release_root}` : "",
5294
+ `install_root=${result.install_root}`,
5295
+ `registry=${result.registry_path}`
5296
+ ].filter(Boolean).join("\n");
5297
+ }
5298
+ function renderLocalToolchainInstall(result) {
5299
+ const lines = [
5300
+ "Local toolchain installed.",
5301
+ `board=${result.board_id}`,
5302
+ `version=${result.version}`,
5303
+ `channel=${result.channel}`,
5304
+ `host=${result.host}`,
5305
+ `install_root=${result.install_root}`,
5306
+ `release_root=${result.release_root}`,
5307
+ `registry=${result.registry_path}`,
5308
+ `source=${result.source.kind}:${result.source.value}`,
5309
+ result.source.downloaded_path ? `downloaded=${result.source.downloaded_path}` : "",
5310
+ `validation=${result.validation.ok ? "ok" : "failed"}`
5311
+ ].filter(Boolean);
5312
+ if (result.installed_paths.length > 0) {
5313
+ lines.push("installed_paths:");
5314
+ for (const installedPath of result.installed_paths) {
5315
+ lines.push(` ${installedPath}`);
5316
+ }
5317
+ }
5318
+ if (result.packages.length > 0) {
5319
+ lines.push("packages:");
5320
+ for (const pkg of result.packages) {
5321
+ lines.push(` ${pkg.id}@${pkg.version}`);
5322
+ }
5323
+ }
5324
+ return lines.join("\n");
5325
+ }
5162
5326
  function renderLocalToolchainValidation(result) {
5163
5327
  const lines = [
5164
5328
  result.ok ? "Local toolchain ready." : "Local toolchain not ready.",
@@ -5921,6 +6085,8 @@ Main workflow:
5921
6085
  4. Run a natural-language local tool loop:
5922
6086
  embed agent run --prompt "验证开发板状态"
5923
6087
  5. Validate or use the local TaishanPi toolchain:
6088
+ embed local toolchain latest
6089
+ embed local toolchain install --source-url <toolchain.tar.gz>
5924
6090
  embed local toolchain validate
5925
6091
  embed local compile taishanpi --source ./main.c --output ./.embed-labs/build/main
5926
6092
  embed local build qt-smoke --build-dir ./.embed-labs/build/qt-smoke
@@ -5966,6 +6132,9 @@ Local hardware:
5966
6132
  embed tool call chip.temperature --input-json '{"host":"198.19.77.2","user":"root"}'
5967
6133
  embed tool call qml.runtime.status --input-json '{"host":"198.19.77.2","user":"root","port":18130}'
5968
6134
  embed device list
6135
+ embed local toolchain latest
6136
+ embed local toolchain current
6137
+ embed local toolchain install --source-url <toolchain.tar.gz>
5969
6138
  embed local toolchain validate
5970
6139
  embed local compile taishanpi --source ./main.c --output ./.embed-labs/build/main
5971
6140
  embed local build qt-smoke --build-dir ./.embed-labs/build/qt-smoke
@@ -6167,6 +6336,9 @@ Usage:
6167
6336
  embed build image generate --workspace <workspace_id> --prompt <request> [--account <account_id>] [--image-profile <profile_id>] [--provider stub|openai|bai|cc|claude-code] [--model <model>] [--execution-mode cloud_worker|dry_run] [--worker-pool <pool>] [--json]
6168
6337
  embed build image boot-logo --logo <local_image> [--account <account_id>] [--project <project_id>] [--board taishanpi] [--variant 1M-RK3566] [--kernel-logo <local_image>] [--rotate -90] [--scale 100] [--output <package.json>] [--json]
6169
6338
  embed image boot-logo compose --package <boot-logo-package.json> --base-image <boot.img|image.img> --output <image> [--manifest <manifest.json>] [--force] [--json]
6339
+ embed local toolchain latest [--board taishanpi-1m-rk3566] [--channel stable] [--metadata-root <path>] [--json]
6340
+ embed local toolchain current [--install-root <path>] [--json]
6341
+ embed local toolchain install [--board taishanpi-1m-rk3566] [--channel stable] [--metadata-root <path>] [--source-url <tar.gz-url>|--source-release-root <path>] [--install-root <path>] [--force] [--json]
6170
6342
  embed local toolchain validate [--release-root <path>] [--json]
6171
6343
  embed local compile taishanpi --source <main.c|main.cpp> --output <artifact> [--release-root <path>] [--account <account_id>] [--json]
6172
6344
  embed local build qt-smoke --build-dir <dir> [--source <qt-smoke-dir>] [--release-root <path>] [--account <account_id>] [--json]