@kvell007/embed-labs-cli 0.1.0-alpha.98 → 0.1.0-alpha.99

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.
@@ -41,7 +41,7 @@ async function progress(steps) {
41
41
  }
42
42
  }
43
43
  function writeProgress(percent, message) {
44
- const line = `[Embed Labs] ${String(percent).padStart(3, " ")}% ${message}\n`;
44
+ const line = `[EmbedLabs] ${String(percent).padStart(3, " ")}% ${message}\n`;
45
45
  process.stdout.write(line);
46
46
  writeDirectConsole(line);
47
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"install-progress.js","sourceRoot":"","sources":["../src/install-progress.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install-progress.js","sourceRoot":"","sources":["../src/install-progress.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,3 @@
1
- export interface LocalToolchainAuthContext {
2
- authenticated: boolean;
3
- profile: string;
4
- source?: string;
5
- account_id?: string;
6
- api_key_id?: string;
7
- device_id?: string;
8
- }
9
1
  export interface LocalToolchainValidationResult {
10
2
  ok: boolean;
11
3
  mode: string;
@@ -18,6 +10,7 @@ export interface LocalToolchainValidationResult {
18
10
  checked_paths: LocalToolchainPathCheck[];
19
11
  missing_paths: string[];
20
12
  path_leaks: LocalToolchainPathLeak[];
13
+ repaired_path_files?: string[];
21
14
  missing_groups: string[];
22
15
  repair_command?: string;
23
16
  summary_for_user: string;
@@ -38,23 +31,20 @@ export interface LocalCompileOptions {
38
31
  sourcePath: string;
39
32
  outputPath: string;
40
33
  releaseRoot?: string;
41
- accountId?: string;
42
- auth: LocalToolchainAuthContext;
43
34
  }
44
35
  export interface LocalQtSmokeBuildOptions {
45
36
  sourceDir?: string;
46
37
  buildDir: string;
47
38
  releaseRoot?: string;
48
39
  targetName?: string;
49
- accountId?: string;
50
- auth: LocalToolchainAuthContext;
51
40
  }
52
41
  export interface LocalCompileResult {
53
42
  board_id: string;
54
43
  operation: "local.compile.single_file" | "local.build.qt_smoke";
55
44
  release_root: string;
56
- account_id?: string;
57
- auth: LocalToolchainAuthContext;
45
+ execution_scope: "local_installation";
46
+ identity_scope: "local_installation";
47
+ uses_local_installation_identity: true;
58
48
  source_path: string;
59
49
  build_dir?: string;
60
50
  artifact_path: string;
@@ -354,6 +344,7 @@ export declare function validateLocalToolchain(input?: string | {
354
344
  releaseRoot?: string;
355
345
  mode?: string;
356
346
  boardId?: string;
347
+ repairPortablePaths?: boolean;
357
348
  }): Promise<LocalToolchainValidationResult>;
358
349
  export declare function compileTaishanPiSingleFile(options: LocalCompileOptions): Promise<LocalCompileResult>;
359
350
  export declare function buildTaishanPiQtSmoke(options: LocalQtSmokeBuildOptions): Promise<LocalCompileResult>;
@@ -14,6 +14,8 @@ const COLOREASYPICO2_RP2350_BOARD_ID = "coloreasypico2-rp2350-monitor";
14
14
  const DEFAULT_CHANNEL = "stable";
15
15
  const DEFAULT_DOWNLOAD_BASE_URL = "https://download.embedboard.com";
16
16
  const DOWNLOAD_REQUEST_TIMEOUT_MS = 12_000;
17
+ const TAISHANPI_TOOLCHAIN_VERSION = "1.0.33";
18
+ const RP2350_MONITOR_TOOLCHAIN_VERSION = "1.0.41";
17
19
  const BUILT_IN_CHANNEL = {
18
20
  schema: "embedlabs.channel.v1",
19
21
  channel: DEFAULT_CHANNEL,
@@ -22,13 +24,13 @@ const BUILT_IN_CHANNEL = {
22
24
  { id: "embedlabs.tools.common.llvm", version: "22.1.3", manifest: "" },
23
25
  { id: "embedlabs.tools.common.arm-none-eabi", version: "15.2.rel1", manifest: "" },
24
26
  { id: "embedlabs.tools.common.e2fsprogs", version: "1.0.0", manifest: "" },
25
- { id: "embedlabs.tools.runtime.qtquick-live-preview", version: "1.0.33", manifest: "" },
26
- { id: "embedlabs.tools.runtime.rp2350-monitor", version: "1.0.33", manifest: "" },
27
+ { id: "embedlabs.tools.runtime.qtquick-live-preview", version: TAISHANPI_TOOLCHAIN_VERSION, manifest: "" },
28
+ { id: "embedlabs.tools.runtime.rp2350-monitor", version: RP2350_MONITOR_TOOLCHAIN_VERSION, manifest: "" },
27
29
  { id: "embedlabs.family.rk356x", version: "1.0.0", manifest: "" },
28
30
  { id: "embedlabs.family.rp2350", version: "1.0.0", manifest: "" },
29
- { id: "embedlabs.board.taishanpi.1m-rk3566", version: "1.0.33", manifest: "" },
30
- { id: "embedlabs.board.pico2w.rp2350-monitor", version: "1.0.33", manifest: "" },
31
- { id: "embedlabs.board.coloreasypico2.rp2350-monitor", version: "1.0.33", manifest: "" }
31
+ { id: "embedlabs.board.taishanpi.1m-rk3566", version: TAISHANPI_TOOLCHAIN_VERSION, manifest: "" },
32
+ { id: "embedlabs.board.pico2w.rp2350-monitor", version: RP2350_MONITOR_TOOLCHAIN_VERSION, manifest: "" },
33
+ { id: "embedlabs.board.coloreasypico2.rp2350-monitor", version: RP2350_MONITOR_TOOLCHAIN_VERSION, manifest: "" }
32
34
  ]
33
35
  };
34
36
  const BUILT_IN_MANIFESTS = {
@@ -67,7 +69,7 @@ const BUILT_IN_MANIFESTS = {
67
69
  "embedlabs.tools.runtime.qtquick-live-preview": {
68
70
  schema: "embedlabs.package.v1",
69
71
  id: "embedlabs.tools.runtime.qtquick-live-preview",
70
- version: "1.0.33",
72
+ version: TAISHANPI_TOOLCHAIN_VERSION,
71
73
  kind: "tools",
72
74
  hosts: ["darwin-arm64", "linux-x86_64"],
73
75
  provides: ["qtquick.live_preview", "qtquick.live_preview.inspector", "qtquick.live_preview.feedback"]
@@ -75,7 +77,7 @@ const BUILT_IN_MANIFESTS = {
75
77
  "embedlabs.tools.runtime.rp2350-monitor": {
76
78
  schema: "embedlabs.package.v1",
77
79
  id: "embedlabs.tools.runtime.rp2350-monitor",
78
- version: "1.0.33",
80
+ version: RP2350_MONITOR_TOOLCHAIN_VERSION,
79
81
  kind: "tools",
80
82
  hosts: ["darwin-arm64", "linux-x86_64"],
81
83
  provides: ["rp2350.monitor.cli", "rp2350.monitor.logic_analyzer", "rp2350.monitor.logic_decode"]
@@ -100,13 +102,13 @@ const BUILT_IN_MANIFESTS = {
100
102
  family: "rp2350",
101
103
  requires: [
102
104
  { id: "embedlabs.tools.common.arm-none-eabi", version: "15.x", roles: ["compile", "uf2"] },
103
- { id: "embedlabs.tools.runtime.rp2350-monitor", version: "^1.0.33", roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
105
+ { id: "embedlabs.tools.runtime.rp2350-monitor", version: `^${RP2350_MONITOR_TOOLCHAIN_VERSION}`, roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
104
106
  ]
105
107
  },
106
108
  "embedlabs.board.taishanpi.1m-rk3566": {
107
109
  schema: "embedlabs.package.v1",
108
110
  id: "embedlabs.board.taishanpi.1m-rk3566",
109
- version: "1.0.33",
111
+ version: TAISHANPI_TOOLCHAIN_VERSION,
110
112
  kind: "board",
111
113
  family: "rk356x",
112
114
  board: "TaishanPi",
@@ -116,14 +118,14 @@ const BUILT_IN_MANIFESTS = {
116
118
  { id: "embedlabs.tools.vendor.rockchip", version: "^1.0.0", roles: ["flash", "resource-image"] },
117
119
  { id: "embedlabs.tools.common.llvm", version: "22.x", roles: ["compile"] },
118
120
  { id: "embedlabs.tools.common.e2fsprogs", version: "^1.0.0", roles: ["userdata-image"] },
119
- { id: "embedlabs.tools.runtime.qtquick-live-preview", version: "^1.0.33", roles: ["qtquick-preview"] }
121
+ { id: "embedlabs.tools.runtime.qtquick-live-preview", version: `^${TAISHANPI_TOOLCHAIN_VERSION}`, roles: ["qtquick-preview"] }
120
122
  ],
121
123
  build_modes: ["local-llvm"]
122
124
  },
123
125
  "embedlabs.board.pico2w.rp2350-monitor": {
124
126
  schema: "embedlabs.package.v1",
125
127
  id: "embedlabs.board.pico2w.rp2350-monitor",
126
- version: "1.0.33",
128
+ version: RP2350_MONITOR_TOOLCHAIN_VERSION,
127
129
  kind: "board",
128
130
  display_name: "Pico 2 W",
129
131
  family: "rp2350",
@@ -132,14 +134,14 @@ const BUILT_IN_MANIFESTS = {
132
134
  requires: [
133
135
  { id: "embedlabs.family.rp2350", version: "^1.0.0" },
134
136
  { id: "embedlabs.tools.common.arm-none-eabi", version: "15.x", roles: ["compile", "uf2", "picotool"] },
135
- { id: "embedlabs.tools.runtime.rp2350-monitor", version: "^1.0.33", roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
137
+ { id: "embedlabs.tools.runtime.rp2350-monitor", version: `^${RP2350_MONITOR_TOOLCHAIN_VERSION}`, roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
136
138
  ],
137
139
  build_modes: ["local-pico-sdk", "optional-rp2350-monitor"]
138
140
  },
139
141
  "embedlabs.board.coloreasypico2.rp2350-monitor": {
140
142
  schema: "embedlabs.package.v1",
141
143
  id: "embedlabs.board.coloreasypico2.rp2350-monitor",
142
- version: "1.0.33",
144
+ version: RP2350_MONITOR_TOOLCHAIN_VERSION,
143
145
  kind: "board",
144
146
  display_name: "ColorEasyPICO2",
145
147
  family: "rp2350",
@@ -148,7 +150,7 @@ const BUILT_IN_MANIFESTS = {
148
150
  requires: [
149
151
  { id: "embedlabs.family.rp2350", version: "^1.0.0" },
150
152
  { id: "embedlabs.tools.common.arm-none-eabi", version: "15.x", roles: ["compile", "uf2", "picotool"] },
151
- { id: "embedlabs.tools.runtime.rp2350-monitor", version: "^1.0.33", roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
153
+ { id: "embedlabs.tools.runtime.rp2350-monitor", version: `^${RP2350_MONITOR_TOOLCHAIN_VERSION}`, roles: ["hardware-control", "logic-analyzer", "debug-probe"] }
152
154
  ],
153
155
  build_modes: ["local-pico-sdk", "optional-rp2350-monitor"]
154
156
  }
@@ -388,7 +390,7 @@ export async function listLocalToolchainEnvironments(options = {}) {
388
390
  release_root: installedCandidate.release_root
389
391
  }
390
392
  : undefined;
391
- const updateAvailable = !!installed?.version && installed.version !== latestVersion;
393
+ const updateAvailable = !!installed?.version && compareLocalToolchainVersionLike(installed.version, latestVersion) < 0;
392
394
  const nativeWindowsTaishanPi = isNativeWindowsTaishanPiHost(boardId, host);
393
395
  const execution = nativeWindowsTaishanPi
394
396
  ? taishanPiWindowsExecutionRoute(host, wslStatus, !!download)
@@ -465,7 +467,8 @@ export async function installLocalToolchain(options = {}) {
465
467
  const installRoot = resolveInstallRoot(options.installRoot);
466
468
  const releaseRoot = resolve(installRoot, "toolchains", latest.board_id, latest.version);
467
469
  const installMode = normalizeLocalToolchainInstallMode(options.mode ?? latest.download?.default_mode);
468
- if (await pathExists(releaseRoot) && !options.force) {
470
+ const hasExplicitInstallSource = Boolean(options.sourceReleaseRoot || options.sourceUrl);
471
+ if (await pathExists(releaseRoot) && !options.force && !hasExplicitInstallSource) {
469
472
  await rewriteLocalToolchainPortablePaths(releaseRoot, latest.board_id);
470
473
  const validation = await validateLocalToolchain({ releaseRoot, mode: installMode, boardId: latest.board_id });
471
474
  if (!validation.ok) {
@@ -645,7 +648,7 @@ export async function windowsWslStatus() {
645
648
  result.usable = list.exit_code === 0 && result.distributions.length > 0;
646
649
  result.taishanpi_execution = taishanPiWindowsExecutionRoute(result.host, result);
647
650
  if (!result.usable) {
648
- result.notes.push("No usable WSL2 distribution is configured yet. Install Ubuntu, restart Windows if requested, then run Embed Labs TaishanPi tools inside WSL2.");
651
+ result.notes.push("No usable WSL2 distribution is configured yet. Install Ubuntu, restart Windows if requested, then run EmbedLabs TaishanPi tools inside WSL2.");
649
652
  }
650
653
  else {
651
654
  result.notes.push("Run TaishanPi local compile, Qt, and image tooling inside the listed WSL2 distribution. Native Windows TaishanPi toolchain packages are intentionally not published.");
@@ -769,7 +772,11 @@ export async function validateLocalToolchain(input) {
769
772
  const releaseRoot = typeof input === "string" ? input : input?.releaseRoot;
770
773
  const mode = normalizeLocalToolchainInstallMode(typeof input === "string" ? undefined : input?.mode);
771
774
  const boardId = normalizeBoardId(typeof input === "string" ? DEFAULT_BOARD_ID : input?.boardId ?? DEFAULT_BOARD_ID);
775
+ const repairPortablePaths = typeof input === "string" ? false : input?.repairPortablePaths === true;
772
776
  const resolvedRoot = await resolveLocalReleaseRoot(releaseRoot, boardId);
777
+ const repaired_path_files = repairPortablePaths
778
+ ? await rewriteLocalToolchainValidationPortablePaths(resolvedRoot, boardId)
779
+ : [];
773
780
  const required = requiredLocalToolchainChecks(mode, boardId);
774
781
  const checked_paths = [];
775
782
  for (const [label, relativePath] of required) {
@@ -783,11 +790,14 @@ export async function validateLocalToolchain(input) {
783
790
  const missing_paths = checked_paths.filter((item) => !item.exists).map((item) => item.path);
784
791
  const path_leaks = await localToolchainPathLeaks(resolvedRoot, boardId);
785
792
  const missing_groups = localToolchainMissingGroups(checked_paths, path_leaks);
786
- const repair_command = missing_paths.length > 0 || path_leaks.length > 0
793
+ const repair_command = missing_paths.length > 0
787
794
  ? `embedlabs local toolchain install --board ${boardId} --mode ${mode}`
788
- : undefined;
795
+ : path_leaks.length > 0
796
+ ? `embedlabs local toolchain validate --board ${boardId} --mode ${mode} --release-root ${resolvedRoot} --repair-portable-paths`
797
+ : undefined;
798
+ const ok = missing_paths.length === 0 && path_leaks.length === 0;
789
799
  return {
790
- ok: missing_paths.length === 0 && path_leaks.length === 0,
800
+ ok,
791
801
  mode,
792
802
  host: {
793
803
  platform: platform(),
@@ -798,18 +808,20 @@ export async function validateLocalToolchain(input) {
798
808
  checked_paths,
799
809
  missing_paths,
800
810
  path_leaks,
811
+ repaired_path_files: repaired_path_files.length > 0 ? repaired_path_files : undefined,
801
812
  missing_groups,
802
813
  repair_command,
803
814
  summary_for_user: localToolchainValidationSummary({
804
815
  boardId,
805
816
  mode,
806
- ok: missing_paths.length === 0,
817
+ ok,
807
818
  missingGroups: missing_groups,
808
819
  repairCommand: repair_command
809
820
  }),
810
821
  notes: [
811
- "Local build commands require an Embed Labs auth token so local resource use remains account attributable.",
812
- `This validator checks the ${boardId} local support layout for install mode ${mode}.`
822
+ "Local build commands run against the local installation identity and do not require an EmbedLabs platform account or platform API key.",
823
+ `This validator checks the ${boardId} local support layout for install mode ${mode}.`,
824
+ ...(repairPortablePaths ? [`Portable path repair rewrote ${repaired_path_files.length} file(s).`] : [])
813
825
  ]
814
826
  };
815
827
  }
@@ -824,6 +836,10 @@ function localToolchainMissingGroups(checkedPaths, pathLeaks = []) {
824
836
  }
825
837
  const label = check.label.toLowerCase();
826
838
  const text = `${check.label} ${check.path}`.toLowerCase();
839
+ if (text.includes("font")) {
840
+ groups.add("qt-fonts/板端中文字体");
841
+ continue;
842
+ }
827
843
  if (label.includes("qt ") || text.includes("qt host") || text.includes("qtquick") || text.includes("qt cmake") || text.includes("qt target")) {
828
844
  groups.add("qt/Qt host、target 或实时预览组件");
829
845
  continue;
@@ -868,6 +884,36 @@ async function rewriteLocalToolchainPortablePaths(releaseRoot, boardId) {
868
884
  }
869
885
  }
870
886
  }
887
+ async function rewriteLocalToolchainValidationPortablePaths(releaseRoot, boardId) {
888
+ if (normalizeBoardId(boardId) !== DEFAULT_BOARD_ID) {
889
+ return [];
890
+ }
891
+ const replacements = shouldRepairAsInstalledToolchainRoot(releaseRoot)
892
+ ? taishanPiPortablePathReplacements(releaseRoot)
893
+ : taishanPiPackagePortablePathReplacements(releaseRoot);
894
+ const files = await taishanPiPortableTextFiles(releaseRoot);
895
+ const rewrittenFiles = [];
896
+ for (const file of files) {
897
+ let content;
898
+ try {
899
+ content = await readFile(file, "utf8");
900
+ }
901
+ catch {
902
+ continue;
903
+ }
904
+ const rewritten = rewritePortablePathContent(content, replacements);
905
+ if (rewritten !== content) {
906
+ await writeFile(file, rewritten, "utf8");
907
+ rewrittenFiles.push(file);
908
+ }
909
+ }
910
+ return rewrittenFiles;
911
+ }
912
+ function shouldRepairAsInstalledToolchainRoot(releaseRoot) {
913
+ const normalizedRoot = resolve(releaseRoot);
914
+ const normalizedHomeToolchains = resolve(homedir(), ".embedlabs", "toolchains");
915
+ return normalizedRoot === normalizedHomeToolchains || normalizedRoot.startsWith(`${normalizedHomeToolchains}/`);
916
+ }
871
917
  async function localToolchainPathLeaks(releaseRoot, boardId) {
872
918
  if (normalizeBoardId(boardId) !== DEFAULT_BOARD_ID || !await pathExists(releaseRoot)) {
873
919
  return [];
@@ -956,11 +1002,11 @@ async function taishanPiPortableTextFiles(releaseRoot) {
956
1002
  ])
957
1003
  ])
958
1004
  ];
959
- const files = [];
1005
+ const files = new Set();
960
1006
  for (const candidate of candidates) {
961
1007
  const file = join(releaseRoot, candidate);
962
1008
  if (await pathExists(file)) {
963
- files.push(file);
1009
+ files.add(file);
964
1010
  }
965
1011
  }
966
1012
  for (const relativeDir of [
@@ -983,11 +1029,48 @@ async function taishanPiPortableTextFiles(releaseRoot) {
983
1029
  }
984
1030
  const file = join(dir, entry.name);
985
1031
  if ([".cmake", ".pri", ".pc", ".json"].includes(extname(file))) {
986
- files.push(file);
1032
+ files.add(file);
987
1033
  }
988
1034
  }
989
1035
  }
990
- return files;
1036
+ for (const relativeDir of [
1037
+ "qt-host",
1038
+ "qt-target",
1039
+ "toolchain",
1040
+ "scripts",
1041
+ "meta",
1042
+ "userdata/rootfs/display-modes"
1043
+ ]) {
1044
+ await collectTaishanPiPortableTextFiles(join(releaseRoot, relativeDir), files);
1045
+ }
1046
+ return [...files].sort();
1047
+ }
1048
+ async function collectTaishanPiPortableTextFiles(directory, files) {
1049
+ let entries;
1050
+ try {
1051
+ entries = await readdir(directory, { withFileTypes: true });
1052
+ }
1053
+ catch {
1054
+ return;
1055
+ }
1056
+ for (const entry of entries) {
1057
+ const candidate = join(directory, entry.name);
1058
+ if (entry.isDirectory()) {
1059
+ await collectTaishanPiPortableTextFiles(candidate, files);
1060
+ continue;
1061
+ }
1062
+ if (entry.isFile() && shouldRewriteTaishanPiPortableTextFile(candidate)) {
1063
+ files.add(candidate);
1064
+ }
1065
+ }
1066
+ }
1067
+ function shouldRewriteTaishanPiPortableTextFile(file) {
1068
+ const extension = extname(file).toLowerCase();
1069
+ if ([".cmake", ".pri", ".prl", ".pc", ".conf", ".la", ".spdx", ".txt", ".json", ".md", ".sh", ".sha256"].includes(extension)) {
1070
+ return true;
1071
+ }
1072
+ const name = basename(file).toLowerCase();
1073
+ return name === "qt-cmake" || name === "qt-cmake-private" || name === "qmake.conf" || name === "qdevice.pri" || name === "qmodule.pri";
991
1074
  }
992
1075
  function moduleToCmakeSuffix(module) {
993
1076
  const map = {
@@ -1012,6 +1095,7 @@ function taishanPiPortablePathReplacements(releaseRoot) {
1012
1095
  ["/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi/.llvm-cross", join(normalizedRoot, "toolchain", "llvm-cross")],
1013
1096
  ["/Volumes/LLVM-TSPI/tspi-rk3566-llvm-release-minimal", normalizedRoot],
1014
1097
  ["/Volumes/LLVM-TSPI/sdk-tools/buildroot/output/rockchip_rk3566/host", join(normalizedRoot, "toolchain", "host")],
1098
+ ["/Volumes/LLVM-TSPI/sdk-tools/userdata-template/qt6-rk3566", join(normalizedRoot, "userdata", "rootfs", "qt6-rk3566-llvm")],
1015
1099
  ["/Volumes/LLVM-TSPI/qt6-host-macos-6.8.3", join(normalizedRoot, "qt-host", "qt6-host-macos-6.8.3")],
1016
1100
  ["/home/ubuntu/embedlabs-qt/qt6-host-linux-x86_64-6.8.3", join(normalizedRoot, "qt-host", "qt6-host-linux-x86_64-6.8.3")],
1017
1101
  ["/Volumes/LLVM-TSPI/qt6-rk3566-llvm-6.8.3", join(normalizedRoot, "qt-target", "qt6-rk3566-llvm-6.8.3")],
@@ -1019,7 +1103,32 @@ function taishanPiPortablePathReplacements(releaseRoot) {
1019
1103
  ["/home/ubuntu/embedlabs-qt/qt-build-host-linux-x86_64-6.8.3", join(normalizedRoot, "qt-host", "qt6-host-linux-x86_64-6.8.3", ".build-info", "qt-build-host-linux-x86_64-6.8.3")],
1020
1104
  ["/Volumes/LLVM-TSPI/qt-build-rk3566-llvm-6.8.3", join(normalizedRoot, "qt-target", "qt6-rk3566-llvm-6.8.3", ".build-info", "qt-build-rk3566-llvm-6.8.3")],
1021
1105
  ["/Volumes/LLVM-TSPI/qt-everywhere-src-6.8.3", join(normalizedRoot, "meta", "source", "qt-everywhere-src-6.8.3")],
1022
- ["/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi", join(normalizedRoot, "meta", "source", "llvm-build-tspi")]
1106
+ ["/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi", join(normalizedRoot, "meta", "source", "llvm-build-tspi")],
1107
+ ["/Volumes/LLVM-TSPI/sdk-tools", join(normalizedRoot, "meta", "source", "sdk-tools")],
1108
+ ["/Volumes/LLVM-TSPI/qt-project/PalletizerQuick-rpi", join(normalizedRoot, "examples", "qt-smoke")]
1109
+ ];
1110
+ }
1111
+ function taishanPiPackagePortablePathReplacements(releaseRoot) {
1112
+ const normalizedRoot = resolve(releaseRoot);
1113
+ return [
1114
+ [normalizedRoot, "@EMBEDLABS_RELEASE_ROOT@"],
1115
+ ["/Volumes/LLVM-TSPI/tspi-rk3566-llvm-release-minimal", "@EMBEDLABS_RELEASE_ROOT@"],
1116
+ ["/Volumes/LLVM-TSPI/sdk-tools/scripts/qt6-rk3566-llvm-toolchain.cmake", "@EMBEDLABS_RELEASE_ROOT@/toolchain/qt6-rk3566-llvm-toolchain.cmake"],
1117
+ ["/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi/scripts/qt6-rk3566-llvm-toolchain.cmake", "@EMBEDLABS_RELEASE_ROOT@/toolchain/qt6-rk3566-llvm-toolchain.cmake"],
1118
+ ["/Volumes/LLVM-TSPI/sdk-tools/.llvm-cross", "@EMBEDLABS_RELEASE_ROOT@/toolchain/llvm-cross"],
1119
+ ["/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi/.llvm-cross", "@EMBEDLABS_RELEASE_ROOT@/toolchain/llvm-cross"],
1120
+ ["/Volumes/LLVM-TSPI/sdk-tools/buildroot/output/rockchip_rk3566/host", "@EMBEDLABS_RELEASE_ROOT@/toolchain/host"],
1121
+ ["/Volumes/LLVM-TSPI/sdk-tools/userdata-template/qt6-rk3566", "@EMBEDLABS_RELEASE_ROOT@/userdata/rootfs/qt6-rk3566-llvm"],
1122
+ ["/Volumes/LLVM-TSPI/qt6-host-macos-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/qt-host/qt6-host-macos-6.8.3"],
1123
+ ["/home/ubuntu/embedlabs-qt/qt6-host-linux-x86_64-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/qt-host/qt6-host-linux-x86_64-6.8.3"],
1124
+ ["/Volumes/LLVM-TSPI/qt6-rk3566-llvm-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/qt-target/qt6-rk3566-llvm-6.8.3"],
1125
+ ["/Volumes/LLVM-TSPI/qt-build-host-macos-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/qt-host/qt6-host-macos-6.8.3/.build-info/qt-build-host-macos-6.8.3"],
1126
+ ["/home/ubuntu/embedlabs-qt/qt-build-host-linux-x86_64-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/qt-host/qt6-host-linux-x86_64-6.8.3/.build-info/qt-build-host-linux-x86_64-6.8.3"],
1127
+ ["/Volumes/LLVM-TSPI/qt-build-rk3566-llvm-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/qt-target/qt6-rk3566-llvm-6.8.3/.build-info/qt-build-rk3566-llvm-6.8.3"],
1128
+ ["/Volumes/LLVM-TSPI/qt-everywhere-src-6.8.3", "@EMBEDLABS_RELEASE_ROOT@/meta/source/qt-everywhere-src-6.8.3"],
1129
+ ["/Users/kvell/kk-project/DBT-Agent-Project/llvm-build-tspi", "@EMBEDLABS_RELEASE_ROOT@/meta/source/llvm-build-tspi"],
1130
+ ["/Volumes/LLVM-TSPI/sdk-tools", "@EMBEDLABS_RELEASE_ROOT@/meta/source/sdk-tools"],
1131
+ ["/Volumes/LLVM-TSPI/qt-project/PalletizerQuick-rpi", "@EMBEDLABS_RELEASE_ROOT@/examples/qt-smoke"]
1023
1132
  ];
1024
1133
  }
1025
1134
  function taishanPiForbiddenPortablePathFragments() {
@@ -1126,6 +1235,12 @@ function requiredLocalToolchainChecks(mode, boardId) {
1126
1235
  ["Qt board runtime Bluetooth library", "userdata/rootfs/qt6-rk3566-llvm/lib/libQt6Bluetooth.so.6"],
1127
1236
  ["Qt board runtime Positioning library", "userdata/rootfs/qt6-rk3566-llvm/lib/libQt6Positioning.so.6"],
1128
1237
  ["Qt board runtime QML imports", "userdata/rootfs/qt6-rk3566-llvm/qml"],
1238
+ ["Qt board runtime fontconfig", "userdata/rootfs/qt6-rk3566-llvm/etc/fonts/fonts.conf"],
1239
+ ["Qt board Chinese font SimHei", "userdata/rootfs/usr/share/fonts/embedlabs/simhei.ttf"],
1240
+ ["Qt board Chinese font SimFang", "userdata/rootfs/usr/share/fonts/embedlabs/simfang.ttf"],
1241
+ ["Qt board Chinese font SimKai", "userdata/rootfs/usr/share/fonts/embedlabs/simkai.ttf"],
1242
+ ["Qt board Latin fallback font DejaVuSans", "userdata/rootfs/usr/share/fonts/embedlabs/DejaVuSans.ttf"],
1243
+ ["Qt board Latin fallback font DejaVuSans Bold", "userdata/rootfs/usr/share/fonts/embedlabs/DejaVuSans-Bold.ttf"],
1129
1244
  ["Qt smoke example", "examples/qt-smoke/CMakeLists.txt"],
1130
1245
  ["QtQuick live preview", "toolkit-runtime/qtquick-live-preview/bin/embed-qml-live-preview"]
1131
1246
  ];
@@ -1207,7 +1322,6 @@ function rp2350ArmToolchainDirName() {
1207
1322
  return "arm-gnu-toolchain-15.2.rel1-darwin-arm64-arm-none-eabi";
1208
1323
  }
1209
1324
  export async function compileTaishanPiSingleFile(options) {
1210
- assertAuthenticated(options.auth);
1211
1325
  if (platform() === "win32" && normalizeBoardId(options.boardId) === DEFAULT_BOARD_ID) {
1212
1326
  return await compileTaishanPiSingleFileWindowsWsl(options);
1213
1327
  }
@@ -1229,8 +1343,6 @@ export async function compileTaishanPiSingleFile(options) {
1229
1343
  boardId: options.boardId,
1230
1344
  operation: "local.compile.single_file",
1231
1345
  releaseRoot,
1232
- accountId: options.accountId,
1233
- auth: options.auth,
1234
1346
  sourcePath,
1235
1347
  artifactPath: outputPath,
1236
1348
  commands: [buildResult]
@@ -1267,15 +1379,12 @@ async function compileTaishanPiSingleFileWindowsWsl(options) {
1267
1379
  boardId: options.boardId,
1268
1380
  operation: "local.compile.single_file",
1269
1381
  releaseRoot,
1270
- accountId: options.accountId,
1271
- auth: options.auth,
1272
1382
  sourcePath,
1273
1383
  artifactPath: outputPath,
1274
1384
  commands: [buildResult]
1275
1385
  });
1276
1386
  }
1277
1387
  export async function buildTaishanPiQtSmoke(options) {
1278
- assertAuthenticated(options.auth);
1279
1388
  if (platform() === "win32") {
1280
1389
  return await buildTaishanPiQtSmokeWindowsWsl(options);
1281
1390
  }
@@ -1312,8 +1421,6 @@ export async function buildTaishanPiQtSmoke(options) {
1312
1421
  boardId: DEFAULT_BOARD_ID,
1313
1422
  operation: "local.build.qt_smoke",
1314
1423
  releaseRoot,
1315
- accountId: options.accountId,
1316
- auth: options.auth,
1317
1424
  sourcePath: sourceDir,
1318
1425
  buildDir,
1319
1426
  artifactPath,
@@ -1363,8 +1470,6 @@ async function buildTaishanPiQtSmokeWindowsWsl(options) {
1363
1470
  boardId: DEFAULT_BOARD_ID,
1364
1471
  operation: "local.build.qt_smoke",
1365
1472
  releaseRoot,
1366
- accountId: options.accountId,
1367
- auth: options.auth,
1368
1473
  sourcePath: sourceDir || sourceWslDir,
1369
1474
  buildDir,
1370
1475
  artifactPath,
@@ -1737,6 +1842,29 @@ function environmentNotes(input) {
1737
1842
  }
1738
1843
  return notes;
1739
1844
  }
1845
+ function compareLocalToolchainVersionLike(left, right) {
1846
+ if (!left && !right)
1847
+ return 0;
1848
+ if (!left)
1849
+ return -1;
1850
+ if (!right)
1851
+ return 1;
1852
+ if (left === right)
1853
+ return 0;
1854
+ const leftParts = localToolchainVersionParts(left);
1855
+ const rightParts = localToolchainVersionParts(right);
1856
+ const width = Math.max(leftParts.length, rightParts.length);
1857
+ for (let index = 0; index < width; index += 1) {
1858
+ const delta = (leftParts[index] ?? 0) - (rightParts[index] ?? 0);
1859
+ if (delta !== 0)
1860
+ return delta > 0 ? 1 : -1;
1861
+ }
1862
+ return left.localeCompare(right);
1863
+ }
1864
+ function localToolchainVersionParts(value) {
1865
+ const matches = value.match(/\d+/g);
1866
+ return matches?.map((item) => Number.parseInt(item, 10)).filter((item) => Number.isFinite(item)) ?? [];
1867
+ }
1740
1868
  function localToolchainInstallModesForDownload(download) {
1741
1869
  if (!download?.components?.length) {
1742
1870
  return [...LOCAL_TOOLCHAIN_INSTALL_MODES];
@@ -2519,8 +2647,9 @@ async function localCompileResult(input) {
2519
2647
  board_id: input.boardId,
2520
2648
  operation: input.operation,
2521
2649
  release_root: input.releaseRoot,
2522
- account_id: input.accountId,
2523
- auth: input.auth,
2650
+ execution_scope: "local_installation",
2651
+ identity_scope: "local_installation",
2652
+ uses_local_installation_identity: true,
2524
2653
  source_path: input.sourcePath,
2525
2654
  build_dir: input.buildDir,
2526
2655
  artifact_path: input.artifactPath,
@@ -2534,11 +2663,6 @@ async function localCompileResult(input) {
2534
2663
  await writeFile(manifestPath, `${JSON.stringify(result, null, 2)}\n`, "utf8");
2535
2664
  return result;
2536
2665
  }
2537
- function assertAuthenticated(auth) {
2538
- if (!auth.authenticated) {
2539
- throw new Error("Embed Labs auth is required for local toolchain builds. Run: embedlabs auth login --token <user-api-key>");
2540
- }
2541
- }
2542
2666
  async function runCommand(command, cwd, stdin) {
2543
2667
  return await new Promise((resolve) => {
2544
2668
  const child = spawn(command[0], command.slice(1), {