@camstack/addon-admin-ui 1.2.258 → 1.2.260
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{AddonCollectionPage-BX0XnPQb.js → AddonCollectionPage-CS0TnWg9.js} +1 -1
- package/dist/assets/Addons-C30etjze.js +1 -0
- package/dist/assets/{AdminTabs-CSovnIie.js → AdminTabs-FTjDtV3h.js} +1 -1
- package/dist/assets/AiProfiles-mbAsm8w-.js +3 -0
- package/dist/assets/{BrokerForm-zK_8Dcox.js → BrokerForm-Q6_-XEV6.js} +1 -1
- package/dist/assets/Build-DEIHGbUT.js +32 -0
- package/dist/assets/{Capabilities-DZdGmm1p.js → Capabilities-BBNd5xr5.js} +1 -1
- package/dist/assets/{CapabilityBadges-dLW1TjJs.js → CapabilityBadges-CrEM9xUa.js} +1 -1
- package/dist/assets/Cluster-Bzkxl6x3.js +11 -0
- package/dist/assets/{Data-cuCuoZJZ.js → Data-TtTvLPLA.js} +1 -1
- package/dist/assets/DetectionIntelligence-DfTa4lpL.js +1 -0
- package/dist/assets/{DeviceAggregateSection-BgIHM0MP.js → DeviceAggregateSection-f6elW-hA.js} +1 -1
- package/dist/assets/DeviceDetail-2sfyugFO.js +2 -0
- package/dist/assets/{Devices-Ch6FOfuB.js → Devices-Co8wNAQR.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-BErA2z2-.js → EmbedPlayerPage-C-PGfe8W.js} +1 -1
- package/dist/assets/Events-BoiEuALN.js +1 -0
- package/dist/assets/{FormBuilder-jIqGNdKD.js → FormBuilder-B3mdR0Gk.js} +1 -1
- package/dist/assets/Identity-CYZ21kQd.js +1 -0
- package/dist/assets/IntegrationDetail-DkvBX9o8.js +1 -0
- package/dist/assets/Integrations-CZio9vzA.js +1 -0
- package/dist/assets/Integrations-CxQSQ9fW.js +1 -0
- package/dist/assets/Locations-D0BRCdcK.js +2 -0
- package/dist/assets/{Logs-BM6XTKrt.js → Logs-zkWqa-Zv.js} +1 -1
- package/dist/assets/{MotionZonesSettings-CQX7yV3y.js → MotionZonesSettings-DPp47_Em.js} +1 -1
- package/dist/assets/{MyAccess-CJbXiIW5.js → MyAccess-BISLeGOK.js} +1 -1
- package/dist/assets/{Network-DPbXs8WB.js → Network-CopgOYrO.js} +1 -1
- package/dist/assets/{NodeAddonsSettingsPanel-D1mmPw8E.js → NodeAddonsSettingsPanel-B5y6dSOO.js} +1 -1
- package/dist/assets/{NodeInferenceDevices-BZT90g18.js → NodeInferenceDevices-MUCKntIr.js} +1 -1
- package/dist/assets/Notifications-C-euUn8Y.js +1 -0
- package/dist/assets/Pipeline-CRvLk6_r.js +1 -0
- package/dist/assets/Plates-ChoLztf-.js +1 -0
- package/dist/assets/{PrivacyMaskSettings-BAmYAzaT.js → PrivacyMaskSettings-Bt6X63Rt.js} +1 -1
- package/dist/assets/{ProviderIcon-DCDpuWgi.js → ProviderIcon-D9PLOXMZ.js} +1 -1
- package/dist/assets/Recordings-TgH0kxt8.js +1 -0
- package/dist/assets/{ScanNetworkModal-Cz8wK3Sf.js → ScanNetworkModal-lEnThbrW.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-DxBU0nwK.js → SceneMonitorEditor-Coey7DkB.js} +1 -1
- package/dist/assets/{Scenes--ADmPstY.js → Scenes-DCGaMi0H.js} +1 -1
- package/dist/assets/{Settings-C9a74W-U.js → Settings-Cya6w94r.js} +1 -1
- package/dist/assets/{Showroom-JqyYWh5s.js → Showroom-CEIjIU3D.js} +1 -1
- package/dist/assets/{StorageLocationsPanel-Ch5YTeaG.js → StorageLocationsPanel-dpSl2bc_.js} +1 -1
- package/dist/assets/{Terminal-WhJmXhAV.js → Terminal-DYbduyac.js} +5 -5
- package/dist/assets/{Viewer-BUVuTunJ.js → Viewer-BCs5TInB.js} +1 -1
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-D3L9YkaA.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BAEaiPOS.js} +1 -1
- package/dist/assets/{archive-BBd9Y5og.js → archive-BDAG8ZtC.js} +1 -1
- package/dist/assets/{authed-media-Cp17W-pc.js → authed-media-BgHAN7mo.js} +1 -1
- package/dist/assets/{boxes-B2dkI7tE.js → boxes-CGA7dQAX.js} +1 -1
- package/dist/assets/circle-slash-xqjuzvya.js +1 -0
- package/dist/assets/{debounced-invalidate-CL0RRPMu.js → debounced-invalidate-DUhUAjlV.js} +1 -1
- package/dist/assets/{dist-C9Mb2vEn.js → dist-CIB8yuhW.js} +1 -1
- package/dist/assets/dist-Cxb_X-h6.js +349 -0
- package/dist/assets/{face-bbox-CRCCB2nD.js → face-bbox-q-9rvLF7.js} +1 -1
- package/dist/assets/{hard-drive-download-CIHN2VkD.js → hard-drive-download-DXfQNx7b.js} +1 -1
- package/dist/assets/{hostInit-BsyyQBn2.js → hostInit-DHzuQRJh.js} +1 -1
- package/dist/assets/index-Dx7jiq4X.js +4 -0
- package/dist/assets/{layers-cSbXjXdl.js → layers-D-Qb89PK.js} +1 -1
- package/dist/assets/{location-owned-usage-BT2pmQo5.js → location-owned-usage-C-JLRZgq.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-0e59474f.js → mf-entry-bootstrap-0-19449b84.js} +2 -2
- package/dist/assets/{player-overlays-B82OVd2b.js → player-overlays-BHhXtyqA.js} +1 -1
- package/dist/assets/remoteEntry-BnoRpCyV.js +1 -0
- package/dist/assets/{send-BUidPUKy.js → send-DtWddy40.js} +1 -1
- package/dist/assets/{settings-2-CoiJ1-tg.js → settings-2-a-fUhkjD.js} +1 -1
- package/dist/assets/{square-check-big-BeLRKn52.js → square-check-big-DBadJoiu.js} +1 -1
- package/dist/assets/src-D1KVMjXF.js +67 -0
- package/dist/assets/src-DJhS86y-.js +349 -0
- package/dist/assets/{use-scenes-feed-BOjzOiOU.js → use-scenes-feed-Cgbz38uA.js} +1 -1
- package/dist/assets/{use-stationary-objects-Bd9Ou1yp.js → use-stationary-objects-NIqG_ma3.js} +1 -1
- package/dist/assets/useEventInvalidation-DE-QGHTV.js +1 -0
- package/dist/assets/{useNodeUrlSelection-GaFsaq3Y.js → useNodeUrlSelection-CjOpKTO_.js} +1 -1
- package/dist/assets/user-round-BFvKN2vL.js +1 -0
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-ta66_Q-u.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-CXmVBdRr.js} +2 -2
- package/dist/index.html +5 -5
- package/dist/server/addon.js +243 -21
- package/package.json +1 -1
- package/dist/assets/Addons-BDOOkMuS.js +0 -1
- package/dist/assets/AiProfiles-E5IAsm2S.js +0 -3
- package/dist/assets/Build-BtjCenWS.js +0 -32
- package/dist/assets/Cluster-BbNceUht.js +0 -11
- package/dist/assets/DetectionIntelligence-G7lCcALp.js +0 -1
- package/dist/assets/DeviceDetail-BdOqOqTl.js +0 -2
- package/dist/assets/Events-CgOvlHhY.js +0 -1
- package/dist/assets/Identity-BWdkMiVS.js +0 -1
- package/dist/assets/IntegrationDetail-BIjcJOw8.js +0 -1
- package/dist/assets/Integrations-5qB154Mm.js +0 -1
- package/dist/assets/Integrations-CR7lMMFk.js +0 -1
- package/dist/assets/Locations-BCTsz8p1.js +0 -1
- package/dist/assets/Notifications-Df8BJ8WO.js +0 -1
- package/dist/assets/Pipeline-DAOklLn2.js +0 -1
- package/dist/assets/Plates-CQi1FcSU.js +0 -1
- package/dist/assets/Recordings-CqoxOlE1.js +0 -1
- package/dist/assets/circle-slash-Beg_P0an.js +0 -1
- package/dist/assets/dist-B8NLJMCh.js +0 -349
- package/dist/assets/index-BpiZqZOx.js +0 -4
- package/dist/assets/remoteEntry-Boe6tAc9.js +0 -1
- package/dist/assets/src-8XVcukAG.js +0 -349
- package/dist/assets/src-jk2FdB5v.js +0 -67
- package/dist/assets/useEventInvalidation-WjkWP5Gl.js +0 -1
- package/dist/assets/user-round-C782gYyr.js +0 -1
package/dist/server/addon.js
CHANGED
|
@@ -5361,7 +5361,7 @@ var ZodIssueCode = {
|
|
|
5361
5361
|
var ZodFirstPartyTypeKind;
|
|
5362
5362
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5363
5363
|
//#endregion
|
|
5364
|
-
//#region ../types/dist/sleep-
|
|
5364
|
+
//#region ../types/dist/sleep-pM_J7YnY.mjs
|
|
5365
5365
|
/**
|
|
5366
5366
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5367
5367
|
* window to float samples (D455).
|
|
@@ -16553,6 +16553,7 @@ sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
|
16553
16553
|
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
16554
16554
|
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
16555
16555
|
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
16556
|
+
sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
|
|
16556
16557
|
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
16557
16558
|
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
16558
16559
|
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
@@ -16833,6 +16834,10 @@ var NcSystemEventKindSchema = _enum([
|
|
|
16833
16834
|
"alarm-disarmed",
|
|
16834
16835
|
"alarm-arming",
|
|
16835
16836
|
"alarm-arm-refused",
|
|
16837
|
+
"alarm-pending",
|
|
16838
|
+
"alarm-rearmed",
|
|
16839
|
+
"alarm-sensor-bypass",
|
|
16840
|
+
"alarm-check-failed",
|
|
16836
16841
|
"addon-updated",
|
|
16837
16842
|
"server-updated",
|
|
16838
16843
|
"export-completed",
|
|
@@ -17428,6 +17433,19 @@ var NcMediaFrameSchema = _enum([
|
|
|
17428
17433
|
"full",
|
|
17429
17434
|
"boxed"
|
|
17430
17435
|
]);
|
|
17436
|
+
/**
|
|
17437
|
+
* How a SENSOR notification shows the cameras that link the sensor.
|
|
17438
|
+
*
|
|
17439
|
+
* `mosaic` — one image composed of every linked camera's photograph, taken at
|
|
17440
|
+
* the trigger. `each` — one image per camera where the target takes several
|
|
17441
|
+
* attachments; a target that takes one keeps the first camera's (the degrade
|
|
17442
|
+
* engine drops the rest by order). Either way ONE notification per event.
|
|
17443
|
+
* Absent = `mosaic`, applied by the Notification Center and deliberately NOT
|
|
17444
|
+
* a Zod default (see NcRulePatchSchema: a default materialises on every
|
|
17445
|
+
* partial patch). Meaningless for a rule whose subject is not a sensor, and a
|
|
17446
|
+
* sensor linked to one camera ships that camera's plain snapshot either way.
|
|
17447
|
+
*/
|
|
17448
|
+
var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
|
|
17431
17449
|
var NcMediaPolicySchema = object({
|
|
17432
17450
|
attach: _enum([
|
|
17433
17451
|
"best",
|
|
@@ -17473,7 +17491,9 @@ var NcMediaPolicySchema = object({
|
|
|
17473
17491
|
* A profile that is not assigned falls back to the cheapest, and the render
|
|
17474
17492
|
* reports which one actually ran.
|
|
17475
17493
|
*/
|
|
17476
|
-
profile: CamProfileSchema.optional()
|
|
17494
|
+
profile: CamProfileSchema.optional(),
|
|
17495
|
+
/** See {@link NcLinkedCameraModeSchema}. */
|
|
17496
|
+
linkedCameras: NcLinkedCameraModeSchema.optional()
|
|
17477
17497
|
});
|
|
17478
17498
|
/**
|
|
17479
17499
|
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
@@ -17593,7 +17613,7 @@ var NcRuleInputSchema = object({
|
|
|
17593
17613
|
cooldownSec: 60,
|
|
17594
17614
|
scope: "rule-device"
|
|
17595
17615
|
}),
|
|
17596
|
-
/** `{{var}}`
|
|
17616
|
+
/** `{{var}}` title/body. The variables are declared in `NC_TEMPLATE_VARS` (@camstack/types) and depend on the rule kind — see `templateVarsFor`. */
|
|
17597
17617
|
template: object({
|
|
17598
17618
|
title: string().max(500).optional(),
|
|
17599
17619
|
body: string().max(2e3).optional()
|
|
@@ -17773,6 +17793,22 @@ var NcRulePatchSchema = NcRuleInputSchema.partial().extend({
|
|
|
17773
17793
|
throttle: NcThrottleSchema.optional(),
|
|
17774
17794
|
priority: number().int().min(1).max(5).optional()
|
|
17775
17795
|
});
|
|
17796
|
+
var NcRuleClearableKeySchema = _enum([
|
|
17797
|
+
"template",
|
|
17798
|
+
"schedule",
|
|
17799
|
+
"targetUsers",
|
|
17800
|
+
"snoozeOptions",
|
|
17801
|
+
"snoozeAllowGlobal",
|
|
17802
|
+
"waitForEnhancement",
|
|
17803
|
+
"actions",
|
|
17804
|
+
"confirm",
|
|
17805
|
+
"groupIdleSec"
|
|
17806
|
+
]);
|
|
17807
|
+
var NcRuleUpdateInputSchema = object({
|
|
17808
|
+
ruleId: string(),
|
|
17809
|
+
patch: NcRulePatchSchema,
|
|
17810
|
+
clear: array(NcRuleClearableKeySchema).optional()
|
|
17811
|
+
});
|
|
17776
17812
|
/** A persisted rule. */
|
|
17777
17813
|
var NcRuleSchema = NcRuleInputSchema.extend({
|
|
17778
17814
|
id: string(),
|
|
@@ -17804,6 +17840,85 @@ var NcTestResultSchema = object({
|
|
|
17804
17840
|
className: string().optional(),
|
|
17805
17841
|
label: string().optional()
|
|
17806
17842
|
});
|
|
17843
|
+
/** The five rule kinds, as data. `NcRuleKind` in `notification/rule-kinds.ts`
|
|
17844
|
+
* is the same union; the template-vars spec pins the two together. */
|
|
17845
|
+
var NcRuleKindSchema = _enum([
|
|
17846
|
+
"detection",
|
|
17847
|
+
"sensor",
|
|
17848
|
+
"occupancy",
|
|
17849
|
+
"sound",
|
|
17850
|
+
"system"
|
|
17851
|
+
]);
|
|
17852
|
+
/** Which producer renders a template: an ordinary rule, a timelapse, a digest. */
|
|
17853
|
+
var NcTemplateFamilySchema = _enum([
|
|
17854
|
+
"rule",
|
|
17855
|
+
"timelapse",
|
|
17856
|
+
"summary"
|
|
17857
|
+
]);
|
|
17858
|
+
/** Which text field of that producer. `previewText` is the timelapse frame
|
|
17859
|
+
* caption, `captionText` the digest mosaic caption — both see fewer vars. */
|
|
17860
|
+
var NcTemplateFieldSchema = _enum([
|
|
17861
|
+
"title",
|
|
17862
|
+
"body",
|
|
17863
|
+
"previewText",
|
|
17864
|
+
"captionText"
|
|
17865
|
+
]);
|
|
17866
|
+
var NcTemplateVarGroupSchema = _enum([
|
|
17867
|
+
"subject",
|
|
17868
|
+
"place",
|
|
17869
|
+
"time",
|
|
17870
|
+
"rule",
|
|
17871
|
+
"occupancy",
|
|
17872
|
+
"sound",
|
|
17873
|
+
"sensor",
|
|
17874
|
+
"system",
|
|
17875
|
+
"digest",
|
|
17876
|
+
"ai"
|
|
17877
|
+
]);
|
|
17878
|
+
/**
|
|
17879
|
+
* ONE `{{var}}` a notification template may name.
|
|
17880
|
+
*
|
|
17881
|
+
* `families` / `fields` / `kinds` / `deliveries` / `systemEventKinds` say WHERE
|
|
17882
|
+
* it has a value; absent = no restriction on that axis. `systemEventKinds` is
|
|
17883
|
+
* read only for a `system` rule. `dynamic` declares a FAMILY of names
|
|
17884
|
+
* (`count_<class>`): the descriptor's `name` is the example member.
|
|
17885
|
+
*/
|
|
17886
|
+
var NcTemplateVarDescriptorSchema = object({
|
|
17887
|
+
name: string().regex(/^\w+$/),
|
|
17888
|
+
label: string(),
|
|
17889
|
+
description: string().optional(),
|
|
17890
|
+
example: string(),
|
|
17891
|
+
group: NcTemplateVarGroupSchema,
|
|
17892
|
+
families: array(NcTemplateFamilySchema).min(1),
|
|
17893
|
+
fields: array(NcTemplateFieldSchema).optional(),
|
|
17894
|
+
kinds: array(NcRuleKindSchema).optional(),
|
|
17895
|
+
deliveries: array(NcDeliverySchema).optional(),
|
|
17896
|
+
systemEventKinds: array(NcSystemEventKindSchema).optional(),
|
|
17897
|
+
dynamic: object({
|
|
17898
|
+
prefix: literal("count_"),
|
|
17899
|
+
from: literal("classes")
|
|
17900
|
+
}).optional()
|
|
17901
|
+
});
|
|
17902
|
+
/** Input to `previewTemplate` — the editor's own context, plus the draft text. */
|
|
17903
|
+
var NcTemplatePreviewInputSchema = object({
|
|
17904
|
+
context: object({
|
|
17905
|
+
family: NcTemplateFamilySchema,
|
|
17906
|
+
field: NcTemplateFieldSchema,
|
|
17907
|
+
kind: NcRuleKindSchema.optional(),
|
|
17908
|
+
delivery: NcDeliverySchema.optional(),
|
|
17909
|
+
systemEventKinds: array(NcSystemEventKindSchema).optional()
|
|
17910
|
+
}),
|
|
17911
|
+
template: object({
|
|
17912
|
+
title: string().max(500).optional(),
|
|
17913
|
+
body: string().max(2e3).optional()
|
|
17914
|
+
})
|
|
17915
|
+
});
|
|
17916
|
+
var NcTemplatePreviewSchema = object({
|
|
17917
|
+
title: string().nullable(),
|
|
17918
|
+
body: string().nullable(),
|
|
17919
|
+
/** Names the template uses that this context never fills — they render empty. */
|
|
17920
|
+
unknown: array(string())
|
|
17921
|
+
});
|
|
17807
17922
|
var NcConditionDescriptorSchema = object({
|
|
17808
17923
|
/** Field id inside `NcConditions` (or `'schedule'` for the rule-level group). */
|
|
17809
17924
|
id: string(),
|
|
@@ -18069,8 +18184,17 @@ object({
|
|
|
18069
18184
|
lastAt: number()
|
|
18070
18185
|
});
|
|
18071
18186
|
/**
|
|
18072
|
-
* The
|
|
18073
|
-
*
|
|
18187
|
+
* The per-mode lists, at most one per mode. Two lists for one mode have no
|
|
18188
|
+
* meaning a reader could agree on (union? the last one?), so they are refused
|
|
18189
|
+
* at the boundary rather than interpreted.
|
|
18190
|
+
*/
|
|
18191
|
+
var NcAlarmNonBlockingListSchema = array(object({
|
|
18192
|
+
mode: AlarmArmModeSchema,
|
|
18193
|
+
deviceIds: array(number().int()).max(200)
|
|
18194
|
+
})).max(8).refine((lists) => new Set(lists.map((l) => l.mode)).size === lists.length, { message: "nonBlocking: at most one list per arm mode" });
|
|
18195
|
+
/**
|
|
18196
|
+
* The three durations the panel's state machine runs on, who hears about its
|
|
18197
|
+
* transitions, and which openings each mode tolerates.
|
|
18074
18198
|
*
|
|
18075
18199
|
* They live on the NOTIFICATION-RULES cap, not on `alarm-panel`, on purpose:
|
|
18076
18200
|
* `alarm-panel` is `deviceNative` and its other provider mirrors somebody
|
|
@@ -18089,21 +18213,39 @@ var NcAlarmSettingsSchema = object({
|
|
|
18089
18213
|
* existed, and therefore what an untouched install keeps doing.
|
|
18090
18214
|
*/
|
|
18091
18215
|
triggeredDurationSec: number().int().min(0).max(3600),
|
|
18092
|
-
/** Send a notification when a mode takes effect. */
|
|
18093
|
-
announceArm: boolean(),
|
|
18094
18216
|
/**
|
|
18095
|
-
*
|
|
18217
|
+
* Deprecated by D630 — every transition is announced. Parsed, never read;
|
|
18218
|
+
* remove after one release. Optional so an older admin's patch (which still
|
|
18219
|
+
* sends it) parses rather than failing the whole save.
|
|
18220
|
+
*/
|
|
18221
|
+
announceArm: boolean().optional(),
|
|
18222
|
+
/**
|
|
18223
|
+
* Target ids from `notification-output`: every alarm transition goes here.
|
|
18096
18224
|
*
|
|
18097
|
-
* Explicit rather than "everyone": an
|
|
18225
|
+
* Explicit rather than "everyone": an alarm announcement is a household
|
|
18098
18226
|
* message, and broadcasting it to every configured endpoint (including a
|
|
18099
18227
|
* webhook wired to something else) is not a default anybody would choose.
|
|
18100
|
-
* Empty
|
|
18101
|
-
*
|
|
18228
|
+
* Empty sends nothing, and the server logs that — silence must be
|
|
18229
|
+
* attributable.
|
|
18102
18230
|
*/
|
|
18103
|
-
announceTargets: array(string().min(1)).max(16)
|
|
18231
|
+
announceTargets: array(string().min(1)).max(16),
|
|
18232
|
+
/**
|
|
18233
|
+
* Per arm mode, the covered devices whose being OPEN does not refuse the
|
|
18234
|
+
* arm (a window left ajar for the cat under `home`, say). At most one entry
|
|
18235
|
+
* per mode is meaningful. Defaulted to `[]` so a blob stored before D630
|
|
18236
|
+
* parses as "every opening blocks" — the behaviour it was written under.
|
|
18237
|
+
*/
|
|
18238
|
+
nonBlocking: NcAlarmNonBlockingListSchema.default([])
|
|
18104
18239
|
});
|
|
18105
|
-
/**
|
|
18106
|
-
|
|
18240
|
+
/**
|
|
18241
|
+
* Every field optional — a tab edits one control at a time.
|
|
18242
|
+
*
|
|
18243
|
+
* `nonBlocking` is re-declared WITHOUT its default: `.partial()` does not
|
|
18244
|
+
* remove an inner `.default()`, so a patch that never named the field would
|
|
18245
|
+
* parse to `nonBlocking: []` and wipe every mode's list on an unrelated edit
|
|
18246
|
+
* (the same trap {@link NcRulePatchSchema} documents).
|
|
18247
|
+
*/
|
|
18248
|
+
var NcAlarmSettingsPatchSchema = NcAlarmSettingsSchema.extend({ nonBlocking: NcAlarmNonBlockingListSchema }).partial();
|
|
18107
18249
|
/**
|
|
18108
18250
|
* What one arm mode actually arms, DERIVED from the enabled rules gated on it.
|
|
18109
18251
|
* Never authored, never stored — see `alarm-mode-coverage.ts` for why a stored
|
|
@@ -18148,6 +18290,36 @@ var NcAlarmModeCoverageSchema = object({
|
|
|
18148
18290
|
*/
|
|
18149
18291
|
skippedDevices: array(NcAlarmSkippedDeviceSchema).default([])
|
|
18150
18292
|
});
|
|
18293
|
+
/** One covered device that reads open, and whether that refuses the arm. */
|
|
18294
|
+
var NcAlarmOpeningSchema = object({
|
|
18295
|
+
deviceId: number().int(),
|
|
18296
|
+
name: string(),
|
|
18297
|
+
/** The device's state word as read (`open`, `unlocked`, …). */
|
|
18298
|
+
state: string(),
|
|
18299
|
+
/** False when the mode's non-blocking list names this device. */
|
|
18300
|
+
blocking: boolean()
|
|
18301
|
+
});
|
|
18302
|
+
/** A device the panel is currently ignoring, and which side of it it is on. */
|
|
18303
|
+
var NcAlarmExclusionViewSchema = object({
|
|
18304
|
+
deviceId: number().int(),
|
|
18305
|
+
name: string(),
|
|
18306
|
+
phase: _enum(["open", "closed"])
|
|
18307
|
+
});
|
|
18308
|
+
/** One mode's openings: devices read open, plus those whose state is unknown. */
|
|
18309
|
+
var NcAlarmModeOpeningsSchema = object({
|
|
18310
|
+
mode: AlarmArmModeSchema,
|
|
18311
|
+
devices: array(NcAlarmOpeningSchema),
|
|
18312
|
+
/** Covered devices whose state could not be read (D49): neither open nor closed. */
|
|
18313
|
+
unknown: array(number().int())
|
|
18314
|
+
});
|
|
18315
|
+
var NcAlarmLiveSchema = object({
|
|
18316
|
+
state: AlarmStateSchema,
|
|
18317
|
+
/** The mode being armed into (exit delay) or held; null when disarmed. */
|
|
18318
|
+
targetMode: AlarmArmModeSchema.nullable(),
|
|
18319
|
+
availableModes: array(AlarmArmModeSchema),
|
|
18320
|
+
openings: array(NcAlarmModeOpeningsSchema),
|
|
18321
|
+
exclusions: array(NcAlarmExclusionViewSchema)
|
|
18322
|
+
});
|
|
18151
18323
|
var NcAlarmConfigSchema = object({
|
|
18152
18324
|
/**
|
|
18153
18325
|
* The panel's device id, or null when this install has no panel (the ensure
|
|
@@ -18157,7 +18329,13 @@ var NcAlarmConfigSchema = object({
|
|
|
18157
18329
|
*/
|
|
18158
18330
|
deviceId: number().int().nullable(),
|
|
18159
18331
|
settings: NcAlarmSettingsSchema,
|
|
18160
|
-
coverage: array(NcAlarmModeCoverageSchema)
|
|
18332
|
+
coverage: array(NcAlarmModeCoverageSchema),
|
|
18333
|
+
/**
|
|
18334
|
+
* The panel as it is NOW — state, what each mode would find open, what is
|
|
18335
|
+
* excluded. Optional: a panel-less hub answers without it, and a client
|
|
18336
|
+
* must not read its absence as "nothing is open".
|
|
18337
|
+
*/
|
|
18338
|
+
live: NcAlarmLiveSchema.optional()
|
|
18161
18339
|
});
|
|
18162
18340
|
/**
|
|
18163
18341
|
* ONE rule's demand on ONE camera's clip ring.
|
|
@@ -18205,10 +18383,7 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
18205
18383
|
kind: "mutation",
|
|
18206
18384
|
auth: "admin",
|
|
18207
18385
|
caller: "required"
|
|
18208
|
-
}), method(object({
|
|
18209
|
-
ruleId: string(),
|
|
18210
|
-
patch: NcRulePatchSchema
|
|
18211
|
-
}), object({ rule: NcRuleSchema }), {
|
|
18386
|
+
}), method(NcRuleUpdateInputSchema, object({ rule: NcRuleSchema }), {
|
|
18212
18387
|
kind: "mutation",
|
|
18213
18388
|
auth: "admin",
|
|
18214
18389
|
caller: "required"
|
|
@@ -18236,7 +18411,10 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
18236
18411
|
}), method(object({}), object({
|
|
18237
18412
|
catalog: array(NcConditionDescriptorSchema),
|
|
18238
18413
|
taxonomy: NcTaxonomySchema.optional()
|
|
18239
|
-
})), method(object({
|
|
18414
|
+
})), method(object({}), object({ vars: array(NcTemplateVarDescriptorSchema) })), method(NcTemplatePreviewInputSchema, NcTemplatePreviewSchema, {
|
|
18415
|
+
kind: "mutation",
|
|
18416
|
+
access: "view"
|
|
18417
|
+
}), method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }), method(object({ artifactId: string().min(1) }), object({ url: string().nullable() }), { auth: "admin" }), method(object({}), object({ snoozes: array(NcSnoozeSchema) }), { caller: "required" }), method(object({ snooze: NcSnoozeInputSchema }), object({ snooze: NcSnoozeSchema }), {
|
|
18240
18418
|
kind: "mutation",
|
|
18241
18419
|
caller: "required"
|
|
18242
18420
|
}), method(object({ snoozeId: string() }), object({ success: literal(true) }), {
|
|
@@ -22669,6 +22847,7 @@ var CAP_TO_KIND = {
|
|
|
22669
22847
|
"enum-sensor": "enum-sensor",
|
|
22670
22848
|
"event-emitter": "device-event",
|
|
22671
22849
|
"lock-control": "lock",
|
|
22850
|
+
cover: "cover",
|
|
22672
22851
|
switch: "switch",
|
|
22673
22852
|
button: "button",
|
|
22674
22853
|
doorbell: "doorbell"
|
|
@@ -37995,6 +38174,12 @@ Object.freeze({
|
|
|
37995
38174
|
addonId: null,
|
|
37996
38175
|
access: "view"
|
|
37997
38176
|
},
|
|
38177
|
+
"notificationRules.getTemplateCatalog": {
|
|
38178
|
+
capName: "notification-rules",
|
|
38179
|
+
capScope: "system",
|
|
38180
|
+
addonId: null,
|
|
38181
|
+
access: "view"
|
|
38182
|
+
},
|
|
37998
38183
|
"notificationRules.listDeviceMutes": {
|
|
37999
38184
|
capName: "notification-rules",
|
|
38000
38185
|
capScope: "system",
|
|
@@ -38013,6 +38198,12 @@ Object.freeze({
|
|
|
38013
38198
|
addonId: null,
|
|
38014
38199
|
access: "view"
|
|
38015
38200
|
},
|
|
38201
|
+
"notificationRules.previewTemplate": {
|
|
38202
|
+
capName: "notification-rules",
|
|
38203
|
+
capScope: "system",
|
|
38204
|
+
addonId: null,
|
|
38205
|
+
access: "view"
|
|
38206
|
+
},
|
|
38016
38207
|
"notificationRules.resolveArtifactUrl": {
|
|
38017
38208
|
capName: "notification-rules",
|
|
38018
38209
|
capScope: "system",
|
|
@@ -43580,6 +43771,37 @@ var NC_AUDIO_DEFAULTS = {
|
|
|
43580
43771
|
};
|
|
43581
43772
|
new Set(["devices", "classes"]);
|
|
43582
43773
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
43774
|
+
var RULE_BODY_ONLY = ["body"];
|
|
43775
|
+
var RULE_TEXT = ["title", "body"];
|
|
43776
|
+
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
43777
|
+
var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
|
|
43778
|
+
var UPDATES = [
|
|
43779
|
+
"addon-update-available",
|
|
43780
|
+
"server-update-available",
|
|
43781
|
+
"wrapper-update-available"
|
|
43782
|
+
];
|
|
43783
|
+
var PACKAGE_UPDATES = ["addon-update-available", "server-update-available"];
|
|
43784
|
+
var ALARM = [
|
|
43785
|
+
"alarm-triggered",
|
|
43786
|
+
"alarm-armed",
|
|
43787
|
+
"alarm-disarmed",
|
|
43788
|
+
"alarm-arming",
|
|
43789
|
+
"alarm-arm-refused"
|
|
43790
|
+
];
|
|
43791
|
+
var COMBINED_ALARM = ["alarm-triggered"];
|
|
43792
|
+
var DEVICE_EVENTS = [
|
|
43793
|
+
"device-online",
|
|
43794
|
+
"device-offline",
|
|
43795
|
+
"device-disabled",
|
|
43796
|
+
"device-enabled",
|
|
43797
|
+
...BATTERY,
|
|
43798
|
+
...CONSUMABLE,
|
|
43799
|
+
"stream-online",
|
|
43800
|
+
"stream-offline",
|
|
43801
|
+
"detection-blind",
|
|
43802
|
+
...ALARM
|
|
43803
|
+
];
|
|
43804
|
+
[...DEVICE_EVENTS], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...COMBINED_ALARM], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_BODY_ONLY], [...RULE_TEXT], [...RULE_TEXT], [...DEVICE_EVENTS], [...RULE_TEXT], [...DEVICE_EVENTS], [...RULE_TEXT], [...BATTERY, ...CONSUMABLE], [...RULE_TEXT], [...CONSUMABLE], [...RULE_TEXT], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...UPDATES], [...RULE_TEXT], [...PACKAGE_UPDATES], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT], [...RULE_TEXT];
|
|
43583
43805
|
/**
|
|
43584
43806
|
* TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
|
|
43585
43807
|
*
|
|
@@ -44074,7 +44296,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
44074
44296
|
capability: adminUiCapability,
|
|
44075
44297
|
provider: {
|
|
44076
44298
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
44077
|
-
getVersion: async () => ({ version: "1.2.
|
|
44299
|
+
getVersion: async () => ({ version: "1.2.260" })
|
|
44078
44300
|
}
|
|
44079
44301
|
}];
|
|
44080
44302
|
}
|
package/package.json
CHANGED
|
@@ -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,gt as f,st as p,vt as m}from"./player-overlays-B82OVd2b.js";import{$ as h,$n as ee,Bn as g,Ea as _,Ec as v,Fn as y,Gn as b,Hn as x,Il as S,In as C,Jn as w,Ln as te,Mn as ne,Pn as re,Q as ie,Qn as T,Rc as E,Rn as D,Sc as O,Sl as ae,Su as k,T as oe,Tl as A,Un as se,Wn as j,Xn as M,Yn as N,_ as P,_l as F,_u as I,bu as ce,cl as L,dl as le,er as ue,fu as R,hn as de,iu as z,qn as B,tl as V,ul as fe,yc as H,zn as pe}from"./src-jk2FdB5v.js";import{nn as U}from"./src-8XVcukAG.js";import{a as me,d as W,s as he}from"./index-BpiZqZOx.js";import{t as G}from"./AdminPage-CiKtOLQm.js";import{t as ge}from"./NodeAddonsSettingsPanel-D1mmPw8E.js";import{r as K,t as q}from"./useNodeUrlSelection-GaFsaq3Y.js";var J=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 Y=new Set([`completed`,`failed`,`partially-failed`,`cancelled`]),_e=new Set([`done`,`failed`,`skipped`]);function X(e){return!_e.has(e.phase)&&!Y.has(e.jobState)}function Z(e,t){let n=new Map,r=[...e].sort((e,t)=>e.createdAtMs-t.createdAtMs);for(let e of r){let r=Y.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 ve(){let{data:e}=x({activeOnly:!0},{refetchOnWindowFocus:!1,refetchInterval:e=>(e.state.data?.length??0)>0?3e3:!1}),{map:t}=O(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 Z([...n.values()],Date.now())},[e,t])}var ye={queued:{icon:R,cls:`bg-muted text-foreground-subtle`,label:`queued`},fetching:{icon:S,cls:`bg-primary/10 text-primary`,label:`fetching`,spin:!0},staged:{icon:S,cls:`bg-primary/10 text-primary`,label:`staged`,spin:!0},validating:{icon:S,cls:`bg-primary/10 text-primary`,label:`validating`,spin:!0},applying:{icon:S,cls:`bg-primary/10 text-primary`,label:`applying`,spin:!0},restarting:{icon:S,cls:`bg-amber-500/10 text-amber-600 dark:text-amber-400`,label:`restarting`,spin:!0},applied:{icon:S,cls:`bg-primary/10 text-primary`,label:`finalizing`,spin:!0},done:{icon:k,cls:`bg-success/10 text-success`,label:`updated`},failed:{icon:J,cls:`bg-danger/10 text-danger`,label:`failed`},skipped:{icon:V,cls:`bg-muted text-foreground-subtle`,label:`skipped`}};function be({progress:e}){let t=ye[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 xe({packageName:e,currentVersion:t,installSource:n,onInstall:r,onClose:a,onSelect:s,selectedVersion:c}){let u=n===`upload`||n===`local`,{data:d,isLoading:f}=D({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(E,{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(S,{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(k,{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(k,{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(z,{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 Se={queued:{icon:R,bg:`bg-muted text-foreground-subtle`,label:`queued`},updating:{icon:S,bg:`bg-primary/10 text-primary`,label:`updating`,spin:!0},"done-pending-restart":{icon:F,bg:`bg-amber-500/10 text-amber-700`,label:`pending restart`},done:{icon:k,bg:`bg-success/10 text-success`,label:`done`},failed:{icon:J,bg:`bg-danger/10 text-danger`,label:`failed`}};function Q({item:e}){let t=Se[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 Ce=`device-export`;function we(e){return e.capabilities.some(e=>(typeof e==`string`?e:e.name)===Ce)}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?A:W,{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(E,{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(S,{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(z,{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`}=y({addonId:e}),r=N({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:g,bundle:_,bulkItem:y,disabledByBulk:x,isSystem:S}){let[C,w]=c(!1),[te,ne]=c(!1),[re,T]=c(!1),[E,D]=c(null);u(()=>{D(null)},[a]);let O=E??a,[k,se]=c(!1),[j,M]=c(!1),[N,P]=c(`logs`),I=s(),ue=me(),R=de(),{manifest:z}=e,V=e.installedOn??[],fe=!_&&!z.protected&&z.removable!==!1,H=!!_,U=_?.displayName??z.name,W=_?.packageName??z.packageName,he=_?.version??z.packageVersion??z.version,G=_?.installSource??e.installSource,K=_?_.bundle?.description??_.addons[0]?.manifest.description:z.description,q=ee({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]}),I.invalidateQueries({queryKey:[[`addonPages`]]}),I.invalidateQueries({queryKey:[[`capabilities`]]})}}),Y=b({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]})}}),_e=pe({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]}),I.invalidateQueries({queryKey:[[`addonPages`]]}),I.invalidateQueries({queryKey:[[`capabilities`]]}),I.invalidateQueries({queryKey:[[`integrations`]]})}}),X=B({onSuccess:()=>{I.invalidateQueries({queryKey:[[`addons`]]}),I.invalidateQueries({queryKey:[[`alerts`]]})}}),Z=e.health,ve=Z?.phase===`failed`&&!Z.inGracePeriod,ye=ve&&Z?.nextRetryAt&&!Z.retrying;return i(`div`,{className:`rounded-lg border bg-surface overflow-hidden ${ve?`border-red-500/50`:`border-border`}`,children:[ve&&Z&&i(`div`,{className:`bg-danger/10 border-b border-danger/30 px-4 py-2.5 flex items-start gap-2.5`,children:[l(J,{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 #`,Z.retryCount,`)`]}),l(`div`,{className:`text-[11px] text-foreground mt-0.5 break-words font-mono`,children:Z.lastError?.message??`Unknown error`}),ye&&Z.nextRetryAt&&i(`div`,{className:`text-[10px] text-foreground-subtle mt-1`,children:[`Auto-retry at `,new Date(Z.nextRetryAt).toLocaleTimeString()]})]}),i(`button`,{type:`button`,disabled:X.isPending||Z.retrying,onClick:e=>{e.stopPropagation(),X.mutate({packageName:W})},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(F,{className:`h-3 w-3 ${X.isPending||Z.retrying?`animate-spin`:``}`}),`Retry now`]})]}),i(`div`,{className:`flex items-start gap-3 px-4 py-3`,children:[l(Te,{isBundle:H||!!z.components&&z.components.length>1,installSource:G,addonId:H?_.addons[0]?.manifest.id:z.id,iconPath:H?_.bundle?.icon??_.addons[0]?.manifest.icon:z.icon,color:H?_.addons[0]?.manifest.color:z.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:U}),!r&&l(Ee,{version:he,availableUpdate:a,...O===void 0?{}:{selectedVersion:O},isUpdating:m,installSource:G,disabled:x,...d&&O!==void 0?{onUpdate:()=>d(O)}:{},onOpenPicker:()=>T(e=>!e),children:re&&l(xe,{packageName:W,currentVersion:he,...G?{installSource:G}:{},...a!==void 0&&O!==void 0?{selectedVersion:O,onSelect:e=>{D(e),T(!1)}}:{},onInstall:e=>{T(!1),_e.mutate({packageName:W,version:e})},onClose:()=>T(!1)})})]}),i(`div`,{className:`flex flex-wrap items-center gap-x-1.5 gap-y-1 mt-0.5`,children:[W!==U&&l(`span`,{className:`text-[10px] text-foreground-subtle font-mono truncate max-w-full`,children:W}),H&&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(A,{className:`h-3 w-3`}),_.addons.length]}),S&&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(F,{className:`h-3 w-3`}),`System`]}),y!=null&&l(Q,{item:y}),g!=null&&l(be,{progress:g})]}),K&&l(`p`,{className:`text-[10px] text-foreground-subtle mt-1 line-clamp-1`,children:K}),!H&&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})]})]})]}),!H&&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(),Y.mutate({addonId:z.id})},disabled:Y.isPending||x,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(F,{className:`h-3 w-3 ${Y.isPending?`animate-spin`:``}`}),`Restart`]}),i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),se(e=>!e)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${k?`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(le,{className:`h-3 w-3`}),`Logs`]}),!H&&i(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),M(!0)},className:`inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium border transition-colors ${j?`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(L,{className:`h-3 w-3`}),`Settings`]}),l(`div`,{className:`flex-1`}),fe&&i(`button`,{type:`button`,onClick:async e=>{e.stopPropagation(),await R({title:`Uninstall ${z.name}?`,message:`This will remove the addon package and all its data. This action cannot be undone.`,confirmLabel:`Uninstall`,variant:`danger`})&&q.mutate({packageName:z.packageName})},disabled:q.isPending||x,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`}),q.isPending?`Removing...`:`Uninstall`]})]}),n&&n.nodes.length>1&&!H&&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))})]}),k&&!H&&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:()=>P(`logs`),className:`px-2 py-0.5 transition-colors ${N===`logs`?`bg-primary/10 text-primary`:`text-foreground-subtle hover:bg-surface-hover`}`,children:`Logs`}),l(`button`,{type:`button`,onClick:()=>P(`events`),className:`px-2 py-0.5 border-l border-border transition-colors ${N===`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(),se(!1)},className:`text-foreground-subtle hover:text-foreground`,children:l(v,{className:`h-3.5 w-3.5`})})]}),N===`logs`&&l(h,{addonId:z.id,maxHeight:`max-h-64`,showFilters:!1}),N===`events`&&l(ie,{addonId:z.id,category:`addon.*`,maxHeight:`max-h-64`})]}),H&&i(o,{children:[l(`button`,{type:`button`,onClick:()=>w(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(C?ce:f,{className:`h-3.5 w-3.5 text-foreground-subtle`})}),C&&l(`div`,{className:`border-t border-border px-3 py-2 space-y-2`,children:_.addons.map(e=>l(Oe,{addon:e,agents:t,hideVersion:!0},e.manifest.id))})]}),j&&!H&&l(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:()=>M(!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(L,{className:`h-4 w-4 text-primary`}),i(`h2`,{className:`text-sm font-semibold text-foreground`,children:[U,` Settings`]})]}),l(`button`,{onClick:()=>M(!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(ge,{nodeId:null,addonIds:[z.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(z)&&i(`div`,{children:[l(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:`Device export`}),l(oe,{addonId:z.id,onOpenDevice:e=>ue(`/devices/${e}`)})]}),G===`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:z.id})]}),z.components&&z.components.length>0&&i(`div`,{children:[i(`div`,{className:`text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-2`,children:[`Components (`,z.components.length,`)`]}),l(`div`,{className:`flex flex-wrap gap-1`,children:z.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:[V.length===0&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:`Hub (local)`}),V.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(),ne(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(ae,{className:`h-3 w-3`}),`Add agent`]}),te&&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&&!V.includes(e.name)).map(e=>l(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),ne(!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&&!V.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:()=>M(!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(S,{className:`w-3.5 h-3.5 animate-spin`}):l(E,{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(``),g=r(h),[_,v]=c(!1),y=t(null);u(()=>{if(!_)return;let e=e=>{y.current&&!y.current.contains(e.target)&&v(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[_]);let{data:b}=se({nodeId:d.id}),x=a(()=>{let e=new Map;for(let t of b??[])e.set(t.name,t.latestVersion);return e},[b]),re=a(()=>(b??[]).filter(e=>!e.isSystem).length,[b]),[ie,E]=c(()=>new Set),[D,O]=c(()=>new Map),ae=e(e=>{E(t=>new Set(t).add(e))},[]),oe=e(e=>{E(t=>{if(!t.has(e))return t;let n=new Set(t);return n.delete(e),n})},[]),A=e((e,t)=>{O(n=>new Map(n).set(e,t))},[]),j=e(e=>{O(t=>{if(!t.has(e))return t;let n=new Map(t);return n.delete(e),n})},[]),N=ue({onMutate:e=>{ae(e.name),j(e.name)},onSuccess:(e,t)=>{oe(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)=>{oe(t.name),A(t.name,e instanceof Error?e.message:String(e))}}),P=ve(),ce=t(new Set);u(()=>{let e=new Set;for(let[t,n]of P)X(n)&&e.add(t);let t=[...ce.current].some(t=>!e.has(t));ce.current=e,t&&(m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addons`,`listUpdates`]]}))},[P,m]);let{data:L}=C(void 0),le=ne({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),R=M({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`,`getAutoUpdateSettings`]]})}}),{data:B,isFetching:V}=w({query:g||void 0},{enabled:_}),H=T(),{data:U}=te(void 0),me=U?.requestedAt,[W,G]=c(null),[ge,K]=c(!1);u(()=>{if(U?.kind===`framework-bulk-update`&&U.requestedAt!==W){G(U.requestedAt),K(!0);let e=window.setTimeout(()=>K(!1),6e3);return()=>window.clearTimeout(e)}},[me,W,U]),de();let q=e(async()=>{let e=(b??[]).filter(e=>!e.isSystem);if(e.length!==0){if(!d.isHub){for(let t of e)await N.mutateAsync({name:t.name,version:t.latestVersion,nodeId:d.id});return}await H.mutateAsync({kind:`update`,targets:e.map(e=>({name:e.name,version:e.latestVersion})),nodeIds:[d.id]})}},[b,d.id,d.isHub,H,N]),J=pe({onSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),m.invalidateQueries({queryKey:[[`addonPages`]]}),m.invalidateQueries({queryKey:[[`capabilities`]]}),m.invalidateQueries({queryKey:[[`integrations`]]})}}),[Y,_e]=c(`type`),[Z,ye]=c(()=>typeof window>`u`?`grouped`:window.localStorage.getItem(`camstack.addons.viewMode`)===`flat`?`flat`:`grouped`),be=e=>{ye(e),typeof window<`u`&&window.localStorage.setItem(`camstack.addons.viewMode`,e)},[xe,Se]=he(),Q=xe.get(`capability`),Ce=a(()=>{let e=n.filter(e=>!Ne(e.manifest.packageName));return d.isHub||(e=e.filter(e=>Fe(e.placement,d.isHub))),Q&&(e=e.filter(e=>(e.manifest.capabilities??[]).some(e=>(typeof e==`string`?e:e.name)===Q))),e},[n,d.isHub,Q]),we=()=>{let e=new URLSearchParams(xe);e.delete(`capability`),Se(e,{replace:!0})},Te=Z===`flat`?Ce:Le(Ce),Ee=a(()=>{let e=[...Te];switch(Y){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,Y]);return i(`div`,{className:`space-y-4`,children:[[...D.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:Y,onChange:e=>_e(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:()=>be(e),className:`px-2.5 py-1.5 transition-colors capitalize ${Z===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(F,{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:()=>le.mutate({channel:e}),disabled:le.isPending,className:`px-2.5 py-1.5 transition-colors capitalize ${L?.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:L?.updateCheckIntervalSeconds??21600,disabled:R.isPending||L===void 0,onChange:e=>{L!==void 0&&R.mutate({channel:L.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 q(),disabled:H.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:[H.isPending?l(S,{className:`w-3 h-3 animate-spin`}):l(z,{className:`w-3 h-3`}),H.isPending?`Updating…`:`Update All (${re})`]}),i(`button`,{type:`button`,onClick:f,disabled:p||H.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(F,{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:y,children:[l(fe,{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),v(!0)},onFocus:()=>v(!0),placeholder:`Search addons on npm...`,disabled:H.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`}),V&&l(S,{className:`absolute right-2.5 top-1/2 -translate-y-1/2 h-3 w-3 text-foreground-subtle animate-spin`}),_&&B&&B.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:[B.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 (`,B.length,`)`]}),B&&B.length>0&&l(`div`,{className:`max-h-72 overflow-auto divide-y divide-border`,children:B.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(k,{className:`h-3 w-3`}),e.installedVersion??`Installed`]}):i(`button`,{type:`button`,onClick:()=>J.mutate({packageName:e.name}),disabled:J.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:[J.isPending?l(S,{className:`h-3 w-3 animate-spin`}):l(z,{className:`h-3 w-3`}),`Install`]})]},e.name))})]})]}),l(Ae,{onUploadSuccess:()=>{m.invalidateQueries({queryKey:[[`addons`]]}),f()}})]}),Q&&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:Q}),l(`button`,{type:`button`,onClick:we,className:`ml-auto text-xs text-foreground-subtle hover:text-foreground underline`,children:`Clear`})]}),ge&&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(I,{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.`})]})]}),Ce.length===0&&l(`div`,{className:`text-xs text-foreground-subtle`,children:n.length===0?`No addons installed`:Q?`No installed addons declare the "${Q}" 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=x.get(t),r=$(e)?e.representative:e,i=n?e=>N.mutate({name:t,version:e,nodeId:d.id}):void 0,a=P.get(t)??null,s=a!==null&&X(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:H.isPending},$(e)?t:e.manifest.id)})})]})}function ze(){let e=s(),{data:n,isLoading:r,isError:a}=g(),{data:o}=_(void 0),{nodes:c}=H(),{selection:d,selectNode:f,requestedNodeId:p}=q(c.length>0?c:[Pe]),m=d.node??Pe,h=m.id,ee=c.length>0?d.staleNodeId:null,v=re(),y=j(),b=v.isPending||y.isPending,x=async()=>{await v.mutateAsync({nodeId:h}),await y.mutateAsync(),e.invalidateQueries({queryKey:[[`addons`]]})},S=t(v);S.current=v;let C=t(p??`hub`);u(()=>{S.current.mutate({nodeId:C.current})},[]);let w=(n??[]).map(Ie).filter(e=>e!==null);return i(G,{children:[i(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[l(P,{selectedNodeId:h,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:[w.length,` installed`]}),i(`button`,{type:`button`,onClick:()=>void x(),disabled:b,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(F,{className:`w-3 h-3 ${b?`animate-spin`:``}`}),`Check for updates`]})]})]}),l(K,{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:w,clusterStatus:o,selectedNode:m,onRefresh:()=>void x(),isRefreshing:b})]})}export{ze as AddonsPage};
|
|
@@ -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,_t as p,at as m,ct as h,st as g,vt as _}from"./player-overlays-B82OVd2b.js";import{At as v,Ec as y,Eu as b,Ft as x,Il as S,It as C,Jl as w,Kt as T,Nt as E,Pt as D,Qt as O,Rt as k,Sl as A,Xc as j,Zt as M,_ as N,ct as P,in as F,iu as ee,jt as te,kt as I,ll as L,lt as R,ql as z,ri as B,rn as ne,su as V,tn as H,ul as re,uu as U,wl as W,xl as G}from"./src-jk2FdB5v.js";import{t as ie}from"./boxes-B2dkI7tE.js";import{t as ae}from"./send-BUidPUKy.js";import{gt as K}from"./src-8XVcukAG.js";import{n as q}from"./index-BpiZqZOx.js";import{t as J}from"./AdminPage-CiKtOLQm.js";import{t as oe}from"./AdminTabs-CSovnIie.js";var se=_(`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 ce=[`llm`,`listProfiles`],le=[`llm`,`listProfileKinds`],ue=[`llm`,`getDefaults`],de=[`llm`,`listRuntimeNodes`],fe=[`llm`,`listModelCatalog`],pe=[`llm`,`getUsage`],me=[{purpose:`vision`,visionOnly:!0},{purpose:`text`,visionOnly:!1}],he=new Map(Object.entries({openai:U,anthropic:U,google:U,"openai-compatible":G,"managed-local":V}));function ge(e){return he.get(e)??null}function Y(e){return typeof e==`string`&&e.length>0?e:void 0}function X(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 Z(e){return e===!0}function _e(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:xe(e.runtime?.extraArgs??[])}}var ve=[`f32`,`f16`,`q8_0`,`q5_1`,`q5_0`,`q4_1`,`q4_0`];function ye(e){return typeof e==`string`&&ve.includes(e)?e:void 0}function be(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 xe(e){return e.map(e=>/\s/.test(e)?`"${e}"`:e).join(` `)}var Se=[`--jinja`,`--cont-batching`];function Ce(e,t,n){let r=X(e.threads),i=X(e.batchSize),a=X(e.ubatchSize),o=ye(e.cacheTypeK),s=ye(e.cacheTypeV);return{nodeId:t,engine:`llama-cpp`,model:n,extraArgs:[...be(Y(e.extraArgs)??``)],contextSize:X(e.contextSize)??4096,gpuLayers:X(e.gpuLayers)??0,...r===void 0?{}:{threads:r},parallel:X(e.parallel)??1,...i===void 0?{}:{batchSize:i},...a===void 0?{}:{ubatchSize:a},flashAttention:Z(e.flashAttention),mlock:Z(e.mlock),noMmap:Z(e.noMmap),...o===void 0?{}:{cacheTypeK:o},...s===void 0?{}:{cacheTypeV:s},autoStart:Z(e.autoStart),idleStopMinutes:X(e.idleStopMinutes)??30}}function we(e,t,n,r,i){let a={id:n?.id??crypto.randomUUID(),name:t,kind:e,addonId:`ai`,enabled:n?.enabled??!0,model:Y(r.model)??n?.model??``,supportsVision:i?.supportsVision??Z(r.supportsVision),timeoutMs:X(r.timeoutMs)??K.totalMs,connectTimeoutMs:X(r.connectTimeoutMs)??K.connectMs,firstTokenTimeoutMs:X(r.firstTokenTimeoutMs)??K.firstTokenMs,idleTimeoutMs:X(r.idleTimeoutMs)??K.idleMs,retry:{enabled:Z(r.retryEnabled),maxAttempts:X(r.retryMaxAttempts)??1},toolsEnabled:Z(r.toolsEnabled)},o=Y(r.baseUrl),s=Y(r.apiKey),c=X(r.temperature),l=X(r.topP),u=X(r.topK),d=X(r.maxTokens),f=X(r.contextLength),p=Y(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:Ce(r,i.nodeId,i.model)}}}function Te(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 Ee=2e3;function Q(e){return`${(e/1e9).toFixed(2)} GB`}function De(e){return e===null?``:e.model.kind===`catalog`?`catalog:${e.model.catalogId}`:e.model.kind===`path`?`node:${e.modelId}`:`custom`}function Oe({nodeId:e,value:t,onChange:n}){let{t:o}=q(),u=m(),[d,f]=s(``),[p,h]=s(null),[g,_]=s(!1),v=a({queryKey:fe,queryFn:()=>u.trpcClient.llm.listModelCatalog.query({})}),y=a({queryKey:[`llm`,`listNodeModels`,e],queryFn:()=>u.trpcClient.llm.listNodeModels.query({nodeId:e})}),b=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`})}}),x=c({mutationFn:t=>u.trpcClient.llm.installModel.mutate({nodeId:e,model:t}),onSuccess:()=>{_(!0),y.refetch()}}),C=a({queryKey:de,enabled:x.isPending,refetchInterval:x.isPending?Ee:!1,queryFn:()=>u.trpcClient.llm.listRuntimeNodes.query({})}).data?.find(t=>t.nodeId===e)?.status?.download,w=i(()=>{let t=(v.data??[]).map(e=>({value:`catalog:${e.id}`,label:`${e.label} · ${e.quantization} · ${Q(e.sizeBytes)}`})),n=(y.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:Q(t.sizeBytes),node:e})})),r=p?.ok===!0?[{value:`custom`,label:`${p.label} · ${Q(p.totalBytes)}`}]:[];return[{value:``,label:o(`ai.selectModel`,`Select a model…`)},...t,...n,...r]},[v.data,y.data,p,e,o]),T=e=>{if(e===``){n(null);return}if(e===`custom`){if(p?.ok!==!0)return;n({model:p.model,modelId:p.label,supportsVision:p.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=y.data?.find(e=>e.file===t);r?.path!==void 0&&n({model:{kind:`path`,path:r.path},modelId:t,supportsVision:!1})},E=e=>{d.trim()!==``&&b.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(ne,{id:`ai-model`,value:De(t),options:w,onChange:e=>T(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(k,{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(),E())}}),r(F,{size:`sm`,variant:`secondary`,type:`button`,disabled:d.trim()===``||b.isPending,onClick:()=>E(),children:[b.isPending?l(S,{className:`h-3.5 w-3.5 animate-spin`}):l(re,{className:`h-3.5 w-3.5`}),o(`ai.hfCheck`,`Check`)]})]}),b.isError&&l(`p`,{className:`mt-2 text-[11px] text-danger`,children:b.error instanceof Error?b.error.message:o(`common.error`,`Error`)}),p?.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:p.message}),p.candidates!==void 0&&p.candidates.length>0&&l(`div`,{className:`mt-1.5 flex flex-wrap gap-1`,children:p.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),b.mutate({ref:t})},children:e},e))}),p.requiredBytes!==void 0&&l(F,{size:`sm`,variant:`secondary`,type:`button`,className:`mt-2`,onClick:()=>E(p.requiredBytes),children:o(`ai.hfOverride`,`Install anyway ({{size}})`,{size:Q(p.requiredBytes)})})]}),p?.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:p.label}),l(M,{variant:p.purpose===`vision`?`info`:`default`,children:p.purpose}),l(M,{variant:`default`,children:Q(p.totalBytes)})]}),p.extraFilenames.length>0&&l(`p`,{className:`mt-1 text-[10px] text-foreground-subtle`,children:o(`ai.hfExtras`,`Also downloads: {{files}}`,{files:p.extraFilenames.join(`, `)})}),r(`div`,{className:`mt-2 flex items-center gap-2`,children:[r(F,{size:`sm`,type:`button`,disabled:x.isPending||g,onClick:()=>x.mutate(p.model),children:[x.isPending?l(S,{className:`h-3.5 w-3.5 animate-spin`}):l(ee,{className:`h-3.5 w-3.5`}),g?o(`ai.hfInstalled`,`Downloaded`):o(`ai.hfInstall`,`Download to {{node}}`,{node:e})]}),C!==void 0&&l(`span`,{className:`text-[10px] text-foreground-subtle`,children:C.phase===`verifying`?o(`ai.hfVerifying`,`verifying {{file}}…`,{file:C.file}):o(`ai.hfDownloading`,`{{file}} ({{index}}/{{count}}) — {{done}}{{total}}`,{file:C.file,index:C.fileIndex,count:C.fileCount,done:Q(C.downloadedBytes),total:C.totalBytes===void 0?``:` / ${Q(C.totalBytes)}`})})]}),x.isError&&l(`p`,{className:`mt-1.5 text-[11px] text-danger`,children:x.error instanceof Error?x.error.message:o(`common.error`,`Error`)})]})]})]})}n();function ke({kind:e,className:t}){let n=ge(e.kind);return n===null?l(`span`,{className:t,children:e.icon}):l(n,{className:t})}function Ae({kinds:e,onPick:t,onCancel:n}){let{t:a}=q(),o=i(()=>Te(e),[e]);return l(I,{open:!0,onOpenChange:e=>!e&&n(),children:r(te,{width:`lg`,placement:`sheet-on-mobile`,scroll:`body`,children:[l(D,{children:l(x,{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(ke,{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(E,{children:l(F,{size:`sm`,variant:`secondary`,type:`button`,onClick:n,children:a(`common.cancel`,`Cancel`)})})]})})}function je({kind:e,existing:t,onSave:n,onCancel:a,saving:c,error:u}){let{t:d}=q(),f=e.kind===`managed-local`,[p,m]=s(t?.name??e.label),[h,g]=s(()=>t===null?{}:_e(t)),[_,y]=s(t?.runtime?.nodeId??`hub`),[b,C]=s(()=>t?.runtime===void 0?null:{model:t.runtime.model,modelId:t.model,supportsVision:t.supportsVision}),w=i(()=>be(Y(h.extraArgs)??``),[h.extraArgs]),O=()=>{if(!f){n(we(e.kind,p,t,h));return}b!==null&&n(we(e.kind,p,t,h,{nodeId:_,model:b.model,modelId:b.modelId,supportsVision:b.supportsVision}))},A=c||p.trim()===``||f&&b===null;return l(I,{open:!0,onOpenChange:e=>!e&&a(),children:r(te,{width:`lg`,placement:`sheet-on-mobile`,scroll:`body`,children:[l(D,{children:r(x,{className:`flex items-center gap-2`,children:[l(ke,{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(k,{id:`ai-profile-name`,value:p,onChange:e=>m(e.target.value),placeholder:e.label})]}),f&&r(o,{children:[l(N,{selectedNodeId:_,onSelect:y,label:d(`ai.runtimeNode`,`Runtime node`),alwaysShow:!0}),l(Oe,{nodeId:_,value:b,onChange:C}),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(k,{id:`ai-extra-args`,value:Y(h.extraArgs)??``,onChange:e=>g({...h,extraArgs:e.target.value}),placeholder:Se.join(` `)}),w.length>0&&l(`div`,{className:`mt-1 flex flex-wrap gap-1`,children:w.map((e,t)=>l(M,{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.`)})]})]}),l(T,{schema:e.configSchema,values:h,onChange:g}),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(E,{children:[f&&b===null&&l(M,{variant:`warning`,children:d(`ai.pickModelFirst`,`pick a model`)}),l(F,{size:`sm`,variant:`secondary`,type:`button`,onClick:a,children:d(`common.cancel`,`Cancel`)}),r(F,{size:`sm`,type:`button`,disabled:A,onClick:O,children:[c&&l(S,{className:`h-3.5 w-3.5 animate-spin`}),t===null?d(`ai.createProfile`,`Create profile`):d(`ai.saveChanges`,`Save changes`)]})]})]})})}n();function Me(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(ke,{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(M,{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(M,{variant:`default`,children:e.runtime.nodeId})},{key:`enabled`,header:e.t(`ai.colOn`,`On`),align:`center`,nowrap:!0,render:t=>l(C,{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(F,{size:`sm`,variant:`ghost`,type:`button`,onClick:()=>e.onTest(t),title:e.t(`ai.test`,`Test`),children:e.testingId===t.id?l(S,{className:`h-3.5 w-3.5 animate-spin`}):l(ae,{className:`h-3.5 w-3.5`})}),l(F,{size:`sm`,variant:`ghost`,type:`button`,disabled:!e.kindByName.has(t.kind),onClick:()=>e.onEdit(t),title:e.t(`common.edit`,`Edit`),children:l(W,{className:`h-3.5 w-3.5`})}),l(F,{size:`sm`,variant:`ghost`,type:`button`,onClick:()=>e.onDelete(t),title:e.t(`common.delete`,`Delete`),children:l(g,{className:`h-3.5 w-3.5 text-danger`})})]})}]}function Ne(){let{t:e}=q(),t=m(),[n,o]=s({mode:`closed`}),[u,d]=s(null),[f,p]=s(null),h=a({queryKey:ce,queryFn:()=>t.trpcClient.llm.listProfiles.query({})}),g=a({queryKey:le,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`}),p(null),_()},onError:t=>p(t instanceof Error?t.message:e(`ai.saveFailed`,`Save failed`))}),y=c({mutationFn:e=>t.trpcClient.llm.deleteProfile.mutate({addonId:e.addonId,profileId:e.id}),onSuccess:_}),b=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}`})}),x=h.data??[],C=i(()=>g.data??[],[g.data]),w=i(()=>{let e=new Map;for(let t of C)e.set(t.kind,t);return e},[C]);return r(J,{icon:j,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(F,{size:`sm`,type:`button`,onClick:()=>{p(null),o({mode:`pick-kind`})},children:[l(A,{className:`h-3.5 w-3.5`}),e(`ai.addProfile`,`Add profile`)]}),children:[h.isError&&l(H,{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(Pe,{profiles:x}),h.isLoading&&l(`div`,{className:`flex items-center justify-center py-16`,children:l(S,{className:`h-6 w-6 animate-spin text-primary`})}),!h.isLoading&&x.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.`)}),x.length>0&&l(O,{children:l(P,{columns:Me({kindByName:w,testResult:u,testingId:b.isPending?b.variables?.id??null:null,t:e,onToggle:e=>v.mutate({...e,enabled:!e.enabled,apiKey:`__redacted__`}),onTest:e=>b.mutate(e),onEdit:e=>{let t=w.get(e.kind);t!==void 0&&(p(null),o({mode:`form`,kind:t,profile:e}))},onDelete:e=>y.mutate(e)}),rows:x,rowKey:e=>e.id,minWidthPx:760,bordered:!1,mobileMode:`scroll`,maxBodyHeight:`max-h-[60vh]`})}),n.mode===`pick-kind`&&l(Ae,{kinds:C,onCancel:()=>o({mode:`closed`}),onPick:e=>o({mode:`form`,kind:e,profile:null})}),n.mode===`form`&&l(je,{kind:n.kind,existing:n.profile,saving:v.isPending,error:f,onSave:e=>v.mutate(e),onCancel:()=>o({mode:`closed`})})]})}function Pe({profiles:e}){let{t}=q(),n=m(),i=a({queryKey:ue,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(O,{children:l(`div`,{className:`grid gap-4 p-4 sm:grid-cols-2`,children:me.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 Fe=5e3;function Ie(e){return`${(e/1e9).toFixed(1)} GB`}function Le(){let{t:e}=q(),t=m(),n=a({queryKey:de,refetchInterval:Fe,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(M,{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(M,{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?`—`:Ie(e.disk.modelsBytes)})},{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(J,{icon:L,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(H,{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(O,{children:l(P,{columns:o,rows:s,rowKey:e=>e.nodeId,minWidthPx:640,bordered:!1,mobileMode:`scroll`,maxBodyHeight:R})})]})}var Re=f(`/addon/ai/test-chat`),ze=f(`/addon/ai/test-chat/chats`),Be=6e5;function Ve(e){let t=e.firstTokenTimeoutMs;if(!(typeof t!=`number`||!Number.isFinite(t)||t<=0))return Math.min(Math.round(t),Be)}function He(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ue(e){if(!He(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 We=[`resolving-image`,`connecting`,`first-token-wait`,`streaming`];function Ge(e){let t;try{t=JSON.parse(e)}catch{return null}if(!He(t))return null;switch(t.kind){case`status`:{let e=We.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:Ue(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*Ke(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=Ge(e);t!==null&&(yield t)}a=r.indexOf(`
|
|
3
|
-
`)}}let e=r.trim();if(e.length>0){let t=Ge(e);t!==null&&(yield t)}}finally{t.releaseLock()}}function qe(e){return e.filter(e=>e.failed!==!0&&e.content.length>0).map(e=>({role:e.role,content:e.content}))}function Je(e){return e.thumbnailBase64===void 0||e.thumbnailBase64.length===0?null:`data:${e.mimeType};base64,${e.thumbnailBase64}`}function Ye(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 Xe(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 Ze(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 Qe=[`pipelineAnalytics`,`listRecentTracks`,`ai-test`],$e=360*60*1e3,et=40,tt=160,$={phase:`connecting`,firstTokenTimeoutMs:0,text:``,mediaSent:null};function nt(){let{t:n}=q(),o=m(),[c,d]=s(``),[f,_]=s(``),[v,x]=s(``),[S,C]=s([]),[T,E]=s(null),[D,A]=s(`none`),[j,M]=s(`throwaway`),[N,P]=s(null),[ee,te]=s([]),[I,L]=s(null),[R,z]=s(null),B=t(null);u(()=>()=>B.current?.abort(),[]);let V=e(async()=>{let e=await fetch(ze,{credentials:`same-origin`});e.ok&&te((await e.json()).chats??[])},[]);u(()=>{j===`persistent`&&V()},[j,V]);let re=a({queryKey:ce,queryFn:()=>o.trpcClient.llm.listProfiles.query({})}),U=i(()=>(re.data??[]).filter(e=>e.enabled),[re.data]),W=U.find(e=>e.id===c)??null,G=R!==null,ie=e(async(e,t)=>{let r=new AbortController;B.current=r,L(null);let i=Ve(W??{});z({...$,firstTokenTimeoutMs:i??0});let a=``,o=null,s,l=null,u=null,d;try{let n=await fetch(Re,{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},...j===`persistent`?{persist:!0,...N===null?{}:{conversationId:N}}:{}})});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 Ke(n.body))switch(e.kind){case`status`:z(t=>({...t??$,phase:e.phase}));break;case`meta`:o=e.mediaSent,s=e.model,z(t=>({...t??$,firstTokenTimeoutMs:e.firstTokenTimeoutMs,mediaSent:e.mediaSent}));break;case`token`:a+=e.text,z(e=>({...e??$,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||L(e instanceof Error?e.message:n(`common.error`,`Error`))}finally{B.current=null,z(null)}d!==void 0&&(P(d),V());let p=r.signal.aborted&&a.length>0;l===null&&a.length===0&&!p||C(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}])},[j,N,W,c,V,f,n]),K=e(()=>{let e=v.trim();if(e===``||c===``||G)return;let t={id:`u-${String(Date.now())}`,role:`user`,content:e,...T===null?{}:{attachmentLabel:T.label,attachmentKind:T.ref.kind}},n=[...S,t];C(n),x(``);let r=T?.ref;E(null),A(`none`),ie(j===`persistent`&&N!==null?[{role:`user`,content:e}]:qe(n),r)},[j,N,v,T,c,ie,G,S]),oe=()=>B.current?.abort(),le=()=>{B.current?.abort(),C([]),E(null),x(``),L(null),z(null),P(null)},ue=async e=>{B.current?.abort();let t=await fetch(`${ze}/${e}`,{credentials:`same-origin`});if(!t.ok)return;let n=await t.json();P(e),C(Ye(n)),z(null),L(null)};return r(J,{icon:w,title:n(`ai.testTitle`,`Test chat`),subtitle:n(j===`persistent`?`ai.testSubtitlePersistent`:`ai.testSubtitle`,j===`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(F,{size:`sm`,variant:`secondary`,type:`button`,disabled:S.length===0&&T===null,onClick:le,children:[l(g,{className:`h-3.5 w-3.5`}),n(`ai.clearChat`,`Clear`)]}),children:[r(O,{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(ne,{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&&!re.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(k,{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(F,{size:`sm`,variant:j===`throwaway`?`primary`:`outline`,type:`button`,onClick:()=>{M(`throwaway`),P(null)},children:n(`ai.throwawayMode`,`Throwaway`)}),l(F,{size:`sm`,variant:j===`persistent`?`primary`:`outline`,type:`button`,onClick:()=>M(`persistent`),children:n(`ai.saveConversation`,`Save conversation`)})]}),j===`persistent`&&r(`div`,{className:`space-y-2`,children:[l(`div`,{className:`flex items-center gap-2`,children:r(F,{size:`sm`,variant:`secondary`,type:`button`,onClick:le,children:[l(se,{className:`h-3.5 w-3.5`}),n(`ai.newChat`,`New chat`)]})}),ee.length>0&&l(`div`,{className:`max-h-36 divide-y divide-border overflow-y-auto rounded-md border border-border`,children:ee.map(e=>l(`button`,{type:`button`,onClick:()=>void ue(e.id),className:`flex w-full px-2.5 py-1.5 text-left text-[11px] hover:bg-surface-hover ${e.id===N?`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.`)}),W!==null&&!W.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.`)})]}),I!==null&&l(H,{title:n(`ai.chatFailed`,`The test call failed`),message:I}),l(rt,{turns:S,live:R}),r(O,{className:`space-y-2 p-3`,children:[T!==null&&r(`div`,{className:`flex items-center gap-2 rounded-md border border-border bg-surface px-2.5 py-1.5`,children:[T.ref.kind===`snapshot`?l(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}):l(b,{className:`h-3.5 w-3.5 text-foreground-subtle`}),l(`span`,{className:`min-w-0 flex-1 truncate text-[11px] text-foreground`,children:T.label}),l(F,{size:`sm`,variant:`ghost`,type:`button`,onClick:()=>E(null),children:l(y,{className:`h-3.5 w-3.5`})})]}),r(`div`,{className:`flex flex-wrap items-center gap-2`,children:[r(F,{size:`sm`,variant:D===`snapshot`?`primary`:`outline`,type:`button`,onClick:()=>A(D===`snapshot`?`none`:`snapshot`),children:[l(p,{className:`h-3.5 w-3.5`}),n(`ai.attachSnapshot`,`Camera snapshot`)]}),r(F,{size:`sm`,variant:D===`track`?`primary`:`outline`,type:`button`,onClick:()=>A(D===`track`?`none`:`track`),children:[l(b,{className:`h-3.5 w-3.5`}),n(`ai.attachTrack`,`Recent track`)]})]}),D===`snapshot`&&l(ot,{onPick:e=>{E({ref:{kind:`snapshot`,deviceId:e.id},label:n(`ai.snapshotOf`,`Snapshot of {{name}}`,{name:e.name})}),A(`none`)}}),D===`track`&&l(ct,{onPick:(e,t)=>{E({ref:{kind:`track`,trackId:e.trackId,deviceId:e.deviceId},label:n(`ai.trackOf`,`{{class}} on {{name}}`,{class:e.label??e.className,name:t})}),A(`none`)}}),r(`div`,{className:`flex items-center gap-2`,children:[l(k,{value:v,onChange:e=>x(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),K())},placeholder:n(`ai.messagePlaceholder`,`Ask the model something…`),"aria-label":n(`ai.message`,`Message`)}),G?r(F,{size:`sm`,variant:`secondary`,type:`button`,onClick:oe,children:[l(h,{className:`h-3.5 w-3.5`}),n(`ai.stop`,`Stop`)]}):r(F,{size:`sm`,type:`button`,disabled:v.trim()===``||c===``,onClick:K,children:[l(ae,{className:`h-3.5 w-3.5`}),n(`ai.send`,`Send`)]})]})]})]})}function rt({turns:e,live:t}){let{t:n}=q();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(O,{children:r(`div`,{className:`max-h-[50vh] space-y-2 overflow-y-auto p-3`,children:[e.map(e=>l(it,{turn:e},e.id)),t!==null&&r(`div`,{className:`space-y-1`,children:[t.mediaSent!==null&&l(at,{attachment:t.mediaSent}),t.text.length>0&&l(it,{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(S,{className:`h-3.5 w-3.5 animate-spin`}),Ze(t.phase,t.firstTokenTimeoutMs)]})]})]})})}function it({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(at,{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(b,{className:`h-3 w-3`}):l(p,{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(p,{className:`h-3 w-3`}):l(b,{className:`h-3 w-3`}),Xe(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 at({attachment:e}){let t=Je(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 ot({onPick:e}){let{t}=q(),n=B({isCamera:!0,projection:`slim`}),r=(n.data??[]).filter(e=>!e.disabled);return n.isLoading?l(S,{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(st,{device:t,onPick:e},t.id))})}function st({device:e,onPick:t}){let{src:n}=d(e.id,{width:tt});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(M,{variant:`warning`,children:`off`}),l(`span`,{className:`truncate text-[10px] text-foreground`,children:e.name})]})]})}function ct({onPick:e}){let{t}=q(),n=m(),o=B({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:[...Qe,s.length],enabled:s.length>0,queryFn:()=>n.trpcClient.pipelineAnalytics.listRecentTracks.query({deviceIds:[...s],since:Date.now()-$e,limit:et,projection:`slim`})});if(o.isLoading||u.isLoading)return l(S,{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(b,{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 lt=1440*60*1e3,ut=[1,7,30,90];function dt(){let{t:e}=q(),t=m(),[n,o]=s(7),c=i(()=>{let e=new Date;return e.setHours(0,0,0,0),e.getTime()-(n-1)*lt},[n]),u=a({queryKey:ce,queryFn:()=>t.trpcClient.llm.listProfiles.query({})}),d=a({queryKey:[...pe,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]),p=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(J,{icon:z,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(ne,{"aria-label":e(`ai.window`,`Window`),value:String(n),options:ut.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(H,{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(O,{children:l(P,{columns:p,rows:h,rowKey:e=>`${e.day}|${e.consumer}|${e.profileId}`,minWidthPx:720,bordered:!1,mobileMode:`scroll`,maxBodyHeight:R})})]})}function ft(){let{t:e}=q();return l(`div`,{className:`flex flex-col p-4`,children:l(oe,{tabs:[{id:`profiles`,label:e(`ai.tabProfiles`,`Profiles`),icon:ie,content:l(Ne,{})},{id:`runtimes`,label:e(`ai.tabRuntimes`,`Runtimes`),icon:L,content:l(Le,{})},{id:`usage`,label:e(`ai.tabUsage`,`Usage`),icon:z,content:l(dt,{})},{id:`test`,label:e(`ai.tabTest`,`Test`),icon:w,content:l(nt,{})}]})})}export{ft as AiProfilesPage,ft as default};
|