@camstack/addon-admin-ui 1.2.58 → 1.2.60
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/AddLocationWizard-nmw7yXa5.js +1 -0
- package/dist/assets/AddonCollectionPage-L-_Ay0C2.js +1 -0
- package/dist/assets/Addons-Ce18i_2K.js +1 -0
- package/dist/assets/{AdminPage-Dq33XE9j.js → AdminPage-CCD07UMs.js} +1 -1
- package/dist/assets/{AdminTabs-SuhxFl_f.js → AdminTabs-VEJ9aAds.js} +1 -1
- package/dist/assets/AiProfiles-BmyaHJsG.js +3 -0
- package/dist/assets/BrokerForm-C_ydrEiE.js +1 -0
- package/dist/assets/Build-B0V3eQCD.js +32 -0
- package/dist/assets/Capabilities-mYaTP3zj.js +1 -0
- package/dist/assets/CapabilityBadges-CUuQq9C6.js +1 -0
- package/dist/assets/Cluster-CAPVntiH.js +1 -0
- package/dist/assets/Data-Cy6cxYnL.js +1 -0
- package/dist/assets/DetectionIntelligence-D_UfLFUs.js +1 -0
- package/dist/assets/{DeviceAggregateSection-CkqESYNX.js → DeviceAggregateSection-cezz4Q1I.js} +1 -1
- package/dist/assets/DeviceDetail-OZn62WTd.js +2 -0
- package/dist/assets/Devices-B7naJHzB.js +1 -0
- package/dist/assets/EmbedPlayerPage-CUJ-TF0I.js +1 -0
- package/dist/assets/Events-C54Nf_FA.js +1 -0
- package/dist/assets/FormBuilder-79Fgr735.js +1 -0
- package/dist/assets/Identity-C-vZI88k.js +1 -0
- package/dist/assets/IntegrationDetail-hg7RVODR.js +1 -0
- package/dist/assets/Integrations-BDhj7UlK.js +1 -0
- package/dist/assets/Integrations-CD7WfSkd.js +1 -0
- package/dist/assets/Logs-BlgZwoZu.js +1 -0
- package/dist/assets/{MaskShapeCanvas-pGn6MKOi.js → MaskShapeCanvas-Dcpby34M.js} +1 -1
- package/dist/assets/MotionZonesSettings-B-y6Y1Xg.js +1 -0
- package/dist/assets/MyAccess-D62ngaEJ.js +2 -0
- package/dist/assets/Network-DNg2yCKK.js +1 -0
- package/dist/assets/NodeAddonsSettingsPanel-B_e7Y4br.js +1 -0
- package/dist/assets/NodeInferenceDevices-DTEpjg6z.js +1 -0
- package/dist/assets/Notifications-DZywZPYK.js +1 -0
- package/dist/assets/Pipeline-BGd2zTfL.js +1 -0
- package/dist/assets/Plates-Dgn8ovPo.js +1 -0
- package/dist/assets/PrivacyMaskSettings-aqN_KJa8.js +1 -0
- package/dist/assets/{ProviderIcon-X2_0sDU9.js → ProviderIcon-CSVJE_O0.js} +1 -1
- package/dist/assets/Recordings-WBG1aCx6.js +1 -0
- package/dist/assets/ScanNetworkModal-BY3gf03t.js +1 -0
- package/dist/assets/SceneMonitorEditor-BZimh2ck.js +1 -0
- package/dist/assets/Scenes-DeCu0w94.js +1 -0
- package/dist/assets/{SchemaTabBar-BrF8ZUiR.js → SchemaTabBar-DC28nb9j.js} +1 -1
- package/dist/assets/Settings-BVd4lsaN.js +1 -0
- package/dist/assets/{Showroom-7m0amlh4.js → Showroom-DFG_5cnr.js} +1 -1
- package/dist/assets/{StableTabPanel-p16epZGa.js → StableTabPanel-Dc954AQl.js} +1 -1
- package/dist/assets/{StatusBadge-Dcr2bw58.js → StatusBadge-CeptlsPG.js} +1 -1
- package/dist/assets/{Terminal-BkKFvIvp.js → Terminal-QEGYVgmV.js} +2 -2
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-DbudtQGC.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-C6w2JXhl.js} +1 -1
- package/dist/assets/_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DhP-Lgiq.js +1 -0
- package/dist/assets/_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-8kv6pj9W.js +6 -0
- package/dist/assets/{_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-DkcC9IVF.js → _virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-DN3UpM8E.js} +1 -1
- package/dist/assets/{_virtual_mf___mfe_internal__admin_ui_host__loadShare__react_mf_2_dom__loadShare__.js-D9-wIasd.js → _virtual_mf___mfe_internal__admin_ui_host__loadShare__react_mf_2_dom__loadShare__.js-BsvPG3BX.js} +1 -1
- package/dist/assets/{_virtual_mf___mfe_internal__admin_ui_host__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DstpX0yz.js → _virtual_mf___mfe_internal__admin_ui_host__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DtoGixA1.js} +1 -1
- package/dist/assets/{_virtual_mf___mfe_internal__admin_ui_host__loadShare__react_mf_2_konva__loadShare__.js-BBBrLLEa.js → _virtual_mf___mfe_internal__admin_ui_host__loadShare__react_mf_2_konva__loadShare__.js-PmiLsYEK.js} +1 -1
- package/dist/assets/{authed-media-B8T1dsFh.js → authed-media-BPd_L9jr.js} +1 -1
- package/dist/assets/{bell-ring-CUDpUeWG.js → bell-ring-BdqqbAsS.js} +1 -1
- package/dist/assets/{boxes-pkqHQIKP.js → boxes-Di4kSEDf.js} +1 -1
- package/dist/assets/build-cluster-graph-BgVD-LXn.js +7 -0
- package/dist/assets/circle-check-big-C6H3pgU0.js +1 -0
- package/dist/assets/{circle-x-R5CNfb24.js → circle-x-BZtdhG1q.js} +1 -1
- package/dist/assets/clock-Dkewc-gM.js +1 -0
- package/dist/assets/{copy-DQHP39o_.js → copy-B3EObRTl.js} +1 -1
- package/dist/assets/{debounced-invalidate-BWBc5uaY.js → debounced-invalidate-kboD8U--.js} +1 -1
- package/dist/assets/dist-CZzC-g02.js +345 -0
- package/dist/assets/{dist-DqwPCDLL.js → dist-DG2WQw7F.js} +1 -1
- package/dist/assets/{download-D8qqR37g.js → download-zOlfMwmw.js} +1 -1
- package/dist/assets/{face-bbox-GlN6DJbE.js → face-bbox-Bdb4p_vZ.js} +1 -1
- package/dist/assets/{hard-drive-DDGRH4_v.js → hard-drive-CEELYlZc.js} +1 -1
- package/dist/assets/{hostInit-BYA5grd_.js → hostInit-DQGrrD-J.js} +1 -1
- package/dist/assets/index-BfeBVcjY.js +4 -0
- package/dist/assets/index-C_00GTmn.css +2 -0
- package/dist/assets/{key-round-DBnD5hXc.js → key-round-B4uUkd69.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-834af401.js → mf-entry-bootstrap-0-f9457985.js} +2 -2
- package/dist/assets/{pencil-hCEUn1IA.js → pencil-BFtrhTcL.js} +1 -1
- package/dist/assets/play-CAOvtlt9.js +1 -0
- package/dist/assets/player-overlays-CYHBR24b.js +1 -0
- package/dist/assets/plus-CT9BkTdL.js +1 -0
- package/dist/assets/power-C3GOj5RH.js +1 -0
- package/dist/assets/{radio-CPfefoam.js → radio-D6rodlbU.js} +1 -1
- package/dist/assets/{refresh-cw-C2McgRco.js → refresh-cw-BBMiW3q-.js} +1 -1
- package/dist/assets/remoteEntry-96xMdM9r.js +1 -0
- package/dist/assets/rotate-ccw-B3RVJZHZ.js +1 -0
- package/dist/assets/rotate-cw-Dt9c2DJW.js +1 -0
- package/dist/assets/search-DTWCy4IW.js +1 -0
- package/dist/assets/send-5Q9K_RF0.js +1 -0
- package/dist/assets/{server-CsRBtCL_.js → server-DVsXQl7s.js} +1 -1
- package/dist/assets/square-CEELVm2C.js +1 -0
- package/dist/assets/{square-check-big-BjxSMbRP.js → square-check-big-B39UzQnv.js} +1 -1
- package/dist/assets/src-gHOaseTq.js +67 -0
- package/dist/assets/src-k7u3Lt4U.js +345 -0
- package/dist/assets/{undo-2-CZfJ2e4-.js → undo-2-DgZBtWUR.js} +1 -1
- package/dist/assets/{upload-B5vgLYAF.js → upload-xzQ3maRZ.js} +1 -1
- package/dist/assets/{useBodyScrollLock-B_rtaBV1.js → useBodyScrollLock-BDocajQE.js} +1 -1
- package/dist/assets/{useEventInvalidation-Dx_csywq.js → useEventInvalidation-HvWohuH6.js} +1 -1
- package/dist/assets/{video-BjqUkGjh.js → video-CRvcPI-y.js} +1 -1
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-6SojcGBS.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-B_q_nV5G.js} +2 -2
- package/dist/assets/{wifi-Nvsx1sGJ.js → wifi-gnm9Xr91.js} +1 -1
- package/dist/assets/{zap-CnaB8TAK.js → zap-D_23PdBs.js} +1 -1
- package/dist/index.html +6 -6
- package/dist/server/addon.js +356 -40
- package/package.json +1 -1
- package/dist/assets/AddLocationWizard-Cmdtjb0W.js +0 -1
- package/dist/assets/AddonCollectionPage-y8thZKiD.js +0 -1
- package/dist/assets/Addons-B9wNlAOy.js +0 -1
- package/dist/assets/AiProfiles-XHdOJhGT.js +0 -1
- package/dist/assets/BrokerForm-BhfOMuh3.js +0 -1
- package/dist/assets/Build-CZbt5dnz.js +0 -32
- package/dist/assets/Capabilities-DW_cF8pr.js +0 -1
- package/dist/assets/CapabilityBadges-CLqqoyhl.js +0 -1
- package/dist/assets/Cluster-wbUSa2Re.js +0 -1
- package/dist/assets/Data-DanAozV1.js +0 -1
- package/dist/assets/DetectionIntelligence-CTmhHAmP.js +0 -1
- package/dist/assets/DeviceDetail-Ddl_t3v8.js +0 -2
- package/dist/assets/Devices-m7dylGih.js +0 -1
- package/dist/assets/EmbedPlayerPage-mrUvuhmS.js +0 -1
- package/dist/assets/Events-CabU88J8.js +0 -1
- package/dist/assets/FormBuilder-DaUdmatu.js +0 -1
- package/dist/assets/Identity-Ds8l4JNd.js +0 -1
- package/dist/assets/IntegrationDetail-DjUM9SnA.js +0 -1
- package/dist/assets/Integrations-C6MckNDg.js +0 -1
- package/dist/assets/Integrations-CVUNXry0.js +0 -1
- package/dist/assets/Logs-DU2VOlmq.js +0 -1
- package/dist/assets/MotionZonesSettings-DVkvgKnc.js +0 -1
- package/dist/assets/MyAccess-BhlABS_W.js +0 -2
- package/dist/assets/Network-D0gir4s-.js +0 -1
- package/dist/assets/NodeAddonsSettingsPanel-CtO75ohk.js +0 -1
- package/dist/assets/NodeInferenceDevices-qUEYtq1P.js +0 -1
- package/dist/assets/Notifications-CwdeYxsw.js +0 -1
- package/dist/assets/Pipeline-vgsETpZ3.js +0 -1
- package/dist/assets/Plates-B5Uqs4w7.js +0 -1
- package/dist/assets/PrivacyMaskSettings-fIxue0-D.js +0 -1
- package/dist/assets/Recordings-BPztmXFS.js +0 -1
- package/dist/assets/ScanNetworkModal-ByoxTvyg.js +0 -1
- package/dist/assets/Settings-Be5E8nSp.js +0 -1
- package/dist/assets/_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DTufy7Ue.js +0 -1
- package/dist/assets/_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-CSJxMxg6.js +0 -6
- package/dist/assets/build-cluster-graph-BWM8pGFr.js +0 -7
- package/dist/assets/circle-check-big-CobJ2qp-.js +0 -1
- package/dist/assets/clock-CUnxvjbi.js +0 -1
- package/dist/assets/dist-Bh4pP3Lk.js +0 -345
- package/dist/assets/index-BhFZLP1H.css +0 -2
- package/dist/assets/index-kOLbwjEX.js +0 -4
- package/dist/assets/play-N-aCIv2P.js +0 -1
- package/dist/assets/player-overlays-BfDIfiH7.js +0 -1
- package/dist/assets/plus-BwBDSSUm.js +0 -1
- package/dist/assets/power-BftD_p5X.js +0 -1
- package/dist/assets/remoteEntry-DFgCYg0q.js +0 -1
- package/dist/assets/rotate-ccw-xAFA8eXV.js +0 -1
- package/dist/assets/rotate-cw-9bzblRxY.js +0 -1
- package/dist/assets/search-B4tuDAaK.js +0 -1
- package/dist/assets/send-D_iwM8fS.js +0 -1
- package/dist/assets/square-9Bf62Szc.js +0 -1
- package/dist/assets/src-BbMtrcN-.js +0 -67
- package/dist/assets/src-BtBhNsTu.js +0 -345
package/dist/server/addon.js
CHANGED
|
@@ -12185,6 +12185,17 @@ var LlmImageSchema = object({
|
|
|
12185
12185
|
bytes: _instanceof(Uint8Array),
|
|
12186
12186
|
mimeType: string()
|
|
12187
12187
|
});
|
|
12188
|
+
/**
|
|
12189
|
+
* Retry policy. `enabled: false` is NOT the same as `maxAttempts: 1` in intent —
|
|
12190
|
+
* the flag is what a consumer table flips, the count is what the operator tunes.
|
|
12191
|
+
* A retry doubles the wall time of a call, so the two gates that run inside a
|
|
12192
|
+
* notification's budget keep it off (see `CONSUMER_RETRY_POLICY` in addon-ai).
|
|
12193
|
+
*/
|
|
12194
|
+
var LlmRetryPolicySchema = object({
|
|
12195
|
+
enabled: boolean().default(false),
|
|
12196
|
+
/** Total attempts INCLUDING the first. 1 = no retry. */
|
|
12197
|
+
maxAttempts: number().int().min(1).max(5).default(1)
|
|
12198
|
+
});
|
|
12188
12199
|
var LlmGenerateBaseInputSchema = object({
|
|
12189
12200
|
/** Collection routing (the notification-output posture). */
|
|
12190
12201
|
addonId: string().optional(),
|
|
@@ -12199,7 +12210,28 @@ var LlmGenerateBaseInputSchema = object({
|
|
|
12199
12210
|
jsonSchema: record(string(), unknown()).optional(),
|
|
12200
12211
|
/** Per-call override of the profile default. */
|
|
12201
12212
|
maxTokens: number().int().positive().optional(),
|
|
12202
|
-
temperature: number().optional()
|
|
12213
|
+
temperature: number().optional(),
|
|
12214
|
+
/** Per-call override of the profile default (nucleus sampling). */
|
|
12215
|
+
topP: number().min(0).max(1).optional(),
|
|
12216
|
+
/** Per-call override of the profile default (top-k sampling). */
|
|
12217
|
+
topK: number().int().positive().optional(),
|
|
12218
|
+
/** Per-call override of `profile.timeoutMs` — the total generation bound. */
|
|
12219
|
+
timeoutMs: number().int().positive().optional(),
|
|
12220
|
+
/** Per-call override; beats both the consumer table and the profile. */
|
|
12221
|
+
retry: LlmRetryPolicySchema.optional(),
|
|
12222
|
+
/**
|
|
12223
|
+
* Caller-minted id that makes this generation CANCELLABLE.
|
|
12224
|
+
*
|
|
12225
|
+
* Without it a caller that stops waiting cannot stop the work: the gates race
|
|
12226
|
+
* the call against 8 s and free their own slot when the timer wins, while the
|
|
12227
|
+
* generation upstream keeps running to `profile.timeoutMs` — 60 s by default,
|
|
12228
|
+
* on a single-threaded local model. The per-camera bound then counts WAITS,
|
|
12229
|
+
* not generations, and the real load is unbounded.
|
|
12230
|
+
*
|
|
12231
|
+
* `AbortSignal` cannot cross a process boundary; an id can. Pass one here and
|
|
12232
|
+
* `llm.cancel({ requestId })` tears the socket down.
|
|
12233
|
+
*/
|
|
12234
|
+
requestId: string().optional()
|
|
12203
12235
|
});
|
|
12204
12236
|
/**
|
|
12205
12237
|
* `llm-runtime` — node-side managed llama.cpp executor (spec §4). Registered
|
|
@@ -12238,8 +12270,49 @@ var ManagedRuntimeConfigSchema = object({
|
|
|
12238
12270
|
gpuLayers: number().int().default(0),
|
|
12239
12271
|
/** Default: cpus-2, clamped ≥1 (resolved node-side). */
|
|
12240
12272
|
threads: number().int().optional(),
|
|
12241
|
-
/** Concurrent slots. */
|
|
12273
|
+
/** Concurrent slots (`--parallel`). */
|
|
12242
12274
|
parallel: number().int().default(1),
|
|
12275
|
+
/** Logical batch size (`-b`). Larger = faster prompt ingest, more RAM. */
|
|
12276
|
+
batchSize: number().int().positive().optional(),
|
|
12277
|
+
/** Physical batch / micro-batch (`-ub`). */
|
|
12278
|
+
ubatchSize: number().int().positive().optional(),
|
|
12279
|
+
/**
|
|
12280
|
+
* `--flash-attn`. Cuts KV-cache memory on the backends that implement it and
|
|
12281
|
+
* is a no-op elsewhere, so it is offered rather than assumed.
|
|
12282
|
+
*/
|
|
12283
|
+
flashAttention: boolean().default(false),
|
|
12284
|
+
/**
|
|
12285
|
+
* `--mlock`. Pins the weights in RAM so the OS cannot page them out mid
|
|
12286
|
+
* inference. Costs the full model size in resident memory — which is exactly
|
|
12287
|
+
* what the RAM budget is counting.
|
|
12288
|
+
*/
|
|
12289
|
+
mlock: boolean().default(false),
|
|
12290
|
+
/**
|
|
12291
|
+
* `--no-mmap`. Reads the whole GGUF up front instead of mapping it. Slower to
|
|
12292
|
+
* start, but avoids the page-fault stalls a network or spinning-disk model
|
|
12293
|
+
* store produces on every first token.
|
|
12294
|
+
*/
|
|
12295
|
+
noMmap: boolean().default(false),
|
|
12296
|
+
/** `--cache-type-k` / `--cache-type-v` — quantising the KV cache is the
|
|
12297
|
+
* cheapest way to fit a longer context in the same RAM. */
|
|
12298
|
+
cacheTypeK: _enum([
|
|
12299
|
+
"f32",
|
|
12300
|
+
"f16",
|
|
12301
|
+
"q8_0",
|
|
12302
|
+
"q5_1",
|
|
12303
|
+
"q5_0",
|
|
12304
|
+
"q4_1",
|
|
12305
|
+
"q4_0"
|
|
12306
|
+
]).optional(),
|
|
12307
|
+
cacheTypeV: _enum([
|
|
12308
|
+
"f32",
|
|
12309
|
+
"f16",
|
|
12310
|
+
"q8_0",
|
|
12311
|
+
"q5_1",
|
|
12312
|
+
"q5_0",
|
|
12313
|
+
"q4_1",
|
|
12314
|
+
"q4_0"
|
|
12315
|
+
]).optional(),
|
|
12243
12316
|
/** Else lazy: first generate boots it. */
|
|
12244
12317
|
autoStart: boolean().default(false),
|
|
12245
12318
|
/** 0 = never; frees RAM after quiet periods. */
|
|
@@ -12327,10 +12400,44 @@ var LlmProfileSchema = object({
|
|
|
12327
12400
|
baseUrl: string().optional(),
|
|
12328
12401
|
/** ConfigUISchema type:'password' — never round-trips (spec §5). */
|
|
12329
12402
|
apiKey: string().optional(),
|
|
12403
|
+
/** Vision on/off. A vision call against a `false` profile is REFUSED, never
|
|
12404
|
+
* degraded to text — that shipped once and produced a confident answer to a
|
|
12405
|
+
* question about a picture nobody sent. */
|
|
12330
12406
|
supportsVision: boolean(),
|
|
12331
12407
|
temperature: number().min(0).max(2).optional(),
|
|
12408
|
+
/** Nucleus sampling. Every wire we speak has it. */
|
|
12409
|
+
topP: number().min(0).max(1).optional(),
|
|
12410
|
+
/** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
|
|
12411
|
+
* wire does, and the client drops it there (measured: the request body gets
|
|
12412
|
+
* `top_p` and no `top_k`). The profile editor hides the field wherever it
|
|
12413
|
+
* would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
|
|
12414
|
+
topK: number().int().positive().optional(),
|
|
12332
12415
|
maxTokens: number().int().positive().optional(),
|
|
12416
|
+
/** Prompt context window. Advisory for cloud kinds (they enforce their own);
|
|
12417
|
+
* for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
|
|
12418
|
+
* the model with, so it is the one field that changes a PROCESS. */
|
|
12419
|
+
contextLength: number().int().positive().optional(),
|
|
12420
|
+
/** Default system prompt. A caller's `system` REPLACES it (never appends —
|
|
12421
|
+
* two system prompts fighting is worse than either alone). */
|
|
12422
|
+
systemPrompt: string().optional(),
|
|
12423
|
+
/** Total generation bound — the only one a unary call has. */
|
|
12333
12424
|
timeoutMs: number().int().positive().default(6e4),
|
|
12425
|
+
/** Wait for response headers only. */
|
|
12426
|
+
connectTimeoutMs: number().int().positive().default(1e4),
|
|
12427
|
+
/** Accepted, but no output yet — a cold GPU load lives here. */
|
|
12428
|
+
firstTokenTimeoutMs: number().int().positive().default(12e4),
|
|
12429
|
+
/** Output started then stopped. */
|
|
12430
|
+
idleTimeoutMs: number().int().positive().default(6e4),
|
|
12431
|
+
/** Profile-level default. The per-consumer table and a per-call override
|
|
12432
|
+
* both beat it — see `resolveRetryPolicy`. */
|
|
12433
|
+
retry: LlmRetryPolicySchema.default({
|
|
12434
|
+
enabled: false,
|
|
12435
|
+
maxAttempts: 1
|
|
12436
|
+
}),
|
|
12437
|
+
/** Whether this profile may use tools. The tool-call plumbing rides the
|
|
12438
|
+
* library; the REGISTRY of callable tools is ours and is empty in v1, so a
|
|
12439
|
+
* `true` here buys the wiring, not behaviour, until tools are registered. */
|
|
12440
|
+
toolsEnabled: boolean().default(false),
|
|
12334
12441
|
extraHeaders: record(string(), string()).optional(),
|
|
12335
12442
|
/** kind === 'managed-local' only (spec §4). */
|
|
12336
12443
|
runtime: ManagedRuntimeConfigSchema.optional()
|
|
@@ -12392,7 +12499,10 @@ var ProfileRefInputSchema = object({
|
|
|
12392
12499
|
addonId: string(),
|
|
12393
12500
|
profileId: string()
|
|
12394
12501
|
});
|
|
12395
|
-
method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(GenerateVisionInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(object({
|
|
12502
|
+
method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(GenerateVisionInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(object({
|
|
12503
|
+
addonId: string().optional(),
|
|
12504
|
+
requestId: string()
|
|
12505
|
+
}), _void(), { kind: "mutation" }), method(object({}), array(LlmProfileKindDescriptorSchema)), method(object({}), array(LlmProfileSchema)), method(object({ profile: LlmProfileSchema }), LlmProfileSchema, {
|
|
12396
12506
|
kind: "mutation",
|
|
12397
12507
|
auth: "admin"
|
|
12398
12508
|
}), method(ProfileRefInputSchema, _void(), {
|
|
@@ -14128,28 +14238,36 @@ var NcOccupancyConditionSchema = object({
|
|
|
14128
14238
|
/**
|
|
14129
14239
|
* Audio condition (IMMEDIATE trigger) — a rule on SOUND, not on a picture.
|
|
14130
14240
|
*
|
|
14131
|
-
*
|
|
14132
|
-
*
|
|
14133
|
-
*
|
|
14134
|
-
*
|
|
14135
|
-
*
|
|
14136
|
-
*
|
|
14137
|
-
*
|
|
14138
|
-
*
|
|
14139
|
-
*
|
|
14140
|
-
*
|
|
14141
|
-
*
|
|
14142
|
-
*
|
|
14143
|
-
*
|
|
14144
|
-
*
|
|
14145
|
-
*
|
|
14146
|
-
*
|
|
14147
|
-
*
|
|
14148
|
-
*
|
|
14149
|
-
*
|
|
14150
|
-
*
|
|
14151
|
-
*
|
|
14152
|
-
* `
|
|
14241
|
+
* **TWO EXCLUSIVE MODES** (operator decision 2026-08-14, D157). Which one a
|
|
14242
|
+
* rule is in is not a stored field — it is WHICH FILTER the rule carries, so
|
|
14243
|
+
* there is no second switch that can disagree with the first and every rule
|
|
14244
|
+
* authored before the decision migrates for free (`audioModeOf`):
|
|
14245
|
+
*
|
|
14246
|
+
* - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
|
|
14247
|
+
* classifier labels with one of them. No window, no percentage:
|
|
14248
|
+
* `hitPercent` and `samplingSeconds` are ignored, and the rule's own
|
|
14249
|
+
* `throttle` cooldown is the only brake. The per-label confidence floor is
|
|
14250
|
+
* the analyzer's (`classificationMinScore`, per device) — a label only
|
|
14251
|
+
* reaches this condition if the classifier was already confident enough.
|
|
14252
|
+
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14253
|
+
* the condition: at least `hitPercent`% of the samples over
|
|
14254
|
+
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
14255
|
+
* {@link NC_AUDIO_DBFS_FLOOR}: negative-going, `0` = full scale). The window
|
|
14256
|
+
* must be FULL before it can match — a window open for two of its ten
|
|
14257
|
+
* seconds is 100% of nothing.
|
|
14258
|
+
*
|
|
14259
|
+
* **Why label mode has no window.** It had one, and it never fired: the
|
|
14260
|
+
* analyzer emits ~1 audio frame per second but YAMNet only LABELS one to three
|
|
14261
|
+
* of them per episode, even through continuous crying. The measured maximum
|
|
14262
|
+
* `hitPercent` over the whole live history was 40 — under the shipped default
|
|
14263
|
+
* of 60, so a label rule could not fire at all, ever. A percentage of frames is
|
|
14264
|
+
* the wrong question to ask of a sparse classifier.
|
|
14265
|
+
*
|
|
14266
|
+
* **Fail-closed when NEITHER is given** — every sample would be a trivial hit
|
|
14267
|
+
* and the rule would fire on silence. The schema cannot express "exactly one
|
|
14268
|
+
* of" without becoming a ZodEffects the cap path would have to special-case, so
|
|
14269
|
+
* the exclusivity is enforced where every editor writes (`patchAudio`) and a
|
|
14270
|
+
* legacy rule carrying both resolves to LABEL (the mode that fires).
|
|
14153
14271
|
*
|
|
14154
14272
|
* Labels are the audio macro classes (`AUDIO_MACRO_LABELS` / the NC taxonomy's
|
|
14155
14273
|
* `audio-*` ids). Both spellings are accepted — the matcher normalizes the
|
|
@@ -14157,13 +14275,13 @@ var NcOccupancyConditionSchema = object({
|
|
|
14157
14275
|
* an operator who typed `dog` mean the same thing.
|
|
14158
14276
|
*/
|
|
14159
14277
|
var NcAudioConditionSchema = object({
|
|
14160
|
-
/**
|
|
14278
|
+
/** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
|
|
14161
14279
|
labels: array(string().min(1)).min(1).optional(),
|
|
14162
|
-
/**
|
|
14280
|
+
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14163
14281
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
14164
|
-
/**
|
|
14282
|
+
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14165
14283
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
14166
|
-
/**
|
|
14284
|
+
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14167
14285
|
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
14168
14286
|
});
|
|
14169
14287
|
/**
|
|
@@ -24119,14 +24237,50 @@ method(object({
|
|
|
24119
24237
|
* thing except the comparator: `similarity` (CLIP cosine at the same ROI coords
|
|
24120
24238
|
* vs condition-tagged references) and `llm` (vision-LLM judgment over the crop).
|
|
24121
24239
|
*
|
|
24122
|
-
*
|
|
24123
|
-
*
|
|
24124
|
-
*
|
|
24125
|
-
*
|
|
24126
|
-
|
|
24127
|
-
|
|
24128
|
-
*
|
|
24240
|
+
* **No `deviceConfig`, deliberately.** This shipped as the D14 widget archetype,
|
|
24241
|
+
* which put a "Scenes" tab on one camera's detail page. That is the wrong shape
|
|
24242
|
+
* for the thing: a scene is a standing question about the property ("is the bin
|
|
24243
|
+
* still out"), and the operator's question is "which of my scenes have tripped",
|
|
24244
|
+
* across every camera at once — not "what does camera 617 think". Buried one
|
|
24245
|
+
* camera deep it also could not be found. The surface is now a top-level admin
|
|
24246
|
+
* page (`/scenes`, `pages/Scenes.tsx`) that lists every scene on every camera and
|
|
24247
|
+
* picks the camera inside the create flow, the same shape Events and Faces have.
|
|
24248
|
+
*
|
|
24249
|
+
* The consequence to keep in mind: `host/scene-monitor-editor` is gone from
|
|
24250
|
+
* `HOST_WIDGETS` too. `scripts/check-host-widget-resolves.ts` asserts BOTH
|
|
24251
|
+
* directions, so a registration nobody declares fails exactly as loudly as a
|
|
24252
|
+
* declaration nobody registers. The editor is imported directly by the page.
|
|
24253
|
+
*
|
|
24254
|
+
* `status.kind:'push'` — the engine pushes on every hysteresis flip /
|
|
24255
|
+
* availability change; consumers never poll.
|
|
24256
|
+
*/
|
|
24257
|
+
/** Extensible condition tag. Seeded 'day' | 'ir' (the two variants the operator
|
|
24258
|
+
* captures) plus 'night' | 'dawn' | 'dusk' from the resolver's sun-times band.
|
|
24259
|
+
* Open by design so more can be added without a wire break.
|
|
24260
|
+
*
|
|
24261
|
+
* Matching does NOT fall back across conditions: cross-condition cosines are
|
|
24262
|
+
* not comparable, so "I have never seen this scene in this light" is reported
|
|
24263
|
+
* as `unknown`, never guessed. A day reference scored against an IR frame
|
|
24264
|
+
* collapses the cosine and would latch a false alarm every single night. */
|
|
24129
24265
|
var SceneConditionSchema = string();
|
|
24266
|
+
/** `matched` = the baseline is what we see; `diverged` = it demonstrably is not;
|
|
24267
|
+
* `unknown` = we cannot judge (no reference for this condition, encoder model
|
|
24268
|
+
* changed, view shifted, no snapshot). `unknown` is a real value, not a null,
|
|
24269
|
+
* and never counts toward hysteresis in either direction. */
|
|
24270
|
+
var SceneVerdictSchema = _enum([
|
|
24271
|
+
"matched",
|
|
24272
|
+
"diverged",
|
|
24273
|
+
"unknown"
|
|
24274
|
+
]);
|
|
24275
|
+
/** Why a scene cannot judge. Named, because this feature's failure mode is
|
|
24276
|
+
* silence that reads as "nothing has happened". */
|
|
24277
|
+
var SceneUnavailableSchema = _enum([
|
|
24278
|
+
"no-reference-for-condition",
|
|
24279
|
+
"view-shifted",
|
|
24280
|
+
"no-vision-profile",
|
|
24281
|
+
"encoder-model-changed",
|
|
24282
|
+
"no-snapshot"
|
|
24283
|
+
]);
|
|
24130
24284
|
/** One captured reference — condition-tagged, model-version-gated. `embedding`
|
|
24131
24285
|
* is `number[]` (Float32Array does NOT survive MsgPack/UDS). */
|
|
24132
24286
|
var SceneReferenceSchema = object({
|
|
@@ -24134,7 +24288,14 @@ var SceneReferenceSchema = object({
|
|
|
24134
24288
|
modelId: string(),
|
|
24135
24289
|
condition: SceneConditionSchema,
|
|
24136
24290
|
capturedAt: number(),
|
|
24137
|
-
thumbnailMediaId: string().optional()
|
|
24291
|
+
thumbnailMediaId: string().optional(),
|
|
24292
|
+
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
24293
|
+
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
24294
|
+
* normalized rect frame a different piece of world, and the scene would
|
|
24295
|
+
* diverge forever with a perfectly plausible cosine. Checked LAZILY, only
|
|
24296
|
+
* when hysteresis is about to flip — one extra encode per candidate
|
|
24297
|
+
* transition, not per poll. */
|
|
24298
|
+
anchorEmbedding: array(number()).optional()
|
|
24138
24299
|
});
|
|
24139
24300
|
var SceneMonitorStateSchema = object({
|
|
24140
24301
|
id: string(),
|
|
@@ -24156,6 +24317,25 @@ var SceneCheckSchema = discriminatedUnion("mode", [object({
|
|
|
24156
24317
|
profileId: string().optional(),
|
|
24157
24318
|
hysteresisCount: number().int().positive()
|
|
24158
24319
|
})]);
|
|
24320
|
+
var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
|
|
24321
|
+
/**
|
|
24322
|
+
* Vision-model adjudication of a candidate flip. Field names deliberately
|
|
24323
|
+
* mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
|
|
24324
|
+
*
|
|
24325
|
+
* `onTimeout` defaults to **'hold'**, the OPPOSITE of `NcConfirmGate`'s
|
|
24326
|
+
* fail-open: a notification suppressed is the worse error there, but a vision
|
|
24327
|
+
* model that timed out has not told us the bin is gone, and a latch is a
|
|
24328
|
+
* stateful claim that costs the operator a trip to reset.
|
|
24329
|
+
*/
|
|
24330
|
+
var SceneConfirmSchema = object({
|
|
24331
|
+
enabled: boolean().default(false),
|
|
24332
|
+
prompt: string().min(1).max(1e3),
|
|
24333
|
+
profileId: string().optional(),
|
|
24334
|
+
timeoutMs: number().int().min(1e3).max(2e4).default(8e3),
|
|
24335
|
+
maxImagePx: number().int().min(64).max(2048).default(448),
|
|
24336
|
+
/** What a timeout / unavailable model means for the PENDING flip. */
|
|
24337
|
+
onTimeout: _enum(["flip", "hold"]).default("hold")
|
|
24338
|
+
});
|
|
24159
24339
|
var SceneMonitorSchema = object({
|
|
24160
24340
|
id: string(),
|
|
24161
24341
|
label: string(),
|
|
@@ -24174,7 +24354,41 @@ var SceneMonitorSchema = object({
|
|
|
24174
24354
|
lastConfidence: number().nullable(),
|
|
24175
24355
|
currentCondition: SceneConditionSchema.nullable(),
|
|
24176
24356
|
availability: _enum(["ok", "unavailable"]),
|
|
24177
|
-
unavailableReason: string().nullable()
|
|
24357
|
+
unavailableReason: string().nullable(),
|
|
24358
|
+
/** Which state is "the initial screen". `null` until the first capture. */
|
|
24359
|
+
baselineStateId: string().nullable(),
|
|
24360
|
+
/** Which boolean drives notification rules and any export. */
|
|
24361
|
+
emit: _enum(["latched", "live"]).default("latched"),
|
|
24362
|
+
/** Live: does the region match the baseline RIGHT NOW. */
|
|
24363
|
+
verdict: SceneVerdictSchema,
|
|
24364
|
+
/** Has it been `diverged` at least once since `armedAt` — the operator's boolean. */
|
|
24365
|
+
latched: boolean(),
|
|
24366
|
+
/** Last reset (or creation). */
|
|
24367
|
+
armedAt: number(),
|
|
24368
|
+
divergedAt: number().nullable(),
|
|
24369
|
+
restoredAt: number().nullable(),
|
|
24370
|
+
/** A check is only COUNTED when the device has been quiet this long. Motion
|
|
24371
|
+
* during the window DISCARDS the observation — a car pulling up in front of
|
|
24372
|
+
* the bin must not be able to spend hysteresis credit. */
|
|
24373
|
+
quietSeconds: number().int().min(0).max(3600).default(60),
|
|
24374
|
+
/** An observation only advances the pending count when it is at least this
|
|
24375
|
+
* far from the previously counted one, so N agreeing checks span real time
|
|
24376
|
+
* rather than N adjacent polls inside one occlusion. */
|
|
24377
|
+
minObservationSpacingSec: number().int().min(0).max(3600).default(120),
|
|
24378
|
+
/** Vision-model adjudication of a candidate flip. Similarity primary only. */
|
|
24379
|
+
confirm: SceneConfirmSchema.optional(),
|
|
24380
|
+
/** Whole-frame anchor cosine below which a flip is REFUSED as `view-shifted`. */
|
|
24381
|
+
anchorThreshold: number().min(0).max(1).default(SCENE_DEFAULT_ANCHOR_THRESHOLD),
|
|
24382
|
+
/** Clear the latch on its own when the scene matches again? Default false —
|
|
24383
|
+
* `restoredAt` and the `scene-restored` edge are recorded regardless, so an
|
|
24384
|
+
* automation can react to the bin coming back without the operator's own
|
|
24385
|
+
* alarm silently clearing itself. */
|
|
24386
|
+
autoRestore: boolean().default(false),
|
|
24387
|
+
/** Named cause when `verdict === 'unknown'`. */
|
|
24388
|
+
unavailable: SceneUnavailableSchema.nullable(),
|
|
24389
|
+
/** Conditions that have at least one comparable reference — the coverage line
|
|
24390
|
+
* ("day ✓ · ir ✓ · dusk ✗") that turns a silent fallback into a visible fact. */
|
|
24391
|
+
coveredConditions: array(SceneConditionSchema)
|
|
24178
24392
|
});
|
|
24179
24393
|
var SceneMonitorStatusSchema = object({
|
|
24180
24394
|
monitors: array(SceneMonitorSchema),
|
|
@@ -24207,7 +24421,14 @@ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSche
|
|
|
24207
24421
|
"both"
|
|
24208
24422
|
]).optional(),
|
|
24209
24423
|
checkIntervalSec: number().optional(),
|
|
24210
|
-
check: SceneCheckSchema.optional()
|
|
24424
|
+
check: SceneCheckSchema.optional(),
|
|
24425
|
+
emit: _enum(["latched", "live"]).optional(),
|
|
24426
|
+
quietSeconds: number().int().min(0).max(3600).optional(),
|
|
24427
|
+
minObservationSpacingSec: number().int().min(0).max(3600).optional(),
|
|
24428
|
+
anchorThreshold: number().min(0).max(1).optional(),
|
|
24429
|
+
autoRestore: boolean().optional(),
|
|
24430
|
+
/** `null` clears the vision-model adjudicator. */
|
|
24431
|
+
confirm: SceneConfirmSchema.nullable().optional()
|
|
24211
24432
|
})
|
|
24212
24433
|
}), _void(), {
|
|
24213
24434
|
kind: "mutation",
|
|
@@ -24244,6 +24465,14 @@ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSche
|
|
|
24244
24465
|
}), _void(), {
|
|
24245
24466
|
kind: "mutation",
|
|
24246
24467
|
auth: "admin"
|
|
24468
|
+
}), method(object({
|
|
24469
|
+
deviceId: number(),
|
|
24470
|
+
monitorId: string(),
|
|
24471
|
+
/** Defaults to TRUE at the provider seam — see `SCENE_RESET_RECAPTURES`. */
|
|
24472
|
+
recapture: boolean().optional()
|
|
24473
|
+
}), _void(), {
|
|
24474
|
+
kind: "mutation",
|
|
24475
|
+
auth: "admin"
|
|
24247
24476
|
});
|
|
24248
24477
|
/**
|
|
24249
24478
|
* Per-stage gating mode applied to the zones a rule references.
|
|
@@ -24552,12 +24781,64 @@ var NetworkAddressSchema = object({
|
|
|
24552
24781
|
family: string(),
|
|
24553
24782
|
internal: boolean()
|
|
24554
24783
|
});
|
|
24784
|
+
/**
|
|
24785
|
+
* Provenance of the site coordinates, and the whole reason this is not just two
|
|
24786
|
+
* numbers.
|
|
24787
|
+
*
|
|
24788
|
+
* - `operator-set` — a human typed it, or accepted a detection. Authoritative;
|
|
24789
|
+
* nothing overwrites it.
|
|
24790
|
+
* - `derived-from-ip` — the hub geolocated its own public IP once, because a
|
|
24791
|
+
* default that is right to a few kilometres beats the coarse UTC clock split
|
|
24792
|
+
* the sun-times consumers otherwise fall back to.
|
|
24793
|
+
*
|
|
24794
|
+
* The UI shows which one it is. An operator who cannot tell a guess from their
|
|
24795
|
+
* own input will eventually trust the guess.
|
|
24796
|
+
*/
|
|
24797
|
+
var SiteLocationSourceSchema = _enum(["operator-set", "derived-from-ip"]);
|
|
24798
|
+
/**
|
|
24799
|
+
* The read shape: the location plus the honest state of the one-shot derivation.
|
|
24800
|
+
*
|
|
24801
|
+
* `derivationAttemptedAt` is what makes the "one call, ever" contract
|
|
24802
|
+
* inspectable. When it is set and `location` is null, the geo-IP lookup ran and
|
|
24803
|
+
* failed; the hub will NOT try again on its own — the fallback is declared
|
|
24804
|
+
* (consumers degrade to their own last resort) and the operator either types the
|
|
24805
|
+
* coordinates or presses detect.
|
|
24806
|
+
*/
|
|
24807
|
+
var SiteLocationStatusSchema = object({
|
|
24808
|
+
location: object({
|
|
24809
|
+
/** WGS84 decimal degrees. */
|
|
24810
|
+
latitude: number().min(-90).max(90),
|
|
24811
|
+
longitude: number().min(-180).max(180),
|
|
24812
|
+
source: SiteLocationSourceSchema,
|
|
24813
|
+
/** Epoch ms the value was last written. */
|
|
24814
|
+
updatedAt: number(),
|
|
24815
|
+
/**
|
|
24816
|
+
* Human-readable place the geo-IP service reported ("Napoli, IT"). Display
|
|
24817
|
+
* only — never parsed, never matched on. Absent for an operator-typed value.
|
|
24818
|
+
*/
|
|
24819
|
+
label: string().optional()
|
|
24820
|
+
}).nullable(),
|
|
24821
|
+
derivationAttemptedAt: number().nullable(),
|
|
24822
|
+
/** Why the last derivation failed, for the UI to show instead of a shrug. */
|
|
24823
|
+
derivationError: string().nullable()
|
|
24824
|
+
});
|
|
24825
|
+
/** `null` clears the location and re-arms nothing — the derivation stays spent. */
|
|
24826
|
+
var SetSiteLocationInputSchema = object({
|
|
24827
|
+
latitude: number().min(-90).max(90),
|
|
24828
|
+
longitude: number().min(-180).max(180)
|
|
24829
|
+
}).nullable();
|
|
24555
24830
|
method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
|
|
24556
24831
|
kind: "mutation",
|
|
24557
24832
|
auth: "admin"
|
|
24558
24833
|
}), method(_void(), _void(), {
|
|
24559
24834
|
kind: "mutation",
|
|
24560
24835
|
auth: "admin"
|
|
24836
|
+
}), method(_void(), SiteLocationStatusSchema), method(SetSiteLocationInputSchema, SiteLocationStatusSchema, {
|
|
24837
|
+
kind: "mutation",
|
|
24838
|
+
auth: "admin"
|
|
24839
|
+
}), method(_void(), SiteLocationStatusSchema, {
|
|
24840
|
+
kind: "mutation",
|
|
24841
|
+
auth: "admin"
|
|
24561
24842
|
});
|
|
24562
24843
|
object({
|
|
24563
24844
|
/** True when the device's tamper switch / case-open contact is
|
|
@@ -27287,6 +27568,12 @@ Object.freeze({
|
|
|
27287
27568
|
addonId: null,
|
|
27288
27569
|
access: "create"
|
|
27289
27570
|
},
|
|
27571
|
+
"llm.cancel": {
|
|
27572
|
+
capName: "llm",
|
|
27573
|
+
capScope: "system",
|
|
27574
|
+
addonId: null,
|
|
27575
|
+
access: "create"
|
|
27576
|
+
},
|
|
27290
27577
|
"llm.deleteModel": {
|
|
27291
27578
|
capName: "llm",
|
|
27292
27579
|
capScope: "system",
|
|
@@ -29537,6 +29824,12 @@ Object.freeze({
|
|
|
29537
29824
|
addonId: null,
|
|
29538
29825
|
access: "create"
|
|
29539
29826
|
},
|
|
29827
|
+
"sceneMonitor.resetScene": {
|
|
29828
|
+
capName: "scene-monitor",
|
|
29829
|
+
capScope: "device",
|
|
29830
|
+
addonId: null,
|
|
29831
|
+
access: "delete"
|
|
29832
|
+
},
|
|
29540
29833
|
"sceneMonitor.updateScene": {
|
|
29541
29834
|
capName: "scene-monitor",
|
|
29542
29835
|
capScope: "device",
|
|
@@ -30215,6 +30508,12 @@ Object.freeze({
|
|
|
30215
30508
|
addonId: null,
|
|
30216
30509
|
access: "create"
|
|
30217
30510
|
},
|
|
30511
|
+
"system.detectSiteLocation": {
|
|
30512
|
+
capName: "system",
|
|
30513
|
+
capScope: "system",
|
|
30514
|
+
addonId: null,
|
|
30515
|
+
access: "create"
|
|
30516
|
+
},
|
|
30218
30517
|
"system.featureFlags": {
|
|
30219
30518
|
capName: "system",
|
|
30220
30519
|
capScope: "system",
|
|
@@ -30233,6 +30532,12 @@ Object.freeze({
|
|
|
30233
30532
|
addonId: null,
|
|
30234
30533
|
access: "view"
|
|
30235
30534
|
},
|
|
30535
|
+
"system.getSiteLocation": {
|
|
30536
|
+
capName: "system",
|
|
30537
|
+
capScope: "system",
|
|
30538
|
+
addonId: null,
|
|
30539
|
+
access: "view"
|
|
30540
|
+
},
|
|
30236
30541
|
"system.health": {
|
|
30237
30542
|
capName: "system",
|
|
30238
30543
|
capScope: "system",
|
|
@@ -30257,6 +30562,12 @@ Object.freeze({
|
|
|
30257
30562
|
addonId: null,
|
|
30258
30563
|
access: "create"
|
|
30259
30564
|
},
|
|
30565
|
+
"system.setSiteLocation": {
|
|
30566
|
+
capName: "system",
|
|
30567
|
+
capScope: "system",
|
|
30568
|
+
addonId: null,
|
|
30569
|
+
access: "create"
|
|
30570
|
+
},
|
|
30260
30571
|
"terminalSession.adoptLegacyMonitor": {
|
|
30261
30572
|
capName: "terminal-session",
|
|
30262
30573
|
capScope: "system",
|
|
@@ -32219,6 +32530,11 @@ Object.freeze({
|
|
|
32219
32530
|
form: "single",
|
|
32220
32531
|
optional: false
|
|
32221
32532
|
}],
|
|
32533
|
+
"sceneMonitor.resetScene": [{
|
|
32534
|
+
name: "deviceId",
|
|
32535
|
+
form: "single",
|
|
32536
|
+
optional: false
|
|
32537
|
+
}],
|
|
32222
32538
|
"sceneMonitor.updateScene": [{
|
|
32223
32539
|
name: "deviceId",
|
|
32224
32540
|
form: "single",
|
|
@@ -32897,7 +33213,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
32897
33213
|
capability: adminUiCapability,
|
|
32898
33214
|
provider: {
|
|
32899
33215
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
32900
|
-
getVersion: async () => ({ version: "1.2.
|
|
33216
|
+
getVersion: async () => ({ version: "1.2.60" })
|
|
32901
33217
|
}
|
|
32902
33218
|
}];
|
|
32903
33219
|
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{La as e,Ma as t,wo as n}from"./src-BbMtrcN-.js";import{I as r,Q as i,S as a,W as o,a as s,o as c,q as l,x as u,z as d}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DTufy7Ue.js";import{p as f}from"./player-overlays-BfDIfiH7.js";import{t as p}from"./FormBuilder-DaUdmatu.js";import{t as m}from"./pencil-hCEUn1IA.js";import{t as h}from"./plus-BwBDSSUm.js";import{t as g}from"./power-BftD_p5X.js";import{P as _,S as v,W as y,i as b,s as x}from"./index-kOLbwjEX.js";var S=y(`star`,[[`path`,{d:`M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z`,key:`r04s7s`}]]);i();function C(e){return e.enabled!==!1}function w(e){return e.isDefault}function T(e,t){let n={id:e.id,type:e.type,displayName:t.displayName??e.displayName,providerId:e.providerId,config:e.config,isDefault:t.isDefault??e.isDefault,isSystem:e.isSystem},r=e.nodeId===void 0?n:{...n,nodeId:e.nodeId},i=t.enabled??e.enabled;return i===void 0?r:{...r,enabled:i}}function E(e){return`${(e/1024**3).toFixed(e>=100*1024**3?0:1)} GB`}function D({location:e}){let t=e.capacity;return t==null?null:a(`span`,{className:`text-[10px] text-foreground-subtle tabular-nums`,children:[E(t.availableBytes),` free of `,E(t.totalBytes)]})}function O(e){let t=e.basePath;if(typeof t==`string`&&t.length>0)return t;let n=Object.keys(e);return n.length===0?``:n.join(`, `)}function k({location:e,cardinality:t,onEdit:n,onDelete:r,onSetDefault:i,onToggleEnabled:o}){let s=O(e.config),c=C(e),l=w(e);return a(`div`,{className:`flex flex-wrap items-center gap-x-3 gap-y-2 px-3 py-2 border-t border-border first:border-t-0 hover:bg-primary/5`,children:[a(`div`,{className:`flex flex-wrap items-center gap-2 min-w-0 flex-1 basis-64`,children:[u(`div`,{className:`w-[88px] shrink-0`,children:e.isDefault?a(`span`,{className:`inline-flex items-center gap-0.5 rounded bg-primary/10 border border-primary/20 px-1.5 py-0.5 text-[10px] font-semibold text-primary uppercase tracking-wide`,title:`Default location for this type`,children:[u(S,{className:`h-2.5 w-2.5 fill-primary`}),`Default`]}):a(`button`,{onClick:()=>i(e),className:`inline-flex items-center gap-0.5 rounded border border-border px-1.5 py-0.5 text-[10px] font-medium text-foreground-subtle hover:text-foreground hover:bg-primary/10 hover:border-primary/30 uppercase tracking-wide`,title:`Promote to default for this type`,children:[u(S,{className:`h-2.5 w-2.5`}),`Set default`]})}),u(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle bg-background border border-border rounded px-1.5 py-0.5 font-mono`,children:e.providerId}),!c&&u(`span`,{className:`text-[10px] uppercase tracking-wide text-warning bg-warning/10 border border-warning/30 rounded px-1.5 py-0.5`,title:`Disabled — nothing new is written here. Existing data stays readable and is still pruned by age.`,children:`disabled`}),e.isSystem&&u(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle bg-background border border-border rounded px-1.5 py-0.5`,title:`System-managed location — cannot be deleted; edit config to relocate`,children:`system`}),e.config.readOnly===!0&&u(`span`,{className:`text-[10px] uppercase tracking-wide text-warning bg-warning/10 border border-warning/30 rounded px-1.5 py-0.5`,title:`Drain mode — reads and age retention continue; nothing new is written here and disk-pressure eviction skips it`,children:`read-only`}),a(`div`,{className:`min-w-0`,children:[u(`div`,{className:`text-xs font-medium text-foreground truncate`,children:e.displayName}),a(`div`,{className:`flex flex-wrap items-center gap-x-2`,children:[s&&u(`span`,{className:`text-[10px] text-foreground-subtle truncate font-mono`,children:s}),u(D,{location:e})]})]})]}),a(`div`,{className:`flex flex-wrap items-center gap-1 shrink-0`,children:[a(`button`,{type:`button`,role:`switch`,"aria-label":`Writes enabled`,"aria-checked":c,disabled:l,onClick:()=>o(e,!c),title:l?`The default location of a type is always enabled — it is the fallback every balancing consumer falls back to. Promote another location to default first.`:c?`Enabled — balancing consumers may write new data here. Click to stop new writes.`:`Disabled — no new data is written here. Existing data stays readable. Click to enable.`,className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium border disabled:cursor-not-allowed ${c?`border-success/30 text-success hover:bg-success/10`:`border-warning/40 text-warning hover:bg-warning/10`}`,children:[u(g,{className:`h-3 w-3`}),c?`Enabled`:`Disabled`]}),!e.isDefault&&a(`button`,{onClick:()=>i(e),className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-foreground-subtle border border-border hover:text-foreground hover:bg-primary/10`,title:`Set as default for this type`,children:[u(S,{className:`h-3 w-3`}),`Set default`]}),a(`button`,{onClick:()=>n(e),className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-foreground-subtle border border-border hover:text-foreground hover:bg-primary/10`,children:[u(m,{className:`h-3 w-3`}),`Edit`]}),!e.isSystem&&t!==`single`&&u(`button`,{onClick:()=>r(e),className:`inline-flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-danger hover:bg-danger/10`,title:`Delete location`,children:u(x,{className:`h-3 w-3`})})]})]})}function A({type:e,displayName:t,description:n,cardinality:r,locations:i,onAdd:s,onEdit:c,onDelete:l,onSetDefault:d,onToggleEnabled:f}){let p=o(()=>{let e=[...i];return e.sort((e,t)=>e.isDefault===t.isDefault?e.displayName.localeCompare(t.displayName):e.isDefault?-1:1),e},[i]);return a(`div`,{className:`rounded-lg border border-border bg-surface`,children:[a(`div`,{className:`flex items-start justify-between border-b border-border px-3 py-2`,children:[a(`div`,{className:`space-y-0.5`,children:[a(`div`,{className:`flex items-center gap-2`,children:[u(`span`,{className:`text-sm font-semibold text-foreground capitalize`,children:t}),u(`span`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle bg-background border border-border rounded px-1.5 py-0.5 font-mono`,children:e})]}),n&&u(`p`,{className:`text-[11px] text-foreground-subtle`,children:n}),r===`single`&&u(`p`,{className:`text-[10px] text-foreground-subtle italic`,children:`Single — one location per type. Edit the existing entry; it can't be split.`})]}),r===`multi`&&a(`button`,{onClick:()=>s(e),className:`inline-flex items-center gap-1 rounded bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground hover:bg-primary/90`,children:[u(h,{className:`h-3 w-3`}),`Add`]})]}),p.length===0?u(`div`,{className:`px-3 py-4 text-center text-[11px] text-foreground-subtle italic`,children:r===`multi`?`No location registered. Click "Add" to register one.`:`No location registered yet — should be auto-seeded at next boot.`}):u(`div`,{children:p.map(e=>u(k,{location:e,cardinality:r,onEdit:c,onDelete:l,onSetDefault:d,onToggleEnabled:f},e.id))})]})}var j=new Set([`proc`,`sys`,`dev`,`run`,`boot`,`lost+found`,`snap`,`bin`,`sbin`,`lib`,`lib32`,`lib64`,`libx32`,`usr`,`etc`,`var`,`opt`,`tmp`,`srv`,`root`,`System`,`Library`,`Applications`,`cores`,`private`]),M=[`recordings`,`data`,`mnt`,`media`,`Volumes`];function N(e){let t=M.findIndex(t=>t===`recordings`?e.startsWith(t):e===t);return t===-1?M.length:t}function P(e){return e.filter(e=>!e.name.startsWith(`.`)&&!j.has(e.name)).toSorted((e,t)=>{let n=N(e.name)-N(t.name);return n===0?e.name.localeCompare(t.name):n}).map(e=>e.path)}i();function F({nodeId:e,value:t,onChange:n}){let i=f().trpcClient,[o,s]=l([]),[c,p]=l(t),[m,h]=l(null),[g,_]=l(null),[v,y]=l(``),b=r(async(t,r)=>{_(null);try{let a=await i.filesystemBrowse.browse.query({nodeId:e,path:t});h(a),p(a.path),r&&n(a.path)}catch(e){_(e instanceof Error?e.message:`browse failed`)}},[i,e,n]);d(()=>{p(t),(async()=>{let n=await i.filesystemBrowse.browse.query({nodeId:e,path:`/`}).then(e=>e).catch(()=>null);if(n){s(P(n.entries)),await b(t.startsWith(`/`)?t:`/`,!1);return}try{let n=await i.filesystemBrowse.listAllowedRoots.query({nodeId:e});s(n),await b(t&&n.some(e=>t.startsWith(e))?t:n[0]??``,!1)}catch(e){s([]),h(null),_(e instanceof Error&&/not available on node/i.test(e.message)?`This node can't be browsed remotely. Enter the path manually.`:e instanceof Error?e.message:`browse unavailable`)}})()},[e]);let x=async()=>{if(!(!v.trim()||!m)){_(null);try{let t=`${m.path.replace(/\/+$/,``)}/${v.trim()}`;await i.filesystemBrowse.createDir.mutate({nodeId:e,path:t}),y(``),await b(m.path,!0)}catch(e){_(e instanceof Error?e.message:`create failed`)}}},S=e=>`${(e/1e9).toFixed(1)} GB`;return a(`div`,{className:`space-y-2 rounded border border-border p-2`,children:[u(`div`,{className:`flex flex-wrap gap-1`,children:o.map(e=>u(`button`,{onClick:()=>void b(e,!0),className:`rounded border border-border px-2 py-0.5 text-[10px] font-mono hover:border-primary/40`,children:e},e))}),u(`input`,{value:c,onChange:e=>{p(e.target.value),n(e.target.value)},placeholder:`/absolute/path`,className:`w-full rounded border border-border bg-background px-2 py-1 text-[11px] font-mono`}),m&&a(`div`,{className:`text-[10px] text-foreground-subtle`,children:[S(m.freeBytes),` free / `,S(m.totalBytes)]}),u(`div`,{className:`max-h-40 space-y-0.5 overflow-y-auto`,children:m?.entries.map(e=>a(`button`,{onClick:()=>void b(e.path,!0),className:`block w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-primary/5`,children:[`📁 `,e.name]},e.path))}),a(`div`,{className:`flex gap-1`,children:[u(`input`,{value:v,onChange:e=>y(e.target.value),placeholder:`new folder`,className:`flex-1 rounded border border-border bg-background px-2 py-1 text-xs`}),u(`button`,{onClick:()=>void x(),className:`rounded border border-border px-2 py-1 text-xs hover:border-primary/40`,children:`Create`})]}),g&&u(`div`,{className:`text-[10px] text-red-400`,children:g})]})}i();function I({location:r,onClose:i,onSaved:d}){let m=c(),h=f().trpcClient,[g,_]=l({...r.config}),[y,x]=l(r.displayName),[S,C]=l(null),[w,T]=l(!1),E=t(),D=o(()=>{let e=E.data;return Array.isArray(e)?e.find(e=>e.providerId===r.providerId)??null:null},[E.data,r.providerId]),O=e({onSuccess:()=>{m.invalidateQueries({queryKey:[[`storage`,`listLocations`]]}),d()}}),k=D?.shouldSaveDiskSpace===!0,A=D?.nodeLocal===!0,[j,M]=l(typeof r.nodeId==`string`?r.nodeId:`hub`),N=typeof g.basePath==`string`?g.basePath:``,P=e=>_(t=>({...t,basePath:e})),I=g.readOnly===!0,L=s({queryKey:[`storage`,`listLocations`,`ro-guard`],queryFn:()=>h.storage.listLocations.query({})}),R=(L.data??[]).filter(e=>e.type===r.type&&e.id!==r.id&&e.config.readOnly!==!0).length,z=!I&&L.data!==void 0&&R===0,B=e=>_(t=>{let n={...t};return delete n.readOnly,e?{...n,readOnly:!0}:n}),V=typeof g.maxUsedGb==`number`?g.maxUsedGb:``,H=e=>{let t=e.trim(),n=t===``?void 0:Number(t);_(e=>{let t={...e};return n===void 0||!Number.isFinite(n)||n<=0?delete t.maxUsedGb:t.maxUsedGb=n,t})},U=typeof g.minFreePercent==`number`?g.minFreePercent:``,W=e=>{let t=e.trim(),n=t===``?void 0:Number(t);_(e=>{let t={...e};return n===void 0||!Number.isFinite(n)?delete t.minFreePercent:t.minFreePercent=Math.min(100,Math.max(0,n)),t})},G=async()=>{T(!0),C(null);try{C(await(e=>h.storage.testConfig.query(e))({providerId:r.providerId,config:g}))}catch(e){C({ok:!1,error:e instanceof Error?e.message:String(e)})}finally{T(!1)}};return u(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm`,onClick:i,children:a(`div`,{className:`w-full max-w-md rounded-xl border border-border bg-surface shadow-2xl`,onClick:e=>e.stopPropagation(),children:[a(`div`,{className:`flex items-start justify-between border-b border-border px-4 py-3`,children:[a(`div`,{className:`space-y-0.5`,children:[a(`h2`,{className:`text-sm font-semibold text-foreground`,children:[`Edit `,r.displayName]}),a(`p`,{className:`text-xs text-foreground-subtle`,children:[u(`span`,{className:`font-mono`,children:r.id}),` ·`,` `,D?.displayName??r.providerId]})]}),u(`button`,{onClick:i,className:`text-foreground-subtle hover:text-foreground`,children:u(b,{className:`h-4 w-4`})})]}),a(`div`,{className:`p-4 space-y-3 max-h-[60vh] overflow-y-auto`,children:[a(`div`,{className:`space-y-1`,children:[u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Display name`}),u(`input`,{type:`text`,value:y,onChange:e=>x(e.target.value),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`})]}),D&&u(p,{schema:D.configSchema,values:g,onChange:_}),a(`div`,{className:`space-y-1`,children:[a(`label`,{className:`flex items-center gap-2 text-xs ${z?`text-foreground-subtle cursor-not-allowed`:`text-foreground cursor-pointer`}`,children:[u(`input`,{type:`checkbox`,checked:I,disabled:z,onChange:e=>B(e.target.checked),className:`accent-primary`}),`Read-only (drain mode)`]}),u(`p`,{className:`text-[10px] text-foreground-subtle`,children:z?`Blocked: this is the last writable location of its type — new footage would have nowhere to go.`:`Reads and age-based retention continue; nothing new is written here and disk-pressure eviction skips it. Use it to slowly decommission a disk.`})]}),A&&a(`div`,{className:`space-y-2`,children:[u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Node`}),u(n,{selectedNodeId:j,onSelect:M,alwaysShow:!0}),u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Path`}),u(F,{nodeId:j,value:N,onChange:P})]}),k&&a(`div`,{className:`space-y-1`,children:[u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Min free disk %`}),u(`input`,{type:`number`,min:0,max:100,value:U,placeholder:D?.minFreePercent==null?``:String(D.minFreePercent),onChange:e=>W(e.target.value),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`}),a(`p`,{className:`text-[10px] text-foreground-subtle`,children:[`When free space on this volume drops below this %, the oldest data stored here is evicted to reclaim space.`,D?.minFreePercent==null?` Empty = use the default.`:` Empty = use the default (${D.minFreePercent}%).`]}),u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Max used (GB)`}),u(`input`,{type:`number`,min:1,value:V,placeholder:`unlimited`,onChange:e=>H(e.target.value),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`}),u(`p`,{className:`text-[10px] text-foreground-subtle`,children:`Hard cap on the TOTAL bytes evictable data (recordings) may occupy on this location, independent of disk free space — oldest footage is evicted past it. Empty = unlimited.`})]}),!D&&!E.isLoading&&a(`div`,{className:`rounded border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-[11px] text-amber-700 dark:text-amber-300`,children:[`Provider `,u(`code`,{className:`font-mono`,children:r.providerId}),` is no longer registered. Field schema unavailable; raw config is preserved on save.`]}),S&&u(`div`,{className:`rounded border px-3 py-2 text-[11px] ${S.ok?`border-success/30 bg-success/5 text-success`:`border-danger/30 bg-danger/5 text-danger`}`,children:S.ok?`Connection OK.`:`Test failed: ${S.error??`unknown error`}`}),O.isError&&u(`div`,{className:`rounded border border-danger/30 bg-danger/5 text-danger px-3 py-2 text-[11px]`,children:O.error instanceof Error?O.error.message:String(O.error)})]}),a(`div`,{className:`flex items-center justify-between gap-2 border-t border-border px-4 py-3`,children:[u(`button`,{onClick:i,className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Cancel`}),a(`div`,{className:`flex items-center gap-2`,children:[u(`button`,{onClick:()=>{G()},disabled:w||!D,className:`rounded border border-border px-3 py-1.5 text-xs text-foreground hover:bg-primary/10 disabled:opacity-50`,children:w?`Testing…`:`Test connection`}),a(`button`,{onClick:()=>{O.mutate({id:r.id,type:r.type,providerId:r.providerId,isDefault:r.isDefault,displayName:y.trim(),config:g,nodeId:A?j:void 0})},disabled:O.isPending||y.trim().length===0,className:`inline-flex items-center gap-1.5 rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50`,children:[O.isPending?u(v,{className:`h-3.5 w-3.5 animate-spin`}):null,O.isPending?`Saving…`:`Save`]})]})]})]})})}function L(e){let t=e.trim().toLowerCase();return t.length===0?``:t.replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)}function R(e,t){let n=L(t);return`${e}:${n.length>0?n:`default`}`}i();function z({initialType:r,onClose:i,onCreated:s}){let d=c(),m=f().trpcClient,[h,g]=l(`picker`),[y,x]=l(r),[S,C]=l(null),[w,T]=l({}),[E,D]=l(``),[O,k]=l(null),[A,j]=l(!1),[M,N]=l(!1),[P,I]=l(`hub`),[L,z]=l(null),[B,V]=l(!1),H=e=>T(t=>({...t,basePath:e})),U=typeof w.basePath==`string`?w.basePath:``,W=t(),G=o(()=>{let e=W.data;return Array.isArray(e)?e:[]},[W.data]),K=W.isLoading,q=e({onSuccess:()=>{d.invalidateQueries({queryKey:[[`storage`,`listLocations`]]}),s()}}),J=o(()=>O!==null&&O.length>0?O:R(y,E),[y,E,O]),Y=async()=>{if(S){V(!0),z(null);try{z(await(e=>m.storage.testConfig.query(e))({providerId:S.providerId,config:w}))}catch(e){z({ok:!1,error:e instanceof Error?e.message:String(e)})}finally{V(!1)}}};return u(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm`,onClick:i,children:a(`div`,{className:`w-full max-w-md rounded-xl border border-border bg-surface shadow-2xl`,onClick:e=>e.stopPropagation(),children:[a(`div`,{className:`flex items-start justify-between border-b border-border px-4 py-3`,children:[a(`div`,{className:`space-y-0.5`,children:[u(`h2`,{className:`text-sm font-semibold text-foreground`,children:{picker:`Add Location — Pick provider`,config:`Add Location — ${S?.displayName??``}`,naming:`Add Location — Name & defaults`}[h]}),a(`p`,{className:`text-xs text-foreground-subtle`,children:[`Type: `,u(`span`,{className:`font-mono`,children:y})]})]}),u(`button`,{onClick:i,className:`text-foreground-subtle hover:text-foreground`,children:u(b,{className:`h-4 w-4`})})]}),h===`picker`&&a(`div`,{className:`p-4 space-y-2`,children:[K&&u(`div`,{className:`text-xs text-foreground-subtle animate-pulse`,children:`Loading providers…`}),!K&&G.length===0&&a(`div`,{className:`rounded border border-border bg-background px-3 py-4 text-center text-xs text-foreground-subtle`,children:[`No storage-provider supports type "`,y,`". Install a compatible addon (e.g.`,` `,u(`code`,{className:`font-mono`,children:`remote-storage`}),`) to enable it.`]}),G.map(e=>a(`button`,{onClick:()=>{C(e),g(`config`)},className:`flex w-full items-center gap-3 rounded-lg border border-border bg-background p-3 text-left hover:border-primary/40 hover:bg-primary/5 transition-colors`,children:[a(`div`,{className:`flex-1 min-w-0`,children:[u(`p`,{className:`text-xs font-semibold text-foreground`,children:e.displayName}),u(`p`,{className:`text-[10px] text-foreground-subtle font-mono mt-0.5 truncate`,children:e.providerId})]}),u(_,{className:`h-4 w-4 text-foreground-subtle flex-shrink-0`})]},e.providerId))]}),h===`config`&&S&&a(`div`,{className:`p-4 space-y-3 max-h-[60vh] overflow-y-auto`,children:[u(p,{schema:S.configSchema,values:w,onChange:T}),S.nodeLocal&&a(`div`,{className:`space-y-2`,children:[u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Node`}),u(n,{selectedNodeId:P,onSelect:I,alwaysShow:!0}),u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Path`}),u(F,{nodeId:P,value:U,onChange:H})]}),L&&u(`div`,{className:`rounded border px-3 py-2 text-[11px] ${L.ok?`border-success/30 bg-success/5 text-success`:`border-danger/30 bg-danger/5 text-danger`}`,children:L.ok?`Connection OK.`:`Test failed: ${L.error??`unknown error`}`}),a(`div`,{className:`flex items-center justify-between pt-1`,children:[u(`button`,{onClick:()=>g(`picker`),className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Back`}),a(`div`,{className:`flex items-center gap-2`,children:[u(`button`,{onClick:()=>{Y()},disabled:B,className:`rounded border border-border px-3 py-1.5 text-xs text-foreground hover:bg-primary/10 disabled:opacity-50`,children:B?`Testing…`:`Test connection`}),u(`button`,{onClick:()=>g(`naming`),className:`rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90`,children:`Next`})]})]})]}),h===`naming`&&S&&a(`div`,{className:`p-4 space-y-3`,children:[a(`div`,{className:`space-y-1`,children:[u(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:`Display name`}),u(`input`,{type:`text`,value:E,onChange:e=>D(e.target.value),placeholder:`${y} on ${S.displayName}`,className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary`})]}),a(`div`,{className:`space-y-1`,children:[a(`label`,{className:`text-[10px] uppercase tracking-wide text-foreground-subtle`,children:[`Id`,` `,u(`span`,{className:`lowercase tracking-normal text-foreground-subtle`,children:`— auto-derived; override if needed`})]}),u(`input`,{type:`text`,value:J,onChange:e=>k(e.target.value),placeholder:R(y,E),className:`w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground font-mono focus:outline-none focus:ring-1 focus:ring-primary`}),a(`p`,{className:`text-[10px] text-foreground-subtle`,children:[`Format: `,u(`code`,{className:`font-mono`,children:`<type>:<slug>`}),`. Lowercase letters, digits, and hyphens only.`]})]}),a(`label`,{className:`flex items-start gap-2 rounded border border-border bg-background px-3 py-2 cursor-pointer hover:bg-primary/5`,children:[u(`input`,{type:`checkbox`,checked:A,onChange:e=>j(e.target.checked),className:`accent-primary mt-0.5`}),a(`div`,{className:`space-y-0.5`,children:[a(`div`,{className:`text-xs font-medium text-foreground`,children:[`Mark as default for type "`,y,`"`]}),a(`div`,{className:`text-[10px] text-foreground-subtle`,children:[`Setting this as default will demote the current default for this type. References like `,a(`code`,{className:`font-mono`,children:[`"`,y,`"`]}),` resolve to whichever location is the default.`]})]})]}),a(`label`,{className:`flex items-start gap-2 rounded border border-border bg-background px-3 py-2 cursor-pointer hover:bg-primary/5`,children:[u(`input`,{type:`checkbox`,checked:M,onChange:e=>N(e.target.checked),className:`accent-primary mt-0.5`}),a(`div`,{className:`space-y-0.5`,children:[u(`div`,{className:`text-xs font-medium text-foreground`,children:`Enable immediately`}),u(`div`,{className:`text-[10px] text-foreground-subtle`,children:`A disabled location receives no writes until enabled — reads and age-based retention still work, nothing new lands here. Leave this off to register the disk now and start using it later.`})]})]}),q.isError&&u(`div`,{className:`rounded border border-danger/30 bg-danger/5 text-danger px-3 py-2 text-[11px]`,children:q.error instanceof Error?q.error.message:String(q.error)}),a(`div`,{className:`flex items-center justify-between pt-1`,children:[u(`button`,{onClick:()=>g(`config`),className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Back`}),a(`div`,{className:`flex items-center gap-2`,children:[u(`button`,{onClick:()=>{x(r),C(null),T({}),D(``),k(null),j(!1),N(!1),z(null),g(`picker`)},className:`rounded px-3 py-1.5 text-xs text-foreground-subtle border border-border hover:text-foreground`,children:`Reset`}),a(`button`,{onClick:()=>{S&&q.mutate({id:J,type:y,displayName:E.trim(),providerId:S.providerId,config:w,isDefault:A,enabled:M,nodeId:S.nodeLocal?P:void 0})},disabled:q.isPending||E.trim().length===0,className:`inline-flex items-center gap-1.5 rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50`,children:[q.isPending?u(v,{className:`h-3.5 w-3.5 animate-spin`}):null,q.isPending?`Saving…`:`Save`]})]})]})]})]})})}export{T as i,I as n,A as r,z as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Co as e,Et as t,So as n,fs as r,g as i,jt as a,ms as o,p as s,v as c}from"./src-BbMtrcN-.js";import{Q as l,S as u,o as d,q as f,x as p,z as m}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DTufy7Ue.js";import{t as h}from"./play-N-aCIv2P.js";import{t as g}from"./plus-BwBDSSUm.js";import{t as _}from"./refresh-cw-C2McgRco.js";import{t as v}from"./square-9Bf62Szc.js";import{G as y,I as b,S as x,V as S,m as C}from"./index-kOLbwjEX.js";import{t as w}from"./AdminPage-Dq33XE9j.js";import{t as T}from"./NodeAddonsSettingsPanel-CtO75ohk.js";l();function E({addonId:e,fallback:t,tileClassName:n,iconPath:r=`assets/icon.svg`}){let[i,a]=f(!1),o=`/api/addon-assets/${e}/${r}`;return p(`div`,{className:`h-10 w-10 rounded-lg flex items-center justify-center shrink-0 ${n}`,children:i?p(t,{className:`h-5 w-5`}):p(`img`,{src:o,alt:e,className:`h-7 w-7 rounded-md bg-white p-1 ring-1 ring-black/5`,onError:()=>a(!0)})})}l();function D({addonId:e,defaultActivity:t,showActivity:n=!0,maxHeight:r=`max-h-64`,defaultTab:a,capability:o}){let[s,l]=f(t??(a===`events`?`events`:`logs`));return u(`div`,{className:`flex flex-col gap-4`,children:[p(T,{nodeId:`hub`,addonIds:[e],level:`global`,capability:o}),n&&u(`div`,{className:`rounded-lg border border-border bg-surface overflow-hidden`,children:[u(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border bg-surface-hover/20`,children:[p(`span`,{className:`text-[11px] font-semibold text-foreground-subtle uppercase tracking-wide`,children:`Activity`}),u(`div`,{className:`flex items-center gap-1`,children:[p(O,{kind:`logs`,active:s===`logs`,onClick:()=>l(`logs`)}),p(O,{kind:`events`,active:s===`events`,onClick:()=>l(`events`)})]})]}),s===`logs`?p(c,{addonId:e,maxHeight:r,showFilters:!1}):p(i,{addonId:e,category:`addon.*`,maxHeight:r})]})]})}function O({kind:e,active:t,onClick:n}){return u(`button`,{onClick:n,className:`inline-flex items-center gap-1 rounded px-2 py-0.5 text-[11px] font-medium transition-colors ${t?`bg-primary/10 text-primary`:`text-foreground-subtle hover:text-foreground hover:bg-surface-hover`}`,children:[p(e===`logs`?C:S,{className:`h-3 w-3`}),e===`logs`?`Logs`:`Events`]})}l();function k(t){let{title:i,subtitle:a,pageIcon:s,itemIcon:c,capability:l,installButtonLabel:d=`Add addon`,items:h,isLoading:_,emptyTitle:v=`No addons installed for this capability`,emptyDescription:x,itemIconColor:S,renderStatusBadges:C,renderPrimaryAction:T,itemError:O,renderExpandedPanel:k,workspaceMaxHeight:N=`max-h-72`,trailing:P,showChrome:F=!1}=t,I=h.length>1,[L,R]=f(()=>h[0]?.addonId??null);m(()=>{L&&(h.some(e=>e.addonId===L)||R(h[0]?.addonId??null))},[h,L]);let z=e=>R(t=>t===e?null:e),B=`/system/addons?capability=${encodeURIComponent(l)}`;return p(w,{icon:F?s:void 0,title:F?i:void 0,subtitle:F?a:void 0,actions:F?p(y,{to:B,children:u(o,{variant:`primary`,size:`sm`,children:[p(g,{className:`h-3.5 w-3.5 mr-1`}),d]})}):void 0,children:_?p(r,{children:p(`div`,{className:`p-6 text-sm text-foreground-subtle`,children:`Loading…`})}):h.length===0?p(r,{children:p(e,{title:v,description:x??`Install an addon that declares the "${l}" capability to get started.`,action:F?p(y,{to:B,children:u(o,{variant:`primary`,size:`sm`,children:[p(g,{className:`h-3.5 w-3.5 mr-1`}),d]})}):void 0})}):u(`div`,{className:`flex flex-col gap-4`,children:[h.map(e=>{let t=!I||L===e.addonId,i=S?.(e)??(e.isActive?`bg-emerald-500/15 text-emerald-700 dark:text-emerald-300`:`bg-foreground-subtle/15 text-foreground-subtle`),a=O?.(e)??null;return u(r,{children:[u(`div`,{className:`flex flex-col gap-3 p-4 sm:flex-row sm:items-center ${t?`border-b border-border`:``}`,children:[u(`div`,{className:`flex items-center gap-3 flex-1 min-w-0`,children:[I&&p(`button`,{type:`button`,onClick:()=>z(e.addonId),"aria-label":t?`Collapse`:`Expand`,className:`shrink-0 p-1 rounded hover:bg-foreground-subtle/10 transition-colors`,children:p(b,{className:`h-4 w-4 text-foreground-subtle transition-transform ${t?`rotate-180`:``}`})}),u(`button`,{type:`button`,onClick:()=>I&&z(e.addonId),className:`flex items-center gap-4 flex-1 min-w-0 text-left ${I?`hover:opacity-80 transition-opacity`:``}`,disabled:!I,children:[p(E,{addonId:e.addonId,fallback:c,tileClassName:i}),u(`div`,{className:`flex-1 min-w-0`,children:[u(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[p(`span`,{className:`font-semibold text-foreground`,children:e.displayName}),p(A,{isActive:e.isActive}),C?.(e)]}),p(`div`,{className:`text-xs text-foreground-subtle mt-1 font-mono break-all`,children:e.addonId})]})]})]}),u(`div`,{className:`flex items-center gap-1 shrink-0 flex-wrap justify-end`,children:[T?.(e),p(j,{capName:e.capName??l,addonId:e.addonId,isActive:e.isActive}),p(M,{addonId:e.addonId,displayName:e.displayName})]})]}),t&&u(`div`,{className:`p-4 flex flex-col gap-3`,children:[a!==null&&p(n,{message:a}),k?.(e),p(D,{addonId:e.addonId,maxHeight:N,capability:e.capName??l})]})]},e.addonId)}),P]})})}function A({isActive:e}){return p(`span`,{className:`text-[10px] rounded-full px-2 py-0.5 font-medium ${e?`bg-emerald-500/15 text-emerald-700 dark:text-emerald-300`:`bg-foreground-subtle/15 text-foreground-subtle`}`,children:e?`Enabled`:`Disabled`})}function j({capName:e,addonId:t,isActive:n}){let r=d(),i=a({onSuccess:()=>{r.invalidateQueries({queryKey:[[`addons`,`listCapabilityProviders`]]})}}),s=i.isPending;return u(o,{size:`sm`,variant:n?`secondary`:`primary`,disabled:s,onClick:()=>i.mutate({capName:e,addonId:t,enabled:!n}),children:[s?p(x,{className:`h-3 w-3 animate-spin`}):p(n?v:h,{className:`h-3 w-3`}),n?`Disable`:`Enable`]})}function M({addonId:e,displayName:n}){let r=d(),i=t({onSuccess:()=>{r.invalidateQueries({queryKey:[[`addons`,`listCapabilityProviders`]]})}});return p(s,{label:`Restart`,icon:_,size:`sm`,title:`Restart "${n}"?`,description:`Restarting the addon bounces its subprocess — the provider will briefly drop and reconnect automatically.`,confirmLabel:`Restart`,triggerVariant:`ghost`,confirmVariant:`danger`,disabled:i.isPending,action:()=>i.mutateAsync({addonId:e})})}export{k as t};
|