camstack 1.2.177 → 1.2.178

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.
@@ -17774,11 +17774,11 @@ var ModelVariantGroupSchema = external_exports.object({
17774
17774
  /** Quantization axis. Omit ⇒ the fp32 base build. */
17775
17775
  precision: external_exports.enum(["fp32", "int8"]).optional(),
17776
17776
  /**
17777
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
17778
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
17779
- * future performance variants plug into.
17777
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
17778
+ * an alternate training of the same family (Scrypted `relu_test`); chip
17779
+ * label is "Test".
17780
17780
  */
17781
- optimization: external_exports.enum(["standard", "fast"]).optional(),
17781
+ optimization: external_exports.enum(["standard", "test"]).optional(),
17782
17782
  /**
17783
17783
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
17784
17784
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -25333,7 +25333,7 @@ var modelConvertCapability = {
25333
25333
  }) }
25334
25334
  };
25335
25335
  var ModelDistributeInputSchema = external_exports.object({
25336
- nodeId: external_exports.string(),
25336
+ targetNodeId: external_exports.string(),
25337
25337
  modelId: external_exports.string(),
25338
25338
  format: external_exports.enum(MODEL_FORMATS),
25339
25339
  entry: ModelCatalogEntrySchema
@@ -28552,39 +28552,19 @@ var CLUSTER_MODEL_SCOPED_STEPS = [{
28552
28552
  label: "Face recognition model",
28553
28553
  defaultModelId: "auraface-r100",
28554
28554
  indexName: "the enrolled face gallery",
28555
- options: [
28556
- {
28557
- id: "auraface-r100",
28558
- label: "AuraFace R100"
28559
- },
28560
- {
28561
- id: "arcface-r100",
28562
- label: "ArcFace (ResNet34)"
28563
- },
28564
- {
28565
- id: "inception-resnet-v1",
28566
- label: "Inception ResNet V1"
28567
- }
28568
- ]
28555
+ options: [{
28556
+ id: "auraface-r100",
28557
+ label: "AuraFace R100"
28558
+ }]
28569
28559
  }, {
28570
28560
  stepId: "clip-embedding",
28571
28561
  label: "Semantic search model",
28572
- defaultModelId: "mobileclip-s1",
28562
+ defaultModelId: "siglip2-b16-224",
28573
28563
  indexName: "the object semantic-search index",
28574
- options: [
28575
- {
28576
- id: "mobileclip-s1",
28577
- label: "MobileCLIP S1"
28578
- },
28579
- {
28580
- id: "mobileclip-s2",
28581
- label: "MobileCLIP S2"
28582
- },
28583
- {
28584
- id: "siglip2-b16-224",
28585
- label: "SigLIP2 B/16 (Apache-2.0)"
28586
- }
28587
- ]
28564
+ options: [{
28565
+ id: "siglip2-b16-224",
28566
+ label: "SigLIP2 B/16 (Apache-2.0)"
28567
+ }]
28588
28568
  }];
28589
28569
  var DEFAULT_CLUSTER_STEP_MODELS = Object.freeze(Object.fromEntries(CLUSTER_MODEL_SCOPED_STEPS.map((s) => [s.stepId, s.defaultModelId])));
28590
28570
  var CLUSTER_STEP_SETTING_FIELDS = [{
@@ -41335,7 +41315,13 @@ var OsdOverlaySchema = external_exports.object({
41335
41315
  */
41336
41316
  availablePositions: external_exports.array(OsdPositionEnum).readonly(),
41337
41317
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
41338
- readOnly: external_exports.boolean().optional()
41318
+ readOnly: external_exports.boolean().optional(),
41319
+ /**
41320
+ * Firmware text ceiling for this overlay. Absent = no known limit.
41321
+ * The OSD manager truncates here on every write — never stores its own
41322
+ * copy on the binding.
41323
+ */
41324
+ maxCharacters: external_exports.number().int().positive().optional()
41339
41325
  });
41340
41326
  var OsdStatusSchema = external_exports.object({ overlays: external_exports.array(OsdOverlaySchema).readonly() });
41341
41327
  var OsdOverlayPatchSchema = external_exports.object({
@@ -41423,7 +41409,9 @@ var OsdTemplateBindingSchema = external_exports.object({
41423
41409
  valuePath: external_exports.string().min(1).max(64),
41424
41410
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
41425
41411
  displayUnit: external_exports.string().max(16).optional(),
41426
- maxDecimals: external_exports.number().int().min(0).max(4).default(1)
41412
+ maxDecimals: external_exports.number().int().min(0).max(4).default(1),
41413
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
41414
+ valueMap: external_exports.record(external_exports.string(), external_exports.string()).optional()
41427
41415
  });
41428
41416
  var OsdNamedTemplateSchema = external_exports.object({
41429
41417
  id: external_exports.string().min(1).max(64),
@@ -41468,18 +41456,11 @@ var OsdSlotBindingSchema = external_exports.object({
41468
41456
  source: OsdSourceSchema,
41469
41457
  /** `${value}` and `${unit}` are substituted; every occurrence. */
41470
41458
  template: external_exports.string().max(96).default("${value}"),
41471
- /** Truncate with an ellipsis past this length. Absent = no limit. */
41472
- maxCharacters: external_exports.number().int().min(4).max(64).optional(),
41473
41459
  /**
41474
41460
  * Decimal places for a numeric value. `0` yields an integer — the
41475
41461
  * documented workaround for firmwares that reject `.` in overlay text.
41476
41462
  */
41477
41463
  maxDecimals: external_exports.number().int().min(0).max(4).default(1),
41478
- /**
41479
- * Appended via `${unit}` when no unit conversion produces a label.
41480
- * Prefer `source.displayUnit` for converted device-state values.
41481
- */
41482
- unitLabel: external_exports.string().max(8).optional(),
41483
41464
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
41484
41465
  valueMap: external_exports.record(external_exports.string(), external_exports.string()).optional(),
41485
41466
  /** Time windows in which the slot is shown. Absent = always. */
@@ -41488,9 +41469,7 @@ var OsdSlotBindingSchema = external_exports.object({
41488
41469
  * Display gate, in the notification centre's condition vocabulary.
41489
41470
  * Only the keys reported by `getConditionSupport` are accepted.
41490
41471
  */
41491
- conditions: NcConditionsSchema.optional(),
41492
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
41493
- fallbackText: external_exports.string().max(64).default("")
41472
+ conditions: NcConditionsSchema.optional()
41494
41473
  });
41495
41474
  var OsdSlotViewSchema = external_exports.object({
41496
41475
  slotId: external_exports.string(),
@@ -58387,7 +58366,7 @@ var NC_TEMPLATE_VARS = [
58387
58366
  {
58388
58367
  name: "devices",
58389
58368
  label: "Devices",
58390
- description: "node-inference-unavailable: the affected cameras, comma-joined. Alarm arm / refusal: HOW MANY devices are armed (or open).",
58369
+ description: "node-inference-unavailable: the affected cameras, comma-joined. Alarm arm / arming / refusal: HOW MANY devices are armed (or open).",
58391
58370
  example: "Ingresso, Garage",
58392
58371
  group: "system",
58393
58372
  families: ["rule"],
@@ -58396,6 +58375,7 @@ var NC_TEMPLATE_VARS = [
58396
58375
  systemEventKinds: [
58397
58376
  "node-inference-unavailable",
58398
58377
  "alarm-armed",
58378
+ "alarm-arming",
58399
58379
  "alarm-arm-refused"
58400
58380
  ]
58401
58381
  },
@@ -58616,18 +58596,18 @@ var NC_TEMPLATE_VARS = [
58616
58596
  {
58617
58597
  name: "rules",
58618
58598
  label: "Covering rules",
58619
- description: "How many enabled rules the armed mode gates.",
58599
+ description: "How many enabled rules the armed / arming mode gates.",
58620
58600
  example: "2",
58621
58601
  group: "system",
58622
58602
  families: ["rule"],
58623
58603
  fields: [...RULE_TEXT],
58624
58604
  kinds: ["system"],
58625
- systemEventKinds: ["alarm-armed"]
58605
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
58626
58606
  },
58627
58607
  {
58628
58608
  name: "names",
58629
58609
  label: "Device names",
58630
- description: "Armed: the devices armed. Arming: the devices this mode cannot arm. Refusal: the open sensors.",
58610
+ description: "Armed / arming: the Active devices (or every skipped name when none are Active). Refusal: the open sensors.",
58631
58611
  example: "Ingresso, Garage",
58632
58612
  group: "system",
58633
58613
  families: ["rule"],
@@ -58648,7 +58628,29 @@ var NC_TEMPLATE_VARS = [
58648
58628
  families: ["rule"],
58649
58629
  fields: [...RULE_TEXT],
58650
58630
  kinds: ["system"],
58651
- systemEventKinds: ["alarm-armed"]
58631
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
58632
+ },
58633
+ {
58634
+ name: "active",
58635
+ label: "Active count",
58636
+ description: "How many named devices the armed / arming mode is watching (title: n attivi / n active).",
58637
+ example: "3",
58638
+ group: "system",
58639
+ families: ["rule"],
58640
+ fields: [...RULE_TEXT],
58641
+ kinds: ["system"],
58642
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
58643
+ },
58644
+ {
58645
+ name: "skipped",
58646
+ label: "Skipped count",
58647
+ description: "How many named devices the mode cannot arm \u2014 muted, detection off, offline (title: m saltati).",
58648
+ example: "1",
58649
+ group: "system",
58650
+ families: ["rule"],
58651
+ fields: [...RULE_TEXT],
58652
+ kinds: ["system"],
58653
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
58652
58654
  },
58653
58655
  {
58654
58656
  name: "bypassedNames",
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  FFMPEG_PATH_ENV,
4
4
  runDiscover
5
- } from "./chunk-QGJT47FV.js";
5
+ } from "./chunk-3AV5PMK2.js";
6
6
  import "./chunk-LMMQX4CK.js";
7
7
 
8
8
  // src/cli.ts
@@ -10,7 +10,7 @@ import { createRequire } from "module";
10
10
  import { fileURLToPath } from "url";
11
11
  import { dirname, resolve as resolve5 } from "path";
12
12
  import * as os5 from "os";
13
- import { parseArgs as parseArgs7 } from "util";
13
+ import { parseArgs as parseArgs8 } from "util";
14
14
 
15
15
  // src/commands/serve.ts
16
16
  import { parseArgs } from "util";
@@ -39,7 +39,7 @@ async function runServe(args) {
39
39
  ...typeof values.data === "string" ? { data: values.data } : {}
40
40
  };
41
41
  Object.assign(process.env, buildServeEnv(opts));
42
- await import("./launcher-5VFRFS7P.js");
42
+ await import("./launcher-2BHKBGSC.js");
43
43
  }
44
44
 
45
45
  // src/commands/agent.ts
@@ -84,7 +84,7 @@ async function runAgent(args) {
84
84
  ...typeof values.port === "string" ? { port: values.port } : {}
85
85
  };
86
86
  Object.assign(process.env, buildAgentEnv(opts));
87
- await import("./launcher-5VFRFS7P.js");
87
+ await import("./launcher-2BHKBGSC.js");
88
88
  }
89
89
 
90
90
  // src/commands/setup.ts
@@ -1134,7 +1134,7 @@ function isUnknown(_value) {
1134
1134
  return true;
1135
1135
  }
1136
1136
  async function resolveServerInteractive(presetNamespace) {
1137
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-VSURSRZZ.js");
1137
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-XEXOBUMG.js");
1138
1138
  if (presetNamespace) {
1139
1139
  const spinner4 = clack.spinner();
1140
1140
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -1844,6 +1844,340 @@ async function runWatch(args) {
1844
1844
  }
1845
1845
  }
1846
1846
 
1847
+ // src/commands/develop.ts
1848
+ import { parseArgs as parseArgs7 } from "util";
1849
+ import {
1850
+ extendAddon,
1851
+ findExample,
1852
+ findWorkspaceRoot,
1853
+ getCapability,
1854
+ listAddonPackages,
1855
+ listCapabilities,
1856
+ listExamples,
1857
+ listSkills,
1858
+ readSkill,
1859
+ requireWorkspaceRoot,
1860
+ scaffoldAddon,
1861
+ scaffoldCapStub,
1862
+ validateAddon,
1863
+ whoProvides
1864
+ } from "@camstack/develop";
1865
+ var HELP = `Usage: camstack develop <subcommand> [options]
1866
+
1867
+ Catalogue:
1868
+ list-addons [--json] List workspace packages with camstack.addons[]
1869
+ list-caps [--json] List *.cap.ts capability names
1870
+ who-provides <cap> [--json] Which addons declare a capability
1871
+ find-example <query> [--json] Ranked core-package examples
1872
+ examples [--json] Full curated example catalogue
1873
+
1874
+ Scaffold / extend:
1875
+ scaffold addon <name> [options] New packages/addon-<name>/
1876
+ --display-name <str>
1877
+ --description <str>
1878
+ --kind empty|provider|notifier|osd|post-analysis
1879
+ --directory <dir> Default: packages
1880
+ --dry-run
1881
+ scaffold cap <name> [options] Stub packages/types/.../<name>.cap.ts
1882
+ --scope system|device
1883
+ --mode singleton|collection
1884
+ --dry-run
1885
+ extend <addon> --entry <id> New manifest entry in an existing package
1886
+ --display-name <str>
1887
+ --description <str>
1888
+ --dry-run
1889
+
1890
+ Validate:
1891
+ validate [addon|--all] [--json] Manifest + vite entries (+ known caps)
1892
+
1893
+ Skills:
1894
+ skills [--json] Paths to the portable skill pack
1895
+ skill <id> Print one skill markdown file
1896
+
1897
+ Also: nx g @camstack/nx-plugin:addon <name> (Nx path to the same idea).
1898
+ `;
1899
+ function printJson(value) {
1900
+ console.log(JSON.stringify(value, null, 2));
1901
+ }
1902
+ function wantJson(args) {
1903
+ return args.includes("--json");
1904
+ }
1905
+ function withoutJson(args) {
1906
+ return args.filter((a) => a !== "--json");
1907
+ }
1908
+ function developHelp() {
1909
+ return HELP;
1910
+ }
1911
+ async function runDevelop(args) {
1912
+ if (args.length === 0 || args[0] === "-h" || args[0] === "--help") {
1913
+ console.log(HELP);
1914
+ return;
1915
+ }
1916
+ const sub = args[0] ?? "";
1917
+ const rest = args.slice(1);
1918
+ switch (sub) {
1919
+ case "list-addons":
1920
+ return cmdListAddons(rest);
1921
+ case "list-caps":
1922
+ return cmdListCaps(rest);
1923
+ case "who-provides":
1924
+ return cmdWhoProvides(rest);
1925
+ case "find-example":
1926
+ return cmdFindExample(rest);
1927
+ case "examples":
1928
+ return cmdExamples(rest);
1929
+ case "scaffold":
1930
+ return cmdScaffold(rest);
1931
+ case "extend":
1932
+ return cmdExtend(rest);
1933
+ case "validate":
1934
+ return cmdValidate(rest);
1935
+ case "skills":
1936
+ return cmdSkills(rest);
1937
+ case "skill":
1938
+ return cmdSkill(rest);
1939
+ default:
1940
+ throw new Error(`Unknown develop subcommand: ${sub}
1941
+
1942
+ ${HELP}`);
1943
+ }
1944
+ }
1945
+ function cmdListAddons(args) {
1946
+ const root = requireWorkspaceRoot();
1947
+ const pkgs = listAddonPackages(root);
1948
+ if (wantJson(args)) {
1949
+ printJson(pkgs);
1950
+ return;
1951
+ }
1952
+ for (const pkg of pkgs) {
1953
+ const ids = pkg.addons.map((a) => a.id).join(", ");
1954
+ console.log(`${pkg.packageName} ${pkg.relativeDir} [${ids}]`);
1955
+ }
1956
+ console.log(`
1957
+ ${pkgs.length} package(s)`);
1958
+ }
1959
+ function cmdListCaps(args) {
1960
+ const root = requireWorkspaceRoot();
1961
+ const caps = listCapabilities(root);
1962
+ if (wantJson(args)) {
1963
+ printJson(caps);
1964
+ return;
1965
+ }
1966
+ for (const cap of caps) {
1967
+ const meta = [cap.scope, cap.mode].filter(Boolean).join("/");
1968
+ console.log(`${cap.name} ${meta} ${cap.relativeFile}`);
1969
+ }
1970
+ console.log(`
1971
+ ${caps.length} capability(ies)`);
1972
+ }
1973
+ function cmdWhoProvides(args) {
1974
+ const json = wantJson(args);
1975
+ const cleaned = withoutJson(args);
1976
+ const cap = cleaned[0];
1977
+ if (!cap) throw new Error("Usage: camstack develop who-provides <cap>");
1978
+ const root = requireWorkspaceRoot();
1979
+ const hits = whoProvides(root, cap);
1980
+ if (json) {
1981
+ printJson(hits);
1982
+ return;
1983
+ }
1984
+ if (hits.length === 0) {
1985
+ console.log(`No addon declares capability \`${cap}\`.`);
1986
+ return;
1987
+ }
1988
+ for (const hit of hits) {
1989
+ console.log(`${hit.package.packageName} ${hit.addon.id} ${hit.package.relativeDir}`);
1990
+ }
1991
+ }
1992
+ function cmdFindExample(args) {
1993
+ const json = wantJson(args);
1994
+ const cleaned = withoutJson(args);
1995
+ const query = cleaned.join(" ").trim();
1996
+ if (!query) throw new Error("Usage: camstack develop find-example <query>");
1997
+ const root = findWorkspaceRoot() ?? process.cwd();
1998
+ const hits = findExample(root, query);
1999
+ if (json) {
2000
+ printJson(hits);
2001
+ return;
2002
+ }
2003
+ if (hits.length === 0) {
2004
+ console.log("No examples matched.");
2005
+ return;
2006
+ }
2007
+ for (const hit of hits.slice(0, 10)) {
2008
+ console.log(
2009
+ `[${hit.score}] ${hit.example.id} ${hit.example.packageDir}
2010
+ ${hit.example.demonstrates}
2011
+ (${hit.rationale})`
2012
+ );
2013
+ }
2014
+ }
2015
+ function cmdExamples(args) {
2016
+ const examples = listExamples();
2017
+ if (wantJson(args)) {
2018
+ printJson(examples);
2019
+ return;
2020
+ }
2021
+ for (const ex of examples) {
2022
+ console.log(`${ex.id} ${ex.kind} ${ex.packageDir}
2023
+ ${ex.demonstrates}`);
2024
+ }
2025
+ }
2026
+ function cmdScaffold(args) {
2027
+ const kind = args[0];
2028
+ if (kind === "addon") return cmdScaffoldAddon(args.slice(1));
2029
+ if (kind === "cap" || kind === "capability") return cmdScaffoldCap(args.slice(1));
2030
+ throw new Error("Usage: camstack develop scaffold addon|cap <name> [options]");
2031
+ }
2032
+ function cmdScaffoldAddon(args) {
2033
+ const { values, positionals } = parseArgs7({
2034
+ args: [...args],
2035
+ options: {
2036
+ "display-name": { type: "string" },
2037
+ description: { type: "string" },
2038
+ kind: { type: "string" },
2039
+ directory: { type: "string" },
2040
+ "dry-run": { type: "boolean" }
2041
+ },
2042
+ allowPositionals: true,
2043
+ strict: true
2044
+ });
2045
+ const name = positionals[0];
2046
+ if (!name) throw new Error("Usage: camstack develop scaffold addon <name>");
2047
+ const kindRaw = typeof values.kind === "string" ? values.kind : "empty";
2048
+ const allowed = /* @__PURE__ */ new Set(["empty", "provider", "notifier", "osd", "post-analysis"]);
2049
+ if (!allowed.has(kindRaw)) {
2050
+ throw new Error(`--kind must be one of: ${[...allowed].join(", ")}`);
2051
+ }
2052
+ const root = requireWorkspaceRoot();
2053
+ const result = scaffoldAddon({
2054
+ workspaceRoot: root,
2055
+ name,
2056
+ ...typeof values["display-name"] === "string" ? { displayName: values["display-name"] } : {},
2057
+ ...typeof values.description === "string" ? { description: values.description } : {},
2058
+ kind: kindRaw,
2059
+ ...typeof values.directory === "string" ? { directory: values.directory } : {},
2060
+ dryRun: values["dry-run"] === true
2061
+ });
2062
+ console.log(
2063
+ values["dry-run"] === true ? `[dry-run] would create ${result.relativeDir}` : `Created ${result.relativeDir}`
2064
+ );
2065
+ for (const f of result.filesWritten) console.log(` + ${f}`);
2066
+ console.log("\nNext:");
2067
+ for (const step of result.nextSteps) console.log(` - ${step}`);
2068
+ }
2069
+ function cmdScaffoldCap(args) {
2070
+ const { values, positionals } = parseArgs7({
2071
+ args: [...args],
2072
+ options: {
2073
+ scope: { type: "string" },
2074
+ mode: { type: "string" },
2075
+ "dry-run": { type: "boolean" }
2076
+ },
2077
+ allowPositionals: true,
2078
+ strict: true
2079
+ });
2080
+ const name = positionals[0];
2081
+ if (!name) throw new Error("Usage: camstack develop scaffold cap <name>");
2082
+ const scope = typeof values.scope === "string" ? values.scope : "system";
2083
+ const mode = typeof values.mode === "string" ? values.mode : "singleton";
2084
+ if (scope !== "system" && scope !== "device") {
2085
+ throw new Error("--scope must be system or device");
2086
+ }
2087
+ if (mode !== "singleton" && mode !== "collection") {
2088
+ throw new Error("--mode must be singleton or collection");
2089
+ }
2090
+ const root = requireWorkspaceRoot();
2091
+ const result = scaffoldCapStub({
2092
+ workspaceRoot: root,
2093
+ name,
2094
+ scope,
2095
+ mode,
2096
+ dryRun: values["dry-run"] === true
2097
+ });
2098
+ console.log(
2099
+ values["dry-run"] === true ? `[dry-run] would write ${result.relativePath}` : `Wrote ${result.relativePath} (${result.exportName})`
2100
+ );
2101
+ console.log("\nNext:");
2102
+ for (const step of result.nextSteps) console.log(` - ${step}`);
2103
+ }
2104
+ function cmdExtend(args) {
2105
+ const { values, positionals } = parseArgs7({
2106
+ args: [...args],
2107
+ options: {
2108
+ entry: { type: "string" },
2109
+ "display-name": { type: "string" },
2110
+ description: { type: "string" },
2111
+ "dry-run": { type: "boolean" }
2112
+ },
2113
+ allowPositionals: true,
2114
+ strict: true
2115
+ });
2116
+ const addon = positionals[0];
2117
+ const entry = typeof values.entry === "string" ? values.entry : void 0;
2118
+ if (!addon || !entry) {
2119
+ throw new Error("Usage: camstack develop extend <addon> --entry <id>");
2120
+ }
2121
+ const root = requireWorkspaceRoot();
2122
+ const result = extendAddon({
2123
+ workspaceRoot: root,
2124
+ addon,
2125
+ entryId: entry,
2126
+ ...typeof values["display-name"] === "string" ? { displayName: values["display-name"] } : {},
2127
+ ...typeof values.description === "string" ? { description: values.description } : {},
2128
+ dryRun: values["dry-run"] === true
2129
+ });
2130
+ console.log(
2131
+ values["dry-run"] === true ? `[dry-run] would extend ${result.packageDir} with ${result.entryId}` : `Extended ${result.packageDir} with entry ${result.entryId}`
2132
+ );
2133
+ for (const f of result.filesWritten) console.log(` ~ ${f}`);
2134
+ console.log("\nNext:");
2135
+ for (const step of result.nextSteps) console.log(` - ${step}`);
2136
+ }
2137
+ function cmdValidate(args) {
2138
+ const json = wantJson(args);
2139
+ const cleaned = withoutJson(args);
2140
+ const query = cleaned[0];
2141
+ const root = requireWorkspaceRoot();
2142
+ const result = validateAddon(root, query);
2143
+ if (json) {
2144
+ printJson(result);
2145
+ } else {
2146
+ if (result.findings.length === 0) {
2147
+ console.log("\u2714 no findings");
2148
+ } else {
2149
+ for (const f of result.findings) {
2150
+ const mark = f.level === "error" ? "\u2718" : f.level === "warn" ? "!" : "\xB7";
2151
+ console.log(`${mark} [${f.code}] ${f.message}`);
2152
+ }
2153
+ }
2154
+ console.log(result.ok ? "\n\u2714 validate ok" : "\n\u2718 validate failed");
2155
+ }
2156
+ if (!result.ok) process.exitCode = 1;
2157
+ }
2158
+ function cmdSkills(args) {
2159
+ const skills = listSkills();
2160
+ if (wantJson(args)) {
2161
+ printJson(skills);
2162
+ return;
2163
+ }
2164
+ console.log("Portable skill pack (@camstack/develop/skills):\n");
2165
+ for (const s of skills) {
2166
+ console.log(`${s.id} ${s.title}
2167
+ ${s.absolutePath}`);
2168
+ }
2169
+ }
2170
+ function cmdSkill(args) {
2171
+ const id = args[0];
2172
+ if (!id) throw new Error("Usage: camstack develop skill <id>");
2173
+ const skill = readSkill(id);
2174
+ if (!skill) {
2175
+ const known = listSkills().map((s) => s.id).join(", ");
2176
+ throw new Error(`Unknown skill: ${id}. Known: ${known}`);
2177
+ }
2178
+ console.log(skill.content);
2179
+ }
2180
+
1847
2181
  // src/cli.ts
1848
2182
  var __dirname = dirname(fileURLToPath(import.meta.url));
1849
2183
  var require2 = createRequire(import.meta.url);
@@ -2078,6 +2412,13 @@ function buildCommands() {
2078
2412
  "a push are coalesced into the next cycle."
2079
2413
  ].join("\n")
2080
2414
  },
2415
+ {
2416
+ name: "develop",
2417
+ aliases: ["addon"],
2418
+ summary: "Authoring tools \u2014 catalogue, scaffold, validate, find-example, skills (same ops as MCP)",
2419
+ run: runDevelop,
2420
+ help: developHelp
2421
+ },
2081
2422
  {
2082
2423
  name: "update",
2083
2424
  aliases: ["upgrade"],
@@ -2111,7 +2452,7 @@ function buildCommands() {
2111
2452
  }
2112
2453
  function parseSubcommandArgs(args, options, allowPositionals) {
2113
2454
  if (args.some((a) => HELP_FLAGS.has(a))) return null;
2114
- const parsed = parseArgs7({
2455
+ const parsed = parseArgs8({
2115
2456
  args: [...args],
2116
2457
  options,
2117
2458
  allowPositionals,
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-QGJT47FV.js";
8
+ } from "./chunk-3AV5PMK2.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -24024,9 +24024,9 @@ var require_zod = __commonJS({
24024
24024
  }
24025
24025
  });
24026
24026
 
24027
- // ../system/dist/dist-DeGPW01G.js
24028
- var require_dist_DeGPW01G = __commonJS({
24029
- "../system/dist/dist-DeGPW01G.js"(exports) {
24027
+ // ../system/dist/dist-CXVXFdJX.js
24028
+ var require_dist_CXVXFdJX = __commonJS({
24029
+ "../system/dist/dist-CXVXFdJX.js"(exports) {
24030
24030
  "use strict";
24031
24031
  var zod = require_zod();
24032
24032
  __require("crypto");
@@ -29287,11 +29287,11 @@ var require_dist_DeGPW01G = __commonJS({
29287
29287
  /** Quantization axis. Omit ⇒ the fp32 base build. */
29288
29288
  precision: zod.z.enum(["fp32", "int8"]).optional(),
29289
29289
  /**
29290
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
29291
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
29292
- * future performance variants plug into.
29290
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
29291
+ * an alternate training of the same family (Scrypted `relu_test`); chip
29292
+ * label is "Test".
29293
29293
  */
29294
- optimization: zod.z.enum(["standard", "fast"]).optional(),
29294
+ optimization: zod.z.enum(["standard", "test"]).optional(),
29295
29295
  /**
29296
29296
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
29297
29297
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -37878,7 +37878,7 @@ var require_dist_DeGPW01G = __commonJS({
37878
37878
  mode: "singleton",
37879
37879
  internal: true,
37880
37880
  methods: { distributeModel: method(zod.z.object({
37881
- nodeId: zod.z.string(),
37881
+ targetNodeId: zod.z.string(),
37882
37882
  modelId: zod.z.string(),
37883
37883
  format: zod.z.enum(MODEL_FORMATS),
37884
37884
  entry: ModelCatalogEntrySchema
@@ -41088,39 +41088,19 @@ var require_dist_DeGPW01G = __commonJS({
41088
41088
  label: "Face recognition model",
41089
41089
  defaultModelId: "auraface-r100",
41090
41090
  indexName: "the enrolled face gallery",
41091
- options: [
41092
- {
41093
- id: "auraface-r100",
41094
- label: "AuraFace R100"
41095
- },
41096
- {
41097
- id: "arcface-r100",
41098
- label: "ArcFace (ResNet34)"
41099
- },
41100
- {
41101
- id: "inception-resnet-v1",
41102
- label: "Inception ResNet V1"
41103
- }
41104
- ]
41091
+ options: [{
41092
+ id: "auraface-r100",
41093
+ label: "AuraFace R100"
41094
+ }]
41105
41095
  }, {
41106
41096
  stepId: "clip-embedding",
41107
41097
  label: "Semantic search model",
41108
- defaultModelId: "mobileclip-s1",
41098
+ defaultModelId: "siglip2-b16-224",
41109
41099
  indexName: "the object semantic-search index",
41110
- options: [
41111
- {
41112
- id: "mobileclip-s1",
41113
- label: "MobileCLIP S1"
41114
- },
41115
- {
41116
- id: "mobileclip-s2",
41117
- label: "MobileCLIP S2"
41118
- },
41119
- {
41120
- id: "siglip2-b16-224",
41121
- label: "SigLIP2 B/16 (Apache-2.0)"
41122
- }
41123
- ]
41100
+ options: [{
41101
+ id: "siglip2-b16-224",
41102
+ label: "SigLIP2 B/16 (Apache-2.0)"
41103
+ }]
41124
41104
  }].map((s) => [s.stepId, s.defaultModelId])));
41125
41105
  var CLUSTER_STEP_SETTING_FIELDS = [{
41126
41106
  stepId: "face-embedding",
@@ -53693,7 +53673,13 @@ var require_dist_DeGPW01G = __commonJS({
53693
53673
  */
53694
53674
  availablePositions: zod.z.array(OsdPositionEnum).readonly(),
53695
53675
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
53696
- readOnly: zod.z.boolean().optional()
53676
+ readOnly: zod.z.boolean().optional(),
53677
+ /**
53678
+ * Firmware text ceiling for this overlay. Absent = no known limit.
53679
+ * The OSD manager truncates here on every write — never stores its own
53680
+ * copy on the binding.
53681
+ */
53682
+ maxCharacters: zod.z.number().int().positive().optional()
53697
53683
  });
53698
53684
  var OsdStatusSchema = zod.z.object({ overlays: zod.z.array(OsdOverlaySchema).readonly() });
53699
53685
  var OsdOverlayPatchSchema = zod.z.object({
@@ -53781,7 +53767,9 @@ var require_dist_DeGPW01G = __commonJS({
53781
53767
  valuePath: zod.z.string().min(1).max(64),
53782
53768
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
53783
53769
  displayUnit: zod.z.string().max(16).optional(),
53784
- maxDecimals: zod.z.number().int().min(0).max(4).default(1)
53770
+ maxDecimals: zod.z.number().int().min(0).max(4).default(1),
53771
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
53772
+ valueMap: zod.z.record(zod.z.string(), zod.z.string()).optional()
53785
53773
  });
53786
53774
  var OsdNamedTemplateSchema = zod.z.object({
53787
53775
  id: zod.z.string().min(1).max(64),
@@ -53826,18 +53814,11 @@ var require_dist_DeGPW01G = __commonJS({
53826
53814
  source: OsdSourceSchema,
53827
53815
  /** `${value}` and `${unit}` are substituted; every occurrence. */
53828
53816
  template: zod.z.string().max(96).default("${value}"),
53829
- /** Truncate with an ellipsis past this length. Absent = no limit. */
53830
- maxCharacters: zod.z.number().int().min(4).max(64).optional(),
53831
53817
  /**
53832
53818
  * Decimal places for a numeric value. `0` yields an integer — the
53833
53819
  * documented workaround for firmwares that reject `.` in overlay text.
53834
53820
  */
53835
53821
  maxDecimals: zod.z.number().int().min(0).max(4).default(1),
53836
- /**
53837
- * Appended via `${unit}` when no unit conversion produces a label.
53838
- * Prefer `source.displayUnit` for converted device-state values.
53839
- */
53840
- unitLabel: zod.z.string().max(8).optional(),
53841
53822
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
53842
53823
  valueMap: zod.z.record(zod.z.string(), zod.z.string()).optional(),
53843
53824
  /** Time windows in which the slot is shown. Absent = always. */
@@ -53846,9 +53827,7 @@ var require_dist_DeGPW01G = __commonJS({
53846
53827
  * Display gate, in the notification centre's condition vocabulary.
53847
53828
  * Only the keys reported by `getConditionSupport` are accepted.
53848
53829
  */
53849
- conditions: NcConditionsSchema.optional(),
53850
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
53851
- fallbackText: zod.z.string().max(64).default("")
53830
+ conditions: NcConditionsSchema.optional()
53852
53831
  });
53853
53832
  var OsdSlotViewSchema = zod.z.object({
53854
53833
  slotId: zod.z.string(),
@@ -72478,6 +72457,8 @@ var require_dist_DeGPW01G = __commonJS({
72478
72457
  [...RULE_TEXT],
72479
72458
  [...RULE_TEXT],
72480
72459
  [...RULE_TEXT],
72460
+ [...RULE_TEXT],
72461
+ [...RULE_TEXT],
72481
72462
  ...STATE_SUMMARY_VARS
72482
72463
  ];
72483
72464
  var TimelapseTemplateSchema = zod.z.object({
@@ -73949,7 +73930,7 @@ var require_alerts_addon = __commonJS({
73949
73930
  [Symbol.toStringTag]: { value: "Module" }
73950
73931
  });
73951
73932
  require_chunk_Cek0wNdY();
73952
- var require_dist10 = require_dist_DeGPW01G();
73933
+ var require_dist10 = require_dist_CXVXFdJX();
73953
73934
  function deviceLabelFromEventData(data) {
73954
73935
  const name = stringNonEmpty(data["name"]) ?? stringNonEmpty(data["deviceName"]);
73955
73936
  if (name !== void 0) return name;
@@ -74773,7 +74754,7 @@ var require_calendars_addon = __commonJS({
74773
74754
  [Symbol.toStringTag]: { value: "Module" }
74774
74755
  });
74775
74756
  require_chunk_Cek0wNdY();
74776
- var require_dist10 = require_dist_DeGPW01G();
74757
+ var require_dist10 = require_dist_CXVXFdJX();
74777
74758
  var require_settle_sources = require_settle_sources_Bhsy57y();
74778
74759
  var zod = require_zod();
74779
74760
  var CALENDAR_COLOR_PALETTE = [
@@ -74987,11 +74968,11 @@ var require_calendars = __commonJS({
74987
74968
  }
74988
74969
  });
74989
74970
 
74990
- // ../system/dist/composition-sources-CUfM-BYp.js
74991
- var require_composition_sources_CUfM_BYp = __commonJS({
74992
- "../system/dist/composition-sources-CUfM-BYp.js"(exports) {
74971
+ // ../system/dist/composition-sources-CAFDvTRs.js
74972
+ var require_composition_sources_CAFDvTRs = __commonJS({
74973
+ "../system/dist/composition-sources-CAFDvTRs.js"(exports) {
74993
74974
  "use strict";
74994
- var require_dist10 = require_dist_DeGPW01G();
74975
+ var require_dist10 = require_dist_CXVXFdJX();
74995
74976
  function normalizedNativeOwner(owner) {
74996
74977
  const trimmed = owner?.trim();
74997
74978
  return trimmed ? trimmed : null;
@@ -75106,8 +75087,8 @@ var require_composer_addon = __commonJS({
75106
75087
  [Symbol.toStringTag]: { value: "Module" }
75107
75088
  });
75108
75089
  require_chunk_Cek0wNdY();
75109
- var require_dist10 = require_dist_DeGPW01G();
75110
- var require_composition_sources = require_composition_sources_CUfM_BYp();
75090
+ var require_dist10 = require_dist_CXVXFdJX();
75091
+ var require_composition_sources = require_composition_sources_CAFDvTRs();
75111
75092
  var zod = require_zod();
75112
75093
  function isRecord$2(value) {
75113
75094
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -78890,7 +78871,7 @@ var require_console_logging = __commonJS({
78890
78871
  [Symbol.toStringTag]: { value: "Module" }
78891
78872
  });
78892
78873
  require_chunk_Cek0wNdY();
78893
- var require_dist10 = require_dist_DeGPW01G();
78874
+ var require_dist10 = require_dist_CXVXFdJX();
78894
78875
  var require_formatter = require_formatter_DqAKDlvN();
78895
78876
  var LEVEL_RANK = {
78896
78877
  debug: 0,
@@ -82959,8 +82940,8 @@ var require_core_blocks_addon = __commonJS({
82959
82940
  "use strict";
82960
82941
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
82961
82942
  var require_chunk = require_chunk_Cek0wNdY();
82962
- var require_dist10 = require_dist_DeGPW01G();
82963
- var require_composition_sources = require_composition_sources_CUfM_BYp();
82943
+ var require_dist10 = require_dist_CXVXFdJX();
82944
+ var require_composition_sources = require_composition_sources_CAFDvTRs();
82964
82945
  var node_crypto = __require("crypto");
82965
82946
  var _camstack_types_node = require_node();
82966
82947
  var node_fs_promises = __require("fs/promises");
@@ -84832,11 +84813,11 @@ var require_core_blocks = __commonJS({
84832
84813
  }
84833
84814
  });
84834
84815
 
84835
- // ../system/dist/retired-settings-keys-D8G5o4Fc.js
84836
- var require_retired_settings_keys_D8G5o4Fc = __commonJS({
84837
- "../system/dist/retired-settings-keys-D8G5o4Fc.js"(exports) {
84816
+ // ../system/dist/retired-settings-keys-D24IW4qo.js
84817
+ var require_retired_settings_keys_D24IW4qo = __commonJS({
84818
+ "../system/dist/retired-settings-keys-D24IW4qo.js"(exports) {
84838
84819
  "use strict";
84839
- var require_dist10 = require_dist_DeGPW01G();
84820
+ var require_dist10 = require_dist_CXVXFdJX();
84840
84821
  function settingsStoreIsAuthoritativeHere(env) {
84841
84822
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
84842
84823
  return raw === "" || raw === "hub";
@@ -85125,8 +85106,8 @@ var require_device_manager_addon = __commonJS({
85125
85106
  [Symbol.toStringTag]: { value: "Module" }
85126
85107
  });
85127
85108
  require_chunk_Cek0wNdY();
85128
- var require_dist10 = require_dist_DeGPW01G();
85129
- var require_retired_settings_keys = require_retired_settings_keys_D8G5o4Fc();
85109
+ var require_dist10 = require_dist_CXVXFdJX();
85110
+ var require_retired_settings_keys = require_retired_settings_keys_D24IW4qo();
85130
85111
  var zod = require_zod();
85131
85112
  var node_crypto = __require("crypto");
85132
85113
  var _camstack_types_node = require_node();
@@ -93321,7 +93302,7 @@ var require_hub_forwarder = __commonJS({
93321
93302
  [Symbol.toStringTag]: { value: "Module" }
93322
93303
  });
93323
93304
  require_chunk_Cek0wNdY();
93324
- var require_dist10 = require_dist_DeGPW01G();
93305
+ var require_dist10 = require_dist_CXVXFdJX();
93325
93306
  var require_formatter = require_formatter_DqAKDlvN();
93326
93307
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
93327
93308
  var HubForwarderDestination = class {
@@ -93458,7 +93439,7 @@ var require_liveness_monitor_addon = __commonJS({
93458
93439
  "use strict";
93459
93440
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
93460
93441
  require_chunk_Cek0wNdY();
93461
- var require_dist10 = require_dist_DeGPW01G();
93442
+ var require_dist10 = require_dist_CXVXFdJX();
93462
93443
  var NO_DEVICES = "liveness:no-devices";
93463
93444
  var ALL_OFFLINE = "liveness:all-devices-offline";
93464
93445
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -93674,7 +93655,7 @@ var require_local_auth_addon = __commonJS({
93674
93655
  [Symbol.toStringTag]: { value: "Module" }
93675
93656
  });
93676
93657
  var require_chunk = require_chunk_Cek0wNdY();
93677
- var require_dist10 = require_dist_DeGPW01G();
93658
+ var require_dist10 = require_dist_CXVXFdJX();
93678
93659
  var node_crypto = __require("crypto");
93679
93660
  node_crypto = require_chunk.__toESM(node_crypto);
93680
93661
  var crypto$1 = __require("crypto");
@@ -101528,7 +101509,7 @@ var require_loki_logging = __commonJS({
101528
101509
  [Symbol.toStringTag]: { value: "Module" }
101529
101510
  });
101530
101511
  require_chunk_Cek0wNdY();
101531
- var require_dist10 = require_dist_DeGPW01G();
101512
+ var require_dist10 = require_dist_CXVXFdJX();
101532
101513
  function sanitizeLabelName(raw) {
101533
101514
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
101534
101515
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -102231,7 +102212,7 @@ var require_native_metrics_addon = __commonJS({
102231
102212
  [Symbol.toStringTag]: { value: "Module" }
102232
102213
  });
102233
102214
  var require_chunk = require_chunk_Cek0wNdY();
102234
- var require_dist10 = require_dist_DeGPW01G();
102215
+ var require_dist10 = require_dist_CXVXFdJX();
102235
102216
  var require_proc_stat = require_proc_stat_DL_WUOhl();
102236
102217
  var node_fs_promises = __require("fs/promises");
102237
102218
  var node_os = __require("os");
@@ -105071,7 +105052,7 @@ var require_filesystem_storage_addon = __commonJS({
105071
105052
  [Symbol.toStringTag]: { value: "Module" }
105072
105053
  });
105073
105054
  var require_chunk = require_chunk_Cek0wNdY();
105074
- var require_dist10 = require_dist_DeGPW01G();
105055
+ var require_dist10 = require_dist_CXVXFdJX();
105075
105056
  var node_crypto = __require("crypto");
105076
105057
  var node_fs_promises = __require("fs/promises");
105077
105058
  var node_path = __require("path");
@@ -106353,8 +106334,8 @@ var require_sqlite_settings_addon = __commonJS({
106353
106334
  [Symbol.toStringTag]: { value: "Module" }
106354
106335
  });
106355
106336
  var require_chunk = require_chunk_Cek0wNdY();
106356
- var require_dist10 = require_dist_DeGPW01G();
106357
- var require_retired_settings_keys = require_retired_settings_keys_D8G5o4Fc();
106337
+ var require_dist10 = require_dist_CXVXFdJX();
106338
+ var require_retired_settings_keys = require_retired_settings_keys_D24IW4qo();
106358
106339
  var require_sqlite_snapshot_protocol = require_sqlite_snapshot_protocol_B9OndqZv();
106359
106340
  var require_wal_checkpoint_policy = require_wal_checkpoint_policy_d2z2qPqx();
106360
106341
  var node_crypto = __require("crypto");
@@ -109550,7 +109531,7 @@ var require_storage_orchestrator_addon = __commonJS({
109550
109531
  [Symbol.toStringTag]: { value: "Module" }
109551
109532
  });
109552
109533
  var require_chunk = require_chunk_Cek0wNdY();
109553
- var require_dist10 = require_dist_DeGPW01G();
109534
+ var require_dist10 = require_dist_CXVXFdJX();
109554
109535
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
109555
109536
  var zod = require_zod();
109556
109537
  var node_crypto = __require("crypto");
@@ -113277,7 +113258,7 @@ var require_system_config_addon = __commonJS({
113277
113258
  [Symbol.toStringTag]: { value: "Module" }
113278
113259
  });
113279
113260
  require_chunk_Cek0wNdY();
113280
- var require_dist10 = require_dist_DeGPW01G();
113261
+ var require_dist10 = require_dist_CXVXFdJX();
113281
113262
  var SECTION_TITLES = {
113282
113263
  server: "Server",
113283
113264
  auth: "Authentication"
@@ -131338,7 +131319,7 @@ var require_winston_logging = __commonJS({
131338
131319
  [Symbol.toStringTag]: { value: "Module" }
131339
131320
  });
131340
131321
  var require_chunk = require_chunk_Cek0wNdY();
131341
- var require_dist10 = require_dist_DeGPW01G();
131322
+ var require_dist10 = require_dist_CXVXFdJX();
131342
131323
  var require_formatter = require_formatter_DqAKDlvN();
131343
131324
  var node_path = __require("path");
131344
131325
  node_path = require_chunk.__toESM(node_path);
@@ -148227,8 +148208,7 @@ var require_addon = __commonJS({
148227
148208
  "setSlotBinding": { "binding": { "__nested__": {
148228
148209
  "enabled": true,
148229
148210
  "template": "${value}",
148230
- "maxDecimals": 1,
148231
- "fallbackText": ""
148211
+ "maxDecimals": 1
148232
148212
  } } },
148233
148213
  "upsertTemplate": { "template": { "__nested__": {
148234
148214
  "bindings": [],
@@ -155004,12 +154984,12 @@ var require_dist2 = __commonJS({
155004
154984
  }
155005
154985
  });
155006
154986
 
155007
- // ../system/dist/child-cap-dispatch-B_0-zpI6.js
155008
- var require_child_cap_dispatch_B_0_zpI6 = __commonJS({
155009
- "../system/dist/child-cap-dispatch-B_0-zpI6.js"(exports) {
154987
+ // ../system/dist/child-cap-dispatch-CvYlCq60.js
154988
+ var require_child_cap_dispatch_CvYlCq60 = __commonJS({
154989
+ "../system/dist/child-cap-dispatch-CvYlCq60.js"(exports) {
155010
154990
  "use strict";
155011
154991
  var require_chunk = require_chunk_Cek0wNdY();
155012
- var require_dist10 = require_dist_DeGPW01G();
154992
+ var require_dist10 = require_dist_CXVXFdJX();
155013
154993
  var require_proc_stat = require_proc_stat_DL_WUOhl();
155014
154994
  require_hub_cap_forward_DmHNjbB0();
155015
154995
  var node_crypto = __require("crypto");
@@ -169548,7 +169528,7 @@ var require_dist3 = __commonJS({
169548
169528
  "use strict";
169549
169529
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
169550
169530
  var require_chunk = require_chunk_Cek0wNdY();
169551
- var require_dist10 = require_dist_DeGPW01G();
169531
+ var require_dist10 = require_dist_CXVXFdJX();
169552
169532
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
169553
169533
  require_alerts();
169554
169534
  var require_builtins_calendars_calendars_addon = require_calendars_addon();
@@ -169579,7 +169559,7 @@ var require_dist3 = __commonJS({
169579
169559
  var require_builtins_winston_logging_index = require_winston_logging();
169580
169560
  var require_event_loop_stall_monitor = require_event_loop_stall_monitor_ey4mbofz();
169581
169561
  var require_tls$1 = require_tls_ue_Xefmv();
169582
- var require_child_cap_dispatch = require_child_cap_dispatch_B_0_zpI6();
169562
+ var require_child_cap_dispatch = require_child_cap_dispatch_CvYlCq60();
169583
169563
  var require_resource_monitor = require_resource_monitor_BgWGRxN5();
169584
169564
  var require_custom_action_registry = require_custom_action_registry_acBY3mHA();
169585
169565
  var zod = require_zod();
@@ -254255,7 +254235,7 @@ var require_dist4 = __commonJS({
254255
254235
  }
254256
254236
  function variantLabel(precision, optimization) {
254257
254237
  const parts = [];
254258
- if (optimization === "fast") parts.push("Fast");
254238
+ if (optimization === "test") parts.push("Test");
254259
254239
  parts.push(precision === "int8" ? "Int8" : "Standard");
254260
254240
  return parts.join(" \xB7 ");
254261
254241
  }
@@ -254305,7 +254285,7 @@ var require_dist4 = __commonJS({
254305
254285
  };
254306
254286
  }).toSorted((a, b) => {
254307
254287
  if (a.resolution !== b.resolution) return (b.resolution ?? Infinity) - (a.resolution ?? Infinity);
254308
- if (a.optimization !== b.optimization) return a.optimization === "fast" ? 1 : -1;
254288
+ if (a.optimization !== b.optimization) return a.optimization === "test" ? 1 : -1;
254309
254289
  return PRECISION_ORDER.indexOf(a.precision) - PRECISION_ORDER.indexOf(b.precision);
254310
254290
  });
254311
254291
  const base = options.find((o) => o.precision === "fp32" && o.optimization === "standard") ?? options[0];
@@ -254441,11 +254421,11 @@ var require_dist4 = __commonJS({
254441
254421
  /** Quantization axis. Omit ⇒ the fp32 base build. */
254442
254422
  precision: zod.z.enum(["fp32", "int8"]).optional(),
254443
254423
  /**
254444
- * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
254445
- * latency-optimized export (e.g. ReLU-activation variant) — the slot the
254446
- * future performance variants plug into.
254424
+ * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
254425
+ * an alternate training of the same family (Scrypted `relu_test`); chip
254426
+ * label is "Test".
254447
254427
  */
254448
- optimization: zod.z.enum(["standard", "fast"]).optional(),
254428
+ optimization: zod.z.enum(["standard", "test"]).optional(),
254449
254429
  /**
254450
254430
  * Input-resolution axis (square input side, px). Omit ⇒ the family's native
254451
254431
  * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
@@ -263788,7 +263768,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263788
263768
  }) }
263789
263769
  };
263790
263770
  var ModelDistributeInputSchema = zod.z.object({
263791
- nodeId: zod.z.string(),
263771
+ targetNodeId: zod.z.string(),
263792
263772
  modelId: zod.z.string(),
263793
263773
  format: zod.z.enum(MODEL_FORMATS),
263794
263774
  entry: ModelCatalogEntrySchema
@@ -267939,39 +267919,19 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
267939
267919
  label: "Face recognition model",
267940
267920
  defaultModelId: "auraface-r100",
267941
267921
  indexName: "the enrolled face gallery",
267942
- options: [
267943
- {
267944
- id: "auraface-r100",
267945
- label: "AuraFace R100"
267946
- },
267947
- {
267948
- id: "arcface-r100",
267949
- label: "ArcFace (ResNet34)"
267950
- },
267951
- {
267952
- id: "inception-resnet-v1",
267953
- label: "Inception ResNet V1"
267954
- }
267955
- ]
267922
+ options: [{
267923
+ id: "auraface-r100",
267924
+ label: "AuraFace R100"
267925
+ }]
267956
267926
  }, {
267957
267927
  stepId: "clip-embedding",
267958
267928
  label: "Semantic search model",
267959
- defaultModelId: "mobileclip-s1",
267929
+ defaultModelId: "siglip2-b16-224",
267960
267930
  indexName: "the object semantic-search index",
267961
- options: [
267962
- {
267963
- id: "mobileclip-s1",
267964
- label: "MobileCLIP S1"
267965
- },
267966
- {
267967
- id: "mobileclip-s2",
267968
- label: "MobileCLIP S2"
267969
- },
267970
- {
267971
- id: "siglip2-b16-224",
267972
- label: "SigLIP2 B/16 (Apache-2.0)"
267973
- }
267974
- ]
267931
+ options: [{
267932
+ id: "siglip2-b16-224",
267933
+ label: "SigLIP2 B/16 (Apache-2.0)"
267934
+ }]
267975
267935
  }];
267976
267936
  var CLUSTER_MODEL_SECTION_ID = "cluster-step-models";
267977
267937
  function clusterModelSettingKey(stepId) {
@@ -281077,7 +281037,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
281077
281037
  */
281078
281038
  availablePositions: zod.z.array(OsdPositionEnum).readonly(),
281079
281039
  /** Firmware does not allow editing the `text` field (e.g. timestamp). */
281080
- readOnly: zod.z.boolean().optional()
281040
+ readOnly: zod.z.boolean().optional(),
281041
+ /**
281042
+ * Firmware text ceiling for this overlay. Absent = no known limit.
281043
+ * The OSD manager truncates here on every write — never stores its own
281044
+ * copy on the binding.
281045
+ */
281046
+ maxCharacters: zod.z.number().int().positive().optional()
281081
281047
  });
281082
281048
  var OsdStatusSchema = zod.z.object({ overlays: zod.z.array(OsdOverlaySchema).readonly() });
281083
281049
  var OsdOverlayPatchSchema = zod.z.object({
@@ -281165,7 +281131,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
281165
281131
  valuePath: zod.z.string().min(1).max(64),
281166
281132
  /** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
281167
281133
  displayUnit: zod.z.string().max(16).optional(),
281168
- maxDecimals: zod.z.number().int().min(0).max(4).default(1)
281134
+ maxDecimals: zod.z.number().int().min(0).max(4).default(1),
281135
+ /** Raw value → display text (same shape as slot binding). Empty string hides. */
281136
+ valueMap: zod.z.record(zod.z.string(), zod.z.string()).optional()
281169
281137
  });
281170
281138
  var OsdNamedTemplateSchema = zod.z.object({
281171
281139
  id: zod.z.string().min(1).max(64),
@@ -281210,18 +281178,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
281210
281178
  source: OsdSourceSchema,
281211
281179
  /** `${value}` and `${unit}` are substituted; every occurrence. */
281212
281180
  template: zod.z.string().max(96).default("${value}"),
281213
- /** Truncate with an ellipsis past this length. Absent = no limit. */
281214
- maxCharacters: zod.z.number().int().min(4).max(64).optional(),
281215
281181
  /**
281216
281182
  * Decimal places for a numeric value. `0` yields an integer — the
281217
281183
  * documented workaround for firmwares that reject `.` in overlay text.
281218
281184
  */
281219
281185
  maxDecimals: zod.z.number().int().min(0).max(4).default(1),
281220
- /**
281221
- * Appended via `${unit}` when no unit conversion produces a label.
281222
- * Prefer `source.displayUnit` for converted device-state values.
281223
- */
281224
- unitLabel: zod.z.string().max(8).optional(),
281225
281186
  /** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
281226
281187
  valueMap: zod.z.record(zod.z.string(), zod.z.string()).optional(),
281227
281188
  /** Time windows in which the slot is shown. Absent = always. */
@@ -281230,9 +281191,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
281230
281191
  * Display gate, in the notification centre's condition vocabulary.
281231
281192
  * Only the keys reported by `getConditionSupport` are accepted.
281232
281193
  */
281233
- conditions: NcConditionsSchema.optional(),
281234
- /** Rendered when the gate is closed or the value unreadable. Empty = hide. */
281235
- fallbackText: zod.z.string().max(64).default("")
281194
+ conditions: NcConditionsSchema.optional()
281236
281195
  });
281237
281196
  var OsdSlotViewSchema = zod.z.object({
281238
281197
  slotId: zod.z.string(),
@@ -306895,7 +306854,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
306895
306854
  {
306896
306855
  name: "devices",
306897
306856
  label: "Devices",
306898
- description: "node-inference-unavailable: the affected cameras, comma-joined. Alarm arm / refusal: HOW MANY devices are armed (or open).",
306857
+ description: "node-inference-unavailable: the affected cameras, comma-joined. Alarm arm / arming / refusal: HOW MANY devices are armed (or open).",
306899
306858
  example: "Ingresso, Garage",
306900
306859
  group: "system",
306901
306860
  families: ["rule"],
@@ -306904,6 +306863,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
306904
306863
  systemEventKinds: [
306905
306864
  "node-inference-unavailable",
306906
306865
  "alarm-armed",
306866
+ "alarm-arming",
306907
306867
  "alarm-arm-refused"
306908
306868
  ]
306909
306869
  },
@@ -307124,18 +307084,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
307124
307084
  {
307125
307085
  name: "rules",
307126
307086
  label: "Covering rules",
307127
- description: "How many enabled rules the armed mode gates.",
307087
+ description: "How many enabled rules the armed / arming mode gates.",
307128
307088
  example: "2",
307129
307089
  group: "system",
307130
307090
  families: ["rule"],
307131
307091
  fields: [...RULE_TEXT],
307132
307092
  kinds: ["system"],
307133
- systemEventKinds: ["alarm-armed"]
307093
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
307134
307094
  },
307135
307095
  {
307136
307096
  name: "names",
307137
307097
  label: "Device names",
307138
- description: "Armed: the devices armed. Arming: the devices this mode cannot arm. Refusal: the open sensors.",
307098
+ description: "Armed / arming: the Active devices (or every skipped name when none are Active). Refusal: the open sensors.",
307139
307099
  example: "Ingresso, Garage",
307140
307100
  group: "system",
307141
307101
  families: ["rule"],
@@ -307156,7 +307116,29 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
307156
307116
  families: ["rule"],
307157
307117
  fields: [...RULE_TEXT],
307158
307118
  kinds: ["system"],
307159
- systemEventKinds: ["alarm-armed"]
307119
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
307120
+ },
307121
+ {
307122
+ name: "active",
307123
+ label: "Active count",
307124
+ description: "How many named devices the armed / arming mode is watching (title: n attivi / n active).",
307125
+ example: "3",
307126
+ group: "system",
307127
+ families: ["rule"],
307128
+ fields: [...RULE_TEXT],
307129
+ kinds: ["system"],
307130
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
307131
+ },
307132
+ {
307133
+ name: "skipped",
307134
+ label: "Skipped count",
307135
+ description: "How many named devices the mode cannot arm \u2014 muted, detection off, offline (title: m saltati).",
307136
+ example: "1",
307137
+ group: "system",
307138
+ families: ["rule"],
307139
+ fields: [...RULE_TEXT],
307140
+ kinds: ["system"],
307141
+ systemEventKinds: ["alarm-armed", "alarm-arming"]
307160
307142
  },
307161
307143
  {
307162
307144
  name: "bypassedNames",
@@ -468362,8 +468344,8 @@ var require_model_distributor = __commonJS({
468362
468344
  });
468363
468345
  }
468364
468346
  async function distributeModelWith(seam, input) {
468365
- const { nodeId, modelId, format: format2, entry } = input;
468366
- if (nodeId === "hub") {
468347
+ const { targetNodeId, modelId, format: format2, entry } = input;
468348
+ if (targetNodeId === "hub") {
468367
468349
  return { ok: true, sha256: "", bytes: 0, path: seam.modelsDir };
468368
468350
  }
468369
468351
  if (!seam.isPresent(entry, format2)) {
@@ -468375,7 +468357,7 @@ var require_model_distributor = __commonJS({
468375
468357
  }
468376
468358
  const tgz = await seam.tar(files);
468377
468359
  const source = seam.stage(tgz);
468378
- const res = await seam.callAgent(nodeId, { modelId, format: format2, source });
468360
+ const res = await seam.callAgent(targetNodeId, { modelId, format: format2, source });
468379
468361
  return { ok: true, sha256: source.sha256, bytes: source.bytes, path: res.path ?? "" };
468380
468362
  }
468381
468363
  function buildModelDistributorProvider(moleculer, loggingService) {
@@ -468401,7 +468383,7 @@ var require_model_distributor = __commonJS({
468401
468383
  return {
468402
468384
  distributeModel: async (input) => {
468403
468385
  logger.info("Distributing model to node", {
468404
- meta: { modelId: input.modelId, format: input.format, nodeId: input.nodeId }
468386
+ meta: { modelId: input.modelId, format: input.format, nodeId: input.targetNodeId }
468405
468387
  });
468406
468388
  return distributeModelWith(seam, input);
468407
468389
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.177",
3
+ "version": "1.2.178",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",
@@ -43,6 +43,7 @@
43
43
  "vitest": "^3.0.0"
44
44
  },
45
45
  "dependencies": {
46
+ "@camstack/develop": "*",
46
47
  "@clack/prompts": "^1.3.0"
47
48
  }
48
49
  }