@stelis/agent-q-core 0.0.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.
Files changed (47) hide show
  1. package/README.md +144 -0
  2. package/dist/adapter-internal.d.ts +5 -0
  3. package/dist/adapter-internal.js +6 -0
  4. package/dist/adapter-internal.js.map +1 -0
  5. package/dist/config.d.ts +74 -0
  6. package/dist/config.js +489 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/core.d.ts +320 -0
  9. package/dist/core.js +840 -0
  10. package/dist/core.js.map +1 -0
  11. package/dist/device.d.ts +55 -0
  12. package/dist/device.js +23 -0
  13. package/dist/device.js.map +1 -0
  14. package/dist/errors.d.ts +6 -0
  15. package/dist/errors.js +20 -0
  16. package/dist/errors.js.map +1 -0
  17. package/dist/host-output-schema.d.ts +2437 -0
  18. package/dist/host-output-schema.js +655 -0
  19. package/dist/host-output-schema.js.map +1 -0
  20. package/dist/protocol-error.d.ts +4 -0
  21. package/dist/protocol-error.js +9 -0
  22. package/dist/protocol-error.js.map +1 -0
  23. package/dist/protocol-management-primitives.d.ts +27 -0
  24. package/dist/protocol-management-primitives.js +51 -0
  25. package/dist/protocol-management-primitives.js.map +1 -0
  26. package/dist/protocol-primitives.d.ts +53 -0
  27. package/dist/protocol-primitives.js +331 -0
  28. package/dist/protocol-primitives.js.map +1 -0
  29. package/dist/protocol.d.ts +207 -0
  30. package/dist/protocol.js +897 -0
  31. package/dist/protocol.js.map +1 -0
  32. package/dist/provider-protocol.d.ts +262 -0
  33. package/dist/provider-protocol.js +637 -0
  34. package/dist/provider-protocol.js.map +1 -0
  35. package/dist/public-error.d.ts +9 -0
  36. package/dist/public-error.js +79 -0
  37. package/dist/public-error.js.map +1 -0
  38. package/dist/safe-text.d.ts +31 -0
  39. package/dist/safe-text.js +143 -0
  40. package/dist/safe-text.js.map +1 -0
  41. package/dist/transport-invariants.d.ts +18 -0
  42. package/dist/transport-invariants.js +24 -0
  43. package/dist/transport-invariants.js.map +1 -0
  44. package/dist/usb.d.ts +76 -0
  45. package/dist/usb.js +454 -0
  46. package/dist/usb.js.map +1 -0
  47. package/package.json +58 -0
package/dist/config.js ADDED
@@ -0,0 +1,489 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { sanitizeDeviceStatusSnapshot, } from "./protocol.js";
5
+ import { MAX_LABEL_LENGTH, PURPOSE_PATTERN, RESERVED_PURPOSES, isIsoTimestamp, isSafeDeviceId, isValidLabel, isValidPurpose, sanitizePortHint, } from "./safe-text.js";
6
+ export const CONFIG_SCHEMA_VERSION = 0;
7
+ // The label/purpose policy is defined once in safe-text.ts (the single source of
8
+ // truth) and re-exported here so existing importers and tests continue to
9
+ // resolve these symbols through config.ts.
10
+ export { MAX_LABEL_LENGTH, PURPOSE_PATTERN, RESERVED_PURPOSES, isValidLabel, isValidPurpose };
11
+ // Unknown-timestamp sentinel. A stored lastSeenAt that is missing or malformed is
12
+ // coerced to the Unix epoch so the field always reaches MCP output as a valid ISO
13
+ // instant. The epoch is a deliberate "unknown / not recently observed" marker:
14
+ // Agent-Q does not invent a plausible current time (a false observation), and it
15
+ // does not drop the device for a bad display-only timestamp.
16
+ const EPOCH_ISO = "1970-01-01T00:00:00.000Z";
17
+ export class ConfigError extends Error {
18
+ code;
19
+ constructor(code, message) {
20
+ super(message);
21
+ this.name = "ConfigError";
22
+ this.code = code;
23
+ }
24
+ }
25
+ export function defaultAgentQConfig() {
26
+ return {
27
+ schemaVersion: CONFIG_SCHEMA_VERSION,
28
+ activeDeviceId: null,
29
+ activeDeviceIdsByPurpose: {},
30
+ devices: [],
31
+ };
32
+ }
33
+ export function getConfigPath(options = {}) {
34
+ const env = options.env ?? process.env;
35
+ const base = env.XDG_CONFIG_HOME && env.XDG_CONFIG_HOME.length > 0
36
+ ? env.XDG_CONFIG_HOME
37
+ : join(options.homeDir ?? homedir(), ".config");
38
+ return join(base, "agent-q", "config.json");
39
+ }
40
+ export class ConfigStore {
41
+ path;
42
+ constructor(path = getConfigPath()) {
43
+ this.path = path;
44
+ }
45
+ // Raw content last warned about, so repeated loads of the same unchanged
46
+ // (hand-edited) config do not re-emit the normalization warning.
47
+ lastWarnedRaw = null;
48
+ async load() {
49
+ try {
50
+ const raw = await readFile(this.path, "utf8");
51
+ const parsed = JSON.parse(raw);
52
+ const normalized = normalizeAgentQConfig(parsed);
53
+ if (normalized !== undefined) {
54
+ // One pipeline produces the config AND the report; every transformation it
55
+ // performs increments the report (guarded by the per-field tests and the
56
+ // fixpoint test), so the warning reflects what was actually changed.
57
+ this.maybeWarnNormalized(raw, normalized.report);
58
+ return normalized.config;
59
+ }
60
+ // Structurally invalid but valid JSON: do not silently overwrite without
61
+ // surfacing it. stderr is safe here; stdout is the MCP JSON-RPC channel.
62
+ // The interpolated path is operator-controlled local config (from
63
+ // getConfigPath or the embedding caller), not untrusted request/device
64
+ // text, so unlike a device/Firmware string it is logged as-is to stay
65
+ // useful for debugging.
66
+ console.warn(`agent-q: config at ${this.path} is not a recognized schema; using defaults.`);
67
+ return defaultAgentQConfig();
68
+ }
69
+ catch (error) {
70
+ if (isNodeError(error) && error.code === "ENOENT") {
71
+ return defaultAgentQConfig();
72
+ }
73
+ if (error instanceof SyntaxError) {
74
+ console.warn(`agent-q: config at ${this.path} is not valid JSON; using defaults.`);
75
+ return defaultAgentQConfig();
76
+ }
77
+ throw error;
78
+ }
79
+ }
80
+ // The single disk-write boundary. It re-runs the same normalization pipeline
81
+ // used on load, so the file on disk can never hold an unsafe record or a
82
+ // dangling route regardless of how the caller built the in-memory config — the
83
+ // boundary enforces the SoT itself rather than trusting callers. Private:
84
+ // callers mutate config only through the methods above.
85
+ async writeConfig(config) {
86
+ const normalized = normalizeAgentQConfig(config);
87
+ if (normalized === undefined) {
88
+ // Unreachable: writeConfig only ever receives a current-schema config built by
89
+ // this store. Fail loudly rather than silently writing defaults (which
90
+ // would drop data) if that assumption ever breaks.
91
+ throw new ConfigError("internal_output_error", "Refusing to write an unrecognized config shape.");
92
+ }
93
+ await mkdir(dirname(this.path), { recursive: true });
94
+ await writeFile(this.path, `${JSON.stringify(normalized.config, null, 2)}\n`, "utf8");
95
+ }
96
+ // One aggregated stderr warning when stored config was normalized, deduped by
97
+ // raw content so a persistent hand-edited file does not warn on every load.
98
+ // Only counts are logged, never a raw (possibly unsafe) value.
99
+ maybeWarnNormalized(rawContent, report) {
100
+ if (reportTotal(report) === 0 || rawContent === this.lastWarnedRaw) {
101
+ return;
102
+ }
103
+ this.lastWarnedRaw = rawContent;
104
+ console.warn(`agent-q: normalized stored config (droppedRecords=${report.droppedRecords}, ` +
105
+ `droppedRoutes=${report.droppedRoutes}, clearedActiveDeviceId=${report.clearedActiveDeviceId}, ` +
106
+ `coercedLabels=${report.coercedLabels}, coercedTimestamps=${report.coercedTimestamps}, ` +
107
+ `sanitizedDeviceDisplayText=${report.sanitizedDeviceDisplayText}, ` +
108
+ `sanitizedPortHints=${report.sanitizedPortHints}).`);
109
+ }
110
+ async listDevices() {
111
+ const config = await this.load();
112
+ return config.devices.map((record) => toDeviceListing(record, config));
113
+ }
114
+ async rememberUsbStatus(status, portPath, options = {}) {
115
+ const config = await this.load();
116
+ const lastSeenAt = (options.observedAt ?? new Date()).toISOString();
117
+ // portPath is an OS-supplied diagnostic string; sanitize it before it is
118
+ // stored and later surfaced as lastPortHint in MCP output.
119
+ const lastPortHint = sanitizePortHint(portPath);
120
+ // Defensive: callers pass a wire-parsed (already sanitized) status, but the
121
+ // write boundary re-applies the same policy so the stored registry can never
122
+ // hold an unsafe identity, invalid provisioning state, or unsanitized display
123
+ // string.
124
+ const safeStatus = sanitizeDeviceStatusSnapshot(status);
125
+ if (safeStatus === null) {
126
+ throw new ConfigError("invalid_device", "Refusing to store a device with an unsafe identity.");
127
+ }
128
+ const safeDevice = safeStatus.device;
129
+ const index = config.devices.findIndex((candidate) => candidate.deviceId === safeDevice.deviceId);
130
+ if (index >= 0) {
131
+ // Status refresh must not wipe local metadata such as label.
132
+ const existing = config.devices[index];
133
+ config.devices[index] = {
134
+ ...existing,
135
+ transport: "usb",
136
+ lastPortHint,
137
+ lastSeenAt,
138
+ lastStatus: safeStatus,
139
+ };
140
+ }
141
+ else {
142
+ config.devices.push({
143
+ deviceId: safeDevice.deviceId,
144
+ transport: "usb",
145
+ lastPortHint,
146
+ lastSeenAt,
147
+ label: null,
148
+ lastStatus: safeStatus,
149
+ });
150
+ }
151
+ if (options.setActive === true) {
152
+ config.activeDeviceId = safeDevice.deviceId;
153
+ }
154
+ await this.writeConfig(config);
155
+ return config;
156
+ }
157
+ async setDeviceMetadata(input) {
158
+ if (!isSafeDeviceId(input.deviceId)) {
159
+ throw new ConfigError("invalid_device_id", "deviceId is not a valid device identifier.");
160
+ }
161
+ if (!Object.prototype.hasOwnProperty.call(input, "label")) {
162
+ throw new ConfigError("invalid_metadata", "set_device_metadata requires at least one metadata field.");
163
+ }
164
+ if (!isValidLabel(input.label)) {
165
+ throw new ConfigError("invalid_label", `label must be null or a 1-${MAX_LABEL_LENGTH} character string.`);
166
+ }
167
+ const config = await this.load();
168
+ const index = config.devices.findIndex((candidate) => candidate.deviceId === input.deviceId);
169
+ if (index < 0) {
170
+ throw new ConfigError("device_not_found", "Device is not known to Agent-Q.");
171
+ }
172
+ const record = {
173
+ ...config.devices[index],
174
+ label: input.label ?? null,
175
+ };
176
+ config.devices[index] = record;
177
+ await this.writeConfig(config);
178
+ return record;
179
+ }
180
+ async setActiveDevice(deviceId, purpose) {
181
+ if (!isSafeDeviceId(deviceId)) {
182
+ throw new ConfigError("invalid_device_id", "deviceId is not a valid device identifier.");
183
+ }
184
+ if (purpose !== undefined) {
185
+ if (RESERVED_PURPOSES.has(purpose)) {
186
+ throw new ConfigError("reserved_purpose", `purpose '${purpose}' is reserved. Omit purpose to set the default device.`);
187
+ }
188
+ if (!isValidPurpose(purpose)) {
189
+ throw new ConfigError("invalid_purpose", "purpose must be 1-32 characters of [A-Za-z0-9_.-].");
190
+ }
191
+ }
192
+ const config = await this.load();
193
+ const record = config.devices.find((candidate) => candidate.deviceId === deviceId);
194
+ if (record === undefined) {
195
+ throw new ConfigError("device_not_found", "Device is not known to Agent-Q.");
196
+ }
197
+ if (purpose === undefined) {
198
+ config.activeDeviceId = deviceId;
199
+ }
200
+ else {
201
+ config.activeDeviceIdsByPurpose[purpose] = deviceId;
202
+ }
203
+ await this.writeConfig(config);
204
+ return record;
205
+ }
206
+ async getActiveDevice(purpose) {
207
+ if (purpose !== undefined && RESERVED_PURPOSES.has(purpose)) {
208
+ throw new ConfigError("reserved_purpose", `purpose '${purpose}' is reserved. Omit purpose to read the default device.`);
209
+ }
210
+ if (purpose !== undefined && !isValidPurpose(purpose)) {
211
+ throw new ConfigError("invalid_purpose", "purpose must be 1-32 characters of [A-Za-z0-9_.-].");
212
+ }
213
+ const config = await this.load();
214
+ // Read the purpose map with an own-property lookup so an inherited name (for
215
+ // example "toString" or "hasOwnProperty") can never resolve to a prototype
216
+ // value instead of an actual routing entry.
217
+ const deviceId = purpose === undefined
218
+ ? config.activeDeviceId
219
+ : Object.prototype.hasOwnProperty.call(config.activeDeviceIdsByPurpose, purpose)
220
+ ? config.activeDeviceIdsByPurpose[purpose]
221
+ : undefined;
222
+ if (deviceId === null || deviceId === undefined || deviceId.length === 0) {
223
+ return undefined;
224
+ }
225
+ return config.devices.find((candidate) => candidate.deviceId === deviceId);
226
+ }
227
+ }
228
+ function toDeviceListing(record, config) {
229
+ const assignedPurposes = Object.entries(config.activeDeviceIdsByPurpose)
230
+ .filter(([, deviceId]) => deviceId === record.deviceId)
231
+ .map(([purpose]) => purpose)
232
+ .sort();
233
+ return {
234
+ deviceId: record.deviceId,
235
+ transport: record.transport,
236
+ lastPortHint: record.lastPortHint,
237
+ lastSeenAt: record.lastSeenAt,
238
+ label: record.label,
239
+ lastStatus: record.lastStatus,
240
+ assignedPurposes,
241
+ isDefaultActive: config.activeDeviceId === record.deviceId,
242
+ };
243
+ }
244
+ /**
245
+ * Drop routing selections that point at devices not present in `devices`.
246
+ * Writes always validate references, so dangling entries only arise from a
247
+ * hand-edited config. Pruning keeps `list_devices` and purpose routing
248
+ * self-consistent instead of failing later with `device_not_found`.
249
+ *
250
+ * Stable exported shape. Internally this is the report-free view of the
251
+ * pipeline's reference-pruning stage ({@link pruneReferences}); load and write
252
+ * thread a NormalizationReport through that stage instead.
253
+ */
254
+ export function normalizeReferences(config) {
255
+ return pruneReferences(config, emptyReport());
256
+ }
257
+ function emptyReport() {
258
+ return {
259
+ droppedRecords: 0,
260
+ droppedRoutes: 0,
261
+ clearedActiveDeviceId: 0,
262
+ coercedLabels: 0,
263
+ coercedTimestamps: 0,
264
+ sanitizedDeviceDisplayText: 0,
265
+ sanitizedPortHints: 0,
266
+ };
267
+ }
268
+ function reportTotal(report) {
269
+ return (report.droppedRecords +
270
+ report.droppedRoutes +
271
+ report.clearedActiveDeviceId +
272
+ report.coercedLabels +
273
+ report.coercedTimestamps +
274
+ report.sanitizedDeviceDisplayText +
275
+ report.sanitizedPortHints);
276
+ }
277
+ // THE single config-normalization pipeline. Both load() (untrusted disk input)
278
+ // and writeConfig() (defensive re-normalization of in-memory state) go through
279
+ // here, and every drop/reset/sanitize/prune is recorded in one report. An empty
280
+ // report therefore means the input was already fully normalized: there is no path
281
+ // that changes the config without recording it. Returns undefined only when the
282
+ // envelope is not a recognized schema — a wholesale fallback to defaults, not a
283
+ // field-level normalization, which the caller surfaces separately.
284
+ function normalizeAgentQConfig(input) {
285
+ const recognized = recognizeConfigShape(input);
286
+ if (recognized === undefined) {
287
+ return undefined;
288
+ }
289
+ const report = emptyReport();
290
+ const assembled = assembleConfig(recognized, report);
291
+ const config = pruneReferences(assembled, report);
292
+ return { config, report };
293
+ }
294
+ // Top-level envelope gate. A config whose envelope is wrong or whose schema
295
+ // version is not current is treated as foreign (the caller uses defaults);
296
+ // individual current-schema device records and routing entries are normalized
297
+ // later rather than rejected wholesale, so one bad record cannot discard the
298
+ // whole registry.
299
+ function recognizeConfigShape(value) {
300
+ if (!isRecord(value)) {
301
+ return undefined;
302
+ }
303
+ if (!(typeof value.activeDeviceId === "string" || value.activeDeviceId === null)) {
304
+ return undefined;
305
+ }
306
+ if (value.schemaVersion === CONFIG_SCHEMA_VERSION) {
307
+ if (!isRecord(value.activeDeviceIdsByPurpose) || !Array.isArray(value.devices)) {
308
+ return undefined;
309
+ }
310
+ return {
311
+ activeDeviceId: value.activeDeviceId,
312
+ activeDeviceIdsByPurpose: value.activeDeviceIdsByPurpose,
313
+ devices: value.devices,
314
+ };
315
+ }
316
+ return undefined;
317
+ }
318
+ // Build a clean registry from loosely-typed input. The disk-ingress trust
319
+ // boundary, mirroring protocol.ts at the wire: records that cannot be made safe
320
+ // are dropped, duplicates removed, salvageable records sanitized, malformed
321
+ // routes discarded. Every change is recorded in `report`.
322
+ function assembleConfig(recognized, report) {
323
+ const normalizedDevices = [];
324
+ const seenDeviceIds = new Set();
325
+ for (const device of recognized.devices) {
326
+ const record = normalizeDeviceRecord(device, report);
327
+ if (record === null) {
328
+ continue;
329
+ }
330
+ if (seenDeviceIds.has(record.deviceId)) {
331
+ // Duplicate deviceId from a hand-edited config: keep the first, drop the rest.
332
+ report.droppedRecords += 1;
333
+ continue;
334
+ }
335
+ seenDeviceIds.add(record.deviceId);
336
+ normalizedDevices.push(record);
337
+ }
338
+ // Purpose names are validated before being used as map keys (isValidPurpose
339
+ // rejects prototype-sensitive names); reads elsewhere use own-property lookups.
340
+ const normalizedPurposes = {};
341
+ for (const [purpose, deviceId] of Object.entries(recognized.activeDeviceIdsByPurpose)) {
342
+ if (isValidPurpose(purpose) && isSafeDeviceId(deviceId)) {
343
+ normalizedPurposes[purpose] = deviceId;
344
+ }
345
+ else {
346
+ report.droppedRoutes += 1;
347
+ }
348
+ }
349
+ // A malformed (non-safe) activeDeviceId is reset to null and counted; a
350
+ // well-formed but dangling one is handled by pruneReferences.
351
+ let activeDeviceId = null;
352
+ if (isSafeDeviceId(recognized.activeDeviceId)) {
353
+ activeDeviceId = recognized.activeDeviceId;
354
+ }
355
+ else if (recognized.activeDeviceId !== null) {
356
+ report.clearedActiveDeviceId += 1;
357
+ }
358
+ return {
359
+ schemaVersion: CONFIG_SCHEMA_VERSION,
360
+ activeDeviceId,
361
+ activeDeviceIdsByPurpose: normalizedPurposes,
362
+ devices: normalizedDevices,
363
+ };
364
+ }
365
+ // Drop routing selections (and a dangling default active id) that point at
366
+ // devices not present in `devices`, recording each removal in `report`.
367
+ function pruneReferences(config, report) {
368
+ const knownDeviceIds = new Set(config.devices.map((device) => device.deviceId));
369
+ let activeDeviceId = config.activeDeviceId;
370
+ if (activeDeviceId !== null && !knownDeviceIds.has(activeDeviceId)) {
371
+ // Well-formed id that names no known device: a dangling active selection.
372
+ activeDeviceId = null;
373
+ report.clearedActiveDeviceId += 1;
374
+ }
375
+ const activeDeviceIdsByPurpose = {};
376
+ for (const [purpose, deviceId] of Object.entries(config.activeDeviceIdsByPurpose)) {
377
+ if (knownDeviceIds.has(deviceId)) {
378
+ activeDeviceIdsByPurpose[purpose] = deviceId;
379
+ }
380
+ else {
381
+ report.droppedRoutes += 1;
382
+ }
383
+ }
384
+ if (activeDeviceId === config.activeDeviceId &&
385
+ Object.keys(activeDeviceIdsByPurpose).length === Object.keys(config.activeDeviceIdsByPurpose).length) {
386
+ return config;
387
+ }
388
+ return { ...config, activeDeviceId, activeDeviceIdsByPurpose };
389
+ }
390
+ // Normalize one stored device record to a safe DeviceRecord, or null when its
391
+ // identity cannot be trusted. deviceId, transport, and the cached device's
392
+ // identity are REJECTED when malformed (the record is dropped); display text,
393
+ // label, port hint, and timestamp are sanitized or reset to a safe value. Every
394
+ // such change is recorded in `report`, so a silently-altered field cannot escape
395
+ // the operator warning.
396
+ function normalizeDeviceRecord(value, report) {
397
+ if (!isRecord(value) || !isSafeDeviceId(value.deviceId) || value.transport !== "usb") {
398
+ report.droppedRecords += 1;
399
+ return null;
400
+ }
401
+ if (!isRecord(value.lastStatus)) {
402
+ report.droppedRecords += 1;
403
+ return null;
404
+ }
405
+ const rawStatus = value.lastStatus;
406
+ const status = sanitizeDeviceStatusSnapshot(rawStatus);
407
+ if (status === null) {
408
+ report.droppedRecords += 1;
409
+ return null;
410
+ }
411
+ const rawDevice = rawStatus.device;
412
+ const device = status.device;
413
+ // Identity invariant: the record id and the cached device id must name the same
414
+ // device. A hand-edited config that splits them would route/select one id while
415
+ // exposing cached status for another, so the record is dropped.
416
+ if (device.deviceId !== value.deviceId) {
417
+ report.droppedRecords += 1;
418
+ return null;
419
+ }
420
+ // Stripping control bytes from (or truncating) firmwareName, hardware, or
421
+ // firmwareVersion is a normalization too; count each present-but-rewritten
422
+ // field so the warning reports it (a missing field defaulting to "" is not
423
+ // counted, matching the label/timestamp rule).
424
+ report.sanitizedDeviceDisplayText += countSanitizedDisplayFields(rawDevice, device);
425
+ const rawLabel = value.label;
426
+ let label;
427
+ if (isValidLabel(rawLabel)) {
428
+ label = rawLabel;
429
+ }
430
+ else {
431
+ label = null;
432
+ // A present-but-invalid label was reset; a missing label (null/undefined) is
433
+ // normal and not counted.
434
+ if (rawLabel !== undefined && rawLabel !== null) {
435
+ report.coercedLabels += 1;
436
+ }
437
+ }
438
+ let lastSeenAt;
439
+ if (isIsoTimestamp(value.lastSeenAt)) {
440
+ lastSeenAt = value.lastSeenAt;
441
+ }
442
+ else {
443
+ lastSeenAt = EPOCH_ISO;
444
+ if (value.lastSeenAt !== undefined) {
445
+ report.coercedTimestamps += 1;
446
+ }
447
+ }
448
+ const lastPortHint = sanitizePortHint(value.lastPortHint);
449
+ // A present-but-rewritten port hint is a sanitization; a missing one is not.
450
+ if (value.lastPortHint !== undefined && lastPortHint !== value.lastPortHint) {
451
+ report.sanitizedPortHints += 1;
452
+ }
453
+ return {
454
+ deviceId: value.deviceId,
455
+ transport: "usb",
456
+ lastPortHint,
457
+ lastSeenAt,
458
+ label,
459
+ lastStatus: status,
460
+ };
461
+ }
462
+ // Number of device display-text fields that sanitization changed. Only a field
463
+ // that was PRESENT on disk and differs from its sanitized form counts, so a clean
464
+ // value adds nothing and a missing field (defaulted to "") is not counted —
465
+ // consistent with how labels and timestamps treat a missing value.
466
+ function countSanitizedDisplayFields(rawDevice, sanitized) {
467
+ if (!isRecord(rawDevice)) {
468
+ return 0;
469
+ }
470
+ const fields = [
471
+ "firmwareName",
472
+ "hardware",
473
+ "firmwareVersion",
474
+ ];
475
+ let count = 0;
476
+ for (const field of fields) {
477
+ if (rawDevice[field] !== undefined && rawDevice[field] !== sanitized[field]) {
478
+ count += 1;
479
+ }
480
+ }
481
+ return count;
482
+ }
483
+ function isRecord(value) {
484
+ return typeof value === "object" && value !== null && !Array.isArray(value);
485
+ }
486
+ function isNodeError(error) {
487
+ return error instanceof Error && "code" in error;
488
+ }
489
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}