@camstack/addon-admin-ui 1.2.106 → 1.2.107
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-DPvpYCGn.js → AddLocationWizard-jaDSCfMe.js} +1 -1
- package/dist/assets/{AddonCollectionPage-DLJXV_3S.js → AddonCollectionPage-BbzrPJ6L.js} +1 -1
- package/dist/assets/{Addons-COnaHviu.js → Addons-CKENyA_0.js} +1 -1
- package/dist/assets/{AdminTabs-ugTfV6vR.js → AdminTabs-DwlG6MYX.js} +1 -1
- package/dist/assets/{AiProfiles-B3OoMGwy.js → AiProfiles-DJZuqxl2.js} +1 -1
- package/dist/assets/{BrokerForm-FW8CGvEw.js → BrokerForm-Ca2dFeu6.js} +1 -1
- package/dist/assets/{Build-CKSSyLHR.js → Build-FaaOQcq6.js} +1 -1
- package/dist/assets/{Capabilities-Bvk135Hx.js → Capabilities-hGCD-XsN.js} +1 -1
- package/dist/assets/{CapabilityBadges-2_RTtE8F.js → CapabilityBadges-B3L7BgCj.js} +1 -1
- package/dist/assets/Cluster-Ehdgj3Kp.js +11 -0
- package/dist/assets/{Data-DUfQYWdR.js → Data-BbpQ2wej.js} +1 -1
- package/dist/assets/{DetectionIntelligence-_SicEHJ7.js → DetectionIntelligence-DjHh8ghB.js} +1 -1
- package/dist/assets/{DeviceAggregateSection-B-LbbxBn.js → DeviceAggregateSection-nls0vMuB.js} +1 -1
- package/dist/assets/{DeviceDetail-QGu4Zppg.js → DeviceDetail-B1kgvRQ1.js} +2 -2
- package/dist/assets/{Devices-DyOwMmsB.js → Devices-Ufx_psHi.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-DLylekcq.js → EmbedPlayerPage-CBglbG4n.js} +1 -1
- package/dist/assets/{Events-Bd7_dT0H.js → Events-DsUrafgO.js} +1 -1
- package/dist/assets/{FormBuilder-DaTNPCtr.js → FormBuilder-CR7w8Uea.js} +1 -1
- package/dist/assets/{Identity-qjHZBREK.js → Identity-D6agnFJl.js} +1 -1
- package/dist/assets/{IntegrationDetail-DaIdJdyp.js → IntegrationDetail-tAyrEEB3.js} +1 -1
- package/dist/assets/{Integrations-BXkqNtA2.js → Integrations-BgScP7uj.js} +1 -1
- package/dist/assets/{Integrations-B3wdYU9G.js → Integrations-BgmTtkes.js} +1 -1
- package/dist/assets/{Logs-B9aMiGDX.js → Logs-SRHHss4v.js} +1 -1
- package/dist/assets/{MotionZonesSettings-BAld-2Lw.js → MotionZonesSettings-Bqo0j30T.js} +1 -1
- package/dist/assets/{MyAccess-DYc5Ia6R.js → MyAccess-C-LZNy3P.js} +1 -1
- package/dist/assets/{Network-DtCqr7_n.js → Network-BMsGa7tx.js} +1 -1
- package/dist/assets/{NodeAddonsSettingsPanel-DCrm5WAe.js → NodeAddonsSettingsPanel-ClAYpMMi.js} +1 -1
- package/dist/assets/{NodeInferenceDevices-DruKQsKv.js → NodeInferenceDevices-Bb4I_qvo.js} +1 -1
- package/dist/assets/{Notifications-DN4WDeO2.js → Notifications-CfqQNKJd.js} +1 -1
- package/dist/assets/{Pipeline-BQaaY2RF.js → Pipeline-OVcA977t.js} +1 -1
- package/dist/assets/{Plates-DzAZ1RGB.js → Plates-xKbZNVW4.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-t81B_gek.js → PrivacyMaskSettings-BY7zHdqw.js} +1 -1
- package/dist/assets/{ProviderIcon-1IBp_VK5.js → ProviderIcon-De4kTHTR.js} +1 -1
- package/dist/assets/{Recordings-C6gSAs30.js → Recordings-BKbyRqgK.js} +1 -1
- package/dist/assets/{ScanNetworkModal-DId274fd.js → ScanNetworkModal-CtBvv4WV.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-B57j4d9e.js → SceneMonitorEditor-BXXt-4IO.js} +1 -1
- package/dist/assets/{Scenes-BJcEln5I.js → Scenes-teIGTKPS.js} +1 -1
- package/dist/assets/{Settings-DxbbgMBy.js → Settings-Dbzxh4Xn.js} +1 -1
- package/dist/assets/{Showroom-CGYvWhTb.js → Showroom-DxVo1-bk.js} +1 -1
- package/dist/assets/{Terminal-Db32GfJu.js → Terminal-DDef9uu4.js} +1 -1
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-x2EKNp38.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BE1fFa1_.js} +1 -1
- package/dist/assets/{bell-ring-fa6SzUi_.js → bell-ring-BwQgH1Jx.js} +1 -1
- package/dist/assets/{boxes-CfnJWdJa.js → boxes-B9qN8khW.js} +1 -1
- package/dist/assets/{build-cluster-graph-BlQoSudm.js → build-cluster-graph-BIxaMDak.js} +1 -1
- package/dist/assets/circle-check-big-CKXV1ppj.js +1 -0
- package/dist/assets/{circle-x-B470_M0K.js → circle-x-C7gUt7YG.js} +1 -1
- package/dist/assets/clock-Buox0pfk.js +1 -0
- package/dist/assets/{copy-Bz5_L_j0.js → copy-CxSGouEq.js} +1 -1
- package/dist/assets/{debounced-invalidate-BgLJ3Lz0.js → debounced-invalidate-Dsi2OJPO.js} +1 -1
- package/dist/assets/dist--DLsnle2.js +349 -0
- package/dist/assets/{dist-BiaTzHe6.js → dist-DP1UHvfy.js} +1 -1
- package/dist/assets/{download-CPPi4lEs.js → download-DZpOPJOl.js} +1 -1
- package/dist/assets/{face-bbox-Bk5OxbZ9.js → face-bbox-DZIslbfV.js} +1 -1
- package/dist/assets/{hostInit-CfHVCMU0.js → hostInit-t_jJvnIC.js} +1 -1
- package/dist/assets/index-2B_jjVhf.css +2 -0
- package/dist/assets/{index-DmGVQVip.js → index-BAEd1ERX.js} +3 -3
- package/dist/assets/{key-round-GUiZ3GBz.js → key-round-CUi3bTtL.js} +1 -1
- package/dist/assets/{layers-BHA4WXNG.js → layers-DBerP-8a.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-72686030.js → mf-entry-bootstrap-0-e5e0a6ce.js} +2 -2
- package/dist/assets/{pencil-CywoEYDw.js → pencil-Cu_AwkkH.js} +1 -1
- package/dist/assets/play-DY-uAc_T.js +1 -0
- package/dist/assets/{player-overlays-C1Oe-16j.js → player-overlays-BxZ5yvH8.js} +1 -1
- package/dist/assets/plus-CV5p_tnx.js +1 -0
- package/dist/assets/power-mTip9q3n.js +1 -0
- package/dist/assets/{radio-lEGHQd-3.js → radio-C3IEQP6m.js} +1 -1
- package/dist/assets/{refresh-cw-BEHJsw3X.js → refresh-cw-BkBjU-Za.js} +1 -1
- package/dist/assets/remoteEntry-M-lPOfwY.js +1 -0
- package/dist/assets/rotate-ccw-DhLsAlK8.js +1 -0
- package/dist/assets/rotate-cw-BwJCwVQH.js +1 -0
- package/dist/assets/{send-CdTPIK-7.js → send-Bu5E9gDd.js} +1 -1
- package/dist/assets/{server-CKXUNcfQ.js → server-CPAJbQJp.js} +1 -1
- package/dist/assets/{shield-DuQG63BO.js → shield-CKyB-C1m.js} +1 -1
- package/dist/assets/square-B3B-lXbz.js +1 -0
- package/dist/assets/{square-check-big-xoQlO2z6.js → square-check-big-CD8B3dsJ.js} +1 -1
- package/dist/assets/src-Ch7OV9gF.js +67 -0
- package/dist/assets/src-MgTxcsw3.js +349 -0
- package/dist/assets/{star-Dij84nD8.js → star-CIhdVMAM.js} +1 -1
- package/dist/assets/{undo-2-DtQ5QK61.js → undo-2-TS368FbX.js} +1 -1
- package/dist/assets/{upload-Bh__Gcoi.js → upload-bq3aTcwf.js} +1 -1
- package/dist/assets/{use-scenes-feed-BAtj9fjN.js → use-scenes-feed-D7fSSLcM.js} +1 -1
- package/dist/assets/useEventInvalidation-CZP-g5gD.js +1 -0
- package/dist/assets/{video-_cSQX0pK.js → video-B2S1p78W.js} +1 -1
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-CCi4D5V9.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-FrPFHt9i.js} +2 -2
- package/dist/assets/{wifi-DFad8LAE.js → wifi-C4xxyMOA.js} +1 -1
- package/dist/assets/{zap-BEaKr1nX.js → zap-BYuFHnmk.js} +1 -1
- package/dist/index.html +6 -6
- package/dist/server/addon.js +256 -26
- package/package.json +1 -1
- package/dist/assets/Cluster-BIIxDRXP.js +0 -1
- package/dist/assets/circle-check-big-C_6LzyMr.js +0 -1
- package/dist/assets/clock-44ycL5OK.js +0 -1
- package/dist/assets/dist-CxVTxcO_.js +0 -349
- package/dist/assets/index-BlRpxCYM.css +0 -2
- package/dist/assets/play-Dfmddr6T.js +0 -1
- package/dist/assets/plus-BpSOCY8P.js +0 -1
- package/dist/assets/power-CNppeI6O.js +0 -1
- package/dist/assets/remoteEntry-CpjMZXjT.js +0 -1
- package/dist/assets/rotate-ccw-ZN_nOrZf.js +0 -1
- package/dist/assets/rotate-cw-CDaIhQNY.js +0 -1
- package/dist/assets/square-BpVTHFXt.js +0 -1
- package/dist/assets/src-DLoxi-uA.js +0 -349
- package/dist/assets/src-DjZVUvrt.js +0 -67
- package/dist/assets/useEventInvalidation-Deon74Uu.js +0 -1
package/dist/server/addon.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
//#region ../types/dist/event-category-
|
|
3
|
+
//#region ../types/dist/event-category-BZL-fdNj.mjs
|
|
4
4
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
5
5
|
EventCategory["SystemBoot"] = "system.boot";
|
|
6
6
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -437,7 +437,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
437
437
|
EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
|
|
438
438
|
/**
|
|
439
439
|
* Periodic per-node process-tree snapshot (camstack-related pids
|
|
440
|
-
* with
|
|
440
|
+
* with root / managed / system classification). Emitted ~0.2 Hz by
|
|
441
441
|
* the metrics-provider addon. Drives the Cluster → Processes tab
|
|
442
442
|
* without polling `metricsProvider.listNodeProcesses`.
|
|
443
443
|
*/
|
|
@@ -11129,6 +11129,19 @@ var SettingsRecordSchema = object({
|
|
|
11129
11129
|
data: record(string(), unknown())
|
|
11130
11130
|
});
|
|
11131
11131
|
/**
|
|
11132
|
+
* One record of a BULK insert — {@link SettingsRecordSchema} with the id made
|
|
11133
|
+
* optional.
|
|
11134
|
+
*
|
|
11135
|
+
* A separate schema rather than loosening the shared one: every other method
|
|
11136
|
+
* on this cap addresses a row BY its id, and making that field optional
|
|
11137
|
+
* everywhere would turn a forgotten key into a silently generated one on
|
|
11138
|
+
* `update` and `delete` as well.
|
|
11139
|
+
*/
|
|
11140
|
+
var BulkRecordSchema = object({
|
|
11141
|
+
id: string().optional(),
|
|
11142
|
+
data: record(string(), unknown())
|
|
11143
|
+
});
|
|
11144
|
+
/**
|
|
11132
11145
|
* Column declaration for a structured (SQL-backed) collection.
|
|
11133
11146
|
*
|
|
11134
11147
|
* Logical types — the backend translates each to the matching SQLite
|
|
@@ -11185,6 +11198,10 @@ method(object({
|
|
|
11185
11198
|
collection: string(),
|
|
11186
11199
|
record: SettingsRecordSchema
|
|
11187
11200
|
}), _void(), { kind: "mutation" }), method(object({
|
|
11201
|
+
namespace: string().optional(),
|
|
11202
|
+
collection: string(),
|
|
11203
|
+
records: array(BulkRecordSchema).readonly()
|
|
11204
|
+
}), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
|
|
11188
11205
|
namespace: string().optional(),
|
|
11189
11206
|
collection: string(),
|
|
11190
11207
|
id: string(),
|
|
@@ -11293,6 +11310,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
11293
11310
|
}), _void(), {
|
|
11294
11311
|
kind: "mutation",
|
|
11295
11312
|
auth: "admin"
|
|
11313
|
+
}), method(object({
|
|
11314
|
+
namespace: string().optional(),
|
|
11315
|
+
collection: string(),
|
|
11316
|
+
records: array(BulkRecordSchema).readonly()
|
|
11317
|
+
}), object({ inserted: number().int() }), {
|
|
11318
|
+
kind: "mutation",
|
|
11319
|
+
auth: "admin"
|
|
11296
11320
|
}), method(object({
|
|
11297
11321
|
namespace: string().optional(),
|
|
11298
11322
|
collection: string(),
|
|
@@ -13061,6 +13085,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
|
|
|
13061
13085
|
limit: number().optional(),
|
|
13062
13086
|
tags: record(string(), string()).optional()
|
|
13063
13087
|
}), array(LogEntrySchema).readonly());
|
|
13088
|
+
var LoadContributionSchema = object({
|
|
13089
|
+
role: _enum([
|
|
13090
|
+
"decode",
|
|
13091
|
+
"transcode",
|
|
13092
|
+
"recording",
|
|
13093
|
+
"streaming",
|
|
13094
|
+
"detection"
|
|
13095
|
+
]),
|
|
13096
|
+
/**
|
|
13097
|
+
* The NUMERIC device id — the same value every log line carries as
|
|
13098
|
+
* `tags.deviceId`. `null` means this cost genuinely belongs to no single
|
|
13099
|
+
* camera (a shared pool), NOT that the contributor forgot to look it up: a
|
|
13100
|
+
* contributor that cannot name its camera must not emit the entry at all,
|
|
13101
|
+
* because an unnamed per-camera entry is indistinguishable from a shared one
|
|
13102
|
+
* and would quietly turn one camera's cost into everybody's.
|
|
13103
|
+
*/
|
|
13104
|
+
deviceId: number().int().positive().nullable(),
|
|
13105
|
+
attribution: _enum([
|
|
13106
|
+
"measured",
|
|
13107
|
+
"accounted",
|
|
13108
|
+
"unattributable"
|
|
13109
|
+
]),
|
|
13110
|
+
/**
|
|
13111
|
+
* What ONE entry is, in the contributor's own words — `615/high`,
|
|
13112
|
+
* `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
|
|
13113
|
+
* family and inventing a common one would lose the only information that
|
|
13114
|
+
* makes two entries for the same camera distinguishable.
|
|
13115
|
+
*/
|
|
13116
|
+
unit: string(),
|
|
13117
|
+
/**
|
|
13118
|
+
* The OS process this cost lives in, when there is one. Present so a
|
|
13119
|
+
* consumer can (a) tell two generations of the same unit apart across a
|
|
13120
|
+
* restart, and (b) subtract claimed processes from the node's process
|
|
13121
|
+
* snapshot to see what NOBODY claimed. Absent for an entry that owns no
|
|
13122
|
+
* process of its own.
|
|
13123
|
+
*/
|
|
13124
|
+
pid: number().int().positive().optional(),
|
|
13125
|
+
/**
|
|
13126
|
+
* When this generation started. The pid's incarnation marker: a consumer
|
|
13127
|
+
* differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
|
|
13128
|
+
* window when this changes, because the counter restarted from zero in a new
|
|
13129
|
+
* process.
|
|
13130
|
+
*/
|
|
13131
|
+
startedAtMs: number().optional(),
|
|
13132
|
+
/**
|
|
13133
|
+
* CUMULATIVE CPU seconds this unit has consumed since it started — user +
|
|
13134
|
+
* system, read from the child's own `/proc/<pid>/stat` at the moment the
|
|
13135
|
+
* contribution is asked for.
|
|
13136
|
+
*
|
|
13137
|
+
* Cumulative and not a rate on purpose: a rate needs a window, a window
|
|
13138
|
+
* needs a sampler, and a new per-node sampler is the defect half of
|
|
13139
|
+
* `docs/architecture/load-ledger.md` documents. A counter can be differenced
|
|
13140
|
+
* by whoever already keeps a history; a rate cannot be un-averaged.
|
|
13141
|
+
*
|
|
13142
|
+
* Absent — never zero — on a node with no `/proc`, on a read failure, and on
|
|
13143
|
+
* an entry with no process.
|
|
13144
|
+
*/
|
|
13145
|
+
cpuSeconds: number().optional(),
|
|
13146
|
+
/** Resident bytes of this unit's process, same source and same rules. */
|
|
13147
|
+
rssBytes: number().optional()
|
|
13148
|
+
});
|
|
13149
|
+
method(_void(), array(LoadContributionSchema).readonly());
|
|
13064
13150
|
/**
|
|
13065
13151
|
* `login-method` — collection cap through which auth addons contribute
|
|
13066
13152
|
* their pre-auth login surfaces to the login page. This is the SINGLE,
|
|
@@ -13264,8 +13350,7 @@ var NodeProcessSchema = object({
|
|
|
13264
13350
|
classification: _enum([
|
|
13265
13351
|
"root",
|
|
13266
13352
|
"managed",
|
|
13267
|
-
"system"
|
|
13268
|
-
"ghost"
|
|
13353
|
+
"system"
|
|
13269
13354
|
]),
|
|
13270
13355
|
/** `$process` addon binding when `managed`, else null. */
|
|
13271
13356
|
addonId: string().nullable(),
|
|
@@ -13273,22 +13358,39 @@ var NodeProcessSchema = object({
|
|
|
13273
13358
|
nodeId: string().nullable(),
|
|
13274
13359
|
/** Truncated command line. */
|
|
13275
13360
|
command: string(),
|
|
13361
|
+
/**
|
|
13362
|
+
* `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
|
|
13363
|
+
* On a runner up for days it barely moves. Fine as a column, useless as a
|
|
13364
|
+
* series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
|
|
13365
|
+
*/
|
|
13276
13366
|
cpuPercent: number(),
|
|
13277
13367
|
memoryRssBytes: number(),
|
|
13368
|
+
/**
|
|
13369
|
+
* Instantaneous CPU% of the process's own threads over the last
|
|
13370
|
+
* process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
|
|
13371
|
+
*
|
|
13372
|
+
* `null` = UNKNOWN, never zero: no previous sample yet (first tick after
|
|
13373
|
+
* boot), the pid was recycled, or this node is not Linux.
|
|
13374
|
+
*/
|
|
13375
|
+
cpuMainPercent: number().nullable(),
|
|
13376
|
+
/**
|
|
13377
|
+
* Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
|
|
13378
|
+
*
|
|
13379
|
+
* This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
|
|
13380
|
+
* `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
|
|
13381
|
+
* does not separate it from `cpuMainPercent` shows "busy" where the truth is
|
|
13382
|
+
* "allocating too much".
|
|
13383
|
+
*
|
|
13384
|
+
* Concurrent GC is the dominant tenant of that pool but not the only one
|
|
13385
|
+
* (background compilation runs there too), so it is reported as
|
|
13386
|
+
* "GC / V8 helpers" rather than as pure collection time. `null` has the same
|
|
13387
|
+
* meaning as on `cpuMainPercent`.
|
|
13388
|
+
*/
|
|
13389
|
+
cpuGcPercent: number().nullable(),
|
|
13390
|
+
/** Threads seen in the tick scan. `null` under the same conditions. */
|
|
13391
|
+
threadCount: number().nullable(),
|
|
13278
13392
|
/** Wall-clock uptime (seconds). Parsed from `ps etime`. */
|
|
13279
|
-
uptimeSec: number()
|
|
13280
|
-
/** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
|
|
13281
|
-
orphaned: boolean()
|
|
13282
|
-
});
|
|
13283
|
-
var KillProcessInputSchema = object({
|
|
13284
|
-
pid: number(),
|
|
13285
|
-
/** Force = SIGKILL. Default is SIGTERM. */
|
|
13286
|
-
force: boolean().optional()
|
|
13287
|
-
});
|
|
13288
|
-
var KillProcessResultSchema = object({
|
|
13289
|
-
success: boolean(),
|
|
13290
|
-
reason: string().optional(),
|
|
13291
|
-
signal: _enum(["SIGTERM", "SIGKILL"]).optional()
|
|
13393
|
+
uptimeSec: number()
|
|
13292
13394
|
});
|
|
13293
13395
|
var DumpHeapSnapshotInputSchema = object({
|
|
13294
13396
|
/** The addon whose runner should dump a heap snapshot. */
|
|
@@ -13301,6 +13403,104 @@ var DumpHeapSnapshotResultSchema = object({
|
|
|
13301
13403
|
pid: number().optional(),
|
|
13302
13404
|
reason: string().optional()
|
|
13303
13405
|
});
|
|
13406
|
+
/**
|
|
13407
|
+
* One point of one function's series.
|
|
13408
|
+
*
|
|
13409
|
+
* The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
|
|
13410
|
+
* point of the whole surface. The two obvious reductions both lie: a mean per
|
|
13411
|
+
* bucket smears a spike away, and taking every Nth sample skips it outright.
|
|
13412
|
+
* Either would give us a tool built to find peaks that does not show peaks.
|
|
13413
|
+
* `...Min` carries the other end, `samples` says how many raw snapshots folded
|
|
13414
|
+
* into the bucket, and a mean stays derivable where it is wanted.
|
|
13415
|
+
*
|
|
13416
|
+
* An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
|
|
13417
|
+
* equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
|
|
13418
|
+
* caller cannot tell which it received — which is what "one reader" means.
|
|
13419
|
+
*/
|
|
13420
|
+
var LoadPointSchema = object({
|
|
13421
|
+
/** Bucket START, or the snapshot's own timestamp when unreduced. */
|
|
13422
|
+
atMs: number(),
|
|
13423
|
+
/** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
|
|
13424
|
+
samples: number().int(),
|
|
13425
|
+
/**
|
|
13426
|
+
* `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
|
|
13427
|
+
* of every snapshot in it reported a thread split. A partial sum is a
|
|
13428
|
+
* smaller number that looks exactly as real as a complete one.
|
|
13429
|
+
*/
|
|
13430
|
+
cpuMainPercent: number().nullable(),
|
|
13431
|
+
cpuMainPercentMin: number().nullable(),
|
|
13432
|
+
cpuGcPercent: number().nullable(),
|
|
13433
|
+
cpuGcPercentMin: number().nullable(),
|
|
13434
|
+
/** Lifetime-average CPU%, summed. Always known — and never a rate. */
|
|
13435
|
+
cpuLifetimePercent: number(),
|
|
13436
|
+
cpuLifetimePercentMin: number(),
|
|
13437
|
+
memoryRssBytes: number(),
|
|
13438
|
+
memoryRssBytesMin: number(),
|
|
13439
|
+
processCount: number().int(),
|
|
13440
|
+
processCountMin: number().int()
|
|
13441
|
+
});
|
|
13442
|
+
/** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
|
|
13443
|
+
var LoadFunctionSeriesSchema = object({
|
|
13444
|
+
key: string(),
|
|
13445
|
+
kind: _enum([
|
|
13446
|
+
"addon",
|
|
13447
|
+
"root",
|
|
13448
|
+
"unattributed"
|
|
13449
|
+
]),
|
|
13450
|
+
/** Oldest-first. A missing interval is MISSING — never zero-filled. */
|
|
13451
|
+
points: array(LoadPointSchema).readonly()
|
|
13452
|
+
});
|
|
13453
|
+
var NodeLoadSeriesSchema = object({
|
|
13454
|
+
nodeId: string(),
|
|
13455
|
+
/** One entry per function seen in the window, heaviest-first. */
|
|
13456
|
+
series: array(LoadFunctionSeriesSchema).readonly(),
|
|
13457
|
+
/**
|
|
13458
|
+
* Width of one returned bucket, in ms. Equals the sampling cadence when no
|
|
13459
|
+
* reduction was needed — so a caller can always say what one point covers
|
|
13460
|
+
* without having to know whether it was reduced.
|
|
13461
|
+
*/
|
|
13462
|
+
bucketMs: number(),
|
|
13463
|
+
/** Raw snapshots that went into this answer, across both tiers. */
|
|
13464
|
+
retainedSamples: number(),
|
|
13465
|
+
/** Oldest snapshot represented, or `null` when nothing is retained. */
|
|
13466
|
+
oldestAtMs: number().nullable(),
|
|
13467
|
+
/** The fixed sampling cadence in force on the cluster, in ms. */
|
|
13468
|
+
cadenceMs: number(),
|
|
13469
|
+
/**
|
|
13470
|
+
* Did the DURABLE tier contribute? `false` means the answer is the hot ring
|
|
13471
|
+
* alone — an agent (which holds no table), or a store that refused.
|
|
13472
|
+
* Reported because "the last hour" and "the last six hours" are different
|
|
13473
|
+
* questions and an operator must not have to guess which was answered.
|
|
13474
|
+
*/
|
|
13475
|
+
durable: boolean()
|
|
13476
|
+
});
|
|
13477
|
+
var GetLoadSeriesInputSchema = object({
|
|
13478
|
+
/**
|
|
13479
|
+
* The node whose series is wanted.
|
|
13480
|
+
*
|
|
13481
|
+
* NOT named `nodeId`: the generated cap router strips a top-level
|
|
13482
|
+
* `nodeId` from every method input and uses it to ROUTE the call to
|
|
13483
|
+
* that node's provider (`generated-cap-routers.ts`). A series target
|
|
13484
|
+
* called `nodeId` would silently become a routing pin and never reach
|
|
13485
|
+
* the provider. The hub holds every node it hears from, so the
|
|
13486
|
+
* ordinary call is unpinned — answered by the hub, for any node.
|
|
13487
|
+
*/
|
|
13488
|
+
forNodeId: string(),
|
|
13489
|
+
/**
|
|
13490
|
+
* EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
|
|
13491
|
+
* holds and receives only what it is missing, so seeding a live chart
|
|
13492
|
+
* from this method cannot double a point already drawn.
|
|
13493
|
+
*/
|
|
13494
|
+
sinceMs: number().optional(),
|
|
13495
|
+
/**
|
|
13496
|
+
* Most points the caller wants PER FUNCTION. The window is reduced to fit,
|
|
13497
|
+
* preserving min and max per bucket.
|
|
13498
|
+
*
|
|
13499
|
+
* Absent means NO reduction — legitimate for a short window and a trap for a
|
|
13500
|
+
* long one, which is why a chart passes its own pixel width.
|
|
13501
|
+
*/
|
|
13502
|
+
maxPoints: number().int().positive().optional()
|
|
13503
|
+
});
|
|
13304
13504
|
var SystemMetricsSchema = object({
|
|
13305
13505
|
cpuPercent: number(),
|
|
13306
13506
|
memoryPercent: number(),
|
|
@@ -13311,10 +13511,7 @@ var SystemMetricsSchema = object({
|
|
|
13311
13511
|
gpuPercent: number().optional(),
|
|
13312
13512
|
gpuMemoryPercent: number().optional()
|
|
13313
13513
|
});
|
|
13314
|
-
method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(
|
|
13315
|
-
kind: "mutation",
|
|
13316
|
-
auth: "admin"
|
|
13317
|
-
}), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
|
|
13514
|
+
method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
|
|
13318
13515
|
kind: "mutation",
|
|
13319
13516
|
auth: "admin"
|
|
13320
13517
|
});
|
|
@@ -26617,6 +26814,15 @@ var LoggingSettingsPatchSchema = object({
|
|
|
26617
26814
|
* authority over the whole hierarchy and answers for every layer, so the
|
|
26618
26815
|
* layer selector needs a name the transport does not already own.
|
|
26619
26816
|
*/
|
|
26817
|
+
/**
|
|
26818
|
+
* One contribution, plus WHO reported it.
|
|
26819
|
+
*
|
|
26820
|
+
* The addon and node are added by the hub as it enumerates providers, never by
|
|
26821
|
+
* the contributor: an addon reporting its own identity could report somebody
|
|
26822
|
+
* else's, and the whole point of this surface is that no claim is made by
|
|
26823
|
+
* anyone but its owner.
|
|
26824
|
+
*/
|
|
26825
|
+
var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
|
|
26620
26826
|
var GetLoggingSettingsInputSchema = object({
|
|
26621
26827
|
scopeNodeId: string().optional(),
|
|
26622
26828
|
/**
|
|
@@ -26675,7 +26881,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
|
|
|
26675
26881
|
}), method(_void(), SiteLocationStatusSchema, {
|
|
26676
26882
|
kind: "mutation",
|
|
26677
26883
|
auth: "admin"
|
|
26678
|
-
}), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
|
|
26884
|
+
}), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
|
|
26679
26885
|
kind: "mutation",
|
|
26680
26886
|
auth: "admin"
|
|
26681
26887
|
});
|
|
@@ -28291,6 +28497,12 @@ Object.freeze({
|
|
|
28291
28497
|
addonId: null,
|
|
28292
28498
|
access: "create"
|
|
28293
28499
|
},
|
|
28500
|
+
"dataStoreProvider.insertMany": {
|
|
28501
|
+
capName: "data-store-provider",
|
|
28502
|
+
capScope: "system",
|
|
28503
|
+
addonId: null,
|
|
28504
|
+
access: "create"
|
|
28505
|
+
},
|
|
28294
28506
|
"dataStoreProvider.isEmpty": {
|
|
28295
28507
|
capName: "data-store-provider",
|
|
28296
28508
|
capScope: "system",
|
|
@@ -29605,6 +29817,12 @@ Object.freeze({
|
|
|
29605
29817
|
addonId: null,
|
|
29606
29818
|
access: "create"
|
|
29607
29819
|
},
|
|
29820
|
+
"loadContribution.list": {
|
|
29821
|
+
capName: "load-contribution",
|
|
29822
|
+
capScope: "system",
|
|
29823
|
+
addonId: null,
|
|
29824
|
+
access: "view"
|
|
29825
|
+
},
|
|
29608
29826
|
"localNetwork.downloadCa": {
|
|
29609
29827
|
capName: "local-network",
|
|
29610
29828
|
capScope: "system",
|
|
@@ -29905,17 +30123,17 @@ Object.freeze({
|
|
|
29905
30123
|
addonId: null,
|
|
29906
30124
|
access: "view"
|
|
29907
30125
|
},
|
|
29908
|
-
"metricsProvider.
|
|
30126
|
+
"metricsProvider.getLoadSeries": {
|
|
29909
30127
|
capName: "metrics-provider",
|
|
29910
30128
|
capScope: "system",
|
|
29911
30129
|
addonId: null,
|
|
29912
30130
|
access: "view"
|
|
29913
30131
|
},
|
|
29914
|
-
"metricsProvider.
|
|
30132
|
+
"metricsProvider.getProcessStats": {
|
|
29915
30133
|
capName: "metrics-provider",
|
|
29916
30134
|
capScope: "system",
|
|
29917
30135
|
addonId: null,
|
|
29918
|
-
access: "
|
|
30136
|
+
access: "view"
|
|
29919
30137
|
},
|
|
29920
30138
|
"metricsProvider.listAddonInstances": {
|
|
29921
30139
|
capName: "metrics-provider",
|
|
@@ -31927,6 +32145,12 @@ Object.freeze({
|
|
|
31927
32145
|
addonId: null,
|
|
31928
32146
|
access: "create"
|
|
31929
32147
|
},
|
|
32148
|
+
"settingsStore.insertMany": {
|
|
32149
|
+
capName: "settings-store",
|
|
32150
|
+
capScope: "system",
|
|
32151
|
+
addonId: null,
|
|
32152
|
+
access: "create"
|
|
32153
|
+
},
|
|
31930
32154
|
"settingsStore.isEmpty": {
|
|
31931
32155
|
capName: "settings-store",
|
|
31932
32156
|
capScope: "system",
|
|
@@ -32539,6 +32763,12 @@ Object.freeze({
|
|
|
32539
32763
|
addonId: null,
|
|
32540
32764
|
access: "create"
|
|
32541
32765
|
},
|
|
32766
|
+
"system.getLoadContributions": {
|
|
32767
|
+
capName: "system",
|
|
32768
|
+
capScope: "system",
|
|
32769
|
+
addonId: null,
|
|
32770
|
+
access: "view"
|
|
32771
|
+
},
|
|
32542
32772
|
"system.getLoggingSettings": {
|
|
32543
32773
|
capName: "system",
|
|
32544
32774
|
capScope: "system",
|
|
@@ -35438,7 +35668,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
35438
35668
|
capability: adminUiCapability,
|
|
35439
35669
|
provider: {
|
|
35440
35670
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
35441
|
-
getVersion: async () => ({ version: "1.2.
|
|
35671
|
+
getVersion: async () => ({ version: "1.2.107" })
|
|
35442
35672
|
}
|
|
35443
35673
|
}];
|
|
35444
35674
|
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as e,K as t,Q as n,S as r,W as i,o as a,q as o,x as s,z as c}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 l}from"./player-overlays-C1Oe-16j.js";import{$i as u,Bo as d,Ct as f,Is as p,Ki as m,Lo as h,Ro as g,Rs as _,St as v,Va as y,Y as b,aa as x,ea as S,ia as C,na as w,oo as T,q as E,qi as D,ra as O,ta as k,un as A,wt as j,xt as M,zo as N}from"./src-DjZVUvrt.js";import{t as P}from"./pencil-CywoEYDw.js";import{t as ee}from"./radio-lEGHQd-3.js";import{t as F}from"./refresh-cw-BEHJsw3X.js";import{t as I}from"./rotate-cw-CDaIhQNY.js";import{t as L}from"./server-CKXUNcfQ.js";import{t as R}from"./upload-Bh__Gcoi.js";import{B as z,L as te,P as ne,U as re,h as ie,i as ae,o as oe,q as B,s as V,t as H,w as U,z as W}from"./index-DmGVQVip.js";import{n as G,t as K}from"./build-cluster-graph-BlQoSudm.js";import{t as q}from"./NodeAddonsSettingsPanel-DCrm5WAe.js";import{t as J}from"./format-size-DIxKXxtj.js";var Y=B(`arrow-down-to-line`,[[`path`,{d:`M12 17V3`,key:`1cwfxf`}],[`path`,{d:`m6 11 6 6 6-6`,key:`12ii2o`}],[`path`,{d:`M19 21H5`,key:`150jfl`}]]),se=B(`git-fork`,[[`circle`,{cx:`12`,cy:`18`,r:`3`,key:`1mpf1b`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`circle`,{cx:`18`,cy:`6`,r:`3`,key:`1h7g24`}],[`path`,{d:`M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9`,key:`1uq4wg`}],[`path`,{d:`M12 12v3`,key:`158kv8`}]]),ce=B(`hard-drive-download`,[[`path`,{d:`M12 2v8`,key:`1q4o3n`}],[`path`,{d:`m16 6-4 4-4-4`,key:`6wukr`}],[`rect`,{width:`20`,height:`8`,x:`2`,y:`14`,rx:`2`,key:`w68u3i`}],[`path`,{d:`M6 18h.01`,key:`uhywen`}],[`path`,{d:`M10 18h.01`,key:`h775k`}]]),le=B(`memory-stick`,[[`path`,{d:`M6 19v-3`,key:`1nvgqn`}],[`path`,{d:`M10 19v-3`,key:`iu8nkm`}],[`path`,{d:`M14 19v-3`,key:`kcehxu`}],[`path`,{d:`M18 19v-3`,key:`1vh91z`}],[`path`,{d:`M8 11V9`,key:`63erz4`}],[`path`,{d:`M16 11V9`,key:`fru6f3`}],[`path`,{d:`M12 11V9`,key:`ha00sb`}],[`path`,{d:`M2 15h20`,key:`16ne18`}],[`path`,{d:`M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z`,key:`lhddv3`}]]),X=B(`skull`,[[`path`,{d:`m12.5 17-.5-1-.5 1h1z`,key:`3me087`}],[`path`,{d:`M15 22a1 1 0 0 0 1-1v-1a2 2 0 0 0 1.56-3.25 8 8 0 1 0-11.12 0A2 2 0 0 0 8 20v1a1 1 0 0 0 1 1z`,key:`1o5pge`}],[`circle`,{cx:`15`,cy:`12`,r:`1`,key:`1tmaij`}],[`circle`,{cx:`9`,cy:`12`,r:`1`,key:`1vctgf`}]]),ue=B(`table-2`,[[`path`,{d:`M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18`,key:`gugj83`}]]);n();function de(e){let t=new FormData;return t.append(`file`,e.file,e.file.name),t.append(`nodeId`,e.nodeId),e.addonId&&t.append(`addonId`,e.addonId),new Promise((n,r)=>{let i=new XMLHttpRequest;i.open(`POST`,`/api/addons/upload`),e.token&&i.setRequestHeader(`Authorization`,`Bearer ${e.token}`),i.upload.addEventListener(`progress`,t=>{t.lengthComputable&&e.onProgress(Math.round(t.loaded/t.total*100))}),i.addEventListener(`load`,()=>{let e;try{e=JSON.parse(i.responseText)}catch{r(Error(`HTTP ${i.status}`));return}i.status>=200&&i.status<300?n(e):r(Error(e.error??`HTTP ${i.status}`))}),i.addEventListener(`error`,()=>r(Error(`Network error during upload`))),i.addEventListener(`abort`,()=>r(Error(`Upload aborted`))),i.send(t)})}function fe({nodeId:e,addons:n,isHub:i}){let c=a(),l=A(),[d,f]=o(null),[p,m]=o(null),[h,g]=o(!1),[_,v]=o(null),[y,b]=o(0),S=t(null),C=k(),w=x(),T=u({nodeId:e}),E=T.data??[],D=new Map(n.map(e=>[e.id,e.capabilities])),O=E.length>0?E.map(e=>({id:e.id,status:e.status,capabilities:D.get(e.id)??[],version:e.version,packageName:e.packageName})):n.map(e=>({id:e.id,status:e.status,capabilities:e.capabilities,version:void 0,packageName:void 0})),j=()=>{c.invalidateQueries({queryKey:[[`nodes`,`topology`]]}),T.refetch()},M=async t=>{f(t);try{await C.mutateAsync({nodeId:e,addonId:t}),j()}catch(e){console.error(`Failed to restart addon:`,e)}finally{f(null)}},N=async t=>{if(await l({title:`Uninstall addon`,message:`Remove "${t}" from ${e}? The addon directory will be deleted on disk.`,confirmLabel:`Uninstall`,variant:`danger`})){m(t);try{await w.mutateAsync({nodeId:e,addonId:t}),j()}catch(e){console.error(`Failed to uninstall addon:`,e)}finally{m(null)}}},P=r(`div`,{className:`flex items-center gap-2 mb-2`,children:[s(`input`,{ref:S,type:`file`,accept:`.tgz,.tar.gz`,className:`hidden`,onChange:async t=>{let n=t.target.files?.[0];if(n){t.target.value=``,v(null),g(!0),b(0);try{await de({file:n,nodeId:e,token:localStorage.getItem(`camstack_admin_token`),onProgress:b}),j()}catch(e){v(e instanceof Error?e.message:String(e))}finally{g(!1),b(0)}}}}),r(`button`,{onClick:()=>S.current?.click(),disabled:h,className:`inline-flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1 text-[11px] font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors disabled:opacity-50`,children:[h?s(U,{className:`h-3 w-3 animate-spin`}):s(R,{className:`h-3 w-3`}),h?`Uploading… ${y}%`:`Upload addon (.tgz)`]}),h&&s(`div`,{className:`flex-1 h-1 rounded-full bg-muted overflow-hidden max-w-[140px]`,children:s(`div`,{className:`h-full bg-primary transition-all`,style:{width:`${y}%`}})}),_&&s(`span`,{className:`text-[10px] text-destructive`,children:_})]});return O.length===0?r(`div`,{children:[P,s(`div`,{className:`py-4 text-xs text-muted-foreground text-center`,children:T.isLoading?`Loading addons…`:`No addons on this node`})]}):r(`div`,{children:[P,s(`div`,{className:`rounded-lg border border-border max-h-[60vh] overflow-auto`,children:r(`table`,{className:`w-full text-xs`,children:[s(`thead`,{className:`sticky top-0 z-10 bg-surface`,children:r(`tr`,{className:`text-muted-foreground text-left`,children:[s(`th`,{className:`px-3 py-2 font-medium`,children:`Addon`}),s(`th`,{className:`px-3 py-2 font-medium`,children:`Version`}),s(`th`,{className:`px-3 py-2 font-medium`,children:`Capabilities`}),s(`th`,{className:`px-3 py-2 font-medium`,children:`Status`}),s(`th`,{className:`px-3 py-2 font-medium w-16`})]})}),s(`tbody`,{children:O.map(e=>r(`tr`,{className:`border-t border-border/50`,children:[r(`td`,{className:`px-3 py-2 font-medium`,children:[s(`div`,{children:e.id}),e.packageName&&s(`div`,{className:`text-[9px] text-muted-foreground`,children:e.packageName})]}),s(`td`,{className:`px-3 py-2 text-muted-foreground`,children:e.version??`—`}),s(`td`,{className:`px-3 py-2`,children:s(`div`,{className:`flex flex-wrap gap-1`,children:e.capabilities.length>0?e.capabilities.map(e=>s(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-blue-500/10 text-blue-400`,children:e},e)):s(`span`,{className:`text-muted-foreground`,children:`—`})})}),s(`td`,{className:`px-3 py-2`,children:s(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full ${e.status===`running`?`bg-success/10 text-success`:e.status===`error`?`bg-destructive/10 text-destructive`:`bg-muted text-muted-foreground`}`,children:e.status})}),s(`td`,{className:`px-3 py-2`,children:r(`div`,{className:`flex items-center gap-1 justify-end`,children:[s(`button`,{onClick:()=>M(e.id),disabled:d===e.id||p===e.id,className:`p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50`,title:`Restart ${e.id}`,children:s(I,{className:`h-3 w-3 ${d===e.id?`animate-spin`:``}`})}),s(`button`,{onClick:()=>N(e.id),disabled:d===e.id||p===e.id,className:`p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-50`,title:`Uninstall ${e.id}`,children:p===e.id?s(U,{className:`h-3 w-3 animate-spin`}):s(V,{className:`h-3 w-3`})})]})})]},e.id))})]})})]})}n();function pe(e){if(e<60)return`${e}s`;let t=Math.floor(e/60);if(t<60)return`${t}m`;let n=Math.floor(t/60);return n<24?`${n}h ${t%60}m`:`${Math.floor(n/24)}d ${n%24}h`}function me({state:e}){return s(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full ${e===`running`?`bg-success/10 text-success`:e===`crashed`||e===`failed`?`bg-destructive/10 text-destructive`:`bg-muted text-muted-foreground`}`,children:e})}var he=[`trace`,`debug`,`info`,`warn`,`error`];function ge({proc:e,nodeId:t,defaultExpanded:n,activePanel:i,onTogglePanel:a}){let c=e.services??[],l=c.length===1,[u,d]=o(l||n),[p,m]=o(null),[h,g]=o(`info`),_=e.name.includes(`(core)`),y=k(),x=w(),S=O(),C=async e=>{m(e);try{await y.mutateAsync({nodeId:t,addonId:e})}catch(e){console.error(`Failed to restart addon:`,e)}finally{m(null)}},T=async()=>{m(e.name);try{await x.mutateAsync({nodeId:t,processName:e.name})}catch(e){console.error(`Failed to restart process:`,e)}finally{m(null)}},D=async n=>{let r=`${t}/${e.name}`;try{await S.mutateAsync({nodeId:r,level:n}),g(n)}catch(e){console.error(`Failed to set log level:`,e)}};return r(`div`,{className:`border border-border/50 rounded-lg overflow-hidden`,children:[r(`div`,{role:l?void 0:`button`,tabIndex:l?void 0:0,onClick:l?void 0:()=>d(!u),onKeyDown:l?void 0:e=>{(e.key===`Enter`||e.key===` `)&&d(!u)},className:`flex items-center gap-2 w-full px-3 py-2 bg-muted/20 transition-colors text-left select-none ${l?``:`hover:bg-muted/40 cursor-pointer`}`,children:[l?s(`span`,{className:`h-3 w-3 shrink-0`}):s(u?W:te,{className:`h-3 w-3 text-muted-foreground shrink-0`}),_?s(L,{className:`h-3.5 w-3.5 text-primary shrink-0`}):s(re,{className:`h-3.5 w-3.5 text-amber-500 shrink-0`}),s(`span`,{className:`text-xs font-semibold flex-1`,children:e.name}),r(`span`,{className:`text-[10px] text-muted-foreground tabular-nums`,children:[`PID `,e.pid]}),s(me,{state:e.state}),r(`span`,{className:`text-[10px] text-muted-foreground tabular-nums`,children:[e.cpuPercent,`% CPU`]}),s(`span`,{className:`text-[10px] text-muted-foreground tabular-nums`,children:J(e.memoryRss)}),s(`span`,{className:`text-[10px] text-muted-foreground tabular-nums`,children:pe(e.uptimeSeconds)}),!_&&r(`div`,{className:`flex items-center gap-1`,onClick:e=>e.stopPropagation(),children:[r(M,{children:[s(j,{className:`text-[9px] px-1.5 py-0.5 rounded border border-border text-muted-foreground hover:text-foreground hover:bg-muted transition-colors font-mono`,title:`Set log level`,children:h}),s(v,{align:`end`,className:`min-w-[70px] py-0.5`,children:he.map(e=>s(f,{onClick:()=>D(e),className:`h-auto px-2 py-1 text-[10px] font-mono ${e===h?`text-primary font-semibold`:``}`,children:e},e))})]}),s(`button`,{onClick:T,disabled:p===e.name,className:`p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50`,title:`Restart process`,children:s(I,{className:`h-3 w-3 ${p===e.name?`animate-spin`:``}`})})]})]}),u&&c.length>0&&s(`div`,{className:`divide-y divide-border/30`,children:c.map(e=>r(`div`,{children:[r(`div`,{className:`flex items-center gap-2 px-3 py-1.5 pl-9 hover:bg-muted/10 transition-colors`,children:[s(`div`,{className:`h-1.5 w-1.5 rounded-full shrink-0 ${e.status===`running`?`bg-success`:`bg-muted-foreground/30`}`}),s(`span`,{className:`text-xs font-medium flex-1 min-w-0 truncate`,children:e.addonId}),e.capabilities.length>0&&r(`div`,{className:`flex gap-1 flex-shrink-0`,children:[e.capabilities.slice(0,3).map(e=>s(`span`,{className:`text-[9px] px-1 py-0.5 rounded bg-blue-500/10 text-blue-400 truncate max-w-[80px]`,children:e},e)),e.capabilities.length>3&&r(`span`,{className:`text-[9px] text-muted-foreground`,children:[`+`,e.capabilities.length-3]})]}),r(`div`,{className:`flex items-center gap-1 shrink-0`,children:[s(`button`,{onClick:()=>a(e.addonId,`logs`),className:`p-0.5 rounded transition-colors ${i?.addonId===e.addonId&&i.type===`logs`?`bg-primary/10 text-primary`:`hover:bg-muted text-muted-foreground hover:text-foreground`}`,title:`Show logs for ${e.addonId}`,children:s(ie,{className:`h-3 w-3`})}),s(`button`,{onClick:()=>a(e.addonId,`events`),className:`p-0.5 rounded transition-colors ${i?.addonId===e.addonId&&i.type===`events`?`bg-primary/10 text-primary`:`hover:bg-muted text-muted-foreground hover:text-foreground`}`,title:`Show events for ${e.addonId}`,children:s(ee,{className:`h-3 w-3`})}),s(`button`,{onClick:()=>C(e.addonId),disabled:p===e.addonId,className:`p-0.5 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50`,title:`Restart ${e.addonId}`,children:s(I,{className:`h-3 w-3 ${p===e.addonId?`animate-spin`:``}`})})]})]}),i?.addonId===e.addonId&&i.type===`logs`&&s(`div`,{className:`border-t border-border/40 bg-muted/5`,children:s(b,{addonId:e.addonId,agentId:t,maxHeight:`max-h-48`,showFilters:!1,onClose:()=>a(e.addonId,`logs`)})}),i?.addonId===e.addonId&&i.type===`events`&&s(`div`,{className:`border-t border-border/40 bg-muted/5`,children:s(E,{addonId:e.addonId,category:`addon.*`,maxHeight:`max-h-48`,onClose:()=>a(e.addonId,`events`)})})]},e.addonId))}),u&&c.length===0&&s(`div`,{className:`px-3 py-2 pl-9 text-[10px] text-muted-foreground`,children:`No services`})]})}function _e({nodeId:e,processes:t}){let[n,r]=o(null),i=(e,t)=>{r(n=>n?.addonId===e&&n.type===t?null:{addonId:e,type:t})};return t.length===0?s(`div`,{className:`py-4 text-xs text-muted-foreground text-center`,children:`No processes on this node`}):s(`div`,{className:`space-y-2 py-1`,children:t.map((t,r)=>s(ge,{proc:t,nodeId:e,defaultExpanded:r===0,activePanel:n,onTogglePanel:i},t.name))})}n();function ve(e){return e<60?`${e}s`:e<3600?`${Math.floor(e/60)}m ${e%60}s`:e<86400?`${Math.floor(e/3600)}h ${Math.floor(e%3600/60)}m`:`${Math.floor(e/86400)}d ${Math.floor(e%86400/3600)}h`}function ye(e,t=80){return e.length<=t?e:`…${e.slice(e.length-t+1)}`}function be({nodeId:e}){let t=a(),n=A(),[c,l]=o(`all`),u=p(`metrics.node-processes-snapshot`,t=>t.nodeId===e),{data:d}=D({nodeId:e}),f=u?.processes??d,h=i(()=>f?[...f]:[],[f]),g=i(()=>c===`ghost`?h.filter(e=>e.classification===`ghost`):h,[h,c]),_=i(()=>{let e=h.filter(e=>e.classification===`ghost`),t=new Map;for(let n of e)t.has(n.ppid)||t.set(n.ppid,[]),t.get(n.ppid).push(n);return[...t.entries()].filter(([,e])=>e.length>1).map(([e,t])=>({ppid:e,children:t})).toSorted((e,t)=>t.children.length-e.children.length)},[h]),v=m({onSettled:()=>{t.invalidateQueries({queryKey:[[`metricsProvider`,`listNodeProcesses`]]})}}),y=i(()=>{let e=new Map;for(let t of h)e.set(t.pid,t.classification);return e},[h]),b=async(t,r)=>{if(t.classification===`root`||t.classification===`system`)return;let i=t.classification===`ghost`?`ghost`:t.addonId??`process`,a=r?`SIGKILL`:`SIGTERM`;await n({title:`Send ${a}?`,message:`Target pid ${t.pid} (${i}) on node ${e}.`,confirmLabel:`Send ${a}`,variant:`danger`})&&v.mutate({nodeId:e,pid:t.pid,force:r})},x=async(t,n)=>{try{await v.mutateAsync({nodeId:e,pid:t,force:n})}catch{}},S=async r=>{let i=y.get(r.ppid);if(i===`root`||i===`system`){await n({title:`Cannot kill protected ancestor`,message:i===`root`?`pid ${r.ppid} is the current node supervisor. Restart the node via the cluster page instead.`:`pid ${r.ppid} is a system ancestor (concurrently / vite / npm wrapper). Killing it would tear down the dev tree.`,confirmLabel:`OK`,cancelLabel:`Close`,variant:`warning`});return}await n({title:`Kill ghost parent + ${r.children.length} child(ren)?`,message:`SIGKILL parent pid ${r.ppid} and SIGTERM ${r.children.length} ghost child(ren) on node ${e}.`,confirmLabel:`Kill all`,variant:`danger`})&&(await Promise.all([x(r.ppid,!0),...r.children.map(e=>x(e.pid,!1))]),t.invalidateQueries({queryKey:[[`metricsProvider`,`listNodeProcesses`]]}))},C=async()=>{let r=h.filter(e=>e.classification===`ghost`);r.length!==0&&await n({title:`Kill all ${r.length} ghost process(es)?`,message:`SIGKILL ${r.length} ghost process(es) on node ${e}. This is irreversible.`,confirmLabel:`Kill all`,variant:`danger`})&&(await Promise.all(r.map(e=>x(e.pid,!0))),t.invalidateQueries({queryKey:[[`metricsProvider`,`listNodeProcesses`]]}))},w=h.filter(e=>e.classification===`ghost`).length,T=h.filter(e=>e.classification===`managed`).length,E=h.filter(e=>e.classification===`root`).length,O=h.filter(e=>e.classification===`system`).length;return r(`div`,{className:`space-y-4`,children:[r(`div`,{className:`flex items-start justify-between gap-4`,children:[r(`p`,{className:`text-[11px] text-foreground-subtle`,children:[`ps`," scan + kernel `$process.list` cross-reference. Ghosts = camstack-shaped commands with no managed binding (usually orphaned to ppid=1). Refreshes every 10s."]}),r(`button`,{type:`button`,onClick:()=>t.invalidateQueries({queryKey:[[`metricsProvider`,`listNodeProcesses`]]}),className:`inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[11px] text-foreground hover:bg-surface-hover`,children:[s(F,{className:`h-3 w-3`}),` Refresh`]})]}),r(`div`,{className:`grid grid-cols-4 gap-3`,children:[r(`div`,{className:`rounded-lg border border-border p-3`,children:[s(`div`,{className:`text-[10px] uppercase tracking-wider text-foreground-subtle`,children:`Root`}),s(`div`,{className:`text-xl font-semibold text-foreground`,children:E})]}),r(`div`,{className:`rounded-lg border border-border p-3`,children:[s(`div`,{className:`text-[10px] uppercase tracking-wider text-foreground-subtle`,children:`Managed`}),s(`div`,{className:`text-xl font-semibold text-foreground`,children:T})]}),r(`div`,{className:`rounded-lg border border-border p-3`,children:[s(`div`,{className:`text-[10px] uppercase tracking-wider text-foreground-subtle`,children:`System`}),s(`div`,{className:`text-xl font-semibold text-foreground`,children:O})]}),r(`div`,{className:`rounded-lg border p-3 ${w>0?`border-destructive/40 bg-destructive/5`:`border-border`}`,children:[r(`div`,{className:`text-[10px] uppercase tracking-wider text-foreground-subtle flex items-center gap-1`,children:[w>0&&s(X,{className:`h-3 w-3 text-destructive`}),` Ghosts`]}),s(`div`,{className:`text-xl font-semibold ${w>0?`text-destructive`:`text-foreground`}`,children:w})]})]}),_.length>0&&r(`div`,{className:`rounded-lg border border-amber-500/40 bg-amber-500/5 p-3`,children:[r(`div`,{className:`flex items-center gap-1 text-[11px] font-semibold text-amber-400 mb-2`,children:[s(oe,{className:`h-3 w-3`}),` Recurring ghost parents (`,_.length,`)`]}),s(`div`,{className:`space-y-1.5`,children:_.map(e=>r(`div`,{className:`text-[11px] text-foreground flex items-center justify-between gap-2`,children:[r(`div`,{className:`flex items-center gap-2`,children:[r(`span`,{className:`font-mono text-foreground-subtle`,children:[`ppid `,e.ppid]}),r(`span`,{children:[`→ `,e.children.length,` ghost(s)`]})]}),r(`button`,{type:`button`,disabled:v.isPending,onClick:()=>{S(e)},className:`inline-flex items-center gap-1 rounded border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[10px] text-amber-400 hover:bg-amber-500/20 disabled:opacity-30`,children:[s(X,{className:`h-3 w-3`}),` Kill parent + `,e.children.length]})]},e.ppid))})]}),r(`div`,{className:`flex items-center justify-between gap-2 text-[11px]`,children:[r(`div`,{className:`flex items-center gap-2`,children:[s(`span`,{className:`text-foreground-subtle`,children:`Filter:`}),r(`button`,{type:`button`,className:`px-2 py-0.5 rounded ${c===`all`?`bg-primary text-primary-foreground`:`border border-border text-foreground hover:bg-surface-hover`}`,onClick:()=>l(`all`),children:[`All (`,h.length,`)`]}),r(`button`,{type:`button`,className:`px-2 py-0.5 rounded ${c===`ghost`?`bg-destructive text-destructive-foreground`:`border border-border text-foreground hover:bg-surface-hover`}`,onClick:()=>l(`ghost`),children:[`Ghost only (`,w,`)`]})]}),w>0&&r(`button`,{type:`button`,disabled:v.isPending,onClick:()=>{C()},className:`inline-flex items-center gap-1 rounded border border-destructive/40 bg-destructive/10 px-2 py-1 text-[11px] font-medium text-destructive hover:bg-destructive/20 disabled:opacity-30`,children:[s(X,{className:`h-3 w-3`}),` Kill all `,w,` ghost(s)`]})]}),s(`div`,{className:`rounded-lg border border-border max-h-[60vh] overflow-auto`,children:r(`table`,{className:`w-full text-xs`,children:[s(`thead`,{className:`sticky top-0 z-10 bg-surface`,children:r(`tr`,{className:`text-foreground-subtle text-[10px] uppercase tracking-wider`,children:[s(`th`,{className:`text-left px-3 py-2`,children:`Class`}),s(`th`,{className:`text-right px-3 py-2`,children:`PID`}),s(`th`,{className:`text-right px-3 py-2`,children:`PPID`}),s(`th`,{className:`text-left px-3 py-2`,children:`Addon`}),s(`th`,{className:`text-left px-3 py-2`,children:`Command`}),s(`th`,{className:`text-right px-3 py-2`,children:`CPU%`}),s(`th`,{className:`text-right px-3 py-2`,children:`RSS`}),s(`th`,{className:`text-right px-3 py-2`,children:`Uptime`}),s(`th`,{className:`w-44`})]})}),r(`tbody`,{children:[g.length===0&&s(`tr`,{children:s(`td`,{colSpan:9,className:`px-3 py-4 text-center text-foreground-subtle text-[11px]`,children:c===`ghost`?`No ghost processes detected.`:`Scanning…`})}),g.map(e=>r(`tr`,{className:`border-t border-border ${e.classification===`ghost`?`bg-destructive/5`:``}`,children:[s(`td`,{className:`px-3 py-2`,children:s(`span`,{className:`inline-block rounded-full px-1.5 py-0.5 text-[10px] font-medium ${e.classification===`ghost`?`bg-destructive/20 text-destructive`:e.classification===`root`?`bg-sky-500/20 text-sky-400`:e.classification===`system`?`bg-foreground-subtle/20 text-foreground-subtle`:`bg-success/20 text-success`}`,children:e.classification})}),s(`td`,{className:`px-3 py-2 text-right font-mono text-foreground`,children:e.pid}),r(`td`,{className:`px-3 py-2 text-right font-mono text-foreground-subtle`,children:[e.ppid,e.orphaned?` ⚠`:``]}),s(`td`,{className:`px-3 py-2 text-foreground-subtle text-[11px]`,children:e.addonId??`—`}),s(`td`,{className:`px-3 py-2 font-mono text-[10px] text-foreground-subtle break-all`,children:ye(e.command)}),s(`td`,{className:`px-3 py-2 text-right text-foreground`,children:e.cpuPercent.toFixed(1)}),s(`td`,{className:`px-3 py-2 text-right text-foreground`,children:J(e.memoryRssBytes)}),s(`td`,{className:`px-3 py-2 text-right text-foreground-subtle`,children:ve(e.uptimeSec)}),s(`td`,{className:`px-3 py-2 text-right`,children:r(`div`,{className:`inline-flex gap-1`,children:[r(`button`,{type:`button`,disabled:v.isPending||e.classification===`root`||e.classification===`system`,onClick:()=>{b(e,!1)},title:`SIGTERM`,className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded border border-border text-[10px] text-foreground hover:bg-surface-hover disabled:opacity-30`,children:[s(V,{className:`h-3 w-3`}),` Term`]}),r(`button`,{type:`button`,disabled:v.isPending||e.classification===`root`||e.classification===`system`,onClick:()=>{b(e,!0)},title:`SIGKILL`,className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded border border-destructive/30 text-[10px] text-destructive hover:bg-destructive/10 disabled:opacity-30`,children:[s(X,{className:`h-3 w-3`}),` Kill`]})]})})]},e.pid))]})]})}),v.isError&&r(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/5 px-3 py-2 text-[11px] text-destructive`,children:[`Kill failed:`,` `,v.error instanceof Error?v.error.message:`unknown`]})]})}function xe({nodeId:e,addonIds:t}){return t.length===0?s(`div`,{className:`py-4 text-xs text-muted-foreground text-center`,children:`No addons on this node`}):s(`div`,{className:`w-full py-2`,children:s(q,{nodeId:e,addonIds:t,level:`global`,selfTabbed:!0})})}n();function Se({nodeId:e,addons:t}){let n=a(),{data:o,isLoading:c}=y({nodeId:e}),l=i(()=>{let e=new Map;for(let n of t)for(let t of n.capabilities){let r=e.get(t)??[];r.push(n.id),e.set(t,r)}return[...e.entries()].toSorted(([e],[t])=>e.localeCompare(t)).map(([e,t])=>({capName:e,providers:t}))},[t]),u=T({onSuccess:()=>{n.invalidateQueries({queryKey:[[`pipelineOrchestrator`,`getCapabilityBindings`]]})}});return l.length===0?s(`div`,{className:`py-4 text-xs text-muted-foreground text-center`,children:`No capabilities on this node`}):s(`div`,{className:`rounded-lg border border-border max-h-[60vh] overflow-auto`,children:r(`table`,{className:`w-full text-xs`,children:[s(`thead`,{className:`sticky top-0 z-10 bg-surface`,children:r(`tr`,{className:`text-muted-foreground text-left`,children:[s(`th`,{className:`px-3 py-2 font-medium w-1/2`,children:`Capability`}),s(`th`,{className:`px-3 py-2 font-medium`,children:`Bound provider`})]})}),s(`tbody`,{children:l.map(({capName:t,providers:n})=>{let i=o?.[t]??n[0]??``,a=n.length===1;return r(`tr`,{className:`border-t border-border/50`,children:[s(`td`,{className:`px-3 py-2 font-medium`,children:t}),s(`td`,{className:`px-3 py-2`,children:s(`select`,{value:i,onChange:n=>u.mutate({nodeId:e,capName:t,addonId:n.target.value}),disabled:a||u.isPending||c,className:`w-full rounded-md border border-border bg-surface px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary disabled:opacity-60`,title:a?`Only one provider installed — choice becomes available once a second addon registers this capability`:void 0,children:n.map(e=>s(`option`,{value:e,children:e},e))})})]},t)})})]})})}n();function Z(e){if(e==null)return`—`;let t=Math.floor(e/1e3),n=Math.floor(t/86400),r=Math.floor(t%86400/3600),i=Math.floor(t%3600/60);return n>0?`${n}d ${r}h ${i}m`:r>0?`${r}h ${i}m`:`${i}m`}function Ce(e){let[t,n]=o(!1),[i,c]=o(e.name),l=a(),u=S({onSuccess:()=>{l.invalidateQueries({queryKey:[[`nodes`,`topology`]]})}}),d=(e.localIps??[]).filter(e=>!e.includes(`:`)),f=(e.localIps??[]).filter(e=>e.includes(`:`)),p=async()=>{if(!i.trim()||i===e.name){n(!1);return}try{await u.mutateAsync({nodeId:e.nodeId,name:i.trim()}),n(!1)}catch(e){console.error(`Rename failed:`,e)}},m=[[`Node ID`,s(`span`,{className:`font-mono text-xs`,children:e.nodeId})],[`Display Name`,t?r(`div`,{className:`flex items-center gap-1.5`,children:[s(`input`,{type:`text`,className:`flex-1 px-2 py-0.5 text-xs border border-border rounded bg-background focus:outline-none focus:ring-1 focus:ring-primary`,value:i,onChange:e=>c(e.target.value),onKeyDown:e=>{e.key===`Enter`&&p(),e.key===`Escape`&&n(!1)},disabled:u.isPending,autoFocus:!0}),s(`button`,{onClick:()=>void p(),disabled:u.isPending,className:`p-0.5 text-success hover:bg-success/10 rounded`,title:`Save`,children:s(z,{className:`h-3.5 w-3.5`})}),s(`button`,{onClick:()=>n(!1),className:`p-0.5 text-muted-foreground hover:bg-muted rounded`,title:`Cancel`,children:s(ae,{className:`h-3.5 w-3.5`})})]}):r(`div`,{className:`flex items-center gap-1.5`,children:[s(`span`,{className:`text-xs`,children:e.name}),!e.isHub&&s(`button`,{onClick:()=>{c(e.name),n(!0)},className:`p-0.5 text-muted-foreground hover:text-primary rounded`,title:`Rename`,children:s(P,{className:`h-3 w-3`})})]})],[`Hostname`,s(`span`,{className:`text-xs`,children:e.hostname})],[`Role`,e.isHub?s(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded bg-primary/10 text-primary font-medium`,children:`Hub`}):s(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded bg-muted text-muted-foreground font-medium`,children:`Agent`})],[`Root Package`,e.rootPackage?r(`span`,{className:`font-mono text-xs`,children:[e.rootPackage.name,`@`,e.rootPackage.version]}):s(`span`,{className:`text-xs text-muted-foreground`,children:`—`})],[`Platform`,r(`span`,{className:`text-xs`,children:[e.platform,` / `,e.arch]})],[`CPU`,r(`span`,{className:`text-xs`,children:[e.cpuModel??`—`,` (`,e.cpuCores,` cores)`]})],[`Memory`,s(`span`,{className:`text-xs`,children:e.memoryMB>0?`${(e.memoryMB/1024).toFixed(1)} GB`:`—`})],[`Uptime`,s(`span`,{className:`text-xs`,children:Z(e.uptime)})],[`Engines`,e.engines.length>0?s(`div`,{className:`flex flex-wrap gap-1`,children:e.engines.map(e=>s(`span`,{className:`text-[9px] px-1.5 py-0.5 rounded-full bg-purple-500/10 text-purple-400 font-medium`,children:e},e))}):s(`span`,{className:`text-xs text-muted-foreground`,children:`—`})]];return d.length>0&&m.push([`IPv4`,s(`div`,{className:`flex flex-wrap gap-1.5`,children:d.map((e,t)=>s(`span`,{className:`font-mono text-xs px-1.5 py-0.5 rounded bg-muted`,children:e},`${e}-${t}`))})]),f.length>0&&m.push([`IPv6`,s(`div`,{className:`flex flex-wrap gap-1.5`,children:f.map((e,t)=>s(`span`,{className:`font-mono text-[10px] px-1.5 py-0.5 rounded bg-muted truncate max-w-[280px]`,title:e,children:e},`${e}-${t}`))})]),s(`div`,{className:`py-2`,children:s(`table`,{className:`w-full text-sm`,children:s(`tbody`,{children:m.map(([e,t],n)=>r(`tr`,{className:n%2==0?`bg-muted/20`:``,children:[s(`td`,{className:`py-1.5 px-2 text-xs font-medium text-muted-foreground w-28 align-top whitespace-nowrap`,children:e}),s(`td`,{className:`py-1.5 px-2`,children:t})]},e))})})})}n();var we=[[`serverManagement`,`getServerPackageStatus`]];function Q({label:e,tone:t}){return s(`span`,{className:`inline-flex items-center rounded px-2 py-0.5 text-[11px] font-medium ${{neutral:`bg-surface-muted text-foreground-subtle`,ok:`bg-emerald-500/15 text-emerald-500`,info:`bg-sky-500/15 text-sky-500`,warn:`bg-amber-500/15 text-amber-500`,error:`bg-red-500/15 text-red-500`}[t]}`,children:e})}function $({label:e,value:t}){return r(`div`,{className:`flex items-center justify-between gap-4 text-sm`,children:[s(`span`,{className:`text-foreground-subtle`,children:e}),s(`span`,{className:`font-mono text-foreground`,children:t??`—`})]})}function Te({node:t}){let{t:n}=H(),i=a(),c=A(),[l,u]=o(!1),f=t.isHub?void 0:{nodeId:t.id},p=N(f,{refetchInterval:1e4,enabled:t.isOnline,retry:1}),m=p.data??null,_=e(()=>{i.invalidateQueries({queryKey:we})},[i]),v=g({onSettled:_}),y=h({onSettled:_}),b=d({onSettled:_}),x=e(async()=>{m?.latestVersion!=null&&await c({title:n(`serverManagement.confirmUpdateTitle`,`Update node root package`),message:n(`serverManagement.confirmUpdateBody`,`Install {{pkg}}@{{version}} on "{{node}}" and restart to apply.`,{pkg:m.packageName,version:m.latestVersion,node:t.name}),confirmLabel:n(`serverManagement.confirmUpdateAction`,`Update & restart`)})&&(await y.mutateAsync({version:m.latestVersion,...f})).restarting&&u(!0)},[y,c,t.name,f,m,n]),S=e(async()=>{await c({title:n(`serverManagement.confirmRestartTitle`,`Restart node`),message:n(`serverManagement.confirmRestartBody`,`Restart "{{node}}"? In-flight requests to this node are dropped.`,{node:t.name}),confirmLabel:n(`serverManagement.confirmRestartAction`,`Restart`),variant:`warning`})&&(await b.mutateAsync(f)).restarting&&u(!0)},[c,t.name,b,f,n]),C=()=>{switch(m?.bootMode){case`data-root`:return{label:n(`serverManagement.bootDataRoot`,`runtime-updatable`),tone:`ok`};case`workspace`:return{label:n(`serverManagement.bootWorkspace`,`dev workspace`),tone:`info`};default:return{label:n(`serverManagement.bootBaked`,`baked image seed`),tone:`neutral`}}},w=()=>{if(m==null)return null;switch(m.updateState){case`checking`:return{label:n(`serverManagement.stateChecking`,`checking…`),tone:`info`};case`staging`:return{label:n(`serverManagement.stateStaging`,`updating…`),tone:`info`};case`pending-restart`:return{label:n(`serverManagement.statePending`,`restart pending`),tone:`warn`};default:return m.updateAvailable?{label:n(`serverManagement.stateUpdateAvailable`,`update available`),tone:`warn`}:{label:n(`serverManagement.stateUpToDate`,`up to date`),tone:`ok`}}},T=m?.bootMode===`workspace`,E=t.isOnline&&m!=null&&!T&&m.updateAvailable&&m.updateState===`idle`&&!y.isPending,D=t.isOnline&&m!=null&&m.updateState===`idle`&&!b.isPending,O=t.isOnline?w():null;return r(`div`,{className:`space-y-4 py-2`,children:[r(`div`,{className:`flex items-center justify-between gap-3`,children:[r(`div`,{className:`flex items-center gap-2 min-w-0`,children:[s(`span`,{className:`font-mono text-xs text-foreground-subtle truncate`,children:m?.packageName??t.rootPackage?.name??`@camstack/server`}),t.isOnline&&m!=null&&s(Q,{...C()})]}),O!=null&&s(Q,{...O})]}),!t.isOnline&&s($,{label:n(`serverManagement.lastReportedVersion`,`Last reported version`),value:t.rootPackage?.version??null}),t.isOnline&&p.isLoading&&r(`div`,{className:`flex items-center gap-2 text-sm text-foreground-subtle`,children:[s(U,{className:`h-4 w-4 animate-spin`}),n(`common.loading`,`Loading…`)]}),t.isOnline&&p.isError&&r(`div`,{className:`space-y-1.5`,children:[s(`p`,{className:`text-sm text-red-500`,children:n(`serverManagement.loadError`,`Could not load the node root-package status.`)}),t.rootPackage!=null&&s($,{label:n(`serverManagement.lastReportedVersion`,`Last reported version`),value:t.rootPackage.version})]}),t.isOnline&&m!=null&&r(`div`,{className:`space-y-1.5`,children:[s($,{label:n(`serverManagement.runningVersion`,`Running version`),value:m.runningVersion}),s($,{label:n(`serverManagement.latestVersion`,`Latest on registry`),value:m.latestVersion}),s($,{label:n(`serverManagement.imageSeedVersion`,`Image seed (baked)`),value:m.seedVersion}),s($,{label:n(`serverManagement.nodeRuntimeVersion`,`Node.js runtime`),value:m.nodeRuntimeVersion}),m.pendingVersion!=null&&s($,{label:n(`serverManagement.pendingVersion`,`Staged (applies on restart)`),value:m.pendingVersion})]}),t.isOnline&&(m?.imageContract?.state===`behind-series`||m?.imageContract?.state===`behind-patch`)&&r(`div`,{className:`rounded-md border px-3 py-2 text-xs leading-relaxed ${m.imageContract.state===`behind-series`?`border-red-500/40 bg-red-500/10 text-red-500`:`border-amber-500/40 bg-amber-500/10 text-amber-500`}`,children:[s(`p`,{className:`mb-0.5 font-semibold`,children:n(`serverManagement.imageContractDiverged`,`Container image diverges from the deployment contract`)}),s(`p`,{children:m.imageContract.message})]}),t.isOnline&&T&&s(`p`,{className:`text-xs text-foreground-subtle`,children:n(`serverManagement.workspaceNote`,`Development workspace detected — runtime updates are disabled (the dev loop resolves code from the workspace).`)}),l&&r(`div`,{className:`flex items-center gap-2 text-sm text-amber-500`,children:[s(U,{className:`h-4 w-4 animate-spin`}),n(`serverManagement.nodeRestarting`,`The node is restarting to apply the change…`)]}),t.isOnline&&r(`div`,{className:`flex flex-wrap items-center gap-2 pt-1`,children:[r(`button`,{type:`button`,className:`inline-flex items-center gap-1.5 rounded border border-border px-2.5 py-1.5 text-xs font-medium text-foreground hover:bg-surface-muted disabled:opacity-50`,disabled:v.isPending||m?.updateState===`staging`,onClick:()=>v.mutate(f),children:[v.isPending?s(U,{className:`h-3.5 w-3.5 animate-spin`}):s(F,{className:`h-3.5 w-3.5`}),n(`serverManagement.checkForUpdate`,`Check for update`)]}),E&&r(`button`,{type:`button`,className:`inline-flex items-center gap-1.5 rounded bg-primary px-2.5 py-1.5 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50`,onClick:()=>void x(),children:[y.isPending?s(U,{className:`h-3.5 w-3.5 animate-spin`}):s(Y,{className:`h-3.5 w-3.5`}),n(`serverManagement.updateTo`,`Update to {{version}}`,{version:m?.latestVersion??``})]}),r(`button`,{type:`button`,className:`inline-flex items-center gap-1.5 rounded border border-border px-2.5 py-1.5 text-xs font-medium text-foreground hover:bg-surface-muted disabled:opacity-50`,disabled:!D,onClick:()=>void S(),children:[b.isPending?s(U,{className:`h-3.5 w-3.5 animate-spin`}):s(I,{className:`h-3.5 w-3.5`}),n(`serverManagement.restart`,`Restart`)]})]}),t.isOnline&&m?.lastCheckedAtMs!=null&&r(`p`,{className:`flex items-center gap-1.5 text-[11px] text-foreground-subtle`,children:[s(ce,{className:`h-3 w-3`}),n(`serverManagement.lastChecked`,`Last checked: {{when}}`,{when:new Date(m.lastCheckedAtMs).toLocaleString()})]})]})}n();function Ee({node:e}){let t=l(),[n,i]=o(`info`),[a,c]=o(!1),u=e.processes??[],d=e.addons.map(e=>e.id),f=async()=>{if(!a){c(!0);try{await Promise.allSettled([t.trpcClient.pipelineOrchestrator.removeAgentSettings.mutate({agentNodeId:e.id}),t.trpcClient.clusterNodes.forgetNode.mutate({nodeId:e.id})])}finally{c(!1)}}};return e.isOnline?r(`div`,{className:`border border-border rounded-xl`,children:[r(`div`,{className:`flex items-center gap-3 px-4 py-3 bg-muted/30 border-b border-border rounded-t-xl`,children:[s(`div`,{className:`w-2.5 h-2.5 rounded-full bg-success`}),s(`span`,{className:`text-sm font-semibold`,children:e.name}),r(`span`,{className:`text-xs text-muted-foreground`,children:[e.cpuModel??e.platform,` ·`,` `,e.memoryMB>0?`${Math.round(e.memoryMB/1024)}GB`:``,` · `,e.arch]}),e.engines.map(e=>s(`span`,{className:`text-[9px] px-1.5 py-0.5 rounded-full bg-purple-500/10 text-purple-400 font-medium`,children:e},e)),r(`div`,{className:`ml-auto flex gap-3 text-xs text-muted-foreground`,children:[r(`span`,{className:`flex items-center gap-1`,children:[s(ne,{className:`h-3 w-3`}),` `,e.cpuPercent,`%`]}),r(`span`,{className:`flex items-center gap-1`,children:[s(le,{className:`h-3 w-3`}),` `,e.memoryPercent,`%`]})]})]}),s(`div`,{className:`sticky top-0 z-20 flex border-b border-border px-4 bg-background overflow-x-auto`,children:[`info`,`addons`,`forks`,`processes`,`settings`,`capabilities`].map(t=>s(`button`,{onClick:()=>i(t),className:`shrink-0 whitespace-nowrap px-3 py-2 text-xs font-medium border-b-2 transition-colors ${n===t?`border-primary text-primary`:`border-transparent text-muted-foreground hover:text-foreground`}`,children:t===`info`?`General`:t===`addons`?`Addons (${e.addons.length})`:t===`forks`?`Forks (${u.length})`:t===`processes`?`Processes`:t===`settings`?`Settings`:`Capabilities`},t))}),r(`div`,{className:`px-4 py-2`,children:[n===`info`&&r(`div`,{className:`space-y-3`,children:[s(Ce,{nodeId:e.id,name:e.name,hostname:e.hostname,platform:e.platform,arch:e.arch,cpuModel:e.cpuModel,cpuCores:e.cpuCores,memoryMB:e.memoryMB,engines:e.engines,isHub:e.isHub,uptime:e.uptime,localIps:e.localIps,rootPackage:e.rootPackage}),s(`div`,{className:`border-t border-border pt-1`,children:s(Te,{node:{id:e.id,name:e.name,isHub:e.isHub,isOnline:e.isOnline,rootPackage:e.rootPackage??null}})})]}),n===`addons`&&s(fe,{nodeId:e.id,addons:e.addons,isHub:e.isHub}),n===`forks`&&s(_e,{nodeId:e.id,processes:u}),n===`processes`&&s(be,{nodeId:e.id}),n===`settings`&&s(xe,{nodeId:e.id,addonIds:d}),n===`capabilities`&&s(Se,{nodeId:e.id,addons:e.addons})]})]}):r(`div`,{className:`border border-border rounded-xl overflow-hidden opacity-60`,children:[r(`div`,{className:`flex items-center gap-3 px-4 py-3 bg-muted/30`,children:[s(`div`,{className:`w-2.5 h-2.5 rounded-full bg-destructive`}),s(`span`,{className:`text-sm font-semibold`,children:e.name}),r(`span`,{className:`text-xs text-muted-foreground`,children:[e.cpuModel??e.platform,` ·`,` `,e.memoryMB>0?`${Math.round(e.memoryMB/1024)}GB`:``,` · `,e.arch]}),e.engines.map(e=>s(`span`,{className:`text-[9px] px-1.5 py-0.5 rounded-full bg-purple-500/10 text-purple-400 font-medium`,children:e},e)),e.rootPackage&&r(`span`,{className:`text-[10px] font-mono px-1.5 py-0.5 rounded bg-muted text-muted-foreground`,children:[e.rootPackage.name,`@`,e.rootPackage.version]}),s(`span`,{className:`ml-auto text-xs px-2 py-0.5 rounded-full bg-destructive/10 text-destructive`,children:`offline`})]}),r(`div`,{className:`flex items-center justify-between gap-3 px-4 py-3`,children:[r(`span`,{className:`text-xs text-muted-foreground`,children:[e.lastSeen?`Last seen ${new Date(e.lastSeen).toLocaleString()} — `:``,e.addons.length,` addon`,e.addons.length===1?``:`s`,` assigned; will resume when node reconnects`]}),r(`button`,{type:`button`,onClick:()=>void f(),disabled:a,title:`Forget this node — removes its saved history and pipeline assignments`,className:`flex items-center gap-1 text-xs px-2 py-1 rounded-md border border-border text-muted-foreground hover:text-destructive hover:border-destructive/50 disabled:opacity-50 transition-colors`,children:[s(V,{className:`h-3 w-3`}),a?`Forgetting…`:`Forget node`]})]})]})}n();function De({nodes:e,focusNodeId:n,focusNonce:r}){let i=[...e].toSorted((e,t)=>e.isHub?-1:t.isHub?1:e.isOnline&&!t.isOnline?-1:!e.isOnline&&t.isOnline?1:e.name.localeCompare(t.name)),a=t(null);return c(()=>{if(!n)return;let e=a.current?.querySelector(`#node-card-${CSS.escape(n)}`);e&&e.scrollIntoView({behavior:`smooth`,block:`start`})},[n,r]),s(`div`,{ref:a,className:`flex flex-col gap-4`,children:i.map(e=>s(`div`,{id:`node-card-${e.id}`,children:s(Ee,{node:e})},e.id))})}n();function Oe(e){let[t,n]=o(()=>typeof window<`u`?window.matchMedia(e).matches:!1);return c(()=>{let t=window.matchMedia(e),r=e=>n(e.matches);return t.addEventListener(`change`,r),()=>t.removeEventListener(`change`,r)},[e]),t}function ke(){let{data:e,isLoading:t}=C(void 0,{staleTime:1/0}),[n,r]=o(null);return _(`cluster.topology-snapshot`,e=>{let t=e.data?.nodes;Array.isArray(t)&&r(t)}),{nodes:i(()=>n??e??[],[n,e]),isLoading:t&&!n}}function Ae(){let{t}=H(),n=A(),[a,c]=o(`table`),[l,u]=o(void 0),[d,f]=o(0),p=Oe(`(max-width: 767px)`),m=p&&a===`graph`?`table`:a,{nodes:g,isLoading:_}=ke(),v=i(()=>K(g),[g]),y=i(()=>g.filter(e=>e.isOnline),[g]),b=y.length,x=g.filter(e=>!e.isOnline).length,S=h(),[C,w]=o(!1),T=e(async()=>{let e=[...y].sort((e,t)=>e.isHub===t.isHub?0:e.isHub?1:-1);if(await n({title:t(`serverManagement.confirmUpdateAllTitle`,`Update all nodes`),message:t(`serverManagement.confirmUpdateAllBody`,`Update and restart every online node, agents first, hub last. Up-to-date nodes are skipped; this page reconnects when the hub comes back.`),confirmLabel:t(`serverManagement.confirmUpdateAllAction`,`Update all & restart`),variant:`warning`})){w(!0);try{for(let t of e)try{await S.mutateAsync(t.isHub?{}:{nodeId:t.id})}catch{}}finally{w(!1)}}},[S,n,y,t]),E=e(e=>{c(`table`),u(e),f(e=>e+1)},[]),D=(e,t,n)=>r(`button`,{onClick:()=>c(e),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-colors ${a===e?`bg-primary text-primary-foreground`:`text-muted-foreground hover:text-foreground`}`,children:[s(n,{className:`h-3.5 w-3.5`}),t]});return r(`div`,{className:`flex flex-col h-full gap-4 p-4`,children:[r(`div`,{className:`flex items-center justify-between gap-2 flex-wrap`,children:[r(`div`,{className:`flex items-center gap-2`,children:[b>0&&r(`span`,{className:`text-xs px-2 py-0.5 rounded-full bg-success/10 text-success`,children:[b,` online`]}),x>0&&r(`span`,{className:`text-xs px-2 py-0.5 rounded-full bg-destructive/10 text-destructive`,children:[x,` offline`]})]}),r(`div`,{className:`flex items-center gap-2`,children:[b>1&&r(`button`,{type:`button`,className:`inline-flex items-center gap-1.5 rounded bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50`,disabled:C,title:t(`serverManagement.updateAllHint`,`Sequenced agents-first, hub-last — up-to-date nodes are skipped.`),onClick:()=>void T(),children:[C?s(U,{className:`h-3.5 w-3.5 animate-spin`}):s(Y,{className:`h-3.5 w-3.5`}),t(`serverManagement.updateAll`,`Update all nodes`)]}),r(`div`,{className:`flex gap-0.5 p-1 rounded-lg bg-muted`,children:[D(`table`,`Table`,ue),!p&&D(`graph`,`Graph`,se)]})]})]}),_?s(`div`,{className:`flex items-center justify-center flex-1 text-muted-foreground`,children:`Loading cluster topology...`}):m===`graph`?s(G,{graph:v,onOpenNodeDetail:E}):s(`div`,{className:`flex-1 overflow-auto`,children:s(De,{nodes:g,focusNodeId:l,focusNonce:d})})]})}export{Ae as ClusterPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{q as e}from"./index-DmGVQVip.js";var t=e(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{q as e}from"./index-DmGVQVip.js";var t=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`polyline`,{points:`12 6 12 12 16 14`,key:`68esgv`}]]);export{t};
|