@camstack/system 1.2.469 → 1.2.471
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/addon-runner.js +97 -31
- package/dist/addon-runner.mjs +97 -31
- package/dist/addon-utils.mjs +1 -1
- package/dist/{agent-https-b-zX78oB.mjs → agent-https-DHBvFZJS.mjs} +1 -1
- package/dist/{agent-https-5OgOR-eF.js → agent-https-bH6bKDeK.js} +1 -1
- package/dist/auth/user-manager.d.ts +2 -2
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +4 -4
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +5 -5
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +5 -5
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-history/device-history.addon.js +1 -1
- package/dist/builtins/device-history/device-history.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +5 -5
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +10 -10
- package/dist/builtins/platform-probe/accelerator-reprobe.d.ts +23 -0
- package/dist/builtins/platform-probe/coral-accelerators.d.ts +50 -11
- package/dist/builtins/platform-probe/index.d.ts +17 -1
- package/dist/builtins/platform-probe/index.js +196 -12
- package/dist/builtins/platform-probe/index.mjs +202 -19
- package/dist/builtins/platform-probe/platform-scorer.d.ts +14 -0
- package/dist/builtins/record-entries/index.js +1 -1
- package/dist/builtins/record-entries/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +20 -20
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +3 -3
- package/dist/builtins/system-config/system-config.addon.mjs +115 -115
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-BGXTiUZm.js → composition-sources-B5uJZXZ1.js} +1 -1
- package/dist/{composition-sources-DTdzzyf0.mjs → composition-sources-DRw_vBKH.mjs} +1 -1
- package/dist/{constants-md_POijo.mjs → constants-5lA8Z9d8.mjs} +1 -1
- package/dist/{constants-2mPqJjkR.js → constants-CToE4OFp.js} +1 -1
- package/dist/{coral-accelerators-oUXmmbc2.js → coral-accelerators-BSVsBVzt.js} +102 -30
- package/dist/coral-accelerators-BW3OcrLD.mjs +231 -0
- package/dist/{custom-action-registry-DZSCLBuT.mjs → custom-action-registry-BGYDjTqY.mjs} +37 -37
- package/dist/{device-ca-CFdyrqeJ.mjs → device-ca-URrs1lxK.mjs} +1 -1
- package/dist/{device-ca-CC58lmNV.js → device-ca-nOCYVFS4.js} +1 -1
- package/dist/{dist-CtVVtyTX.mjs → dist-5XUG7iYJ.mjs} +6839 -1416
- package/dist/{dist-DuBtzSCh.js → dist-BjcWEfRy.js} +6839 -1416
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-BLsX_2cL.js → hub-mdns-ciao-vEWhJ_SD.js} +2 -2
- package/dist/{hub-mdns-ciao-CmuWLPci.mjs → hub-mdns-ciao-zD3JojB_.mjs} +2 -2
- package/dist/index.js +8 -8
- package/dist/index.mjs +225 -225
- package/dist/{restore-archive-CxPAuaNs.js → restore-archive-B64m2nAj.js} +1 -1
- package/dist/{restore-archive-D2w3z_ob.mjs → restore-archive-CN1pJTRn.mjs} +94 -94
- package/dist/{wal-maintenance-EK28XXnc.js → wal-maintenance-BNXVX-ot.js} +0 -0
- package/dist/{wal-maintenance-DeluFl_1.mjs → wal-maintenance-Bl2I-ZcR.mjs} +0 -0
- package/package.json +1 -1
- package/dist/coral-accelerators-Qhn5TOYZ.mjs +0 -165
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BjcWEfRy.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
const require_log_file_read_protocol = require("../../log-file-read-protocol-D0WcLbIV.js");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ln as logDestinationCapability, ei as BaseAddon } from "../../dist-
|
|
1
|
+
import { Ln as logDestinationCapability, ei as BaseAddon } from "../../dist-5XUG7iYJ.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
import { a as LogFileIndexStore, i as serveRead, n as isFromReader, t as CancelBook } from "../../log-file-read-protocol-B7M3X3bT.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $r as errMsg, Kr as compositionSourceKey } from "./dist-
|
|
1
|
+
import { $r as errMsg, Kr as compositionSourceKey } from "./dist-5XUG7iYJ.mjs";
|
|
2
2
|
//#region src/builtins/core-blocks/composition-sources.ts
|
|
3
3
|
/**
|
|
4
4
|
* Describe what a composition reads and writes for SAVE-time validation
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** `secret://system/global/meshCaKey` — EC P-256 PKCS#8 PEM of the hub mesh CA. */
|
|
2
|
-
var MESH_CA_KEY_REF = require("./dist-
|
|
2
|
+
var MESH_CA_KEY_REF = require("./dist-BjcWEfRy.js").buildSecretRef({
|
|
3
3
|
owner: "system",
|
|
4
4
|
scope: { kind: "global" },
|
|
5
5
|
fieldPath: "meshCaKey"
|
|
@@ -29,14 +29,34 @@ function currentDelegateHost() {
|
|
|
29
29
|
override: process.env[_camstack_types_node.EDGETPU_LIB_ENV]
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
/** usbfs names a device `/dev/bus/usb/<busnum>/<devnum>`, each zero-padded to three digits. */
|
|
33
|
+
function usbDeviceNode(device, fsx) {
|
|
34
|
+
const bus = Number.parseInt(fsx.readUsbAttr(device, "busnum"), 10);
|
|
35
|
+
const dev = Number.parseInt(fsx.readUsbAttr(device, "devnum"), 10);
|
|
36
|
+
if (!Number.isInteger(bus) || !Number.isInteger(dev) || bus <= 0 || dev <= 0) return null;
|
|
37
|
+
return `/dev/bus/usb/${String(bus).padStart(3, "0")}/${String(dev).padStart(3, "0")}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* USB units: sysfs is the HOST's view — a container whose `/dev/bus/usb`
|
|
41
|
+
* mapping was removed still lists the stick under `/sys/bus/usb/devices`. A
|
|
42
|
+
* listed Coral is usable only when its usbfs device node is in this process's
|
|
43
|
+
* view AND opens read/write; otherwise it is present but not accessible.
|
|
44
|
+
*/
|
|
45
|
+
function classifyUsb(devices, fsx) {
|
|
46
|
+
let usable = 0;
|
|
47
|
+
const inaccessibleNodes = [];
|
|
48
|
+
for (const device of devices) {
|
|
35
49
|
const vendor = fsx.readUsbAttr(device, "idVendor").toLowerCase();
|
|
36
50
|
const product = fsx.readUsbAttr(device, "idProduct").toLowerCase();
|
|
37
|
-
if (CORAL_USB_IDS.some((id) => id.vendor === vendor && id.product === product))
|
|
51
|
+
if (!CORAL_USB_IDS.some((id) => id.vendor === vendor && id.product === product)) continue;
|
|
52
|
+
const node = usbDeviceNode(device, fsx);
|
|
53
|
+
if (node !== null && fsx.exists(node) && fsx.canOpen(node)) usable++;
|
|
54
|
+
else inaccessibleNodes.push(node ?? `/sys/bus/usb/devices/${device}`);
|
|
38
55
|
}
|
|
39
|
-
return
|
|
56
|
+
return {
|
|
57
|
+
usable,
|
|
58
|
+
inaccessibleNodes
|
|
59
|
+
};
|
|
40
60
|
}
|
|
41
61
|
function countPciCorals(fsx) {
|
|
42
62
|
let count = 0;
|
|
@@ -70,32 +90,56 @@ function classifyPci(fsx) {
|
|
|
70
90
|
};
|
|
71
91
|
}
|
|
72
92
|
/**
|
|
73
|
-
* Detect Coral Edge TPUs on USB and PCIe/M.2.
|
|
93
|
+
* Detect Coral Edge TPUs on USB and PCIe/M.2 — the answer only. See
|
|
94
|
+
* {@link detectCoralAccelerator} for the evidence that decided it.
|
|
95
|
+
*/
|
|
96
|
+
function classifyCoralAccelerator(fsx, delegateHost = currentDelegateHost()) {
|
|
97
|
+
return detectCoralAccelerator(fsx, delegateHost).info;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Detect Coral Edge TPUs on USB and PCIe/M.2, with the evidence that decided.
|
|
74
101
|
*
|
|
75
|
-
* - USB: every matching USB device counts (multiple Corals run concurrently)
|
|
102
|
+
* - USB: every matching USB device counts (multiple Corals run concurrently),
|
|
103
|
+
* usable only if its `/dev/bus/usb/<BBB>/<DDD>` node opens read/write — a
|
|
104
|
+
* listed stick whose node is missing or refused is `device-not-accessible`.
|
|
76
105
|
* - PCIe: the apex driver's units, each usable only if its device node opens;
|
|
77
106
|
* a Coral PCI function the driver did not bind is `driver-missing`.
|
|
78
|
-
* - Fallback: when
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
107
|
+
* - Fallback: when the USB bus is NOT OBSERVABLE (`/sys/bus/usb/devices`
|
|
108
|
+
* missing, unreadable or empty — a macOS desktop, a restricted container)
|
|
109
|
+
* and no PCI Coral was seen, an installed libedgetpu delegate means one USB
|
|
110
|
+
* Coral is assumed. A bus that IS readable and lists no Coral id is the
|
|
111
|
+
* answer: no USB Coral. The delegate stays installed after a stick is
|
|
112
|
+
* unplugged or moved to another node, so it is evidence only where nothing
|
|
113
|
+
* better exists (D919).
|
|
82
114
|
*
|
|
83
115
|
* Returns `null` only when no Coral was found at all; a present-but-unusable
|
|
84
116
|
* Coral is reported with its typed reason, never as absent (D393/D315).
|
|
85
117
|
*/
|
|
86
|
-
function
|
|
87
|
-
const
|
|
118
|
+
function detectCoralAccelerator(fsx, delegateHost = currentDelegateHost()) {
|
|
119
|
+
const usbDevices = fsx.listUsbDevices();
|
|
120
|
+
const usbBus = usbDevices !== null && usbDevices.length > 0 ? "observed" : "unobservable";
|
|
121
|
+
const usb = usbDevices === null ? {
|
|
122
|
+
usable: 0,
|
|
123
|
+
inaccessibleNodes: []
|
|
124
|
+
} : classifyUsb(usbDevices, fsx);
|
|
125
|
+
const usbSeen = usb.usable + usb.inaccessibleNodes.length;
|
|
126
|
+
const inaccessibleUsbNodes = usb.inaccessibleNodes;
|
|
88
127
|
const pci = classifyPci(fsx);
|
|
89
128
|
const units = [];
|
|
90
|
-
if (usb > 0) units.push({
|
|
129
|
+
if (usb.usable > 0) units.push({
|
|
91
130
|
bus: "usb",
|
|
92
|
-
count: usb
|
|
131
|
+
count: usb.usable
|
|
93
132
|
});
|
|
94
133
|
if (pci.usable > 0) units.push({
|
|
95
134
|
bus: "pci",
|
|
96
135
|
count: pci.usable
|
|
97
136
|
});
|
|
98
137
|
const unavailable = [];
|
|
138
|
+
if (usb.inaccessibleNodes.length > 0) unavailable.push({
|
|
139
|
+
bus: "usb",
|
|
140
|
+
count: usb.inaccessibleNodes.length,
|
|
141
|
+
reason: "device-not-accessible"
|
|
142
|
+
});
|
|
99
143
|
if (pci.driverMissing > 0) unavailable.push({
|
|
100
144
|
bus: "pci",
|
|
101
145
|
count: pci.driverMissing,
|
|
@@ -106,25 +150,47 @@ function classifyCoralAccelerator(fsx, delegateHost = currentDelegateHost()) {
|
|
|
106
150
|
count: pci.notAccessible,
|
|
107
151
|
reason: "device-not-accessible"
|
|
108
152
|
});
|
|
109
|
-
if (units.length > 0 || unavailable.length > 0) return
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
153
|
+
if (units.length > 0 || unavailable.length > 0) return {
|
|
154
|
+
info: unavailable.length > 0 ? {
|
|
155
|
+
type: "coral-edgetpu",
|
|
156
|
+
units,
|
|
157
|
+
unavailable
|
|
158
|
+
} : {
|
|
159
|
+
type: "coral-edgetpu",
|
|
160
|
+
units
|
|
161
|
+
},
|
|
162
|
+
usbBus,
|
|
163
|
+
decidedBy: usbSeen > 0 ? "usb-ids" : "pci",
|
|
164
|
+
inaccessibleUsbNodes
|
|
116
165
|
};
|
|
117
|
-
if ((0, _camstack_types_node.chooseEdgetpuDelegate)({
|
|
166
|
+
if (usbBus === "unobservable" && (0, _camstack_types_node.chooseEdgetpuDelegate)({
|
|
118
167
|
...delegateHost,
|
|
119
168
|
exists: (p) => fsx.exists(p)
|
|
120
169
|
}) !== null) return {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
170
|
+
info: {
|
|
171
|
+
type: "coral-edgetpu",
|
|
172
|
+
units: [{
|
|
173
|
+
bus: "usb",
|
|
174
|
+
count: 1
|
|
175
|
+
}]
|
|
176
|
+
},
|
|
177
|
+
usbBus,
|
|
178
|
+
decidedBy: "delegate-fallback",
|
|
179
|
+
inaccessibleUsbNodes
|
|
126
180
|
};
|
|
127
|
-
return
|
|
181
|
+
return {
|
|
182
|
+
info: null,
|
|
183
|
+
usbBus,
|
|
184
|
+
decidedBy: "none",
|
|
185
|
+
inaccessibleUsbNodes
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function safeListOrNull(dir) {
|
|
189
|
+
try {
|
|
190
|
+
return node_fs.default.readdirSync(dir);
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
128
194
|
}
|
|
129
195
|
function safeList(dir) {
|
|
130
196
|
try {
|
|
@@ -142,7 +208,7 @@ function safeRead(path) {
|
|
|
142
208
|
}
|
|
143
209
|
/** The real filesystem view: `/sys` for enumeration, `/dev` for access. */
|
|
144
210
|
var nodeCoralFs = {
|
|
145
|
-
listUsbDevices: () =>
|
|
211
|
+
listUsbDevices: () => safeListOrNull("/sys/bus/usb/devices"),
|
|
146
212
|
readUsbAttr: (device, attr) => safeRead(`/sys/bus/usb/devices/${device}/${attr}`),
|
|
147
213
|
listPciDevices: () => safeList("/sys/bus/pci/devices"),
|
|
148
214
|
readPciAttr: (device, attr) => safeRead(`/sys/bus/pci/devices/${device}/${attr}`),
|
|
@@ -170,6 +236,12 @@ Object.defineProperty(exports, "classifyCoralAccelerator", {
|
|
|
170
236
|
return classifyCoralAccelerator;
|
|
171
237
|
}
|
|
172
238
|
});
|
|
239
|
+
Object.defineProperty(exports, "detectCoralAccelerator", {
|
|
240
|
+
enumerable: true,
|
|
241
|
+
get: function() {
|
|
242
|
+
return detectCoralAccelerator;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
173
245
|
Object.defineProperty(exports, "nodeCoralFs", {
|
|
174
246
|
enumerable: true,
|
|
175
247
|
get: function() {
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { EDGETPU_LIB_ENV, chooseEdgetpuDelegate, nodeDataRootFromEnv } from "@camstack/types/node";
|
|
2
|
+
import Kt from "node:fs";
|
|
3
|
+
//#region src/builtins/platform-probe/coral-accelerators.ts
|
|
4
|
+
/**
|
|
5
|
+
* Coral USB Edge TPU USB identifiers.
|
|
6
|
+
*
|
|
7
|
+
* The device enumerates as `1a6e:089a` (Global Unichip) BEFORE the libedgetpu
|
|
8
|
+
* firmware loads, then re-enumerates as `18d1:9302` (Google) AFTER. Either id
|
|
9
|
+
* means a Coral is physically attached, so both count as a positive signal.
|
|
10
|
+
*/
|
|
11
|
+
var CORAL_USB_IDS = [{
|
|
12
|
+
vendor: "1a6e",
|
|
13
|
+
product: "089a"
|
|
14
|
+
}, {
|
|
15
|
+
vendor: "18d1",
|
|
16
|
+
product: "9302"
|
|
17
|
+
}];
|
|
18
|
+
/** The PCIe / M.2 Coral's PCI function id (Global Unichip "Apex"). */
|
|
19
|
+
var CORAL_PCI_VENDOR = "0x1ac1";
|
|
20
|
+
var CORAL_PCI_DEVICE = "0x089a";
|
|
21
|
+
/** A unit the apex driver bound: `/sys/class/apex/apex_<N>` ↔ `/dev/apex_<N>`. */
|
|
22
|
+
var APEX_ENTRY = /^apex_(\d+)$/;
|
|
23
|
+
function currentDelegateHost() {
|
|
24
|
+
return {
|
|
25
|
+
platform: process.platform,
|
|
26
|
+
dataDir: nodeDataRootFromEnv(process.env),
|
|
27
|
+
override: process.env[EDGETPU_LIB_ENV]
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** usbfs names a device `/dev/bus/usb/<busnum>/<devnum>`, each zero-padded to three digits. */
|
|
31
|
+
function usbDeviceNode(device, fsx) {
|
|
32
|
+
const bus = Number.parseInt(fsx.readUsbAttr(device, "busnum"), 10);
|
|
33
|
+
const dev = Number.parseInt(fsx.readUsbAttr(device, "devnum"), 10);
|
|
34
|
+
if (!Number.isInteger(bus) || !Number.isInteger(dev) || bus <= 0 || dev <= 0) return null;
|
|
35
|
+
return `/dev/bus/usb/${String(bus).padStart(3, "0")}/${String(dev).padStart(3, "0")}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* USB units: sysfs is the HOST's view — a container whose `/dev/bus/usb`
|
|
39
|
+
* mapping was removed still lists the stick under `/sys/bus/usb/devices`. A
|
|
40
|
+
* listed Coral is usable only when its usbfs device node is in this process's
|
|
41
|
+
* view AND opens read/write; otherwise it is present but not accessible.
|
|
42
|
+
*/
|
|
43
|
+
function classifyUsb(devices, fsx) {
|
|
44
|
+
let usable = 0;
|
|
45
|
+
const inaccessibleNodes = [];
|
|
46
|
+
for (const device of devices) {
|
|
47
|
+
const vendor = fsx.readUsbAttr(device, "idVendor").toLowerCase();
|
|
48
|
+
const product = fsx.readUsbAttr(device, "idProduct").toLowerCase();
|
|
49
|
+
if (!CORAL_USB_IDS.some((id) => id.vendor === vendor && id.product === product)) continue;
|
|
50
|
+
const node = usbDeviceNode(device, fsx);
|
|
51
|
+
if (node !== null && fsx.exists(node) && fsx.canOpen(node)) usable++;
|
|
52
|
+
else inaccessibleNodes.push(node ?? `/sys/bus/usb/devices/${device}`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
usable,
|
|
56
|
+
inaccessibleNodes
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function countPciCorals(fsx) {
|
|
60
|
+
let count = 0;
|
|
61
|
+
for (const device of fsx.listPciDevices()) {
|
|
62
|
+
const vendor = fsx.readPciAttr(device, "vendor").toLowerCase();
|
|
63
|
+
const product = fsx.readPciAttr(device, "device").toLowerCase();
|
|
64
|
+
if (vendor === CORAL_PCI_VENDOR && product === CORAL_PCI_DEVICE) count++;
|
|
65
|
+
}
|
|
66
|
+
return count;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* PCIe units: each `/sys/class/apex/apex_N` is a unit the driver bound; it is
|
|
70
|
+
* usable only when `/dev/apex_N` is in this process's view AND opens read/write.
|
|
71
|
+
* PCI functions with the Coral id beyond the bound units have no driver.
|
|
72
|
+
*/
|
|
73
|
+
function classifyPci(fsx) {
|
|
74
|
+
let usable = 0;
|
|
75
|
+
let notAccessible = 0;
|
|
76
|
+
for (const entry of fsx.listApexClass()) {
|
|
77
|
+
const match = APEX_ENTRY.exec(entry);
|
|
78
|
+
if (match === null) continue;
|
|
79
|
+
const node = `/dev/apex_${match[1]}`;
|
|
80
|
+
if (fsx.exists(node) && fsx.canOpen(node)) usable++;
|
|
81
|
+
else notAccessible++;
|
|
82
|
+
}
|
|
83
|
+
const driverMissing = Math.max(0, countPciCorals(fsx) - usable - notAccessible);
|
|
84
|
+
return {
|
|
85
|
+
usable,
|
|
86
|
+
notAccessible,
|
|
87
|
+
driverMissing
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Detect Coral Edge TPUs on USB and PCIe/M.2 — the answer only. See
|
|
92
|
+
* {@link detectCoralAccelerator} for the evidence that decided it.
|
|
93
|
+
*/
|
|
94
|
+
function classifyCoralAccelerator(fsx, delegateHost = currentDelegateHost()) {
|
|
95
|
+
return detectCoralAccelerator(fsx, delegateHost).info;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Detect Coral Edge TPUs on USB and PCIe/M.2, with the evidence that decided.
|
|
99
|
+
*
|
|
100
|
+
* - USB: every matching USB device counts (multiple Corals run concurrently),
|
|
101
|
+
* usable only if its `/dev/bus/usb/<BBB>/<DDD>` node opens read/write — a
|
|
102
|
+
* listed stick whose node is missing or refused is `device-not-accessible`.
|
|
103
|
+
* - PCIe: the apex driver's units, each usable only if its device node opens;
|
|
104
|
+
* a Coral PCI function the driver did not bind is `driver-missing`.
|
|
105
|
+
* - Fallback: when the USB bus is NOT OBSERVABLE (`/sys/bus/usb/devices`
|
|
106
|
+
* missing, unreadable or empty — a macOS desktop, a restricted container)
|
|
107
|
+
* and no PCI Coral was seen, an installed libedgetpu delegate means one USB
|
|
108
|
+
* Coral is assumed. A bus that IS readable and lists no Coral id is the
|
|
109
|
+
* answer: no USB Coral. The delegate stays installed after a stick is
|
|
110
|
+
* unplugged or moved to another node, so it is evidence only where nothing
|
|
111
|
+
* better exists (D919).
|
|
112
|
+
*
|
|
113
|
+
* Returns `null` only when no Coral was found at all; a present-but-unusable
|
|
114
|
+
* Coral is reported with its typed reason, never as absent (D393/D315).
|
|
115
|
+
*/
|
|
116
|
+
function detectCoralAccelerator(fsx, delegateHost = currentDelegateHost()) {
|
|
117
|
+
const usbDevices = fsx.listUsbDevices();
|
|
118
|
+
const usbBus = usbDevices !== null && usbDevices.length > 0 ? "observed" : "unobservable";
|
|
119
|
+
const usb = usbDevices === null ? {
|
|
120
|
+
usable: 0,
|
|
121
|
+
inaccessibleNodes: []
|
|
122
|
+
} : classifyUsb(usbDevices, fsx);
|
|
123
|
+
const usbSeen = usb.usable + usb.inaccessibleNodes.length;
|
|
124
|
+
const inaccessibleUsbNodes = usb.inaccessibleNodes;
|
|
125
|
+
const pci = classifyPci(fsx);
|
|
126
|
+
const units = [];
|
|
127
|
+
if (usb.usable > 0) units.push({
|
|
128
|
+
bus: "usb",
|
|
129
|
+
count: usb.usable
|
|
130
|
+
});
|
|
131
|
+
if (pci.usable > 0) units.push({
|
|
132
|
+
bus: "pci",
|
|
133
|
+
count: pci.usable
|
|
134
|
+
});
|
|
135
|
+
const unavailable = [];
|
|
136
|
+
if (usb.inaccessibleNodes.length > 0) unavailable.push({
|
|
137
|
+
bus: "usb",
|
|
138
|
+
count: usb.inaccessibleNodes.length,
|
|
139
|
+
reason: "device-not-accessible"
|
|
140
|
+
});
|
|
141
|
+
if (pci.driverMissing > 0) unavailable.push({
|
|
142
|
+
bus: "pci",
|
|
143
|
+
count: pci.driverMissing,
|
|
144
|
+
reason: "driver-missing"
|
|
145
|
+
});
|
|
146
|
+
if (pci.notAccessible > 0) unavailable.push({
|
|
147
|
+
bus: "pci",
|
|
148
|
+
count: pci.notAccessible,
|
|
149
|
+
reason: "device-not-accessible"
|
|
150
|
+
});
|
|
151
|
+
if (units.length > 0 || unavailable.length > 0) return {
|
|
152
|
+
info: unavailable.length > 0 ? {
|
|
153
|
+
type: "coral-edgetpu",
|
|
154
|
+
units,
|
|
155
|
+
unavailable
|
|
156
|
+
} : {
|
|
157
|
+
type: "coral-edgetpu",
|
|
158
|
+
units
|
|
159
|
+
},
|
|
160
|
+
usbBus,
|
|
161
|
+
decidedBy: usbSeen > 0 ? "usb-ids" : "pci",
|
|
162
|
+
inaccessibleUsbNodes
|
|
163
|
+
};
|
|
164
|
+
if (usbBus === "unobservable" && chooseEdgetpuDelegate({
|
|
165
|
+
...delegateHost,
|
|
166
|
+
exists: (p) => fsx.exists(p)
|
|
167
|
+
}) !== null) return {
|
|
168
|
+
info: {
|
|
169
|
+
type: "coral-edgetpu",
|
|
170
|
+
units: [{
|
|
171
|
+
bus: "usb",
|
|
172
|
+
count: 1
|
|
173
|
+
}]
|
|
174
|
+
},
|
|
175
|
+
usbBus,
|
|
176
|
+
decidedBy: "delegate-fallback",
|
|
177
|
+
inaccessibleUsbNodes
|
|
178
|
+
};
|
|
179
|
+
return {
|
|
180
|
+
info: null,
|
|
181
|
+
usbBus,
|
|
182
|
+
decidedBy: "none",
|
|
183
|
+
inaccessibleUsbNodes
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function safeListOrNull(dir) {
|
|
187
|
+
try {
|
|
188
|
+
return Kt.readdirSync(dir);
|
|
189
|
+
} catch {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function safeList(dir) {
|
|
194
|
+
try {
|
|
195
|
+
return Kt.readdirSync(dir);
|
|
196
|
+
} catch {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function safeRead(path) {
|
|
201
|
+
try {
|
|
202
|
+
return Kt.readFileSync(path, "utf8").trim();
|
|
203
|
+
} catch {
|
|
204
|
+
return "";
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/** The real filesystem view: `/sys` for enumeration, `/dev` for access. */
|
|
208
|
+
var nodeCoralFs = {
|
|
209
|
+
listUsbDevices: () => safeListOrNull("/sys/bus/usb/devices"),
|
|
210
|
+
readUsbAttr: (device, attr) => safeRead(`/sys/bus/usb/devices/${device}/${attr}`),
|
|
211
|
+
listPciDevices: () => safeList("/sys/bus/pci/devices"),
|
|
212
|
+
readPciAttr: (device, attr) => safeRead(`/sys/bus/pci/devices/${device}/${attr}`),
|
|
213
|
+
listApexClass: () => safeList("/sys/class/apex"),
|
|
214
|
+
canOpen: (path) => {
|
|
215
|
+
try {
|
|
216
|
+
Kt.accessSync(path, Kt.constants.R_OK | Kt.constants.W_OK);
|
|
217
|
+
return true;
|
|
218
|
+
} catch {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
exists: (path) => {
|
|
223
|
+
try {
|
|
224
|
+
return Kt.existsSync(path);
|
|
225
|
+
} catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
//#endregion
|
|
231
|
+
export { detectCoralAccelerator as n, nodeCoralFs as r, classifyCoralAccelerator as t };
|