@camstack/addon-admin-ui 1.2.321 → 1.2.327

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 (130) hide show
  1. package/dist/assets/AddonCollectionPage-BYXUgNt8.js +1 -0
  2. package/dist/assets/Addons-DEsDluhx.js +1 -0
  3. package/dist/assets/AdminTabs-LKFnCZJa.js +1 -0
  4. package/dist/assets/AiProfiles-DGGskdrq.js +3 -0
  5. package/dist/assets/BrokerForm-CpCP-cuf.js +1 -0
  6. package/dist/assets/Build-y-iIlqwk.js +40 -0
  7. package/dist/assets/Calendars-DmNaEOHh.js +1 -0
  8. package/dist/assets/{Capabilities-BtxZsNCc.js → Capabilities-BUyyWS5i.js} +1 -1
  9. package/dist/assets/Cluster-BWGyPCVc.js +11 -0
  10. package/dist/assets/CompositionEditor-DR1G8J6D.js +1 -0
  11. package/dist/assets/CompositionEditorPage-COr2E2Ng.js +1 -0
  12. package/dist/assets/Data-CfBy8uzC.js +1 -0
  13. package/dist/assets/DetectionIntelligence-CV18a65N.js +1 -0
  14. package/dist/assets/DeviceDetail-C22K00sz.js +2 -0
  15. package/dist/assets/DeviceDoActionFields-CqFczBRR.js +1 -0
  16. package/dist/assets/Devices-D-gwyCgk.js +1 -0
  17. package/dist/assets/{EmbedPlayerPage-CzJ7wpeT.js → EmbedPlayerPage-BMn2kfo9.js} +1 -1
  18. package/dist/assets/Events-BqPx8kDj.js +1 -0
  19. package/dist/assets/Identity-DBbbdqnw.js +1 -0
  20. package/dist/assets/IntegrationDetail-DAb7G7fY.js +1 -0
  21. package/dist/assets/Integrations-C80svUZO.js +1 -0
  22. package/dist/assets/Integrations-ggcIU4Vk.js +1 -0
  23. package/dist/assets/Locations-Ci2bUyML.js +3 -0
  24. package/dist/assets/Logs-BA8e6vYN.js +1 -0
  25. package/dist/assets/ModelLicenses-CkAoslFM.js +1 -0
  26. package/dist/assets/{MotionZonesSettings-Ld-j-FOf.js → MotionZonesSettings-yUFzAS0j.js} +1 -1
  27. package/dist/assets/{MyAccess-CEbNjn9u.js → MyAccess-Cn7uVFhV.js} +1 -1
  28. package/dist/assets/Network-Bm6MoFC2.js +1 -0
  29. package/dist/assets/NodeAddonsSettingsPanel-BJXDDiTE.js +1 -0
  30. package/dist/assets/{NodeInferenceDevices-C4V1E570.js → NodeInferenceDevices-BbvTDa9I.js} +1 -1
  31. package/dist/assets/Notifications-D2EOXTl0.js +1 -0
  32. package/dist/assets/Pipeline-gUdmxBeA.js +1 -0
  33. package/dist/assets/{Plates-Ca44Vd3M.js → Plates-WM-X0QbX.js} +1 -1
  34. package/dist/assets/{PrivacyMaskSettings-BZrLQhuR.js → PrivacyMaskSettings-e-q-iS5G.js} +1 -1
  35. package/dist/assets/Recordings-COsPyII_.js +1 -0
  36. package/dist/assets/ScanNetworkModal-BkwyGjtP.js +1 -0
  37. package/dist/assets/{SceneMonitorEditor-DArl0gdm.js → SceneMonitorEditor-Cy_ctsoP.js} +1 -1
  38. package/dist/assets/{Scenes-8TVhXKCo.js → Scenes-CM5gfP56.js} +1 -1
  39. package/dist/assets/{Settings-Cdmn2EOP.js → Settings-diV7EZGf.js} +1 -1
  40. package/dist/assets/Showroom-B4oLevgz.js +1 -0
  41. package/dist/assets/{StorageLocationsPanel-GrDRDlUC.js → StorageLocationsPanel-BHnRg0RU.js} +1 -1
  42. package/dist/assets/{Terminal-BgTJMbXD.js → Terminal-Cef3PoGi.js} +3 -3
  43. package/dist/assets/Viewer-DG9fPu6Q.js +1 -0
  44. package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-CToXmC93.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BSGODArd.js} +1 -1
  45. package/dist/assets/{archive-bhxXcFdH.js → archive-BSV_Edqx.js} +1 -1
  46. package/dist/assets/{authed-media-Ct8tZsG_.js → authed-media-DNQTkl__.js} +1 -1
  47. package/dist/assets/{boxes-j_W4wNc5.js → boxes-4oXlPoua.js} +1 -1
  48. package/dist/assets/circle-slash-Dv1fvn11.js +1 -0
  49. package/dist/assets/{debounced-invalidate-CS4VcU8J.js → debounced-invalidate-BiO8-XOu.js} +1 -1
  50. package/dist/assets/device-integration-icon-Bgr6soyC.js +1 -0
  51. package/dist/assets/device-picker-model-DHmWldZJ.js +1 -0
  52. package/dist/assets/{dist-CuhmUcM3.js → dist-B0PPWfPE.js} +1 -1
  53. package/dist/assets/dist-NV_sDPNr.js +356 -0
  54. package/dist/assets/{face-bbox-BA9vvYUv.js → face-bbox-FnQ7mArR.js} +1 -1
  55. package/dist/assets/{hard-drive-download-CfRqYj8Y.js → hard-drive-download-Dwddfgke.js} +1 -1
  56. package/dist/assets/{hostInit-DTBgPT5y.js → hostInit-Doc3-KXw.js} +1 -1
  57. package/dist/assets/index-Dj-5KPic.js +4 -0
  58. package/dist/assets/index-ZqdYeoA9.css +2 -0
  59. package/dist/assets/{layers-QOUNNTM5.js → layers-dcoNdv3X.js} +1 -1
  60. package/dist/assets/location-owned-usage-D9hjyHoI.js +1 -0
  61. package/dist/assets/{mf-entry-bootstrap-0-1b5dfdc3.js → mf-entry-bootstrap-0-a5afa6e9.js} +2 -2
  62. package/dist/assets/mount-DHmWldZJ.js +1 -0
  63. package/dist/assets/notification-schedule-field-D1esy-w-.js +1 -0
  64. package/dist/assets/{player-overlays-BiMOywnH.js → player-overlays-D16jpLuq.js} +1 -1
  65. package/dist/assets/remoteEntry-DG_clDD-.js +1 -0
  66. package/dist/assets/{send-BJx_S3it.js → send-D8FSzLx_.js} +1 -1
  67. package/dist/assets/{settings-2-sRY7papp.js → settings-2-CNe1vvNy.js} +1 -1
  68. package/dist/assets/{square-check-big-DIDWLK6q.js → square-check-big-D-z4gacg.js} +1 -1
  69. package/dist/assets/src-BMs7x0zW.js +356 -0
  70. package/dist/assets/src-DaxJDrEG.js +67 -0
  71. package/dist/assets/{use-scenes-feed-BFRrjPGp.js → use-scenes-feed-CIvUspv6.js} +1 -1
  72. package/dist/assets/{use-stationary-objects-CjBY7Bah.js → use-stationary-objects-B5gmDICk.js} +1 -1
  73. package/dist/assets/useEventInvalidation-DHmWldZJ.js +1 -0
  74. package/dist/assets/{useNodeUrlSelection-9ogG1-47.js → useNodeUrlSelection-SjWMLV7k.js} +1 -1
  75. package/dist/assets/useTranslation-Bc5yH9V9.js +1 -0
  76. package/dist/assets/user-round-B24IGs8J.js +1 -0
  77. package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-Bd4_VZHP.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-BoTgdglg.js} +2 -2
  78. package/dist/index.html +9 -6
  79. package/dist/server/addon.js +137 -14
  80. package/package.json +1 -1
  81. package/dist/assets/AddonCollectionPage-C14Ubc3f.js +0 -1
  82. package/dist/assets/Addons-CmJY3DwS.js +0 -1
  83. package/dist/assets/AdminTabs-C21VrmV_.js +0 -1
  84. package/dist/assets/AiProfiles-BH2ZYTl5.js +0 -3
  85. package/dist/assets/BrokerForm-By4IXV0P.js +0 -1
  86. package/dist/assets/Build-Cp9lhbSa.js +0 -375
  87. package/dist/assets/Calendars-h1teotWN.js +0 -1
  88. package/dist/assets/CapabilityBadges-BgQFN1-C.js +0 -1
  89. package/dist/assets/Cluster-uH4CH_sI.js +0 -11
  90. package/dist/assets/CompositionEditor-Bs5sVten.js +0 -1
  91. package/dist/assets/CompositionEditorPage-DsEl8vZ-.js +0 -1
  92. package/dist/assets/Data-CY8b0eCB.js +0 -1
  93. package/dist/assets/DetectionIntelligence-B4kwPyMu.js +0 -1
  94. package/dist/assets/DeviceAggregateSection-C0M5zQC1.js +0 -1
  95. package/dist/assets/DeviceDetail-CqHrJksE.js +0 -2
  96. package/dist/assets/DeviceDoActionFields-B47q7Ngn.js +0 -1
  97. package/dist/assets/Devices-Dca55GnC.js +0 -1
  98. package/dist/assets/Events-CcWUIz0i.js +0 -1
  99. package/dist/assets/FormBuilder-iv7Ebt5-.js +0 -1
  100. package/dist/assets/Identity-BR5Rw3pD.js +0 -1
  101. package/dist/assets/IntegrationDetail-DZ4HfJVF.js +0 -1
  102. package/dist/assets/Integrations-BNU3UHsF.js +0 -1
  103. package/dist/assets/Integrations-Ccz0pSvl.js +0 -1
  104. package/dist/assets/Locations-DLhnYvxu.js +0 -3
  105. package/dist/assets/Logs-DcBhR7U7.js +0 -1
  106. package/dist/assets/ModelLicenses-DBFEHhra.js +0 -1
  107. package/dist/assets/Network-CzFkkboD.js +0 -1
  108. package/dist/assets/NodeAddonsSettingsPanel-Dg2oOlws.js +0 -1
  109. package/dist/assets/Notifications-Dead4gNT.js +0 -1
  110. package/dist/assets/Pipeline-C44r0T6e.js +0 -1
  111. package/dist/assets/ProviderIcon-CVcRB0Yd.js +0 -1
  112. package/dist/assets/Recordings-CYBEyS1q.js +0 -1
  113. package/dist/assets/ScanNetworkModal-C7ZNIVzp.js +0 -1
  114. package/dist/assets/SchemaTabBar-Bvm8GY8a.js +0 -1
  115. package/dist/assets/Showroom-t_xYTBoZ.js +0 -1
  116. package/dist/assets/StableTabPanel-Dc954AQl.js +0 -1
  117. package/dist/assets/Viewer-a-EDGNWZ.js +0 -1
  118. package/dist/assets/circle-slash-B992-uTX.js +0 -1
  119. package/dist/assets/device-integration-icon-BX2mTvZ2.js +0 -1
  120. package/dist/assets/device-picker-model-CjhoBZQq.js +0 -1
  121. package/dist/assets/dist-CKSjSzEl.js +0 -349
  122. package/dist/assets/index-BBheY5o3.css +0 -2
  123. package/dist/assets/index-BTdhzpJ6.js +0 -4
  124. package/dist/assets/location-owned-usage-DdLAmFZB.js +0 -1
  125. package/dist/assets/remoteEntry-DnroQusC.js +0 -1
  126. package/dist/assets/src-BIIk_uZx.js +0 -67
  127. package/dist/assets/src-BMvSPnxA.js +0 -349
  128. package/dist/assets/useDevice-B5hZ9Kwg.js +0 -1
  129. package/dist/assets/useEventInvalidation-CjhoBZQq.js +0 -1
  130. package/dist/assets/user-round-CCoCiRZv.js +0 -1
@@ -5380,7 +5380,7 @@ var ZodIssueCode = {
5380
5380
  var ZodFirstPartyTypeKind;
5381
5381
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5382
5382
  //#endregion
5383
- //#region ../types/dist/sleep-CDCONfkt.mjs
5383
+ //#region ../types/dist/sleep-DXKLNFvA.mjs
5384
5384
  /**
5385
5385
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5386
5386
  * window to float samples (D455).
@@ -5688,6 +5688,43 @@ function hydrateField(field, values) {
5688
5688
  }
5689
5689
  const rawValue = storedValue !== void 0 ? storedValue : defaultValue !== void 0 ? defaultValue : null;
5690
5690
  const value = field.type === "textarea" && field.isJson && rawValue !== null && typeof rawValue === "object" ? JSON.stringify(rawValue, null, 2) : rawValue;
5691
+ if (field.type === "tags" && typeof field.suggestionsFrom === "string") {
5692
+ const from = values[field.suggestionsFrom];
5693
+ const extra = Array.isArray(from) ? from.filter((s) => typeof s === "string" && s.length > 0) : [];
5694
+ const merged = [...new Set([...field.suggestions ?? [], ...extra])];
5695
+ return {
5696
+ ...field,
5697
+ suggestions: merged,
5698
+ value
5699
+ };
5700
+ }
5701
+ if ((field.type === "select" || field.type === "multiselect") && typeof field.optionsFrom === "string") {
5702
+ const from = values[field.optionsFrom];
5703
+ const byValue = /* @__PURE__ */ new Map();
5704
+ for (const opt of field.options) byValue.set(opt.value, opt);
5705
+ if (Array.isArray(from)) for (const entry of from) {
5706
+ if (typeof entry === "string" && entry.length > 0) {
5707
+ if (!byValue.has(entry)) byValue.set(entry, {
5708
+ value: entry,
5709
+ label: entry
5710
+ });
5711
+ continue;
5712
+ }
5713
+ if (entry === null || typeof entry !== "object") continue;
5714
+ const v = Reflect.get(entry, "value");
5715
+ const lbl = Reflect.get(entry, "label");
5716
+ if (typeof v !== "string" || v.length === 0) continue;
5717
+ if (!byValue.has(v)) byValue.set(v, {
5718
+ value: v,
5719
+ label: typeof lbl === "string" && lbl.length > 0 ? lbl : v
5720
+ });
5721
+ }
5722
+ return {
5723
+ ...field,
5724
+ options: [...byValue.values()],
5725
+ value
5726
+ };
5727
+ }
5691
5728
  return {
5692
5729
  ...field,
5693
5730
  value
@@ -10898,7 +10935,16 @@ var AutomationActionSchema = discriminatedUnion("kind", [
10898
10935
  }),
10899
10936
  object({
10900
10937
  kind: literal("cap"),
10901
- deviceId: union([number().int(), object({ $var: string().min(1) })]),
10938
+ /**
10939
+ * One device, several same-family devices (locks / climate family / …),
10940
+ * or `{ $var }` for the device that triggered the run. An array is
10941
+ * fan-out at codegen — each id gets the same cap.method call.
10942
+ */
10943
+ deviceId: union([
10944
+ number().int(),
10945
+ array(number().int()).min(1),
10946
+ object({ $var: string().min(1) })
10947
+ ]),
10902
10948
  cap: string().min(1),
10903
10949
  method: string().min(1),
10904
10950
  /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
@@ -14051,7 +14097,7 @@ DeviceType.Camera;
14051
14097
  * This matters here more than anywhere else in the repo, because every provider
14052
14098
  * that knows a device's host knows its PASSWORD too: `{ host, port, username,
14053
14099
  * password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
14054
- * and `http://admin:hunter2@192.168.50.139/` is a URL a browser accepts. The
14100
+ * and `http://admin:hunter2@192.168.x.x/` is a URL a browser accepts. The
14055
14101
  * camera's own page will ask for its own login. That is correct, and pre-
14056
14102
  * filling it is the operator's business, not ours.
14057
14103
  *
@@ -17539,10 +17585,35 @@ var SendResultSchema = object({
17539
17585
  });
17540
17586
  /** Same shape as SendResult — kept as a distinct name for the test panel. */
17541
17587
  var TestResultSchema = SendResultSchema;
17542
- method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema), { auth: "admin" }), method(object({
17588
+ /**
17589
+ * Pre-save credential probe against a partial (unsaved) target config.
17590
+ * `resolvedUrl` never includes secrets (token stripped from path).
17591
+ */
17592
+ var ProbeTargetConfigResultSchema = object({
17593
+ ok: boolean(),
17594
+ resolvedUrl: string(),
17595
+ httpStatus: number().int().optional(),
17596
+ stateInstance: string().optional(),
17597
+ error: string().optional()
17598
+ });
17599
+ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema), { auth: "admin" }), method(object({ targetId: string() }), TargetSchema, { auth: "admin" }), method(object({
17543
17600
  kind: string(),
17544
- config: record(string(), unknown()).optional()
17601
+ config: record(string(), unknown()).optional(),
17602
+ /**
17603
+ * When editing / duplicating, the blank password field never round-trips
17604
+ * the stored token. Pass the source target id so the provider can restore
17605
+ * secrets server-side before dialling (same merge as upsert).
17606
+ */
17607
+ targetId: string().optional()
17545
17608
  }), array(DiscoveredTargetSchema), { auth: "admin" }), method(object({
17609
+ kind: string(),
17610
+ config: record(string(), unknown()),
17611
+ /** See `discoverTargets.targetId` — restore stored secrets for a blank password. */
17612
+ targetId: string().optional()
17613
+ }), ProbeTargetConfigResultSchema, {
17614
+ kind: "mutation",
17615
+ auth: "admin"
17616
+ }), method(object({
17546
17617
  targetId: string(),
17547
17618
  notification: NotificationSchema
17548
17619
  }), SendResultSchema, {
@@ -17554,7 +17625,16 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
17554
17625
  }), TestResultSchema, {
17555
17626
  kind: "mutation",
17556
17627
  auth: "admin"
17557
- }), method(object({ target: TargetSchema }), TargetSchema, {
17628
+ }), method(object({
17629
+ target: TargetSchema,
17630
+ /**
17631
+ * Duplicate flow: create a NEW target id while copying secrets from an
17632
+ * existing row. The UI never holds the stored token; blank / redacted
17633
+ * password fields are restored from this source (D634 still applies if
17634
+ * destinations diverge without a re-typed secret).
17635
+ */
17636
+ cloneSecretsFrom: string().optional()
17637
+ }), TargetSchema, {
17558
17638
  kind: "mutation",
17559
17639
  auth: "admin"
17560
17640
  }), method(object({ targetId: string() }), _void(), {
@@ -19935,17 +20015,41 @@ var NC_ALARM_TRIGGERED_MAX_SEC = 3600;
19935
20015
  var NcAlarmDelaySecSchema = number().int().min(0).max(600);
19936
20016
  var NcAlarmTriggeredSecSchema = number().int().min(0).max(NC_ALARM_TRIGGERED_MAX_SEC);
19937
20017
  var uniqueModes = (entries) => new Set(entries.map((e) => e.mode)).size === entries.length;
20018
+ /**
20019
+ * What the panel does when a bounded triggered window ends.
20020
+ * - `rearmAfter` — return to the armed mode
20021
+ * - `disableAfter` — auto-disarm
20022
+ * - `doNothing` — stay triggered until a human disarms
20023
+ */
20024
+ var NcAlarmPostTriggeredActionSchema = _enum([
20025
+ "rearmAfter",
20026
+ "disableAfter",
20027
+ "doNothing"
20028
+ ]);
19938
20029
  var NcAlarmModeDelaysListSchema = array(object({
19939
20030
  mode: AlarmArmModeSchema,
19940
20031
  exitDelaySec: NcAlarmDelaySecSchema.optional(),
19941
20032
  entryDelaySec: NcAlarmDelaySecSchema.optional(),
19942
- triggeredDurationSec: NcAlarmTriggeredSecSchema.optional()
20033
+ /**
20034
+ * Duration of `triggered` before {@link postTriggeredAction}. Kept as the
20035
+ * historical field name so older clients still read/write a number.
20036
+ */
20037
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.optional(),
20038
+ postTriggeredAction: NcAlarmPostTriggeredActionSchema.optional(),
20039
+ /**
20040
+ * When this mode may be armed. Absent / null = always allowed (same as a
20041
+ * rule with no `schedule`). Evaluated with {@link isScheduleActive}.
20042
+ */
20043
+ schedule: NcScheduleSchema.optional()
19943
20044
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
19944
20045
  var NcAlarmModeDelaysEditListSchema = array(object({
19945
20046
  mode: AlarmArmModeSchema,
19946
20047
  exitDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
19947
20048
  entryDelaySec: NcAlarmDelaySecSchema.nullable().optional(),
19948
- triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional()
20049
+ triggeredDurationSec: NcAlarmTriggeredSecSchema.nullable().optional(),
20050
+ postTriggeredAction: NcAlarmPostTriggeredActionSchema.nullable().optional(),
20051
+ /** Set a schedule, or `null` to clear (mode always allowed again). */
20052
+ schedule: NcScheduleSchema.nullable().optional()
19949
20053
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
19950
20054
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
19951
20055
  var NcAlarmNonBlockingEditSchema = object({
@@ -20017,12 +20121,18 @@ var NcAlarmSettingsSchema = object({
20017
20121
  /** Grace period between a trigger and the alarm firing. 0 = immediate. */
20018
20122
  entryDelaySec: NcAlarmDelaySecSchema,
20019
20123
  /**
20020
- * How long `triggered` lasts before the panel re-arms itself.
20021
- * **0 = until an operator disarms it** — the behaviour before this field
20022
- * existed, and therefore what an untouched install keeps doing.
20124
+ * How long `triggered` lasts before {@link postTriggeredAction} runs.
20125
+ * Ignored when the action is `doNothing`. Historical name kept so older
20126
+ * clients still round-trip a number.
20023
20127
  */
20024
20128
  triggeredDurationSec: NcAlarmTriggeredSecSchema,
20025
20129
  /**
20130
+ * What happens when the triggered window ends. Absent on a blob older than
20131
+ * this field → derived from {@link triggeredDurationSec} (`>0` ⇒ rearmAfter,
20132
+ * else doNothing).
20133
+ */
20134
+ postTriggeredAction: NcAlarmPostTriggeredActionSchema.optional(),
20135
+ /**
20026
20136
  * Deprecated by D630 — every transition is announced. Parsed, never read;
20027
20137
  * remove after one release. Optional so an older admin's patch (which still
20028
20138
  * sends it) parses rather than failing the whole save.
@@ -30254,7 +30364,7 @@ var LocalInterfaceSchema = object({
30254
30364
  name: string(),
30255
30365
  family: _enum(["IPv4", "IPv6"]),
30256
30366
  address: string(),
30257
- /** CIDR shorthand (e.g. `192.168.1.10/24`). Empty when OS doesn't expose. */
30367
+ /** CIDR shorthand (e.g. `192.168.x.x/24`). Empty when OS doesn't expose. */
30258
30368
  cidr: string(),
30259
30369
  /** OS netmask. Stable across calls so the SDK can hash on it. */
30260
30370
  netmask: string(),
@@ -30700,7 +30810,7 @@ var MeshPeerSchema = object({
30700
30810
  tags: array(string()).readonly(),
30701
30811
  /** True when the peer advertises itself as an exit-node candidate. */
30702
30812
  exitNodeOption: boolean(),
30703
- /** Subnet routes the peer advertises (e.g. `["192.168.1.0/24"]`). */
30813
+ /** Subnet routes the peer advertises (e.g. `["192.168.x.x/24"]`). */
30704
30814
  advertisedRoutes: array(string()).readonly(),
30705
30815
  /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
30706
30816
  userLogin: string().nullable(),
@@ -39598,6 +39708,12 @@ Object.freeze({
39598
39708
  addonId: null,
39599
39709
  access: "view"
39600
39710
  },
39711
+ "notificationOutput.getTarget": {
39712
+ capName: "notification-output",
39713
+ capScope: "system",
39714
+ addonId: null,
39715
+ access: "view"
39716
+ },
39601
39717
  "notificationOutput.listTargetKinds": {
39602
39718
  capName: "notification-output",
39603
39719
  capScope: "system",
@@ -39610,6 +39726,12 @@ Object.freeze({
39610
39726
  addonId: null,
39611
39727
  access: "view"
39612
39728
  },
39729
+ "notificationOutput.probeTargetConfig": {
39730
+ capName: "notification-output",
39731
+ capScope: "system",
39732
+ addonId: null,
39733
+ access: "create"
39734
+ },
39613
39735
  "notificationOutput.send": {
39614
39736
  capName: "notification-output",
39615
39737
  capScope: "system",
@@ -43319,6 +43441,7 @@ Object.freeze({
43319
43441
  access: "create"
43320
43442
  }
43321
43443
  });
43444
+ DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
43322
43445
  DeviceFeature.BatteryOperated;
43323
43446
  /**
43324
43447
  * The vocabulary, in the order a picker offers it.
@@ -48264,7 +48387,7 @@ var AdminUIAddon = class extends BaseAddon {
48264
48387
  capability: adminUiCapability,
48265
48388
  provider: {
48266
48389
  getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
48267
- getVersion: async () => ({ version: "1.2.321" })
48390
+ getVersion: async () => ({ version: "1.2.327" })
48268
48391
  }
48269
48392
  }];
48270
48393
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-admin-ui",
3
- "version": "1.2.321",
3
+ "version": "1.2.327",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Admin UI — Vite frontend build and server-side addon",
@@ -1 +0,0 @@
1
- import{I as e,Q as t,S as n,W as r,o as i,q as a,x as o,z as s}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{Z as c,_t as l,ct as u,gt as d}from"./player-overlays-BiMOywnH.js";import{Au as f,Cd as p,Cn as m,Dt as h,V as g,_n as _,_u as v,bn as y,gr as b,gt as x,gu as S,ht as C,iu as w,ur as T,uu as E,xn as D}from"./src-BIIk_uZx.js";import{d as O}from"./index-BTdhzpJ6.js";import{t as k}from"./AdminPage-CiKtOLQm.js";import{t as A}from"./NodeAddonsSettingsPanel-Dg2oOlws.js";t();function j({addonId:e,fallback:t,tileClassName:n,iconPath:r=`assets/icon.svg`}){let[i,s]=a(!1),l=c(`/api/addon-assets/${e}/${r}`);return o(`div`,{className:`h-10 w-10 rounded-lg flex items-center justify-center shrink-0 ${n}`,children:i?o(t,{className:`h-5 w-5`}):o(`img`,{src:l,alt:e,className:`h-7 w-7 rounded-md bg-white p-1 ring-1 ring-black/5`,onError:()=>s(!0)})})}t();function M({addonId:e,defaultActivity:t,showActivity:r=!0,maxHeight:i=`max-h-64`,defaultTab:s,capability:c}){let[l,u]=a(t??(s===`events`?`events`:`logs`));return n(`div`,{className:`flex flex-col gap-4`,children:[o(A,{nodeId:`hub`,addonIds:[e],level:`global`,capability:c}),r&&n(`div`,{className:`rounded-lg border border-border bg-surface overflow-hidden`,children:[n(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border bg-surface-hover/20`,children:[o(`span`,{className:`text-[11px] font-semibold text-foreground-subtle uppercase tracking-wide`,children:`Activity`}),n(`div`,{className:`flex items-center gap-1`,children:[o(N,{kind:`logs`,active:l===`logs`,onClick:()=>u(`logs`)}),o(N,{kind:`events`,active:l===`events`,onClick:()=>u(`events`)})]})]}),l===`logs`?o(x,{addonId:e,maxHeight:i,showFilters:!1}):o(C,{addonId:e,category:`addon.*`,maxHeight:i})]})]})}function N({kind:e,active:t,onClick:r}){return n(`button`,{onClick:r,className:`inline-flex items-center gap-1 rounded px-2 py-0.5 text-[11px] font-medium transition-colors ${t?`bg-primary/10 text-primary`:`text-foreground-subtle hover:text-foreground hover:bg-surface-hover`}`,children:[o(e===`logs`?w:p,{className:`h-3 w-3`}),e===`logs`?`Logs`:`Events`]})}t();function P(t){let{title:i,subtitle:c,pageIcon:l,itemIcon:u,capability:d,installButtonLabel:f=`Add addon`,items:p,isLoading:h,emptyTitle:v=`No addons installed for this capability`,emptyDescription:b,itemIconColor:x,renderStatusBadges:C,renderPrimaryAction:w,itemError:T,renderExpandedPanel:E,workspaceMaxHeight:A=`max-h-72`,trailing:j,showChrome:N=!1}=t,P=p.length>1,[I,z]=a(()=>p[0]?.addonId??null);s(()=>{I&&(p.some(e=>e.addonId===I)||z(p[0]?.addonId??null))},[p,I]);let B=e(e=>z(t=>t===e?null:e),[]),V=`/system/addons?capability=${encodeURIComponent(d)}`,H=e(e=>e.addonId,[]),U=e(e=>`${e.displayName} ${e.addonId}`,[]),W=e(e=>!P||I===e.addonId,[P,I]),G=e(e=>{P&&B(e.addonId)},[P,B]),K=r(()=>[{key:`provider`,header:`Provider`,headerClassName:`w-[55%]`,cell:e=>o(F,{item:e,itemIcon:u,iconColor:x?.(e)??null,expanded:!P||I===e.addonId,collapsible:P,onToggle:B,statusBadges:C?.(e)??null})},{key:`actions`,header:``,headerClassName:`w-[45%] text-right`,cellClassName:`text-right`,cell:e=>n(`span`,{className:`inline-flex items-center gap-1 flex-wrap justify-end`,onClick:e=>e.stopPropagation(),children:[w?.(e),o(L,{capName:e.capName??d,addonId:e.addonId,isActive:e.isActive}),o(R,{addonId:e.addonId,displayName:e.displayName})]})}],[u,d,P,x,I,w,C,B]),q=e(e=>{let t=T?.(e)??null;return n(`div`,{className:`flex flex-col gap-3 py-3`,children:[t!==null&&o(y,{message:t}),E?.(e),o(M,{addonId:e.addonId,maxHeight:A,capability:e.capName??d})]})},[d,T,E,A]);return o(k,{icon:N?l:void 0,title:N?i:void 0,subtitle:N?c:void 0,actions:N?o(O,{to:V,children:n(m,{variant:`primary`,size:`sm`,children:[o(S,{className:`h-3.5 w-3.5 mr-1`}),f]})}):void 0,children:h?o(_,{children:o(`div`,{className:`p-6 text-sm text-foreground-subtle`,children:`Loading…`})}):p.length===0?o(_,{children:o(D,{title:v,description:b??`Install an addon that declares the "${d}" capability to get started.`,action:N?o(O,{to:V,children:n(m,{variant:`primary`,size:`sm`,children:[o(S,{className:`h-3.5 w-3.5 mr-1`}),f]})}):void 0})}):n(`div`,{className:`space-y-4`,children:[o(g,{mode:`generic`,items:p,getKey:H,getSearchText:U,columns:K,onRowClick:G,isExpanded:W,renderExpanded:q,searchPlaceholder:`Search providers`,emptyLabel:`No provider matches this search.`}),j]})})}function F({item:e,itemIcon:t,iconColor:r,expanded:i,collapsible:a,onToggle:s,statusBadges:c}){let u=r??(e.isActive?`bg-emerald-500/15 text-emerald-700 dark:text-emerald-300`:`bg-foreground-subtle/15 text-foreground-subtle`);return n(`div`,{className:`flex items-center gap-2.5 min-w-0`,children:[a&&o(`button`,{type:`button`,onClick:t=>{t.stopPropagation(),s(e.addonId)},"aria-label":i?`Collapse`:`Expand`,"aria-expanded":i,className:`flex h-5 w-5 flex-shrink-0 items-center justify-center rounded text-foreground-subtle transition-colors hover:bg-surface-hover hover:text-foreground`,children:o(i?l:d,{className:`h-3.5 w-3.5`})}),o(j,{addonId:e.addonId,fallback:t,tileClassName:u}),n(`div`,{className:`flex min-w-0 flex-col`,children:[n(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[o(`span`,{className:`font-semibold text-foreground`,children:e.displayName}),o(I,{isActive:e.isActive}),c]}),o(`div`,{className:`text-xs text-foreground-subtle mt-0.5 font-mono break-all`,children:e.addonId})]})]})}function I({isActive:e}){return o(`span`,{className:`text-[10px] rounded-full px-2 py-0.5 font-medium ${e?`bg-emerald-500/15 text-emerald-700 dark:text-emerald-300`:`bg-foreground-subtle/15 text-foreground-subtle`}`,children:e?`Enabled`:`Disabled`})}function L({capName:e,addonId:t,isActive:r}){let a=i(),s=b({onSuccess:()=>{a.invalidateQueries({queryKey:[[`addons`,`listCapabilityProviders`]]})}}),c=s.isPending;return n(m,{size:`sm`,variant:r?`secondary`:`primary`,disabled:c,onClick:()=>s.mutate({capName:e,addonId:t,enabled:!r}),children:[c?o(f,{className:`h-3 w-3 animate-spin`}):o(r?u:v,{className:`h-3 w-3`}),r?`Disable`:`Enable`]})}function R({addonId:e,displayName:t}){let n=i(),r=T({onSuccess:()=>{n.invalidateQueries({queryKey:[[`addons`,`listCapabilityProviders`]]})}});return o(h,{label:`Restart`,icon:E,size:`sm`,title:`Restart "${t}"?`,description:`Restarting the addon bounces its subprocess — the provider will briefly drop and reconnect automatically.`,confirmLabel:`Restart`,triggerVariant:`ghost`,confirmVariant:`danger`,disabled:r.isPending,action:()=>r.mutateAsync({addonId:e})})}export{P as t};
@@ -1 +0,0 @@
1
- import{I as e,K as t,Q as n,R as r,S as i,W as a,b as o,o as s,q as c,x as l,z as u}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{Z as d,_t as f,st as p,yt as m}from"./player-overlays-BiMOywnH.js";import{$n as h,Au as g,B as ee,Jl as _,Pn as te,Zn as v,Zu as y,_r as b,ad as x,ar as S,cr as C,er as w,fl as T,fr as ne,gt as re,gu as ie,hd as E,hl as D,hr as O,ht as ae,ir as oe,iu as se,j as ce,jl as k,lr as A,mr as j,nr as M,pd as le,po as N,pr as P,pu as ue,rr as F,ru as I,sr as L,tr as de,tu as fe,ud as R,ur as z,uu as B,vr as pe,yl as V,yr as me,yu as H}from"./src-BIIk_uZx.js";import{Dr as U}from"./src-BMvSPnxA.js";import{f as he,m as ge}from"./index-BTdhzpJ6.js";import{t as W}from"./AdminPage-CiKtOLQm.js";import{t as _e}from"./NodeAddonsSettingsPanel-Dg2oOlws.js";import{r as G,t as K}from"./useNodeUrlSelection-9ogG1-47.js";var q=m(`octagon-alert`,[[`path`,{d:`M12 16h.01`,key:`1drbdi`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z`,key:`1fd625`}]]);n();var J=new Set([`completed`,`failed`,`partially-failed`,`cancelled`]),ve=new Set([`done`,`failed`,`skipped`]);function Y(e){return!ve.has(e.phase)&&!J.has(e.jobState)}function X(e,t){let n=new Map,r=[...e].sort((e,t)=>e.createdAtMs-t.createdAtMs);for(let e of r){let r=J.has(e.state);for(let i of e.tasks)r&&i.finishedAtMs!==null&&t-i.finishedAtMs>6e4||n.set(i.packageName,{jobId:e.jobId,packageName:i.packageName,phase:i.phase,fromVersion:i.fromVersion,toVersion:i.toVersion,error:i.error,jobState:e.state,finishedAtMs:i.finishedAtMs})}return n}function ye(){let{data:e}=L({activeOnly:!0},{refetchOnWindowFocus:!1,refetchInterval:e=>(e.state.data?.length??0)>0?3e3:!1}),{map:t}=D(U.AddonsJobProgress,e=>e.job.jobId);return a(()=>{let n=new Map;for(let t of e??[])n.set(t.jobId,t);for(let[e,r]of t)n.set(e,r.job);return X([...n.values()],Date.now())},[e,t])}var be={queued:{icon:x,cls:`bg-muted text-foreground-subtle`,label:`queued`},fetching:{icon:g,cls:`bg-primary/10 text-primary`,label:`fetching`,spin:!0},staged:{icon:g,cls:`bg-primary/10 text-primary`,label:`staged`,spin:!0},validating:{icon:g,cls:`bg-primary/10 text-primary`,label:`validating`,spin:!0},applying:{icon:g,cls:`bg-primary/10 text-primary`,label:`applying`,spin:!0},restarting:{icon:g,cls:`bg-amber-500/10 text-amber-600 dark:text-amber-400`,label:`restarting`,spin:!0},applied:{icon:g,cls:`bg-primary/10 text-primary`,label:`finalizing`,spin:!0},done:{icon:E,cls:`bg-success/10 text-success`,label:`updated`},failed:{icon:q,cls:`bg-danger/10 text-danger`,label:`failed`},skipped:{icon:_,cls:`bg-muted text-foreground-subtle`,label:`skipped`}};function xe({progress:e}){let t=be[e.phase],n=t.icon,r=e.error??`${e.packageName}: ${e.fromVersion??`?`} → ${e.toVersion}`;return i(`span`,{"data-testid":`addon-job-progress`,className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded shrink-0 ${t.cls}`,title:r,children:[l(n,{className:`w-2.5 h-2.5 ${t.spin?`animate-spin`:``}`}),t.label,i(`span`,{className:`font-mono`,children:[`→ `,e.toVersion]})]})}function Se({packageName:e,currentVersion:t,installSource:n,onInstall:r,onClose:a,onSelect:s,selectedVersion:c}){let u=n===`upload`||n===`local`,{data:d,isLoading:f}=F({name:e});return i(`div`,{className:`fixed z-50 w-72 rounded-lg border border-border bg-surface shadow-xl overflow-hidden`,style:{top:`auto`,bottom:`auto`},ref:e=>{if(!e)return;let t=e.parentElement?.getBoundingClientRect();if(!t)return;let n=window.innerHeight-t.bottom,r=t.top;n<280&&r>n?(e.style.bottom=`${window.innerHeight-t.top+4}px`,e.style.top=`auto`):(e.style.top=`${t.bottom+4}px`,e.style.bottom=`auto`),e.style.right=`${window.innerWidth-t.right}px`},onClick:e=>e.stopPropagation(),children:[i(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border`,children:[l(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle font-medium`,children:`Versions`}),l(`button`,{type:`button`,onClick:a,className:`text-foreground-subtle hover:text-foreground`,children:l(V,{className:`h-3 w-3`})})]}),u&&i(`div`,{className:`flex items-start gap-2 px-3 py-2 border-b border-border bg-cyan-500/10 text-[10px]`,children:[l(k,{className:`h-3 w-3 mt-0.5 text-cyan-500 shrink-0`}),i(`div`,{className:`text-cyan-700 dark:text-cyan-200`,children:[i(`span`,{className:`font-semibold`,children:[n===`upload`?`Uploaded copy`:`Local copy`,` in place.`]}),` `,`Re-install `,l(`span`,{className:`font-mono`,children:t}),` from npm to track upstream releases again.`]})]}),f&&i(`div`,{className:`flex items-center justify-center gap-2 py-6 text-[10px] text-foreground-subtle`,children:[l(g,{className:`h-3.5 w-3.5 animate-spin`}),`Loading versions...`]}),d&&l(`div`,{className:`max-h-64 overflow-auto divide-y divide-border`,children:d.map(e=>{let n=e.version===t,a=s!==void 0&&e.version===c,d=/-(alpha|beta|rc|dev|canary|next)/i.test(e.version),f=i(o,{children:[l(`span`,{className:`font-mono flex-1 text-left ${n?`text-primary font-semibold`:d?`text-amber-400`:`text-foreground`}`,children:e.version}),n&&l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium bg-primary/10 text-primary`,children:`current`}),e.distTags.map(e=>l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium ${e===`latest`?`bg-emerald-500/15 text-emerald-400`:e===`beta`?`bg-amber-500/15 text-amber-400`:`bg-gray-500/15 text-gray-400`}`,children:e},e)),e.deprecated&&l(`span`,{className:`text-[9px] text-red-400 line-through`,children:`deprecated`}),l(`span`,{className:`text-[9px] text-foreground-subtle shrink-0`,children:new Date(e.publishedAt).toLocaleDateString()})]});return s?i(`button`,{type:`button`,"aria-label":`Select ${e.version}`,onClick:()=>s(e.version),className:`w-full flex items-center gap-2 px-3 py-2 text-[11px] ${a?`bg-primary/5`:`hover:bg-surface-hover`} transition-colors`,children:[f,a?l(E,{className:`h-3 w-3 text-primary shrink-0`}):l(`span`,{className:`w-3 shrink-0`})]},e.version):i(`div`,{className:`flex items-center gap-2 px-3 py-2 text-[11px] ${n?`bg-primary/5`:`hover:bg-surface-hover`} transition-colors`,children:[f,n&&!u?l(E,{className:`h-3 w-3 text-primary shrink-0`}):l(`button`,{type:`button`,onClick:()=>r(e.version),className:`shrink-0 rounded p-0.5 hover:bg-primary/20 text-foreground-subtle hover:text-primary transition-colors`,title:n?`Re-install ${e.version} from npm`:`Install ${e.version}`,children:l(y,{className:`h-3 w-3`})})]},e.version)})}),d&&d.length===0&&l(`div`,{className:`py-4 text-center text-[10px] text-foreground-subtle`,children:`No versions found`})]})}var Ce={queued:{icon:x,bg:`bg-muted text-foreground-subtle`,label:`queued`},updating:{icon:g,bg:`bg-primary/10 text-primary`,label:`updating`,spin:!0},"done-pending-restart":{icon:B,bg:`bg-amber-500/10 text-amber-700`,label:`pending restart`},done:{icon:E,bg:`bg-success/10 text-success`,label:`done`},failed:{icon:q,bg:`bg-danger/10 text-danger`,label:`failed`}};function Z({item:e}){let t=Ce[e.status],n=t.icon;return i(`span`,{className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded ${t.bg}`,title:e.error,children:[l(n,{className:`w-2.5 h-2.5 ${t.spin?`animate-spin`:``}`}),t.label]})}n();var Q=`device-export`;function we(e){return e.capabilities.some(e=>(typeof e==`string`?e:e.name)===Q)}function Te({isBundle:e,installSource:t,addonId:n,iconPath:r,color:a}){let[o,s]=c(!1),u=a?{backgroundColor:`${a.startsWith(`#`)?a:`#${a}`}26`}:void 0,f=e?`bg-indigo-500/20 text-indigo-700 dark:text-indigo-300`:`bg-purple-500/20 text-purple-700 dark:text-purple-300`,p=n&&r?d(`/api/addon-assets/${n}/${r}`):null,m=!!p&&!o;return i(`div`,{className:`relative flex-shrink-0`,children:[l(`div`,{className:`h-9 w-9 rounded-lg flex items-center justify-center ${u?``:f}`,style:u,children:m?l(`img`,{src:p,alt:n,className:`h-5 w-5`,onError:()=>s(!0)}):l(e?H:ue,{className:`h-4 w-4`})}),t===`local`&&l(`span`,{className:`absolute -top-1.5 -left-1.5 text-[7px] font-bold leading-none bg-orange-500 text-white px-1 py-0.5 rounded -rotate-12 shadow-sm`,children:`DEV`}),t===`npm`&&l(`span`,{className:`absolute -top-1 -left-1 w-4 h-4 rounded bg-[#cb3837] flex items-center justify-center -rotate-12 shadow-sm`,children:l(`svg`,{viewBox:`0 0 780 250`,className:`w-[11px] h-[11px]`,children:l(`path`,{fill:`#fff`,d:`M240 250h100V50h100v200h340V0H0v250z`})})}),t===`upload`&&l(`span`,{className:`absolute -top-1.5 -left-1.5 flex items-center justify-center h-4 w-4 rounded bg-cyan-500 -rotate-12 shadow-sm`,children:l(k,{className:`h-2.5 w-2.5 text-white`})})]})}function Ee({version:e,availableUpdate:t,selectedVersion:n,isUpdating:r,installSource:a,disabled:o,onUpdate:s,onOpenPicker:c,children:u}){if(r)return i(`span`,{className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border border-blue-500/30 bg-blue-500/10 text-blue-400 shrink-0`,children:[l(g,{className:`h-3 w-3 animate-spin`}),`Updating…`]});if(t){let r=n??t;return i(`div`,{className:`relative inline-flex items-center gap-1 shrink-0`,children:[s&&i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),s()},disabled:o,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-semibold border border-blue-500/30 bg-blue-500/10 text-blue-400 hover:bg-blue-500/20 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,title:`Update to ${r}`,children:[l(y,{className:`h-3 w-3`}),`Update`]}),i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),c()},disabled:o,"aria-label":`Select version to install`,title:`Installed ${e} — update available. Selected ${r}; tap to choose another version.`,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-bold font-mono border border-amber-500/40 bg-amber-500/15 text-amber-500 hover:bg-amber-500/25 animate-pulse disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,children:[l(`span`,{className:`font-normal opacity-70`,children:e}),l(`span`,{className:`font-normal opacity-70`,children:`→`}),r,l(f,{className:`h-3 w-3`})]}),u]})}return i(`div`,{className:`relative inline-flex items-center gap-1 shrink-0`,children:[i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),c()},disabled:o,className:[`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-bold font-mono border transition-colors disabled:opacity-50 disabled:cursor-not-allowed`,a===`local`?`border-orange-500/30 bg-orange-500/10 text-orange-400 hover:bg-orange-500/20`:`border-emerald-500/30 bg-emerald-500/10 text-emerald-400 hover:bg-emerald-500/20`].join(` `),title:`Version ${e} — tap to view all versions`,children:[e,l(f,{className:`h-3 w-3 opacity-50`})]}),u]})}function De({addonId:e}){let t=s(),{data:n=`inherit`}=w({addonId:e}),r=j({onSuccess:()=>{t.invalidateQueries({queryKey:[[`addons`,`getAddonAutoUpdate`]]})}});return l(`div`,{className:`flex rounded-lg border border-border overflow-hidden text-[10px] font-medium`,children:[`inherit`,`off`,`latest`,`beta`].map(t=>l(`button`,{type:`button`,onClick:n=>{n.stopPropagation(),r.mutate({addonId:e,channel:t})},disabled:r.isPending,className:`px-2.5 py-1 transition-colors capitalize ${n===t?t===`inherit`?`bg-gray-700/50 text-gray-700 dark:text-gray-300`:t===`off`?`bg-gray-700 text-gray-700 dark:text-gray-300`:t===`latest`?`bg-blue-500/20 text-blue-400`:`bg-amber-500/20 text-amber-400`:`bg-transparent text-foreground-subtle hover:bg-surface-hover`} ${t===`inherit`?``:`border-l border-border`}`,children:t},t))})}function Oe({addon:e,agents:t=[],clusterStatus:n,hideVersion:r,availableUpdate:a,onUpdate:d,isUpdating:m,jobProgress:h,bundle:g,bulkItem:_,disabledByBulk:v,isSystem:y}){let[b,x]=c(!1),[S,C]=c(!1),[w,T]=c(!1),[E,D]=c(null);u(()=>{D(null)},[a]);let O=E??a,[ce,k]=c(!1),[A,j]=c(!1),[M,N]=c(`logs`),P=s(),ue=he(),F=te(),{manifest:I}=e,L=e.installedOn??[],de=!g&&!I.protected&&I.removable!==!1,R=!!g,me=g?.displayName??I.name,U=g?.packageName??I.packageName,ge=g?.version??I.packageVersion??I.version,W=g?.installSource??e.installSource,G=g?g.bundle?.description??g.addons[0]?.manifest.description:I.description,K=pe({onSuccess:()=>{P.invalidateQueries({queryKey:[[`addons`]]}),P.invalidateQueries({queryKey:[[`addonPages`]]}),P.invalidateQueries({queryKey:[[`capabilities`]]})}}),J=z({onSuccess:()=>{P.invalidateQueries({queryKey:[[`addons`]]})}}),ve=oe({onSuccess:()=>{P.invalidateQueries({queryKey:[[`addons`]]}),P.invalidateQueries({queryKey:[[`addonPages`]]}),P.invalidateQueries({queryKey:[[`capabilities`]]}),P.invalidateQueries({queryKey:[[`integrations`]]})}}),Y=ne({onSuccess:()=>{P.invalidateQueries({queryKey:[[`addons`]]}),P.invalidateQueries({queryKey:[[`alerts`]]})}}),X=e.health,ye=X?.phase===`failed`&&!X.inGracePeriod,be=ye&&X?.nextRetryAt&&!X.retrying;return i(`div`,{className:`rounded-lg border bg-surface overflow-hidden ${ye?`border-red-500/50`:`border-border`}`,children:[ye&&X&&i(`div`,{className:`bg-danger/10 border-b border-danger/30 px-4 py-2.5 flex items-start gap-2.5`,children:[l(q,{className:`h-4 w-4 text-danger shrink-0 mt-0.5`}),i(`div`,{className:`flex-1 min-w-0`,children:[i(`div`,{className:`text-xs font-semibold text-danger`,children:[`Failed to load (attempt #`,X.retryCount,`)`]}),l(`div`,{className:`text-[11px] text-foreground mt-0.5 break-words font-mono`,children:X.lastError?.message??`Unknown error`}),be&&X.nextRetryAt&&i(`div`,{className:`text-[10px] text-foreground-subtle mt-1`,children:[`Auto-retry at `,new Date(X.nextRetryAt).toLocaleTimeString()]})]}),i(`button`,{type:`button`,disabled:Y.isPending||X.retrying,onClick:e=>{e.stopPropagation(),Y.mutate({packageName:U})},className:`inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-[11px] font-semibold border border-red-400/40 bg-red-400/10 text-red-700 dark:text-red-300 hover:bg-red-400/20 disabled:opacity-50 disabled:cursor-not-allowed transition-colors shrink-0`,title:`Reset retry counter and force immediate reload`,children:[l(B,{className:`h-3 w-3 ${Y.isPending||X.retrying?`animate-spin`:``}`}),`Retry now`]})]}),i(`div`,{className:`flex items-start gap-3 px-4 py-3`,children:[l(Te,{isBundle:R||!!I.components&&I.components.length>1,installSource:W,addonId:R?g.addons[0]?.manifest.id:I.id,iconPath:R?g.bundle?.icon??g.addons[0]?.manifest.icon:I.icon,color:R?g.addons[0]?.manifest.color:I.color}),i(`div`,{className:`flex-1 min-w-0`,children:[i(`div`,{className:`flex items-start justify-between gap-2`,children:[l(`span`,{className:`text-sm font-semibold text-foreground truncate min-w-0`,children:me}),!r&&l(Ee,{version:ge,availableUpdate:a,...O===void 0?{}:{selectedVersion:O},isUpdating:m,installSource:W,disabled:v,...d&&O!==void 0?{onUpdate:()=>d(O)}:{},onOpenPicker:()=>T(e=>!e),children:w&&l(Se,{packageName:U,currentVersion:ge,...W?{installSource:W}:{},...a!==void 0&&O!==void 0?{selectedVersion:O,onSelect:e=>{D(e),T(!1)}}:{},onInstall:e=>{T(!1),ve.mutate({packageName:U,version:e})},onClose:()=>T(!1)})})]}),i(`div`,{className:`flex flex-wrap items-center gap-x-1.5 gap-y-1 mt-0.5`,children:[U!==me&&l(`span`,{className:`text-[10px] text-foreground-subtle font-mono truncate max-w-full`,children:U}),R&&i(`span`,{className:`text-[10px] rounded-full bg-primary/10 text-primary px-2 py-0.5 font-medium shrink-0 inline-flex items-center gap-1`,children:[l(H,{className:`h-3 w-3`}),g.addons.length]}),y&&i(`span`,{className:`text-[10px] rounded-full bg-amber-500/15 text-amber-700 dark:text-amber-300 px-2 py-0.5 font-medium shrink-0 inline-flex items-center gap-1`,title:`System package — updating restarts the hub`,children:[l(B,{className:`h-3 w-3`}),`System`]}),_!=null&&l(Z,{item:_}),h!=null&&l(xe,{progress:h})]}),G&&l(`p`,{className:`text-[10px] text-foreground-subtle mt-1 line-clamp-1`,children:G}),!R&&e.process&&i(`div`,{className:`flex flex-wrap items-center gap-1.5 mt-1`,children:[l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium ${e.process.mode===`forked`?`bg-blue-500/15 text-blue-400`:`bg-gray-500/15 text-gray-400`}`,children:e.process.mode===`forked`?`forked`:`in-process`}),e.process.pid!=null&&i(`span`,{className:`text-[9px] font-mono text-foreground-subtle`,children:[`PID `,e.process.pid]}),l(`span`,{className:`text-[9px] rounded-full px-1.5 py-0.5 font-medium ${e.process.state===`running`?`bg-emerald-500/15 text-emerald-400`:e.process.state===`crashed`||e.process.state===`failed`?`bg-red-500/15 text-red-400`:`bg-gray-500/15 text-gray-400`}`,children:e.process.state})]})]})]}),!R&&i(`div`,{className:`flex items-center gap-1 px-4 py-1.5 border-t border-border/50 bg-surface-hover/20`,children:[i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),J.mutate({addonId:I.id})},disabled:J.isPending||v,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border border-border text-foreground-subtle hover:text-blue-400 hover:border-blue-500/30 hover:bg-blue-500/10 disabled:opacity-50 transition-colors`,children:[l(B,{className:`h-3 w-3 ${J.isPending?`animate-spin`:``}`}),`Restart`]}),i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),k(e=>!e)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${ce?`border-primary/30 bg-primary/10 text-primary`:`border-border text-foreground-subtle hover:text-foreground hover:border-primary/30 hover:bg-primary/10`}`,children:[l(se,{className:`h-3 w-3`}),`Logs`]}),!R&&i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),j(!0)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${A?`border-primary/30 bg-primary/10 text-primary`:`border-border text-foreground-subtle hover:text-foreground hover:border-primary/30 hover:bg-primary/10`}`,children:[l(fe,{className:`h-3 w-3`}),`Settings`]}),l(`div`,{className:`flex-1`}),de&&i(`button`,{type:`button`,onClick:async e=>{e.stopPropagation(),await F({title:`Uninstall ${I.name}?`,message:`This will remove the addon package and all its data. This action cannot be undone.`,confirmLabel:`Uninstall`,variant:`danger`})&&K.mutate({packageName:I.packageName})},disabled:K.isPending||v,className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border border-border text-foreground-subtle hover:text-red-400 hover:border-red-500/30 hover:bg-red-500/10 disabled:opacity-50 transition-colors`,children:[l(p,{className:`h-3 w-3`}),K.isPending?`Removing...`:`Uninstall`]})]}),n&&n.nodes.length>1&&!R&&i(`div`,{className:`border-t border-border px-4 py-2 bg-muted/10`,children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle mb-1.5`,children:`Cluster Deployment`}),l(`div`,{className:`space-y-1`,children:n.nodes.map(e=>i(`div`,{className:`flex items-center gap-2 text-[10px]`,children:[l(`div`,{className:`h-1.5 w-1.5 rounded-full shrink-0 ${e.status===`offline`?`bg-muted-foreground/30`:e.synced?`bg-success`:`bg-amber-500`}`}),l(`span`,{className:`font-medium text-foreground min-w-[60px]`,children:e.name}),l(`span`,{className:`font-mono text-foreground-subtle`,children:e.version}),!e.synced&&e.status!==`offline`&&l(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-400 border border-amber-500/20`,children:`outdated`}),e.status===`offline`&&l(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-muted text-muted-foreground`,children:`offline`}),e.synced&&e.status!==`offline`&&l(`span`,{className:`text-[9px] text-success`,children:`synced`})]},e.nodeId))})]}),ce&&!R&&i(`div`,{className:`border-t border-border`,children:[i(`div`,{className:`flex items-center px-4 py-1 bg-surface-hover/20 border-b border-border/50`,children:[i(`div`,{className:`flex rounded border border-border overflow-hidden text-[9px]`,children:[l(`button`,{type:`button`,onClick:()=>N(`logs`),className:`px-2 py-0.5 transition-colors ${M===`logs`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Logs`}),l(`button`,{type:`button`,onClick:()=>N(`events`),className:`px-2 py-0.5 border-l border-border transition-colors ${M===`events`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Events`})]}),l(`div`,{className:`flex-1`}),l(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),k(!1)},className:`text-foreground-subtle hover:text-foreground`,children:l(V,{className:`h-3.5 w-3.5`})})]}),M===`logs`&&l(re,{addonId:I.id,maxHeight:`max-h-64`,showFilters:!1}),M===`events`&&l(ae,{addonId:I.id,category:`addon.*`,maxHeight:`max-h-64`})]}),R&&i(o,{children:[l(`button`,{type:`button`,onClick:()=>x(e=>!e),className:`w-full flex items-center justify-center border-t border-border py-1 hover:bg-surface-hover/50 transition-colors`,children:l(b?le:f,{className:`h-3.5 w-3.5 text-foreground-subtle`})}),b&&l(`div`,{className:`border-t border-border px-3 py-2 space-y-2`,children:g.addons.map(e=>l(Oe,{addon:e,agents:t,hideVersion:!0},e.manifest.id))})]}),A&&!R&&l(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:()=>j(!1),children:i(`div`,{className:`w-full max-w-lg max-h-[80vh] rounded-xl border border-border bg-surface shadow-2xl flex flex-col overflow-hidden`,onClick:e=>e.stopPropagation(),children:[i(`div`,{className:`flex items-center justify-between px-5 py-3 border-b border-border flex-shrink-0`,children:[i(`div`,{className:`flex items-center gap-2`,children:[l(fe,{className:`h-4 w-4 text-primary`}),i(`h2`,{className:`text-sm font-semibold text-foreground`,children:[me,` Settings`]})]}),l(`button`,{onClick:()=>j(!1),className:`text-foreground-subtle hover:text-foreground transition-colors p-1 rounded`,children:l(V,{className:`h-4 w-4`})})]}),i(`div`,{className:`flex-1 overflow-y-auto px-5 py-4 space-y-4`,children:[l(`div`,{className:`text-[10px] text-foreground-subtle mb-2`,children:`Cluster-wide settings — one value for every node. Per-node settings live under Cluster → the node → Settings.`}),l(_e,{nodeId:null,addonIds:[I.id],level:`global`,fieldScope:`cluster`,emptyMessage:`This addon exposes no cluster-wide settings. Anything it can configure is per-node — open it from Cluster → the node → Settings.`}),we(I)&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Device export`}),l(ee,{addonId:I.id,onOpenDevice:e=>ue(`/devices/${e}`)})]}),W===`npm`&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Auto-Update`}),l(De,{addonId:I.id})]}),I.components&&I.components.length>0&&i(`div`,{children:[i(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:[`Components (`,I.components.length,`)`]}),l(`div`,{className:`flex flex-wrap gap-1`,children:I.components.map(e=>l(`span`,{className:`text-[10px] rounded bg-background border border-border px-1.5 py-0.5 text-foreground-subtle font-mono`,children:e},e))})]}),t.length>=2&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Installed on`}),i(`div`,{className:`flex items-center gap-1.5 flex-wrap`,children:[L.length===0&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Hub (local)`}),L.map(e=>l(`span`,{className:`rounded-full bg-surface-hover border border-border px-2 py-0.5 text-[10px] text-foreground-subtle`,children:e},e)),i(`div`,{className:`relative`,children:[i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),C(e=>!e)},className:`inline-flex items-center gap-1 rounded-full border border-dashed border-border px-2 py-0.5 text-[10px] text-foreground-subtle hover:text-foreground hover:border-primary transition-colors`,title:`Install on more agents`,children:[l(ie,{className:`h-3 w-3`}),`Add agent`]}),S&&i(`div`,{className:`absolute left-0 top-full mt-1 z-10 min-w-[160px] rounded-md border border-border bg-surface shadow-lg overflow-hidden`,children:[t.filter(e=>!e.isHub&&!L.includes(e.name)).map(e=>l(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),C(!1)},className:`w-full text-left px-3 py-1.5 text-[10px] text-foreground hover:bg-surface-hover transition-colors`,children:e.name},e.id)),t.filter(e=>!e.isHub&&!L.includes(e.name)).length===0&&l(`div`,{className:`px-3 py-1.5 text-[10px] text-foreground-subtle`,children:`No available agents`})]})]})]})]})]}),l(`div`,{className:`flex items-center justify-end px-5 py-3 border-t border-border flex-shrink-0`,children:l(`button`,{type:`button`,onClick:()=>j(!1),className:`rounded-lg border border-border px-3 py-1.5 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors`,children:`Close`})})]})})]})}n();var ke=`.tgz,.tar.gz,.zip`;function Ae({onUploadSuccess:n}){let[r,a]=c(!1),s=t(null),u=e(async e=>{a(!0);let t=new FormData;t.append(`file`,e);let r=localStorage.getItem(`camstack_admin_token`)??``;try{(await(await fetch(d(`/api/addons/upload`),{method:`POST`,headers:{Authorization:`Bearer ${r}`},body:t})).json()).success&&n()}finally{a(!1)}},[n]);return i(o,{children:[l(`input`,{ref:s,type:`file`,accept:ke,onChange:e(e=>{let t=e.target.files?.[0];t&&u(t),e.target.value=``},[u]),className:`hidden`}),i(`button`,{type:`button`,onClick:()=>s.current?.click(),disabled:r,className:`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md bg-surface hover:bg-surface-hover border border-border disabled:opacity-50 transition-colors`,children:[r?l(g,{className:`w-3.5 h-3.5 animate-spin`}):l(k,{className:`w-3.5 h-3.5`}),r?`Uploading...`:`Upload`]})]})}n();var je=[{seconds:900,label:`15m`},{seconds:3600,label:`1h`},{seconds:21600,label:`6h`},{seconds:43200,label:`12h`},{seconds:86400,label:`24h`}],Me=new Set([`@camstack/system`,`@camstack/types`,`@camstack/sdk`,`@camstack/shm-ring`,`@camstack/ui-library`]);function Ne(e){return e!==void 0&&Me.has(e)}var Pe={id:`hub`,name:`Hub`,isHub:!0,isOnline:!0};function Fe(e,t){let n=e??`hub-only`;return n===`any-node`?!0:n===`hub-only`?t:!t}function Ie(e){let t=e;if(!t?.manifest)return null;let n={...t.manifest,name:t.manifest.name??t.manifest.id,version:t.manifest.version??`0.0.0`,capabilities:t.manifest.capabilities??[]},r=t.process,i=r?{pid:r.pid,mode:r.mode===`forked`?`forked`:`in-process`,state:r.state??`unknown`}:void 0,a=t.health,o=t.declaration?.execution,s=t.manifest.execution,c=o?.placement??s?.placement;return{manifest:n,enabled:!0,source:t.source,installSource:t.installSource,installedOn:[],...i?{process:i}:{},hasBackup:t.hasBackup,...a?{health:a}:{},...c?{placement:c}:{}}}function Le(e){let t=new Map,n=[];for(let r of e){let e=r.manifest.packageName;if(!e){n.push(r);continue}let i=t.get(e);if(i)i.addons.push(r);else{let n=r.manifest.bundle,i={packageName:e,displayName:n?.displayName??r.manifest.packageDisplayName??r.manifest.name,version:r.manifest.packageVersion,addons:[r],...r.installSource===void 0?{}:{installSource:r.installSource},...n===void 0?{}:{bundle:n}};t.set(e,i)}}let r=[];for(let e of t.values())e.bundle!==void 0||e.addons.length>=2?r.push({bundle:e,representative:e.addons[0]}):r.push(e.addons[0]);return r.push(...n),r}function $(e){return`bundle`in e}function Re({addons:n,clusterStatus:o,selectedNode:d,onRefresh:f,isRefreshing:p}){let m=s(),[h,ee]=c(``),_=r(h),[x,S]=c(!1),w=t(null);u(()=>{if(!x)return;let e=e=>{w.current&&!w.current.contains(e.target)&&S(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[x]);let{data:T}=C({nodeId:d.id}),ne=a(()=>{let e=new Map;for(let t of T??[])e.set(t.name,t.latestVersion);return e},[T]),re=a(()=>(T??[]).filter(e=>!e.isSystem).length,[T]),[ie,D]=c(()=>new Set),[ae,se]=c(()=>new Map),ce=e(e=>{D(t=>new Set(t).add(e))},[]),k=e(e=>{D(t=>{if(!t.has(e))return t;let n=new Set(t);return n.delete(e),n})},[]),A=e((e,t)=>{se(n=>new Map(n).set(e,t))},[]),j=e(e=>{se(t=>{if(!t.has(e))return t;let n=new Map(t);return n.delete(e),n})},[]),le=me({onMutate:e=>{ce(e.name),j(e.name)},onSuccess:(e,t)=>{k(t.name);let n=e;if(n&&n.success===!1){A(t.name,n.error??`Update failed (no error message returned by server)`);return}m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]})},onError:(e,t)=>{k(t.name),A(t.name,e instanceof Error?e.message:String(e))}}),N=ye(),ue=t(new Set);u(()=>{let e=new Set;for(let[t,n]of N)Y(n)&&e.add(t);let t=[...ue.current].some(t=>!e.has(t));ue.current=e,t&&(m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]}))},[N,m]);let{data:F}=de(void 0),L=v({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),fe=O({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),{data:z,isFetching:pe}=P({query:_||void 0},{enabled:x}),V=b(),{data:H}=M(void 0),U=H?.requestedAt,[he,W]=c(null),[_e,G]=c(!1);u(()=>{if(H?.kind===`framework-bulk-update`&&H.requestedAt!==he){W(H.requestedAt),G(!0);let e=window.setTimeout(()=>G(!1),6e3);return()=>window.clearTimeout(e)}},[U,he,H]),te();let K=e(async()=>{let e=(T??[]).filter(e=>!e.isSystem);if(e.length!==0){if(!d.isHub){for(let t of e)await le.mutateAsync({name:t.name,version:t.latestVersion,nodeId:d.id});return}await V.mutateAsync({kind:`update`,targets:e.map(e=>({name:e.name,version:e.latestVersion})),nodeIds:[d.id]})}},[T,d.id,d.isHub,V,le]),q=oe({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addonPages`]]}),m.invalidateQueries({queryKey:[[`capabilities`]]}),m.invalidateQueries({queryKey:[[`integrations`]]})}}),[J,ve]=c(`type`),[X,be]=c(()=>typeof window>`u`?`grouped`:window.localStorage.getItem(`camstack.addons.viewMode`)===`flat`?`flat`:`grouped`),xe=e=>{be(e),typeof window<`u`&&window.localStorage.setItem(`camstack.addons.viewMode`,e)},[Se,Ce]=ge(),Z=Se.get(`capability`),Q=a(()=>{let e=n.filter(e=>!Ne(e.manifest.packageName));return d.isHub||(e=e.filter(e=>Fe(e.placement,d.isHub))),Z&&(e=e.filter(e=>(e.manifest.capabilities??[]).some(e=>(typeof e==`string`?e:e.name)===Z))),e},[n,d.isHub,Z]),we=()=>{let e=new URLSearchParams(Se);e.delete(`capability`),Ce(e,{replace:!0})},Te=X===`flat`?Q:Le(Q),Ee=a(()=>{let e=[...Te];switch(J){case`type`:e.sort((e,t)=>{let n=+!$(e),r=+!$(t);if(n!==r)return n-r;let i=$(e)?e.bundle.displayName:e.manifest.name,a=$(t)?t.bundle.displayName:t.manifest.name;return i.localeCompare(a)});break;case`name`:e.sort((e,t)=>{let n=$(e)?e.bundle.displayName:e.manifest.name,r=$(t)?t.bundle.displayName:t.manifest.name;return n.localeCompare(r)});break;case`source`:e.sort((e,t)=>{let n=$(e)?e.bundle.installSource??``:e.installSource??``,r=$(t)?t.bundle.installSource??``:t.installSource??``;return n.localeCompare(r)});break}return e},[Te,J]);return i(`div`,{className:`space-y-4`,children:[[...ae.entries()].map(([e,t])=>l(`div`,{className:`rounded-md border border-danger/30 bg-danger/5 px-3 py-2 text-[11px]`,children:i(`div`,{className:`flex items-start justify-between gap-3`,children:[i(`div`,{className:`space-y-0.5`,children:[i(`div`,{className:`font-medium text-danger`,children:[`Failed to update `,e]}),l(`div`,{className:`text-foreground-subtle font-mono`,children:t})]}),l(`button`,{type:`button`,onClick:()=>j(e),className:`text-foreground-subtle hover:text-foreground text-[10px]`,children:`dismiss`})]})},e)),i(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[i(`div`,{className:`flex items-center gap-1.5`,children:[l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Sort:`}),i(`select`,{value:J,onChange:e=>ve(e.target.value),className:`rounded-md border border-border bg-surface px-2 py-1.5 text-[11px] text-foreground focus:outline-none focus:border-primary/50`,children:[l(`option`,{value:`type`,children:`Bundles first`}),l(`option`,{value:`name`,children:`Name`}),l(`option`,{value:`source`,children:`Install source`})]})]}),i(`div`,{className:`flex items-center gap-1.5`,children:[l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`View:`}),l(`div`,{className:`flex rounded-md border border-border overflow-hidden text-[10px] font-medium`,children:[`grouped`,`flat`].map(e=>l(`button`,{type:`button`,onClick:()=>xe(e),className:`px-2.5 py-1.5 transition-colors capitalize ${X===e?`bg-primary/10 text-primary`:`bg-transparent text-foreground-subtle hover:bg-surface-hover`}`,title:e===`grouped`?`Group multi-addon packages into a bundle card`:`Show every addon as its own card`,children:e},e))})]}),d.isHub&&i(`div`,{className:`flex items-center gap-1.5`,children:[l(B,{className:`h-3 w-3 text-foreground-subtle`}),l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Auto-Update:`}),l(`div`,{className:`flex rounded-md border border-border overflow-hidden text-[10px] font-medium`,children:[`off`,`latest`,`beta`].map(e=>l(`button`,{type:`button`,onClick:()=>L.mutate({channel:e}),disabled:L.isPending,className:`px-2.5 py-1.5 transition-colors capitalize ${F?.channel===e?e===`off`?`bg-gray-700 text-gray-200`:e===`latest`?`bg-blue-500/20 text-blue-400`:`bg-amber-500/20 text-amber-400`:`bg-transparent text-foreground-subtle hover:bg-surface-hover`} ${e===`off`?``:`border-l border-border`}`,children:e},e))})]}),d.isHub&&i(`div`,{className:`flex items-center gap-1.5`,children:[l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Check every:`}),l(`select`,{className:`rounded-md border border-border bg-transparent px-1.5 py-1 text-[10px] font-medium text-foreground-subtle`,value:F?.updateCheckIntervalSeconds??21600,disabled:fe.isPending||F===void 0,onChange:e=>{F!==void 0&&fe.mutate({channel:F.channel,updateCheckIntervalSeconds:Number(e.target.value)})},children:je.map(e=>l(`option`,{value:e.seconds,children:e.label},e.seconds))})]}),re>0&&i(`button`,{type:`button`,onClick:()=>void K(),disabled:V.isPending,className:`flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] rounded-md bg-blue-500/10 text-blue-400 hover:bg-blue-500/20 border border-blue-500/30 disabled:opacity-50 transition-colors font-medium`,children:[V.isPending?l(g,{className:`w-3 h-3 animate-spin`}):l(y,{className:`w-3 h-3`}),V.isPending?`Updating…`:`Update All (${re})`]}),i(`button`,{type:`button`,onClick:f,disabled:p||V.isPending,className:`flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] rounded-md bg-surface hover:bg-surface-hover border border-border disabled:opacity-50 transition-colors`,children:[l(B,{className:`w-3 h-3 ${p?`animate-spin`:``}`}),`Refresh`]})]}),i(`div`,{className:`flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3`,children:[i(`div`,{className:`relative flex-1 min-w-0 sm:min-w-[200px]`,ref:w,children:[l(I,{className:`absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-foreground-subtle`}),l(`input`,{type:`text`,value:h,onChange:e=>{ee(e.target.value),S(!0)},onFocus:()=>S(!0),placeholder:`Search addons on npm...`,disabled:V.isPending,className:`w-full rounded-lg border border-border bg-background pl-9 pr-3 py-2 text-xs text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-primary disabled:opacity-50 disabled:cursor-not-allowed`}),pe&&l(g,{className:`absolute right-2.5 top-1/2 -translate-y-1/2 h-3 w-3 text-foreground-subtle animate-spin`}),x&&z&&z.length>0&&i(`div`,{className:`absolute left-0 right-0 top-full mt-1 z-40 rounded-lg border border-border bg-surface shadow-xl overflow-hidden`,children:[z.length>0&&i(`div`,{className:`px-3 py-1.5 text-[10px] uppercase tracking-wide text-foreground-subtle border-b border-border`,children:[`npm results (`,z.length,`)`]}),z&&z.length>0&&l(`div`,{className:`max-h-72 overflow-auto divide-y divide-border`,children:z.map(e=>i(`div`,{className:`flex items-center gap-3 px-3 py-2 hover:bg-surface-hover transition-colors`,children:[l(`div`,{className:`w-6 h-6 rounded-md bg-primary/10 flex items-center justify-center text-primary text-[9px] font-bold shrink-0`,children:e.name.replace(`@camstack/addon-`,``).charAt(0).toUpperCase()}),i(`div`,{className:`flex-1 min-w-0`,children:[i(`div`,{className:`flex items-baseline gap-2 min-w-0`,children:[l(`span`,{className:`text-[11px] font-semibold break-words`,children:e.name.replace(/^@camstack\/(addon-)?/,``)}),i(`span`,{className:`text-[10px] text-foreground-subtle shrink-0`,children:[`v`,e.version]})]}),l(`div`,{className:`font-mono text-[9px] text-foreground-subtle/80 truncate`,children:e.name}),e.description&&l(`div`,{className:`text-[10px] text-foreground-subtle truncate`,children:e.description})]}),e.installed?i(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 text-[10px] font-medium rounded-md border border-emerald-500/30 bg-emerald-500/10 text-emerald-400 shrink-0`,children:[l(E,{className:`h-3 w-3`}),e.installedVersion??`Installed`]}):i(`button`,{type:`button`,onClick:()=>q.mutate({packageName:e.name}),disabled:q.isPending,className:`inline-flex items-center gap-1 px-2 py-1 text-[10px] font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 transition-colors shrink-0`,children:[q.isPending?l(g,{className:`h-3 w-3 animate-spin`}):l(y,{className:`h-3 w-3`}),`Install`]})]},e.name))})]})]}),l(Ae,{onUploadSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),f()}})]}),Z&&i(`div`,{className:`flex items-center gap-2 px-3 py-2 rounded-lg bg-primary/10 border border-primary/30 text-sm`,children:[l(`span`,{className:`text-foreground-subtle`,children:`Filtering by capability:`}),l(`span`,{className:`font-mono text-primary font-semibold`,children:Z}),l(`button`,{type:`button`,onClick:we,className:`ml-auto text-xs text-foreground-subtle hover:text-foreground underline`,children:`Clear`})]}),_e&&i(`div`,{className:`fixed top-[calc(env(safe-area-inset-top)+1rem)] right-[calc(env(safe-area-inset-right)+1rem)] z-50 flex items-start gap-2 px-3 py-2.5 rounded-md border border-green-500/30 bg-green-500/10 shadow-lg backdrop-blur-sm max-w-sm pointer-events-auto`,children:[l(R,{className:`w-4 h-4 shrink-0 mt-0.5 text-green-400`}),i(`div`,{children:[l(`div`,{className:`text-[11px] font-semibold text-foreground`,children:`Bulk update completed`}),l(`div`,{className:`text-[10px] text-foreground-subtle mt-0.5`,children:`System packages updated — hub restarted successfully.`})]})]}),Q.length===0&&l(`div`,{className:`text-xs text-foreground-subtle`,children:n.length===0?`No addons installed`:Z?`No installed addons declare the "${Z}" capability. Browse the npm catalog above to find a compatible addon.`:`No addons compatible with ${d.name} (placement filter active)`}),l(`div`,{className:`space-y-2`,children:Ee.map(e=>{let t=$(e)?e.bundle.packageName:e.manifest.packageName,n=ne.get(t),r=$(e)?e.representative:e,i=n?e=>le.mutate({name:t,version:e,nodeId:d.id}):void 0,a=N.get(t)??null,s=a!==null&&Y(a);return l(Oe,{addon:r,clusterStatus:o?.[r.manifest.id],bundle:$(e)?e.bundle:void 0,availableUpdate:n,isUpdating:ie.has(t)||s,jobProgress:a,onUpdate:i,disabledByBulk:V.isPending},$(e)?t:e.manifest.id)})})]})}function ze(){let e=s(),{data:n,isLoading:r,isError:a}=S(),{data:o}=N(void 0),{nodes:c}=T(),{selection:d,selectNode:f,requestedNodeId:p}=K(c.length>0?c:[Pe]),m=d.node??Pe,g=m.id,ee=c.length>0?d.staleNodeId:null,_=h(),te=A(),v=_.isPending||te.isPending,y=async()=>{await _.mutateAsync({nodeId:g}),await te.mutateAsync(),e.invalidateQueries({queryKey:[[`addons`]]})},b=t(_);b.current=_;let x=t(p??`hub`);u(()=>{b.current.mutate({nodeId:x.current})},[]);let C=(n??[]).map(Ie).filter(e=>e!==null);return i(W,{children:[i(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[l(ce,{selectedNodeId:g,onSelect:f}),i(`div`,{className:`flex items-center gap-3 flex-wrap`,children:[!r&&!a&&i(`span`,{className:`text-[10px] rounded-full bg-primary/10 text-primary px-2 py-0.5 font-medium`,children:[C.length,` installed`]}),i(`button`,{type:`button`,onClick:()=>void y(),disabled:v,className:`inline-flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] rounded-md bg-surface hover:bg-surface-hover border border-border disabled:opacity-50 transition-colors`,title:`Re-fetch addons + check npm for new versions`,children:[l(B,{className:`w-3 h-3 ${v?`animate-spin`:``}`}),`Check for updates`]})]})]}),l(G,{staleNodeId:ee,shownNodeName:m.name}),!m.isHub&&i(`div`,{className:`rounded-md border border-warning/30 bg-warning/5 px-3 py-2 text-[11px] text-foreground-subtle`,children:[`Showing only addons compatible with`,` `,l(`span`,{className:`font-medium text-foreground`,children:m.name}),` — agents only run`,` `,l(`code`,{className:`font-mono`,children:`agent-only`}),` and`,` `,l(`code`,{className:`font-mono`,children:`any-node`}),` addons. Install / uninstall is hub-driven; agents auto-sync from the hub.`]}),r&&l(`div`,{className:`text-xs text-foreground-subtle animate-pulse`,children:`Loading…`}),a&&l(`div`,{className:`text-xs text-danger`,children:`Failed to load addons`}),!r&&!a&&l(Re,{addons:C,clusterStatus:o,selectedNode:m,onRefresh:()=>void y(),isRefreshing:v})]})}export{ze as AddonsPage};
@@ -1 +0,0 @@
1
- import{S as e,x as t}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{m as n}from"./index-BTdhzpJ6.js";import{t as r}from"./StableTabPanel-Dc954AQl.js";function i({tabs:i,defaultTab:a}){let[o,s]=n(),c=o.get(`tab`),l=a??i[0]?.id??``,u=i.some(e=>e.id===c)?c:l,d=i.find(e=>e.id===u)??i[0],f=e=>{let t=new URLSearchParams(o);if(e!==u)for(let e of d?.ownedParams??[])t.delete(e);t.set(`tab`,e),s(t,{replace:!0})};return e(`div`,{className:`space-y-3`,children:[t(`div`,{className:`flex border-b border-border overflow-x-auto`,children:i.map(n=>{let r=n.icon;return e(`button`,{onClick:()=>f(n.id),className:`flex shrink-0 items-center gap-1.5 whitespace-nowrap px-3 py-2 text-xs font-medium border-b-2 transition-colors ${n.id===u?`border-primary text-primary`:`border-transparent text-foreground-subtle hover:text-foreground`}`,children:[r&&t(r,{className:`h-3.5 w-3.5`}),n.label]},n.id)})}),t(r,{tabKey:u,children:d?.content})]})}export{i as t};
@@ -1,3 +0,0 @@
1
- import{I as e,K as t,Q as n,S as r,W as i,a,b as o,q as s,t as c,x as l,z as u}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{W as d,Z as f,at as p,ct as m,st as h,vt as g,yt as _}from"./player-overlays-BiMOywnH.js";import{$t as v,Au as y,Cn as b,Et as x,Hi as S,Hu as C,Jt as w,Kt as T,Qt as E,Sn as D,Tt as O,Ul as k,Vu as A,Xt as j,Zt as M,Zu as N,_n as P,bd as F,bn as I,ed as ee,gn as L,gu as R,hu as te,j as z,nu as B,qt as V,rd as H,ru as U,tn as W,un as G,vu as K,yl as ne}from"./src-BIIk_uZx.js";import{t as re}from"./boxes-j_W4wNc5.js";import{t as ie}from"./send-BJx_S3it.js";import{_n as q}from"./src-BMvSPnxA.js";import{l as J}from"./index-BTdhzpJ6.js";import{t as Y}from"./AdminPage-CiKtOLQm.js";import{t as ae}from"./AdminTabs-C21VrmV_.js";var oe=_(`message-square-plus`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}],[`path`,{d:`M12 8v6`,key:`1ib9pf`}],[`path`,{d:`M9 11h6`,key:`1fldmi`}]]);n();var se=[`llm`,`listProfiles`],ce=[`llm`,`listProfileKinds`],le=[`llm`,`getDefaults`],ue=[`llm`,`listRuntimeNodes`],de=[`llm`,`listModelCatalog`],fe=[`llm`,`getUsage`],pe=[{purpose:`vision`,visionOnly:!0},{purpose:`text`,visionOnly:!1}],me=new Map(Object.entries({openai:H,anthropic:H,google:H,"openai-compatible":te,"managed-local":ee,"apple-foundation":ee}));function he(e){return me.get(e)??null}function X(e){return typeof e==`string`&&e.length>0?e:void 0}function Z(e){if(typeof e==`number`&&Number.isFinite(e))return e;if(typeof e==`string`&&e.trim()!==``){let t=Number(e);return Number.isFinite(t)?t:void 0}}function Q(e){return e===!0}function ge(e){return{model:e.model,baseUrl:e.baseUrl,apiKey:e.apiKey,supportsVision:e.supportsVision,temperature:e.temperature,topP:e.topP,topK:e.topK,maxTokens:e.maxTokens,contextLength:e.contextLength,systemPrompt:e.systemPrompt,timeoutMs:e.timeoutMs,connectTimeoutMs:e.connectTimeoutMs,firstTokenTimeoutMs:e.firstTokenTimeoutMs,idleTimeoutMs:e.idleTimeoutMs,retryEnabled:e.retry.enabled,retryMaxAttempts:e.retry.maxAttempts,toolsEnabled:e.toolsEnabled,contextSize:e.runtime?.contextSize,gpuLayers:e.runtime?.gpuLayers,threads:e.runtime?.threads,parallel:e.runtime?.parallel,idleStopMinutes:e.runtime?.idleStopMinutes,batchSize:e.runtime?.batchSize,ubatchSize:e.runtime?.ubatchSize,flashAttention:e.runtime?.flashAttention,mlock:e.runtime?.mlock,noMmap:e.runtime?.noMmap,cacheTypeK:e.runtime?.cacheTypeK,cacheTypeV:e.runtime?.cacheTypeV,extraArgs:be(e.runtime?.extraArgs??[])}}var _e=[`f32`,`f16`,`q8_0`,`q5_1`,`q5_0`,`q4_1`,`q4_0`];function ve(e){return typeof e==`string`&&_e.includes(e)?e:void 0}function ye(e){let t=[],n=``,r=null;for(let i of e){if(r!==null){i===r?r=null:n+=i;continue}if(i===`"`||i===`'`){r=i;continue}if(/\s/.test(i)){n!==``&&t.push(n),n=``;continue}n+=i}return n!==``&&t.push(n),t}function be(e){return e.map(e=>/\s/.test(e)?`"${e}"`:e).join(` `)}var xe=[`--jinja`,`--cont-batching`];function Se(e,t,n){let r=Z(e.threads),i=Z(e.batchSize),a=Z(e.ubatchSize),o=ve(e.cacheTypeK),s=ve(e.cacheTypeV);return{nodeId:t,engine:`llama-cpp`,model:n,extraArgs:[...ye(X(e.extraArgs)??``)],contextSize:Z(e.contextSize)??4096,gpuLayers:Z(e.gpuLayers)??0,...r===void 0?{}:{threads:r},parallel:Z(e.parallel)??1,...i===void 0?{}:{batchSize:i},...a===void 0?{}:{ubatchSize:a},flashAttention:Q(e.flashAttention),mlock:Q(e.mlock),noMmap:Q(e.noMmap),...o===void 0?{}:{cacheTypeK:o},...s===void 0?{}:{cacheTypeV:s},autoStart:Q(e.autoStart),idleStopMinutes:Z(e.idleStopMinutes)??30}}function Ce(e,t,n,r,i){let a={id:n?.id??crypto.randomUUID(),name:t,kind:e,addonId:`ai`,enabled:n?.enabled??!0,model:X(r.model)??n?.model??``,supportsVision:i?.supportsVision??Q(r.supportsVision),timeoutMs:Z(r.timeoutMs)??q.totalMs,connectTimeoutMs:Z(r.connectTimeoutMs)??q.connectMs,firstTokenTimeoutMs:Z(r.firstTokenTimeoutMs)??q.firstTokenMs,idleTimeoutMs:Z(r.idleTimeoutMs)??q.idleMs,retry:{enabled:Q(r.retryEnabled),maxAttempts:Z(r.retryMaxAttempts)??1},toolsEnabled:Q(r.toolsEnabled)},o=X(r.baseUrl),s=X(r.apiKey),c=Z(r.temperature),l=Z(r.topP),u=Z(r.topK),d=Z(r.maxTokens),f=Z(r.contextLength),p=X(r.systemPrompt);return{...a,...o===void 0?{}:{baseUrl:o},...s===void 0?{}:{apiKey:s},...c===void 0?{}:{temperature:c},...l===void 0?{}:{topP:l},...u===void 0?{}:{topK:u},...d===void 0?{}:{maxTokens:d},...f===void 0?{}:{contextLength:f},...p===void 0?{}:{systemPrompt:p},...i===void 0?{}:{model:i.modelId,runtime:Se(r,i.nodeId,i.model)}}}function we(e){let t=new Map;for(let n of e){let e=t.get(n.addonId)??[];e.push(n),t.set(n.addonId,e)}return[...t.entries()].map(([e,t])=>({addonId:e,kinds:t}))}var Te=`apple-system`;function Ee(e,t,n,r){return{...Ce(`apple-foundation`,e,t,n),model:Te,supportsVision:!1,appleFoundation:{nodeId:r}}}var De={deviceNotEligible:{key:`ai.appleNotEligible`,text:`not eligible`,tone:`default`},appleIntelligenceNotEnabled:{key:`ai.appleIntelligenceOff`,text:`Apple Intelligence off`,tone:`warning`},modelNotReady:{key:`ai.appleModelNotReady`,text:`model downloading`,tone:`warning`},osTooOld:{key:`ai.appleOsTooOld`,text:`macOS too old`,tone:`default`},helperMissing:{key:`ai.appleHelperMissing`,text:`helper missing`,tone:`danger`},helperCrashed:{key:`ai.appleHelperCrashed`,text:`helper crashed`,tone:`danger`}};function Oe(e){let t=t=>({nodeId:e.nodeId,selectable:!1,labelKey:`ai.appleUnknown`,labelDefault:`unknown`,detail:t,tone:`default`});if(!e.reachable)return t(e.error??null);let n=e.apple;if(n===void 0)return t(null);switch(n.state){case`available`:return{nodeId:e.nodeId,selectable:!0,labelKey:`ai.appleAvailable`,labelDefault:`available`,detail:`macOS ${n.osVersion} · ${n.imageInput?`text + images`:`text only`}`,tone:`success`};case`unavailable`:{let t=De[n.reason];return{nodeId:e.nodeId,selectable:!1,labelKey:t.key,labelDefault:t.text,detail:n.detail,tone:t.tone}}case`unsupported-platform`:return{nodeId:e.nodeId,selectable:!1,labelKey:`ai.appleNotMac`,labelDefault:`not a Mac`,detail:n.platform,tone:`default`};case`unknown`:return t(n.error)}}var ke=2e3;function $(e){return`${(e/1e9).toFixed(2)} GB`}function Ae(e){return e===null?``:e.model.kind===`catalog`?`catalog:${e.model.catalogId}`:e.model.kind===`path`?`node:${e.modelId}`:`custom`}function je({nodeId:e,value:t,onChange:n}){let{t:o}=J(),u=p(),[d,f]=s(``),[m,h]=s(null),[g,_]=s(!1),v=a({queryKey:de,queryFn:()=>u.trpcClient.llm.listModelCatalog.query({})}),x=a({queryKey:[`llm`,`listNodeModels`,e],queryFn:()=>u.trpcClient.llm.listNodeModels.query({nodeId:e})}),S=c({mutationFn:e=>u.trpcClient.llm.resolveModelRef.mutate(e),onSuccess:e=>{h(e),_(!1),e.ok&&n({model:e.model,modelId:e.label,supportsVision:e.purpose===`vision`})}}),C=c({mutationFn:t=>u.trpcClient.llm.installModel.mutate({nodeId:e,model:t}),onSuccess:()=>{_(!0),x.refetch()}}),w=a({queryKey:ue,enabled:C.isPending,refetchInterval:C.isPending?ke:!1,queryFn:()=>u.trpcClient.llm.listRuntimeNodes.query({})}).data?.find(t=>t.nodeId===e)?.status?.download,T=i(()=>{let t=(v.data??[]).map(e=>({value:`catalog:${e.id}`,label:`${e.label} · ${e.quantization} · ${$(e.sizeBytes)}`})),n=(x.data??[]).filter(e=>e.catalogId===void 0&&e.path!==void 0).map(t=>({value:`node:${t.file}`,label:o(`ai.onNode`,`{{file}} · {{size}} · on {{node}}`,{file:t.file,size:$(t.sizeBytes),node:e})})),r=m?.ok===!0?[{value:`custom`,label:`${m.label} · ${$(m.totalBytes)}`}]:[];return[{value:``,label:o(`ai.selectModel`,`Select a model…`)},...t,...n,...r]},[v.data,x.data,m,e,o]),E=e=>{if(e===``){n(null);return}if(e===`custom`){if(m?.ok!==!0)return;n({model:m.model,modelId:m.label,supportsVision:m.purpose===`vision`});return}if(e.startsWith(`catalog:`)){let t=e.slice(8),r=v.data?.find(e=>e.id===t);n({model:{kind:`catalog`,catalogId:t},modelId:t,supportsVision:r?.purpose===`vision`});return}let t=e.slice(5),r=x.data?.find(e=>e.file===t);r?.path!==void 0&&n({model:{kind:`path`,path:r.path},modelId:t,supportsVision:!1})},O=e=>{d.trim()!==``&&S.mutate({ref:d.trim(),...e===void 0?{}:{maxBytes:e}})};return r(`div`,{className:`space-y-2`,children:[r(`div`,{children:[l(`label`,{className:`mb-1 block text-[11px] font-medium text-foreground`,htmlFor:`ai-model`,children:o(`ai.model`,`Model`)}),l(D,{id:`ai-model`,value:Ae(t),options:T,onChange:e=>E(e.target.value)})]}),r(`div`,{className:`rounded-md border border-border bg-surface-subtle px-3 py-2.5`,children:[l(`div`,{className:`mb-1 text-[11px] font-medium text-foreground`,children:o(`ai.hfTitle`,`Add a model from Hugging Face`)}),l(`p`,{className:`mb-2 text-[10px] leading-relaxed text-foreground-subtle`,children:o(`ai.hfHint`,`Paste a GGUF file URL, or type org/repo — add :QUANT (e.g. unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q4_K_M) when the repo publishes more than one quantization.`)}),r(`div`,{className:`flex gap-2`,children:[l(W,{value:d,onChange:e=>f(e.target.value),placeholder:`unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q4_K_M`,onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),O())}}),r(b,{size:`sm`,variant:`secondary`,type:`button`,disabled:d.trim()===``||S.isPending,onClick:()=>O(),children:[S.isPending?l(y,{className:`h-3.5 w-3.5 animate-spin`}):l(U,{className:`h-3.5 w-3.5`}),o(`ai.hfCheck`,`Check`)]})]}),S.isError&&l(`p`,{className:`mt-2 text-[11px] text-danger`,children:S.error instanceof Error?S.error.message:o(`common.error`,`Error`)}),m?.ok===!1&&r(`div`,{className:`mt-2 rounded-md border border-danger/40 bg-danger/10 px-2.5 py-2`,children:[l(`p`,{className:`text-[11px] text-danger`,children:m.message}),m.candidates!==void 0&&m.candidates.length>0&&l(`div`,{className:`mt-1.5 flex flex-wrap gap-1`,children:m.candidates.map(e=>l(`button`,{type:`button`,className:`rounded border border-border bg-surface px-1.5 py-0.5 text-[10px] text-foreground hover:border-primary/50`,onClick:()=>{let t=`${d.trim().split(`:`)[0]??``}:${e}`;f(t),S.mutate({ref:t})},children:e},e))}),m.requiredBytes!==void 0&&l(b,{size:`sm`,variant:`secondary`,type:`button`,className:`mt-2`,onClick:()=>O(m.requiredBytes),children:o(`ai.hfOverride`,`Install anyway ({{size}})`,{size:$(m.requiredBytes)})})]}),m?.ok===!0&&r(`div`,{className:`mt-2 rounded-md border border-border bg-surface px-2.5 py-2`,children:[r(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[l(`span`,{className:`text-[11px] font-medium text-foreground`,children:m.label}),l(L,{variant:m.purpose===`vision`?`info`:`default`,children:m.purpose}),l(L,{variant:`default`,children:$(m.totalBytes)})]}),m.extraFilenames.length>0&&l(`p`,{className:`mt-1 text-[10px] text-foreground-subtle`,children:o(`ai.hfExtras`,`Also downloads: {{files}}`,{files:m.extraFilenames.join(`, `)})}),r(`div`,{className:`mt-2 flex items-center gap-2`,children:[r(b,{size:`sm`,type:`button`,disabled:C.isPending||g,onClick:()=>C.mutate(m.model),children:[C.isPending?l(y,{className:`h-3.5 w-3.5 animate-spin`}):l(N,{className:`h-3.5 w-3.5`}),g?o(`ai.hfInstalled`,`Downloaded`):o(`ai.hfInstall`,`Download to {{node}}`,{node:e})]}),w!==void 0&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:w.phase===`verifying`?o(`ai.hfVerifying`,`verifying {{file}}…`,{file:w.file}):o(`ai.hfDownloading`,`{{file}} ({{index}}/{{count}}) — {{done}}{{total}}`,{file:w.file,index:w.fileIndex,count:w.fileCount,done:$(w.downloadedBytes),total:w.totalBytes===void 0?``:` / ${$(w.totalBytes)}`})})]}),C.isError&&l(`p`,{className:`mt-1.5 text-[11px] text-danger`,children:C.error instanceof Error?C.error.message:o(`common.error`,`Error`)})]})]})]})}function Me({value:e,onChange:t}){let{t:n}=J(),i=p(),o=a({queryKey:ue,queryFn:()=>i.trpcClient.llm.listRuntimeNodes.query({})});return r(`div`,{children:[l(`div`,{className:`mb-1 text-[11px] font-medium text-foreground`,children:n(`ai.appleNode`,`Mac that runs it`)}),o.isPending&&r(`div`,{className:`flex items-center gap-1.5 text-[11px] text-foreground-subtle`,children:[l(y,{className:`h-3.5 w-3.5 animate-spin`}),n(`ai.appleAsking`,`Asking the nodes…`)]}),o.isError&&l(`p`,{className:`text-[11px] text-danger`,children:o.error instanceof Error?o.error.message:n(`ai.runtimesFailed`,`Failed to read runtime nodes`)}),o.isSuccess&&o.data.length===0&&l(`p`,{className:`text-[11px] text-foreground-subtle`,children:n(`ai.noRuntimes`,`No node advertises the llm-runtime capability.`)}),o.isSuccess&&o.data.length>0&&l(`div`,{role:`radiogroup`,className:`space-y-1.5`,children:o.data.map(i=>{let a=Oe(i),o=a.nodeId===e;return r(`button`,{type:`button`,role:`radio`,"aria-checked":o,disabled:!a.selectable&&!o,onClick:()=>t(a.nodeId),className:`flex w-full items-center justify-between gap-2 rounded-md border px-3 py-2 text-left text-xs transition-colors disabled:cursor-not-allowed disabled:opacity-60 ${o?`border-primary bg-primary/10`:`border-border bg-surface hover:bg-surface-hover`}`,children:[r(`span`,{className:`min-w-0`,children:[l(`span`,{className:`block font-medium text-foreground`,children:a.nodeId}),a.detail!==null&&l(`span`,{className:`block truncate text-[10px] text-foreground-subtle`,children:a.detail})]}),l(L,{variant:a.tone,children:n(a.labelKey,a.labelDefault)})]},a.nodeId)})}),l(`p`,{className:`mt-1.5 text-[10px] leading-relaxed text-foreground-subtle`,children:n(`ai.appleHint`,`Text only for now — notification titles and summaries. Apple refuses prompts framed as surveillance; when it does, the next profile in the chain answers instead.`)})]})}n();function Ne({kind:e,className:t}){let n=he(e.kind);return n===null?l(`span`,{className:t,children:e.icon}):l(n,{className:t})}function Pe({kinds:e,onPick:t,onCancel:n}){let{t:a}=J(),o=i(()=>we(e),[e]);return l(T,{open:!0,onOpenChange:e=>!e&&n(),children:r(w,{width:`lg`,placement:`sheet-on-mobile`,scroll:`body`,children:[l(M,{children:l(E,{children:a(`ai.chooseKind`,`Choose a profile type`)})}),r(V,{className:`space-y-4 pr-1`,children:[o.length===0&&l(`p`,{className:`text-xs text-foreground-subtle`,children:a(`ai.noKinds`,`No AI provider is installed.`)}),o.map(e=>r(`div`,{children:[l(`div`,{className:`mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle`,children:e.addonId}),l(`div`,{className:`grid grid-cols-2 gap-2 sm:grid-cols-3`,children:e.kinds.map(n=>r(`button`,{type:`button`,onClick:()=>t(n),className:`flex flex-col items-center gap-1.5 rounded-lg border border-border bg-surface px-3 py-3 text-xs transition-colors hover:border-primary/50 hover:bg-surface-hover`,children:[l(Ne,{kind:n,className:`h-5 w-5 text-foreground-subtle`}),l(`span`,{className:`font-medium text-foreground`,children:n.label})]},`${e.addonId}:${n.kind}`))})]},e.addonId))]}),l(j,{children:l(b,{size:`sm`,variant:`secondary`,type:`button`,onClick:n,children:a(`common.cancel`,`Cancel`)})})]})})}function Fe({kind:e,existing:t,onSave:n,onCancel:a,saving:c,error:u}){let{t:d}=J(),f=e.kind===`managed-local`,p=e.kind===`apple-foundation`,[m,h]=s(t?.appleFoundation?.nodeId??null),[g,_]=s(t?.name??e.label),[v,x]=s(()=>t===null?{}:ge(t)),[S,C]=s(t?.runtime?.nodeId??`hub`),[D,O]=s(()=>t?.runtime===void 0?null:{model:t.runtime.model,modelId:t.model,supportsVision:t.supportsVision}),k=i(()=>ye(X(v.extraArgs)??``),[v.extraArgs]),A=()=>{if(p){if(m===null)return;n(Ee(g,t,v,m));return}if(!f){n(Ce(e.kind,g,t,v));return}D!==null&&n(Ce(e.kind,g,t,v,{nodeId:S,model:D.model,modelId:D.modelId,supportsVision:D.supportsVision}))},N=c||g.trim()===``||f&&D===null||p&&m===null;return l(T,{open:!0,onOpenChange:e=>!e&&a(),children:r(w,{width:`lg`,placement:`sheet-on-mobile`,scroll:`body`,children:[l(M,{children:r(E,{className:`flex items-center gap-2`,children:[l(Ne,{kind:e,className:`h-4 w-4 text-foreground-subtle`}),t===null?d(`ai.newProfile`,`New {{kind}} profile`,{kind:e.label}):d(`ai.editProfile`,`Edit {{name}}`,{name:t.name})]})}),r(V,{className:`space-y-3 pr-1`,children:[u!==null&&l(`div`,{className:`rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-xs text-danger`,children:u}),r(`div`,{children:[l(`label`,{className:`mb-1 block text-[11px] font-medium text-foreground`,htmlFor:`ai-profile-name`,children:d(`ai.name`,`Name`)}),l(W,{id:`ai-profile-name`,value:g,onChange:e=>_(e.target.value),placeholder:e.label})]}),f&&r(o,{children:[l(z,{selectedNodeId:S,onSelect:C,label:d(`ai.runtimeNode`,`Runtime node`),alwaysShow:!0}),l(je,{nodeId:S,value:D,onChange:O}),r(`div`,{children:[l(`label`,{className:`mb-1 block text-[11px] font-medium text-foreground`,htmlFor:`ai-extra-args`,children:d(`ai.extraArgs`,`Additional llama-server arguments`)}),l(W,{id:`ai-extra-args`,value:X(v.extraArgs)??``,onChange:e=>x({...v,extraArgs:e.target.value}),placeholder:xe.join(` `)}),k.length>0&&l(`div`,{className:`mt-1 flex flex-wrap gap-1`,children:k.map((e,t)=>l(L,{variant:`default`,children:e},`${e}-${String(t)}`))}),l(`p`,{className:`mt-1 text-[10px] leading-relaxed text-foreground-subtle`,children:d(`ai.extraArgsHint`,`Flags this form does not already own. Vision models generally need --jinja; some language-only models do not like it. Context size, GPU layers, parallel slots, flash attention and the KV-cache types are set in the fields below — repeating one here is rejected at start.`)})]})]}),p&&l(Me,{value:m,onChange:h}),l(G,{schema:e.configSchema,values:v,onChange:x}),t!==null&&l(`p`,{className:`text-[10px] text-foreground-subtle`,children:d(`ai.secretHint`,`A stored API key is never shown. Leave it as-is to keep it; type a new value to replace it.`)})]}),r(j,{children:[f&&D===null&&l(L,{variant:`warning`,children:d(`ai.pickModelFirst`,`pick a model`)}),p&&m===null&&l(L,{variant:`warning`,children:d(`ai.pickAppleNodeFirst`,`pick a Mac`)}),l(b,{size:`sm`,variant:`secondary`,type:`button`,onClick:a,children:d(`common.cancel`,`Cancel`)}),r(b,{size:`sm`,type:`button`,disabled:N,onClick:A,children:[c&&l(y,{className:`h-3.5 w-3.5 animate-spin`}),t===null?d(`ai.createProfile`,`Create profile`):d(`ai.saveChanges`,`Save changes`)]})]})]})})}n();function Ie(e){return[{key:`name`,header:e.t(`ai.colProfile`,`Profile`),render:t=>{let n=e.kindByName.get(t.kind);return r(`span`,{className:`flex items-center gap-2`,children:[l(`span`,{className:`flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-surface`,title:n?.label??t.kind,children:n===void 0?l(`span`,{className:`text-xs text-foreground-subtle`,children:`?`}):l(Ne,{kind:n,className:`h-4 w-4 text-foreground-subtle`})}),r(`span`,{className:`min-w-0`,children:[l(`span`,{className:`block truncate text-sm font-medium text-foreground`,children:t.name}),e.testResult?.id===t.id&&l(`span`,{className:`block truncate text-[10px] ${e.testResult.ok?`text-success`:`text-danger`}`,children:e.testResult.text})]})]})}},{key:`kind`,header:e.t(`ai.colKind`,`Kind`),nowrap:!0,render:t=>l(`span`,{className:`text-[11px] text-foreground-subtle`,children:e.kindByName.get(t.kind)?.label??t.kind})},{key:`model`,header:e.t(`ai.colModel`,`Model`),render:e=>l(`span`,{className:`text-[11px] text-foreground`,children:e.model})},{key:`vision`,header:e.t(`ai.colVision`,`Vision`),align:`center`,nowrap:!0,render:t=>t.supportsVision?l(L,{variant:`info`,style:`outline`,children:e.t(`ai.vision`,`vision`)}):l(`span`,{className:`text-[11px] text-foreground-subtle`,children:`—`})},{key:`node`,header:e.t(`ai.colNode`,`Node`),nowrap:!0,render:e=>e.runtime===void 0?l(`span`,{className:`text-[11px] text-foreground-subtle`,children:`—`}):l(L,{variant:`default`,children:e.runtime.nodeId})},{key:`enabled`,header:e.t(`ai.colOn`,`On`),align:`center`,nowrap:!0,render:t=>l(v,{checked:t.enabled,onCheckedChange:()=>e.onToggle(t),"aria-label":`toggle ${t.name}`})},{key:`actions`,header:``,align:`right`,nowrap:!0,render:t=>r(`span`,{className:`flex items-center justify-end gap-1`,children:[l(b,{size:`sm`,variant:`ghost`,type:`button`,onClick:()=>e.onTest(t),title:e.t(`ai.test`,`Test`),children:e.testingId===t.id?l(y,{className:`h-3.5 w-3.5 animate-spin`}):l(ie,{className:`h-3.5 w-3.5`})}),l(b,{size:`sm`,variant:`ghost`,type:`button`,disabled:!e.kindByName.has(t.kind),onClick:()=>e.onEdit(t),title:e.t(`common.edit`,`Edit`),children:l(K,{className:`h-3.5 w-3.5`})}),l(b,{size:`sm`,variant:`ghost`,type:`button`,onClick:()=>e.onDelete(t),title:e.t(`common.delete`,`Delete`),children:l(h,{className:`h-3.5 w-3.5 text-danger`})})]})}]}function Le(){let{t:e}=J(),t=p(),[n,o]=s({mode:`closed`}),[u,d]=s(null),[f,m]=s(null),h=a({queryKey:se,queryFn:()=>t.trpcClient.llm.listProfiles.query({})}),g=a({queryKey:ce,queryFn:async()=>(await t.trpcClient.llm.listProfileKinds.query({})).map(e=>({...e,configSchema:e.configSchema}))}),_=()=>{h.refetch()},v=c({mutationFn:e=>t.trpcClient.llm.upsertProfile.mutate({profile:e}),onSuccess:()=>{o({mode:`closed`}),m(null),_()},onError:t=>m(t instanceof Error?t.message:e(`ai.saveFailed`,`Save failed`))}),x=c({mutationFn:e=>t.trpcClient.llm.deleteProfile.mutate({addonId:e.addonId,profileId:e.id}),onSuccess:_}),S=c({mutationFn:e=>t.trpcClient.llm.testProfile.mutate({addonId:e.addonId,profileId:e.id}),onSuccess:(e,t)=>d({id:t.id,ok:e.ok,text:e.ok?`${e.text} (${String(e.usage.outputTokens)} tok, ${String(e.latencyMs)}ms)`:`${e.code}: ${e.message}`})}),C=h.data??[],w=i(()=>g.data??[],[g.data]),T=i(()=>{let e=new Map;for(let t of w)e.set(t.kind,t);return e},[w]);return r(Y,{icon:k,title:e(`ai.profilesTitle`,`AI profiles`),subtitle:e(`ai.profilesSubtitle`,`One row = one usable model endpoint. The defaults below decide who answers when a feature names no profile.`),actions:r(b,{size:`sm`,type:`button`,onClick:()=>{m(null),o({mode:`pick-kind`})},children:[l(R,{className:`h-3.5 w-3.5`}),e(`ai.addProfile`,`Add profile`)]}),children:[h.isError&&l(I,{title:e(`ai.loadFailed`,`Failed to load profiles`),message:h.error instanceof Error?h.error.message:e(`common.error`,`Error`),onRetry:()=>void h.refetch()}),l(Re,{profiles:C}),h.isLoading&&l(`div`,{className:`flex items-center justify-center py-16`,children:l(y,{className:`h-6 w-6 animate-spin text-primary`})}),!h.isLoading&&C.length===0&&l(`div`,{className:`py-16 text-center text-xs text-foreground-subtle`,children:e(`ai.noProfiles`,`No AI profiles yet. Click "Add profile" to configure one.`)}),C.length>0&&l(P,{children:l(O,{columns:Ie({kindByName:T,testResult:u,testingId:S.isPending?S.variables?.id??null:null,t:e,onToggle:e=>v.mutate({...e,enabled:!e.enabled,apiKey:`__redacted__`}),onTest:e=>S.mutate(e),onEdit:e=>{let t=T.get(e.kind);t!==void 0&&(m(null),o({mode:`form`,kind:t,profile:e}))},onDelete:e=>x.mutate(e)}),rows:C,rowKey:e=>e.id,minWidthPx:760,bordered:!1,mobileMode:`scroll`,maxBodyHeight:`max-h-[60vh]`})}),n.mode===`pick-kind`&&l(Pe,{kinds:w,onCancel:()=>o({mode:`closed`}),onPick:e=>o({mode:`form`,kind:e,profile:null})}),n.mode===`form`&&l(Fe,{kind:n.kind,existing:n.profile,saving:v.isPending,error:f,onSave:e=>v.mutate(e),onCancel:()=>o({mode:`closed`})})]})}function Re({profiles:e}){let{t}=J(),n=p(),i=a({queryKey:le,queryFn:()=>n.trpcClient.llm.getDefaults.query({})}),o=c({mutationFn:e=>n.trpcClient.llm.setDefault.mutate({selector:{purpose:e.purpose},profileId:e.profileId}),onSuccess:()=>{i.refetch()}}),s=e=>(i.data??[]).find(t=>`purpose`in t.selector&&t.selector.purpose===e)?.profileId??``,u=e=>e===`vision`?t(`ai.defaultVision`,`Default vision profile`):t(`ai.defaultText`,`Default text profile`);return l(P,{children:l(`div`,{className:`grid gap-4 p-4 sm:grid-cols-2`,children:pe.map(({purpose:n,visionOnly:i})=>{let a=i?e.filter(e=>e.supportsVision):e,c=s(n),d=e.find(e=>e.id===c);return r(`div`,{children:[l(`label`,{className:`mb-1 block text-[11px] font-medium text-foreground`,htmlFor:`llm-default-${n}`,children:u(n)}),r(`select`,{id:`llm-default-${n}`,"aria-label":u(n),className:`h-7 w-full rounded-md border border-border bg-surface px-2.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`,value:c,onChange:e=>o.mutate({purpose:n,profileId:e.target.value===``?null:e.target.value}),children:[l(`option`,{value:``,children:t(`ai.none`,`None`)}),c!==``&&!a.some(e=>e.id===c)&&l(`option`,{value:c,children:d?.name??c}),a.map(e=>r(`option`,{value:e.id,children:[e.name,` · `,e.model]},e.id))]}),c!==``&&d===void 0&&l(`p`,{className:`mt-1 text-[10px] text-danger`,children:t(`ai.defaultMissing`,`This default names a profile that no longer exists.`)}),d!==void 0&&!d.enabled&&l(`p`,{className:`mt-1 text-[10px] text-warning`,children:t(`ai.defaultDisabled`,`This default profile is disabled — callers resolve to no profile.`)}),o.error!=null&&l(`p`,{className:`mt-1 text-[10px] text-danger`,children:String(o.error)})]},n)})})})}n();var ze=5e3;function Be(e){return`${(e/1e9).toFixed(1)} GB`}function Ve(){let{t:e}=J(),t=p(),n=a({queryKey:ue,refetchInterval:ze,queryFn:()=>t.trpcClient.llm.listRuntimeNodes.query({})}),o=i(()=>[{key:`node`,header:e(`ai.colNode`,`Node`),render:e=>l(`span`,{className:`text-sm font-medium text-foreground`,children:e.nodeId})},{key:`state`,header:e(`ai.colState`,`State`),nowrap:!0,render:t=>r(`span`,{className:`flex items-center gap-1.5`,children:[l(L,{variant:t.reachable?`success`:`danger`,children:t.reachable?t.status?.state??e(`ai.ready`,`ready`):e(`ai.unreachable`,`unreachable`)}),t.status?.downloadProgress!==void 0&&l(L,{variant:`info`,children:`${String(Math.round(t.status.downloadProgress*100))}%`})]})},{key:`model`,header:e(`ai.colModel`,`Model`),render:e=>l(`span`,{className:`text-[11px] text-foreground`,children:e.status?.modelId??`—`})},{key:`disk`,header:e(`ai.colDisk`,`On disk`),align:`right`,nowrap:!0,render:e=>l(`span`,{className:`text-[11px] text-foreground-subtle`,children:e.disk===void 0?`—`:Be(e.disk.modelsBytes)})},{key:`apple`,header:e(`ai.colApple`,`Apple on-device`),render:t=>{let n=Oe(t);return r(`span`,{className:`flex flex-col items-start gap-0.5`,children:[l(L,{variant:n.tone,children:e(n.labelKey,n.labelDefault)}),n.detail!==null&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:n.detail})]})}},{key:`error`,header:e(`ai.colError`,`Error`),render:e=>e.error===void 0?l(`span`,{className:`text-[11px] text-foreground-subtle`,children:`—`}):l(`span`,{className:`text-[11px] text-danger`,children:e.error})}],[e]),s=n.data??[];return r(Y,{icon:B,title:e(`ai.runtimesTitle`,`Managed runtimes`),subtitle:e(`ai.runtimesSubtitle`,`Nodes advertising the llm-runtime capability: what each has loaded, what it is downloading, and how much model data sits on its disk.`),children:[n.isError&&l(I,{title:e(`ai.runtimesFailed`,`Failed to read runtime nodes`),message:n.error instanceof Error?n.error.message:e(`common.error`,`Error`),onRetry:()=>void n.refetch()}),s.length===0?l(`div`,{className:`py-16 text-center text-xs text-foreground-subtle`,children:e(`ai.noRuntimes`,`No node advertises the llm-runtime capability.`)}):l(P,{children:l(O,{columns:o,rows:s,rowKey:e=>e.nodeId,minWidthPx:760,bordered:!1,mobileMode:`scroll`,maxBodyHeight:x})})]})}var He=f(`/addon/ai/test-chat`),Ue=f(`/addon/ai/test-chat/chats`),We=6e5;function Ge(e){let t=e.firstTokenTimeoutMs;if(!(typeof t!=`number`||!Number.isFinite(t)||t<=0))return Math.min(Math.round(t),We)}function Ke(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function qe(e){if(!Ke(e))return null;let t=e.kind;return t!==`snapshot`&&t!==`track`||typeof e.mimeType!=`string`||typeof e.sizeBytes!=`number`?null:{kind:t,mimeType:e.mimeType,sizeBytes:e.sizeBytes,...typeof e.mediaKind==`string`?{mediaKind:e.mediaKind}:{},...typeof e.capturedAt==`number`?{capturedAt:e.capturedAt}:{},...typeof e.thumbnailBase64==`string`?{thumbnailBase64:e.thumbnailBase64}:{}}}var Je=[`resolving-image`,`connecting`,`first-token-wait`,`streaming`];function Ye(e){let t;try{t=JSON.parse(e)}catch{return null}if(!Ke(t))return null;switch(t.kind){case`status`:{let e=Je.find(e=>e===t.phase);return e===void 0?null:{kind:`status`,phase:e}}case`meta`:return typeof t.profileName!=`string`||typeof t.model!=`string`?null:{kind:`meta`,profileName:t.profileName,model:t.model,mediaSent:qe(t.mediaSent),streamed:t.streamed===!0,firstTokenTimeoutMs:typeof t.firstTokenTimeoutMs==`number`?t.firstTokenTimeoutMs:0};case`token`:return typeof t.text==`string`?{kind:`token`,text:t.text}:null;case`done`:return{kind:`done`,inputTokens:typeof t.inputTokens==`number`?t.inputTokens:0,outputTokens:typeof t.outputTokens==`number`?t.outputTokens:0,latencyMs:typeof t.latencyMs==`number`?t.latencyMs:0,truncated:t.truncated===!0,...typeof t.conversationId==`string`?{conversationId:t.conversationId}:{}};case`error`:return{kind:`error`,code:typeof t.code==`string`?t.code:`adapter-error`,message:typeof t.message==`string`?t.message:`the provider returned an error`};default:return null}}async function*Xe(e){let t=e.getReader(),n=new TextDecoder,r=``;try{for(;;){let{done:e,value:i}=await t.read();if(e)break;r+=n.decode(i,{stream:!0});let a=r.indexOf(`
2
- `);for(;a>=0;){let e=r.slice(0,a).trim();if(r=r.slice(a+1),e.length>0){let t=Ye(e);t!==null&&(yield t)}a=r.indexOf(`
3
- `)}}let e=r.trim();if(e.length>0){let t=Ye(e);t!==null&&(yield t)}}finally{t.releaseLock()}}function Ze(e){return e.filter(e=>e.failed!==!0&&e.content.length>0).map(e=>({role:e.role,content:e.content}))}function Qe(e){return e.thumbnailBase64===void 0||e.thumbnailBase64.length===0?null:`data:${e.mimeType};base64,${e.thumbnailBase64}`}function $e(e){return e.messages.map((t,n)=>{let r=t.mediaSent??void 0;return{id:`${e.id}-${String(n)}`,role:t.role,content:t.content,...t.attachment===void 0?{}:{attachmentRef:t.attachment,attachmentKind:t.attachment.kind},...r===void 0?{}:{attachment:r}}})}function et(e){let t=e.sizeBytes<1024*1024?`${(e.sizeBytes/1024).toFixed(0)} KB`:`${(e.sizeBytes/(1024*1024)).toFixed(1)} MB`,n=[e.kind===`snapshot`?`camera snapshot`:`track best-shot`,t];return e.mediaKind!==void 0&&n.push(e.mediaKind),e.capturedAt!==void 0&&n.push(new Date(e.capturedAt).toLocaleTimeString()),n.join(` · `)}function tt(e,t){switch(e){case`resolving-image`:return`fetching the picture…`;case`connecting`:return`connecting to the provider…`;case`first-token-wait`:return t>0?`the model is loading / thinking — a cold load can take minutes (up to ${String(Math.round(t/1e3))}s)`:`the model is loading / thinking — a cold load can take minutes`;case`streaming`:return`answering…`}}n();var nt=[`pipelineAnalytics`,`listRecentTracks`,`ai-test`],rt=360*60*1e3,it=40,at=160,ot={phase:`connecting`,firstTokenTimeoutMs:0,text:``,mediaSent:null};function st(){let{t:n}=J(),o=p(),[c,d]=s(``),[f,_]=s(``),[v,y]=s(``),[x,S]=s([]),[w,T]=s(null),[E,O]=s(`none`),[k,A]=s(`throwaway`),[j,M]=s(null),[N,ee]=s([]),[L,R]=s(null),[te,z]=s(null),B=t(null);u(()=>()=>B.current?.abort(),[]);let V=e(async()=>{let e=await fetch(Ue,{credentials:`same-origin`});e.ok&&ee((await e.json()).chats??[])},[]);u(()=>{k===`persistent`&&V()},[k,V]);let H=a({queryKey:se,queryFn:()=>o.trpcClient.llm.listProfiles.query({})}),U=i(()=>(H.data??[]).filter(e=>e.enabled),[H.data]),G=U.find(e=>e.id===c)??null,K=te!==null,re=e(async(e,t)=>{let r=new AbortController;B.current=r,R(null);let i=Ge(G??{});z({...ot,firstTokenTimeoutMs:i??0});let a=``,o=null,s,l=null,u=null,d;try{let n=await fetch(He,{method:`POST`,headers:{"content-type":`application/json`},credentials:`same-origin`,signal:r.signal,body:JSON.stringify({profileId:c,messages:e,...f.trim()===``?{}:{system:f.trim()},...t===void 0?{}:{attachment:t},...i===void 0?{}:{firstTokenTimeoutMs:i},...k===`persistent`?{persist:!0,...j===null?{}:{conversationId:j}}:{}})});if(!n.ok||n.body===null){let e=await n.text().catch(()=>``);throw Error(e.length>0?e:`HTTP ${String(n.status)}`)}for await(let e of Xe(n.body))switch(e.kind){case`status`:z(t=>({...t??ot,phase:e.phase}));break;case`meta`:o=e.mediaSent,s=e.model,z(t=>({...t??ot,firstTokenTimeoutMs:e.firstTokenTimeoutMs,mediaSent:e.mediaSent}));break;case`token`:a+=e.text,z(e=>({...e??ot,text:a}));break;case`done`:u={outputTokens:e.outputTokens,latencyMs:e.latencyMs},d=e.conversationId;break;case`error`:l=`${e.code}: ${e.message}`;break}}catch(e){r.signal.aborted||R(e instanceof Error?e.message:n(`common.error`,`Error`))}finally{B.current=null,z(null)}d!==void 0&&(M(d),V());let p=r.signal.aborted&&a.length>0;l===null&&a.length===0&&!p||S(e=>[...e,{id:`a-${String(Date.now())}`,role:`assistant`,content:l??a,...l===null?{}:{failed:!0},...o===null?{}:{attachment:o},...s!==void 0&&l===null?{model:s}:{},...u===null?{}:u}])},[k,j,G,c,V,f,n]),q=e(()=>{let e=v.trim();if(e===``||c===``||K)return;let t={id:`u-${String(Date.now())}`,role:`user`,content:e,...w===null?{}:{attachmentLabel:w.label,attachmentKind:w.ref.kind}},n=[...x,t];S(n),y(``);let r=w?.ref;T(null),O(`none`),re(k===`persistent`&&j!==null?[{role:`user`,content:e}]:Ze(n),r)},[k,j,v,w,c,re,K,x]),ae=()=>B.current?.abort(),ce=()=>{B.current?.abort(),S([]),T(null),y(``),R(null),z(null),M(null)},le=async e=>{B.current?.abort();let t=await fetch(`${Ue}/${e}`,{credentials:`same-origin`});if(!t.ok)return;let n=await t.json();M(e),S($e(n)),z(null),R(null)};return r(Y,{icon:C,title:n(`ai.testTitle`,`Test chat`),subtitle:n(k===`persistent`?`ai.testSubtitlePersistent`:`ai.testSubtitle`,k===`persistent`?`Conversations are saved for you and can be reopened. Throwaway mode is still available.`:`A throwaway conversation with one profile. Attach a live camera snapshot or a recent track to check the model can actually read a picture. Nothing is saved — only the usage row.`),actions:r(b,{size:`sm`,variant:`secondary`,type:`button`,disabled:x.length===0&&w===null,onClick:ce,children:[l(h,{className:`h-3.5 w-3.5`}),n(`ai.clearChat`,`Clear`)]}),children:[r(P,{className:`space-y-3 p-4`,children:[r(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[r(`div`,{children:[l(`label`,{className:`mb-1 block text-[11px] font-medium text-foreground`,htmlFor:`ai-test-profile`,children:n(`ai.profile`,`Profile`)}),l(D,{id:`ai-test-profile`,value:c,onChange:e=>d(e.target.value),options:[{value:``,label:n(`ai.selectProfile`,`Select a profile…`)},...U.map(e=>({value:e.id,label:`${e.name} · ${e.model}${e.supportsVision?` · vision`:``}`}))]}),U.length===0&&!H.isLoading&&l(`p`,{className:`mt-1 text-[10px] text-foreground-subtle`,children:n(`ai.noEnabledProfiles`,`No enabled profile. Add one on the Profiles tab.`)})]}),r(`div`,{children:[l(`label`,{className:`mb-1 block text-[11px] font-medium text-foreground`,htmlFor:`ai-test-system`,children:n(`ai.systemPrompt`,`System prompt (optional)`)}),l(W,{id:`ai-test-system`,value:f,onChange:e=>_(e.target.value),placeholder:n(`ai.systemPlaceholder`,`Answer in one short sentence.`)})]})]}),r(`div`,{className:`flex flex-wrap items-center gap-2`,children:[l(b,{size:`sm`,variant:k===`throwaway`?`primary`:`outline`,type:`button`,onClick:()=>{A(`throwaway`),M(null)},children:n(`ai.throwawayMode`,`Throwaway`)}),l(b,{size:`sm`,variant:k===`persistent`?`primary`:`outline`,type:`button`,onClick:()=>A(`persistent`),children:n(`ai.saveConversation`,`Save conversation`)})]}),k===`persistent`&&r(`div`,{className:`space-y-2`,children:[l(`div`,{className:`flex items-center gap-2`,children:r(b,{size:`sm`,variant:`secondary`,type:`button`,onClick:ce,children:[l(oe,{className:`h-3.5 w-3.5`}),n(`ai.newChat`,`New chat`)]})}),N.length>0&&l(`div`,{className:`max-h-36 divide-y divide-border overflow-y-auto rounded-md border border-border`,children:N.map(e=>l(`button`,{type:`button`,onClick:()=>void le(e.id),className:`flex w-full px-2.5 py-1.5 text-left text-[11px] hover:bg-surface-hover ${e.id===j?`bg-primary/10`:``}`,children:l(`span`,{className:`min-w-0 flex-1 truncate text-foreground`,children:e.title})},e.id))})]}),l(`p`,{className:`text-[10px] text-foreground-subtle`,children:n(`ai.streamNote`,`The answer streams as the model produces it. A cold model can take a while to load — the status line says which phase it is in.`)}),G!==null&&!G.supportsVision&&l(`p`,{className:`text-[10px] text-warning`,children:n(`ai.notVision`,`This profile is not vision-capable — an attached image will be refused before anything is read.`)})]}),L!==null&&l(I,{title:n(`ai.chatFailed`,`The test call failed`),message:L}),l(ct,{turns:x,live:te}),r(P,{className:`space-y-2 p-3`,children:[w!==null&&r(`div`,{className:`flex items-center gap-2 rounded-md border border-border bg-surface px-2.5 py-1.5`,children:[w.ref.kind===`snapshot`?l(g,{className:`h-3.5 w-3.5 text-foreground-subtle`}):l(F,{className:`h-3.5 w-3.5 text-foreground-subtle`}),l(`span`,{className:`min-w-0 flex-1 truncate text-[11px] text-foreground`,children:w.label}),l(b,{size:`sm`,variant:`ghost`,type:`button`,onClick:()=>T(null),children:l(ne,{className:`h-3.5 w-3.5`})})]}),r(`div`,{className:`flex flex-wrap items-center gap-2`,children:[r(b,{size:`sm`,variant:E===`snapshot`?`primary`:`outline`,type:`button`,onClick:()=>O(E===`snapshot`?`none`:`snapshot`),children:[l(g,{className:`h-3.5 w-3.5`}),n(`ai.attachSnapshot`,`Camera snapshot`)]}),r(b,{size:`sm`,variant:E===`track`?`primary`:`outline`,type:`button`,onClick:()=>O(E===`track`?`none`:`track`),children:[l(F,{className:`h-3.5 w-3.5`}),n(`ai.attachTrack`,`Recent track`)]})]}),E===`snapshot`&&l(dt,{onPick:e=>{T({ref:{kind:`snapshot`,deviceId:e.id},label:n(`ai.snapshotOf`,`Snapshot of {{name}}`,{name:e.name})}),O(`none`)}}),E===`track`&&l(pt,{onPick:(e,t)=>{T({ref:{kind:`track`,trackId:e.trackId,deviceId:e.deviceId},label:n(`ai.trackOf`,`{{class}} on {{name}}`,{class:e.label??e.className,name:t})}),O(`none`)}}),r(`div`,{className:`flex items-center gap-2`,children:[l(W,{value:v,onChange:e=>y(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),q())},placeholder:n(`ai.messagePlaceholder`,`Ask the model something…`),"aria-label":n(`ai.message`,`Message`)}),K?r(b,{size:`sm`,variant:`secondary`,type:`button`,onClick:ae,children:[l(m,{className:`h-3.5 w-3.5`}),n(`ai.stop`,`Stop`)]}):r(b,{size:`sm`,type:`button`,disabled:v.trim()===``||c===``,onClick:q,children:[l(ie,{className:`h-3.5 w-3.5`}),n(`ai.send`,`Send`)]})]})]})]})}function ct({turns:e,live:t}){let{t:n}=J();return e.length===0&&t===null?l(`div`,{className:`py-12 text-center text-xs text-foreground-subtle`,children:n(`ai.chatEmpty`,`Pick a profile, optionally attach a camera snapshot or a recent track, and send a message. Nothing here is saved.`)}):l(P,{children:r(`div`,{className:`max-h-[50vh] space-y-2 overflow-y-auto p-3`,children:[e.map(e=>l(lt,{turn:e},e.id)),t!==null&&r(`div`,{className:`space-y-1`,children:[t.mediaSent!==null&&l(ut,{attachment:t.mediaSent}),t.text.length>0&&l(lt,{turn:{id:`live`,role:`assistant`,content:t.text},streaming:!0}),r(`div`,{className:`flex items-center gap-2 text-[11px] text-foreground-subtle`,children:[l(y,{className:`h-3.5 w-3.5 animate-spin`}),tt(t.phase,t.firstTokenTimeoutMs)]})]})]})})}function lt({turn:e,streaming:t=!1}){let n=e.role===`user`,i=e.failed===!0?`border-danger/40 bg-danger/10`:`border-border bg-surface`;return l(`div`,{className:`flex ${n?`justify-end`:`justify-start`}`,children:r(`div`,{className:`max-w-[85%] rounded-lg border px-3 py-2 ${n?`border-primary/40 bg-primary/10`:i}`,children:[r(`p`,{className:`whitespace-pre-wrap break-words text-xs text-foreground`,children:[e.content,t&&l(`span`,{className:`ml-0.5 animate-pulse text-primary`,children:`▌`})]}),e.attachment!==void 0&&l(ut,{attachment:e.attachment}),e.attachmentLabel!==void 0&&r(`p`,{className:`mt-1 flex items-center gap-1 text-[10px] text-foreground-subtle`,children:[e.attachmentKind===`track`?l(F,{className:`h-3 w-3`}):l(g,{className:`h-3 w-3`}),e.attachmentLabel]}),e.attachment!==void 0&&r(`p`,{className:`mt-1 flex items-center gap-1 text-[10px] text-foreground-subtle`,children:[e.attachment.kind===`snapshot`?l(g,{className:`h-3 w-3`}):l(F,{className:`h-3 w-3`}),et(e.attachment)]}),e.model!==void 0&&l(`p`,{className:`mt-1 text-[10px] text-foreground-subtle`,children:`${e.model} · ${String(e.outputTokens??0)} tok · ${String(e.latencyMs??0)} ms`})]})})}function ut({attachment:e}){let t=Qe(e);return t===null?null:l(`img`,{src:t,alt:`sent to the model`,className:`mt-1 max-h-32 rounded-md border border-border object-contain`})}function dt({onPick:e}){let{t}=J(),n=S({isCamera:!0,projection:`slim`}),r=(n.data??[]).filter(e=>!e.disabled);return n.isLoading?l(y,{className:`h-4 w-4 animate-spin text-foreground-subtle`}):r.length===0?l(`p`,{className:`text-[11px] text-foreground-subtle`,children:t(`ai.noCameras`,`No camera found.`)}):l(`div`,{className:`grid max-h-56 grid-cols-2 gap-2 overflow-y-auto sm:grid-cols-4`,children:r.map(t=>l(ft,{device:t,onPick:e},t.id))})}function ft({device:e,onPick:t}){let{src:n}=d(e.id,{width:at});return r(`button`,{type:`button`,onClick:()=>t(e),className:`overflow-hidden rounded-md border border-border bg-surface text-left transition-colors hover:border-primary/50`,children:[l(`span`,{className:`block aspect-video w-full bg-background-elevated`,children:n!==null&&l(`img`,{src:n,alt:``,className:`h-full w-full object-cover`,loading:`lazy`})}),r(`span`,{className:`flex items-center gap-1 px-2 py-1`,children:[!e.online&&l(L,{variant:`warning`,children:`off`}),l(`span`,{className:`truncate text-[10px] text-foreground`,children:e.name})]})]})}function pt({onPick:e}){let{t}=J(),n=p(),o=S({isCamera:!0,projection:`slim`}),s=i(()=>(o.data??[]).map(e=>e.id),[o.data]),c=i(()=>{let e=new Map;for(let t of o.data??[])e.set(t.id,t.name);return e},[o.data]),u=a({queryKey:[...nt,s.length],enabled:s.length>0,queryFn:()=>n.trpcClient.pipelineAnalytics.listRecentTracks.query({deviceIds:[...s],since:Date.now()-rt,limit:it,projection:`slim`})});if(o.isLoading||u.isLoading)return l(y,{className:`h-4 w-4 animate-spin text-foreground-subtle`});let d=u.data?.tracks??[];return d.length===0?l(`p`,{className:`text-[11px] text-foreground-subtle`,children:t(`ai.noTracks`,`No track in the last 6 hours.`)}):l(`div`,{className:`max-h-56 divide-y divide-border overflow-y-auto rounded-md border border-border`,children:d.map(t=>r(`button`,{type:`button`,onClick:()=>e(t,c.get(t.deviceId)??String(t.deviceId)),className:`flex w-full items-center gap-2 px-2.5 py-1.5 text-left text-[11px] hover:bg-surface-hover`,children:[l(F,{className:`h-3.5 w-3.5 shrink-0 text-foreground-subtle`}),l(`span`,{className:`min-w-0 flex-1 truncate text-foreground`,children:t.label??t.className}),l(`span`,{className:`shrink-0 text-foreground-subtle`,children:c.get(t.deviceId)??t.deviceId}),l(`span`,{className:`shrink-0 text-foreground-subtle`,children:new Date(t.lastSeen).toLocaleTimeString()})]},t.trackId))})}n();var mt=1440*60*1e3,ht=[1,7,30,90];function gt(){let{t:e}=J(),t=p(),[n,o]=s(7),c=i(()=>{let e=new Date;return e.setHours(0,0,0,0),e.getTime()-(n-1)*mt},[n]),u=a({queryKey:se,queryFn:()=>t.trpcClient.llm.listProfiles.query({})}),d=a({queryKey:[...fe,n],queryFn:()=>t.trpcClient.llm.getUsage.query({since:c})}),f=i(()=>{let e=new Map;for(let t of u.data??[])e.set(t.id,t.name);return e},[u.data]),m=i(()=>[{key:`day`,header:e(`ai.colDay`,`Day`),nowrap:!0,render:e=>e.day},{key:`consumer`,header:e(`ai.colConsumer`,`Consumer`),nowrap:!0,render:e=>l(`span`,{className:`text-[11px] text-foreground`,children:e.consumer})},{key:`profile`,header:e(`ai.colProfile`,`Profile`),render:e=>l(`span`,{className:`text-[11px] text-foreground`,children:f.get(e.profileId)??e.profileId})},{key:`calls`,header:e(`ai.colCalls`,`Calls`),align:`right`,nowrap:!0,render:e=>String(e.calls)},{key:`okErr`,header:e(`ai.colOkErr`,`OK / err`),align:`right`,nowrap:!0,render:e=>l(`span`,{className:e.errorCalls>0?`text-danger`:void 0,children:`${String(e.okCalls)} / ${String(e.errorCalls)}`})},{key:`tokens`,header:e(`ai.colTokens`,`In / out tok`),align:`right`,nowrap:!0,render:e=>`${String(e.inputTokens)} / ${String(e.outputTokens)}`},{key:`latency`,header:e(`ai.colAvgMs`,`Avg ms`),align:`right`,nowrap:!0,render:e=>String(Math.round(e.avgLatencyMs))}],[f,e]),h=d.data??[];return r(Y,{icon:A,title:e(`ai.usageTitle`,`Usage`),subtitle:e(`ai.usageSubtitle`,`Server-side rollup per day, consumer and profile — never raw call rows. Errors are counted, so a profile that always fails is visible here before a feature reports it.`),actions:l(`div`,{className:`w-40`,children:l(D,{"aria-label":e(`ai.window`,`Window`),value:String(n),options:ht.map(t=>({value:String(t),label:e(`ai.lastDays`,`Last {{days}} days`,{days:t})})),onChange:e=>o(Number(e.target.value))})}),children:[d.isError&&l(I,{title:e(`ai.usageFailed`,`Failed to read usage`),message:d.error instanceof Error?d.error.message:e(`common.error`,`Error`),onRetry:()=>void d.refetch()}),h.length===0?l(`div`,{className:`py-16 text-center text-xs text-foreground-subtle`,children:e(`ai.noUsage`,`No AI calls in this window.`)}):l(P,{children:l(O,{columns:m,rows:h,rowKey:e=>`${e.day}|${e.consumer}|${e.profileId}`,minWidthPx:720,bordered:!1,mobileMode:`scroll`,maxBodyHeight:x})})]})}function _t(){let{t:e}=J();return l(`div`,{className:`flex flex-col p-4`,children:l(ae,{tabs:[{id:`profiles`,label:e(`ai.tabProfiles`,`Profiles`),icon:re,content:l(Le,{})},{id:`runtimes`,label:e(`ai.tabRuntimes`,`Runtimes`),icon:B,content:l(Ve,{})},{id:`usage`,label:e(`ai.tabUsage`,`Usage`),icon:A,content:l(gt,{})},{id:`test`,label:e(`ai.tabTest`,`Test`),icon:C,content:l(st,{})}]})})}export{_t as AiProfilesPage,_t as default};
@@ -1 +0,0 @@
1
- import{Q as e,S as t,W as n,q as r,x as i}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js";import{Au as a,Jr as o,Vr as s,fn as c}from"./src-BIIk_uZx.js";import{t as l}from"./FormBuilder-iv7Ebt5-.js";e();function u(e,t){if(!e)return t;let n=new Set;for(let r of e.sections){let e=r.fields;for(let r of e)!(`key`in r)||typeof r.key!=`string`||c(r,t,e)&&n.add(r.key)}let r={};for(let[e,i]of Object.entries(t))n.has(e)&&(r[e]=i);return r}function d({kind:e,addonId:c,initialValues:d,onSubmit:f,onCancel:p,submitLabel:m,disabled:h}){let[g,_]=r(d??{}),[v,y]=r(null),b=s({kind:e,...c===void 0?{}:{addonId:c}}),x=n(()=>{let e=b.data;if(e&&typeof e==`object`&&`sections`in e&&Array.isArray(e.sections))return e},[b.data]),S=o(),C=async()=>{y(null);let t=u(x,g);try{let n=await S.mutateAsync({kind:e,settings:t,...c===void 0?{}:{addonId:c}});y(n.ok?{ok:!0}:{ok:!1,error:n.error})}catch(e){y({ok:!1,error:e instanceof Error?e.message:String(e)})}};return t(`div`,{className:`space-y-3`,children:[b.isLoading&&t(`div`,{className:`flex items-center gap-2 text-xs text-foreground-subtle`,children:[i(a,{className:`h-3.5 w-3.5 animate-spin`}),` Loading schema…`]}),x&&i(l,{schema:x,values:g,onChange:_}),b.isError&&t(`div`,{className:`rounded border border-danger/30 bg-danger/5 text-danger px-3 py-2 text-[11px]`,children:[`Failed to load settings schema:`,` `,b.error instanceof Error?b.error.message:`Unknown error`]}),!x&&!b.isLoading&&!b.isError&&t(`div`,{className:`rounded border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-[11px] text-amber-700 dark:text-amber-300`,children:[`No settings schema available for kind `,i(`code`,{className:`font-mono`,children:e}),`. Its broker addon may not be installed or running.`]}),v&&i(`div`,{className:`rounded border px-3 py-2 text-[11px] ${v.ok?`border-success/30 bg-success/5 text-success`:`border-danger/30 bg-danger/5 text-danger`}`,children:v.ok?`Connection OK.`:`Test failed: ${v.error??`unknown error`}`}),t(`div`,{className:`flex items-center justify-between gap-2 pt-1`,children:[i(`button`,{type:`button`,onClick:p,className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Cancel`}),t(`div`,{className:`flex items-center gap-2`,children:[i(`button`,{type:`button`,onClick:()=>{C()},disabled:S.isPending||!x,className:`rounded border border-border px-3 py-1.5 text-xs text-foreground hover:bg-primary/10 disabled:opacity-50`,children:S.isPending?`Testing…`:`Test connection`}),i(`button`,{type:`button`,onClick:()=>{f(u(x,g))},disabled:!x||h,className:`inline-flex items-center gap-1.5 rounded bg-primary px-4 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50`,children:m??`Save`})]})]})]})}export{d as t};