@camstack/addon-terminal 0.1.26 → 0.1.28
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/addon.js +438 -228
- package/dist/addon.mjs +438 -228
- package/package.json +1 -1
package/dist/addon.mjs
CHANGED
|
@@ -7642,7 +7642,7 @@ var RecordingBandSchema = object({
|
|
|
7642
7642
|
postBufferSec: number().min(0).optional()
|
|
7643
7643
|
});
|
|
7644
7644
|
({
|
|
7645
|
-
preBufferSec:
|
|
7645
|
+
preBufferSec: 15,
|
|
7646
7646
|
postBufferSec: 30
|
|
7647
7647
|
}).postBufferSec * 1e3;
|
|
7648
7648
|
/**
|
|
@@ -13790,128 +13790,103 @@ var COCO_TO_MACRO = {
|
|
|
13790
13790
|
var AUDIO_MACRO_LABELS = [
|
|
13791
13791
|
{
|
|
13792
13792
|
id: "speech",
|
|
13793
|
-
name: "Speech"
|
|
13794
|
-
icon: "🗣️"
|
|
13793
|
+
name: "Speech"
|
|
13795
13794
|
},
|
|
13796
13795
|
{
|
|
13797
13796
|
id: "scream",
|
|
13798
|
-
name: "Scream / Shout"
|
|
13799
|
-
icon: "😱"
|
|
13797
|
+
name: "Scream / Shout"
|
|
13800
13798
|
},
|
|
13801
13799
|
{
|
|
13802
13800
|
id: "crying",
|
|
13803
|
-
name: "Crying / Baby"
|
|
13804
|
-
icon: "😢"
|
|
13801
|
+
name: "Crying / Baby"
|
|
13805
13802
|
},
|
|
13806
13803
|
{
|
|
13807
13804
|
id: "laughter",
|
|
13808
|
-
name: "Laughter"
|
|
13809
|
-
icon: "😂"
|
|
13805
|
+
name: "Laughter"
|
|
13810
13806
|
},
|
|
13811
13807
|
{
|
|
13812
13808
|
id: "music",
|
|
13813
|
-
name: "Music"
|
|
13814
|
-
icon: "🎵"
|
|
13809
|
+
name: "Music"
|
|
13815
13810
|
},
|
|
13816
13811
|
{
|
|
13817
13812
|
id: "dog",
|
|
13818
|
-
name: "Dog"
|
|
13819
|
-
icon: "🐕"
|
|
13813
|
+
name: "Dog"
|
|
13820
13814
|
},
|
|
13821
13815
|
{
|
|
13822
13816
|
id: "cat",
|
|
13823
|
-
name: "Cat"
|
|
13824
|
-
icon: "🐈"
|
|
13817
|
+
name: "Cat"
|
|
13825
13818
|
},
|
|
13826
13819
|
{
|
|
13827
13820
|
id: "bird",
|
|
13828
|
-
name: "Bird"
|
|
13829
|
-
icon: "🐦"
|
|
13821
|
+
name: "Bird"
|
|
13830
13822
|
},
|
|
13831
13823
|
{
|
|
13832
13824
|
id: "animal",
|
|
13833
|
-
name: "Animal (other)"
|
|
13834
|
-
icon: "🐾"
|
|
13825
|
+
name: "Animal (other)"
|
|
13835
13826
|
},
|
|
13836
13827
|
{
|
|
13837
13828
|
id: "alarm",
|
|
13838
|
-
name: "Alarm / Siren"
|
|
13839
|
-
icon: "🚨"
|
|
13829
|
+
name: "Alarm / Siren"
|
|
13840
13830
|
},
|
|
13841
13831
|
{
|
|
13842
13832
|
id: "doorbell",
|
|
13843
|
-
name: "Doorbell / Knock"
|
|
13844
|
-
icon: "🔔"
|
|
13833
|
+
name: "Doorbell / Knock"
|
|
13845
13834
|
},
|
|
13846
13835
|
{
|
|
13847
13836
|
id: "glass_breaking",
|
|
13848
|
-
name: "Glass Breaking"
|
|
13849
|
-
icon: "💥"
|
|
13837
|
+
name: "Glass Breaking"
|
|
13850
13838
|
},
|
|
13851
13839
|
{
|
|
13852
13840
|
id: "gunshot",
|
|
13853
|
-
name: "Gunshot / Explosion"
|
|
13854
|
-
icon: "💣"
|
|
13841
|
+
name: "Gunshot / Explosion"
|
|
13855
13842
|
},
|
|
13856
13843
|
{
|
|
13857
13844
|
id: "vehicle",
|
|
13858
|
-
name: "Vehicle"
|
|
13859
|
-
icon: "🚗"
|
|
13845
|
+
name: "Vehicle"
|
|
13860
13846
|
},
|
|
13861
13847
|
{
|
|
13862
13848
|
id: "siren",
|
|
13863
|
-
name: "Emergency Siren"
|
|
13864
|
-
icon: "🚑"
|
|
13849
|
+
name: "Emergency Siren"
|
|
13865
13850
|
},
|
|
13866
13851
|
{
|
|
13867
13852
|
id: "fire",
|
|
13868
|
-
name: "Fire / Smoke"
|
|
13869
|
-
icon: "🔥"
|
|
13853
|
+
name: "Fire / Smoke"
|
|
13870
13854
|
},
|
|
13871
13855
|
{
|
|
13872
13856
|
id: "water",
|
|
13873
|
-
name: "Water"
|
|
13874
|
-
icon: "💧"
|
|
13857
|
+
name: "Water"
|
|
13875
13858
|
},
|
|
13876
13859
|
{
|
|
13877
13860
|
id: "wind",
|
|
13878
|
-
name: "Wind / Weather"
|
|
13879
|
-
icon: "🌬️"
|
|
13861
|
+
name: "Wind / Weather"
|
|
13880
13862
|
},
|
|
13881
13863
|
{
|
|
13882
13864
|
id: "door",
|
|
13883
|
-
name: "Door"
|
|
13884
|
-
icon: "🚪"
|
|
13865
|
+
name: "Door"
|
|
13885
13866
|
},
|
|
13886
13867
|
{
|
|
13887
13868
|
id: "footsteps",
|
|
13888
|
-
name: "Footsteps"
|
|
13889
|
-
icon: "👣"
|
|
13869
|
+
name: "Footsteps"
|
|
13890
13870
|
},
|
|
13891
13871
|
{
|
|
13892
13872
|
id: "crowd",
|
|
13893
|
-
name: "Crowd / Chatter"
|
|
13894
|
-
icon: "👥"
|
|
13873
|
+
name: "Crowd / Chatter"
|
|
13895
13874
|
},
|
|
13896
13875
|
{
|
|
13897
13876
|
id: "telephone",
|
|
13898
|
-
name: "Telephone"
|
|
13899
|
-
icon: "📞"
|
|
13877
|
+
name: "Telephone"
|
|
13900
13878
|
},
|
|
13901
13879
|
{
|
|
13902
13880
|
id: "engine",
|
|
13903
|
-
name: "Engine / Motor"
|
|
13904
|
-
icon: "⚙️"
|
|
13881
|
+
name: "Engine / Motor"
|
|
13905
13882
|
},
|
|
13906
13883
|
{
|
|
13907
13884
|
id: "tools",
|
|
13908
|
-
name: "Tools / Construction"
|
|
13909
|
-
icon: "🔨"
|
|
13885
|
+
name: "Tools / Construction"
|
|
13910
13886
|
},
|
|
13911
13887
|
{
|
|
13912
13888
|
id: "silence",
|
|
13913
|
-
name: "Silence"
|
|
13914
|
-
icon: "🤫"
|
|
13889
|
+
name: "Silence"
|
|
13915
13890
|
}
|
|
13916
13891
|
];
|
|
13917
13892
|
var YAMNET_TO_MACRO = {
|
|
@@ -16413,7 +16388,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16413
16388
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16414
16389
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16415
16390
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16416
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16391
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16417
16392
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16418
16393
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16419
16394
|
* (`getObjectEvents` et al.).
|
|
@@ -16708,6 +16683,35 @@ var TrackSchema = object({
|
|
|
16708
16683
|
*/
|
|
16709
16684
|
hasFace: boolean().optional(),
|
|
16710
16685
|
/**
|
|
16686
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16687
|
+
* face an operator could ASSIGN to an identity.
|
|
16688
|
+
*
|
|
16689
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16690
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16691
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16692
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16693
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16694
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16695
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16696
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16697
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16698
|
+
* operator something to assign and delivers nothing.
|
|
16699
|
+
*
|
|
16700
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16701
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16702
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16703
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16704
|
+
*
|
|
16705
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16706
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16707
|
+
*
|
|
16708
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16709
|
+
* before the column omits it, and so does every server that predates the
|
|
16710
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16711
|
+
* never infer "no assignable face".
|
|
16712
|
+
*/
|
|
16713
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16714
|
+
/**
|
|
16711
16715
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16712
16716
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16713
16717
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -18097,6 +18101,32 @@ var DetailResultSchema = object({
|
|
|
18097
18101
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
18098
18102
|
bbox: NativeCropBboxSchema.optional(),
|
|
18099
18103
|
embedding: string().optional(),
|
|
18104
|
+
/**
|
|
18105
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
18106
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
18107
|
+
* the consuming gate treats as accept — never as reject.
|
|
18108
|
+
*/
|
|
18109
|
+
embeddingMagnitude: number().optional(),
|
|
18110
|
+
/**
|
|
18111
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
18112
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
18113
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
18114
|
+
* the inference this model exists to forbid.
|
|
18115
|
+
*
|
|
18116
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
18117
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
18118
|
+
* its previous assumption instead of refusing.
|
|
18119
|
+
*
|
|
18120
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
18121
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
18122
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
18123
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
18124
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
18125
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
18126
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
18127
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
18128
|
+
*/
|
|
18129
|
+
embeddingModelId: string().optional(),
|
|
18100
18130
|
label: string().optional(),
|
|
18101
18131
|
/**
|
|
18102
18132
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -18972,6 +19002,12 @@ var CameraStatusSchema = object({
|
|
|
18972
19002
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
18973
19003
|
fetchedAt: number()
|
|
18974
19004
|
});
|
|
19005
|
+
var InferenceDeviceExclusionReasonSchema = _enum([
|
|
19006
|
+
"disabled",
|
|
19007
|
+
"unavailable",
|
|
19008
|
+
"cannot-host-camera-root",
|
|
19009
|
+
"accelerator-preferred"
|
|
19010
|
+
]);
|
|
18975
19011
|
var NodeInferenceDeviceSchema = object({
|
|
18976
19012
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
18977
19013
|
key: string(),
|
|
@@ -19002,7 +19038,17 @@ var NodeInferenceDeviceSchema = object({
|
|
|
19002
19038
|
* available per format; this is the stored selection that becomes the
|
|
19003
19039
|
* default for EVERY camera landing on this accelerator.
|
|
19004
19040
|
*/
|
|
19005
|
-
steps: record(string(), DeviceStepConfigSchema).optional()
|
|
19041
|
+
steps: record(string(), DeviceStepConfigSchema).optional(),
|
|
19042
|
+
/**
|
|
19043
|
+
* `null` when the device IS a camera-root candidate on this node; otherwise
|
|
19044
|
+
* the reason the dispatcher drops it. Computed by the SAME
|
|
19045
|
+
* `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
|
|
19046
|
+
* never disagree with the election — deriving it in the UI from
|
|
19047
|
+
* `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
|
|
19048
|
+
* the node's model catalog) and `accelerator-preferred` (needs the node-wide
|
|
19049
|
+
* "an accelerator is serving" predicate).
|
|
19050
|
+
*/
|
|
19051
|
+
exclusion: InferenceDeviceExclusionReasonSchema.nullable()
|
|
19006
19052
|
});
|
|
19007
19053
|
var NodeInferenceDevicesSchema = object({
|
|
19008
19054
|
nodeId: string(),
|
|
@@ -19561,6 +19607,7 @@ var snapshotCapability = {
|
|
|
19561
19607
|
isBattery: boolean(),
|
|
19562
19608
|
reason: _enum([
|
|
19563
19609
|
"disabled",
|
|
19610
|
+
"offline",
|
|
19564
19611
|
"sleeping",
|
|
19565
19612
|
"unreachable",
|
|
19566
19613
|
"waking"
|
|
@@ -19650,9 +19697,17 @@ targets: array(object({
|
|
|
19650
19697
|
sleeping: boolean(),
|
|
19651
19698
|
/** Current device state rendered over the cached frame. State images
|
|
19652
19699
|
* remain authoritative even when their photographic background is
|
|
19653
|
-
* old; null means the link must carry a current camera frame.
|
|
19700
|
+
* old; null means the link must carry a current camera frame.
|
|
19701
|
+
*
|
|
19702
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19703
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19704
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19705
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19706
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19707
|
+
* state. */
|
|
19654
19708
|
stateReason: _enum([
|
|
19655
19709
|
"disabled",
|
|
19710
|
+
"offline",
|
|
19656
19711
|
"sleeping",
|
|
19657
19712
|
"unreachable",
|
|
19658
19713
|
"waking"
|
|
@@ -23991,7 +24046,12 @@ var ListResultSchema = object({
|
|
|
23991
24046
|
probedAt: number()
|
|
23992
24047
|
});
|
|
23993
24048
|
var PreferredSchema = LocalInterfaceSchema.nullable();
|
|
23994
|
-
|
|
24049
|
+
/**
|
|
24050
|
+
* Candidate base URL for the SDK to race on connect. Order matters —
|
|
24051
|
+
* the SDK should attempt these top-to-bottom with a short per-candidate
|
|
24052
|
+
* timeout (e.g. 1500ms) and cache the winner for the session.
|
|
24053
|
+
*/
|
|
24054
|
+
var ConnectionEndpointSchema = object({
|
|
23995
24055
|
/** Operator-facing label (e.g. "LAN — en0", "Public tunnel"). */
|
|
23996
24056
|
label: string(),
|
|
23997
24057
|
/** Fully-formed base URL with scheme + host + port. */
|
|
@@ -24034,7 +24094,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
|
|
|
24034
24094
|
* ordering between polls.
|
|
24035
24095
|
*/
|
|
24036
24096
|
priority: number()
|
|
24037
|
-
})
|
|
24097
|
+
});
|
|
24098
|
+
/**
|
|
24099
|
+
* Where the advertised local port came from. Ordered most → least
|
|
24100
|
+
* authoritative, and the whole point of returning it: a client must be able to
|
|
24101
|
+
* tell a FACT about the hub's socket from an echo of its own guess.
|
|
24102
|
+
*/
|
|
24103
|
+
var LocalPortSourceEnum = _enum([
|
|
24104
|
+
"server-config",
|
|
24105
|
+
"server-env",
|
|
24106
|
+
"caller-hint",
|
|
24107
|
+
"default"
|
|
24108
|
+
]);
|
|
24109
|
+
/** The port every LAN/loopback `baseUrl` in the same result was built with. */
|
|
24110
|
+
var AdvertisedLocalPortSchema = object({
|
|
24111
|
+
port: number().int().min(1).max(65535),
|
|
24112
|
+
source: LocalPortSourceEnum
|
|
24113
|
+
});
|
|
24114
|
+
var GetConnectionEndpointsResultSchema = object({
|
|
24115
|
+
endpoints: array(ConnectionEndpointSchema).readonly(),
|
|
24116
|
+
/**
|
|
24117
|
+
* The port the hub built the LAN/loopback URLs with, and where that number
|
|
24118
|
+
* came from.
|
|
24119
|
+
*
|
|
24120
|
+
* Returned rather than merely applied, because "the URL is right" and "the
|
|
24121
|
+
* client can KNOW the URL is right" are different properties. A client that
|
|
24122
|
+
* only sees a corrected URL cannot distinguish a hub that fixed the port from
|
|
24123
|
+
* a hub that echoed the port the client sent, so it cannot decide whether to
|
|
24124
|
+
* race the candidate or discard it. With `source` it can: anything but
|
|
24125
|
+
* `caller-hint` is the hub's own socket.
|
|
24126
|
+
*
|
|
24127
|
+
* Absent on hubs predating this field — a client that finds it missing is
|
|
24128
|
+
* talking to an echoing hub and must degrade exactly as it does for
|
|
24129
|
+
* `caller-hint`.
|
|
24130
|
+
*/
|
|
24131
|
+
localPort: AdvertisedLocalPortSchema
|
|
24132
|
+
});
|
|
24038
24133
|
/**
|
|
24039
24134
|
* The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
|
|
24040
24135
|
* AUTO (resolved from the candidate ranking at send time); `resolved` reports
|
|
@@ -24055,8 +24150,13 @@ var AllowedAddressesSchema = object({
|
|
|
24055
24150
|
*/
|
|
24056
24151
|
addresses: array(string()).readonly() });
|
|
24057
24152
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24058
|
-
/**
|
|
24059
|
-
|
|
24153
|
+
/**
|
|
24154
|
+
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
24155
|
+
* written against the echoing contract keep working; the hub uses it
|
|
24156
|
+
* only when it cannot read its own port, and says so via
|
|
24157
|
+
* `localPort.source === 'caller-hint'`.
|
|
24158
|
+
*/
|
|
24159
|
+
port: number().int().min(1).max(65535).optional(),
|
|
24060
24160
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
24061
24161
|
* candidate. Default `true`. */
|
|
24062
24162
|
includeLoopback: boolean().optional(),
|
|
@@ -37242,7 +37342,6 @@ var NC_AUDIO_DEFAULTS = {
|
|
|
37242
37342
|
hitPercent: 60,
|
|
37243
37343
|
samplingSeconds: 10
|
|
37244
37344
|
};
|
|
37245
|
-
new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
|
|
37246
37345
|
new Set(["devices", "classes"]);
|
|
37247
37346
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
37248
37347
|
/**
|
|
@@ -37476,6 +37575,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
37476
37575
|
createdAt: number(),
|
|
37477
37576
|
updatedAt: number()
|
|
37478
37577
|
});
|
|
37578
|
+
Object.freeze(Object.fromEntries([{
|
|
37579
|
+
stepId: "face-embedding",
|
|
37580
|
+
label: "Face recognition model",
|
|
37581
|
+
defaultModelId: "arcface-r100",
|
|
37582
|
+
indexName: "the enrolled face gallery",
|
|
37583
|
+
options: [
|
|
37584
|
+
{
|
|
37585
|
+
id: "arcface-r100",
|
|
37586
|
+
label: "ArcFace (ResNet34)"
|
|
37587
|
+
},
|
|
37588
|
+
{
|
|
37589
|
+
id: "auraface-r100",
|
|
37590
|
+
label: "AuraFace R100"
|
|
37591
|
+
},
|
|
37592
|
+
{
|
|
37593
|
+
id: "inception-resnet-v1",
|
|
37594
|
+
label: "Inception ResNet V1"
|
|
37595
|
+
}
|
|
37596
|
+
]
|
|
37597
|
+
}, {
|
|
37598
|
+
stepId: "clip-embedding",
|
|
37599
|
+
label: "Semantic search model",
|
|
37600
|
+
defaultModelId: "mobileclip-s1",
|
|
37601
|
+
indexName: "the object semantic-search index",
|
|
37602
|
+
options: [{
|
|
37603
|
+
id: "mobileclip-s1",
|
|
37604
|
+
label: "MobileCLIP S1"
|
|
37605
|
+
}, {
|
|
37606
|
+
id: "mobileclip-s2",
|
|
37607
|
+
label: "MobileCLIP S2"
|
|
37608
|
+
}]
|
|
37609
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
37610
|
+
string().min(1);
|
|
37479
37611
|
object({
|
|
37480
37612
|
/**
|
|
37481
37613
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -37496,10 +37628,21 @@ object({
|
|
|
37496
37628
|
*/
|
|
37497
37629
|
square: boolean()
|
|
37498
37630
|
});
|
|
37499
|
-
|
|
37631
|
+
/**
|
|
37632
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
37633
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
37634
|
+
*/
|
|
37635
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
37500
37636
|
paddingRatio: .15,
|
|
37501
37637
|
square: false
|
|
37502
|
-
}
|
|
37638
|
+
};
|
|
37639
|
+
Object.freeze({
|
|
37640
|
+
x: 0,
|
|
37641
|
+
y: 0,
|
|
37642
|
+
w: 1,
|
|
37643
|
+
h: 1
|
|
37644
|
+
});
|
|
37645
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
37503
37646
|
/**
|
|
37504
37647
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
37505
37648
|
*
|
|
@@ -44111,6 +44254,38 @@ var TerminalSessionManager = class {
|
|
|
44111
44254
|
* (`node-pty`) and should update via `camstack deploy` independently of the
|
|
44112
44255
|
* framework, exactly like the node-av decoder addon.
|
|
44113
44256
|
*/
|
|
44257
|
+
/**
|
|
44258
|
+
* Default argv for the Glances profile — deliberately EMPTY.
|
|
44259
|
+
*
|
|
44260
|
+
* Measured on the hub (2026-08-21, glances 4.5.6, embedded Python, a real pty
|
|
44261
|
+
* at the terminal camera's own 120x40 grid, CPU sampled from
|
|
44262
|
+
* /proc/<pid>/{utime,stime} so the number is the process's own and not the
|
|
44263
|
+
* box's contention):
|
|
44264
|
+
*
|
|
44265
|
+
* argv CPU (of one core)
|
|
44266
|
+
* (none — this default) 0.8 %
|
|
44267
|
+
* -t 3 0.7 %
|
|
44268
|
+
* -t 5 0.6 %
|
|
44269
|
+
* --disable-plugin processlist 0.7 %
|
|
44270
|
+
* --disable-plugin containers 0.9 %
|
|
44271
|
+
* --disable-plugin sensors 0.8 %
|
|
44272
|
+
* --disable-process 0.8 %
|
|
44273
|
+
* -t 3 --disable-plugin processlist,containers,sensors 0.5 %
|
|
44274
|
+
* -t 5 --disable-plugin processlist,containers,sensors 0.4 %
|
|
44275
|
+
*
|
|
44276
|
+
* Startup costs 0.19 core-seconds; steady state is 1.0 % of one core at 36 MB
|
|
44277
|
+
* RSS. The whole tuning range is worth ~0.4 % of ONE core out of 20 — below the
|
|
44278
|
+
* noise floor of a box that idles at 2.6 cores — while every entry that buys
|
|
44279
|
+
* something removes a panel the operator opened the camera to read. `-t` is
|
|
44280
|
+
* additionally counter-productive here: the terminal camera renders at 2 FPS
|
|
44281
|
+
* and glances already repaints every 2 s, so slowing glances only makes the
|
|
44282
|
+
* camera show stale numbers.
|
|
44283
|
+
*
|
|
44284
|
+
* So the default ships empty and the knob stays in front of the operator.
|
|
44285
|
+
* Anyone who does want to trade panels for CPU has the numbers above.
|
|
44286
|
+
*/
|
|
44287
|
+
var DEFAULT_GLANCES_ARGS = [];
|
|
44288
|
+
var GLANCES_ARGS_DESCRIPTION = "Exact arguments passed to Glances. One tag per argv entry. Empty is the measured-best default: at the camera grid Glances costs ~1% of one core, and the cheapest tuning found (`-t 5 --disable-plugin processlist,containers,sensors`) saves only ~0.4% of one core while removing the panels most people open it for. `-t` also makes the camera show stale numbers — it renders at 2 FPS and Glances already repaints every 2s.";
|
|
44114
44289
|
var DEFAULTS = {
|
|
44115
44290
|
btmPath: "",
|
|
44116
44291
|
btmEnabled: true,
|
|
@@ -44120,7 +44295,7 @@ var DEFAULTS = {
|
|
|
44120
44295
|
topArgs: [],
|
|
44121
44296
|
glancesEnabled: true,
|
|
44122
44297
|
glancesPath: "",
|
|
44123
|
-
glancesArgs:
|
|
44298
|
+
glancesArgs: DEFAULT_GLANCES_ARGS,
|
|
44124
44299
|
allowShell: false,
|
|
44125
44300
|
shellPath: "",
|
|
44126
44301
|
maxSessions: 4,
|
|
@@ -44507,85 +44682,13 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44507
44682
|
return this.instanceInfo(instance);
|
|
44508
44683
|
}
|
|
44509
44684
|
globalSettingsSchema() {
|
|
44510
|
-
return this.schema({ sections: [
|
|
44511
|
-
|
|
44512
|
-
|
|
44513
|
-
|
|
44514
|
-
|
|
44515
|
-
|
|
44516
|
-
this.field({
|
|
44517
|
-
type: "boolean",
|
|
44518
|
-
key: "btmEnabled",
|
|
44519
|
-
label: "Enable BTM camera",
|
|
44520
|
-
default: true,
|
|
44521
|
-
perNode: true
|
|
44522
|
-
}),
|
|
44523
|
-
this.field({
|
|
44524
|
-
type: "text",
|
|
44525
|
-
key: "btmPath",
|
|
44526
|
-
label: "BTM binary",
|
|
44527
|
-
description: "Path to the `btm` (bottom) executable. Leave empty to resolve from PATH.",
|
|
44528
|
-
placeholder: "btm",
|
|
44529
|
-
default: "",
|
|
44530
|
-
perNode: true
|
|
44531
|
-
}),
|
|
44532
|
-
this.field({
|
|
44533
|
-
type: "tags",
|
|
44534
|
-
key: "btmArgs",
|
|
44535
|
-
label: "BTM arguments",
|
|
44536
|
-
description: "Exact arguments passed to btm.",
|
|
44537
|
-
default: [],
|
|
44538
|
-
perNode: true
|
|
44539
|
-
}),
|
|
44540
|
-
this.field({
|
|
44541
|
-
type: "boolean",
|
|
44542
|
-
key: "topEnabled",
|
|
44543
|
-
label: "Enable Top camera",
|
|
44544
|
-
default: true,
|
|
44545
|
-
perNode: true
|
|
44546
|
-
}),
|
|
44547
|
-
this.field({
|
|
44548
|
-
type: "text",
|
|
44549
|
-
key: "topPath",
|
|
44550
|
-
label: "Top binary",
|
|
44551
|
-
placeholder: "top",
|
|
44552
|
-
default: "",
|
|
44553
|
-
perNode: true
|
|
44554
|
-
}),
|
|
44555
|
-
this.field({
|
|
44556
|
-
type: "tags",
|
|
44557
|
-
key: "topArgs",
|
|
44558
|
-
label: "Top arguments",
|
|
44559
|
-
description: "Exact arguments passed to top.",
|
|
44560
|
-
default: [],
|
|
44561
|
-
perNode: true
|
|
44562
|
-
}),
|
|
44563
|
-
this.field({
|
|
44564
|
-
type: "boolean",
|
|
44565
|
-
key: "glancesEnabled",
|
|
44566
|
-
label: "Enable Glances camera",
|
|
44567
|
-
description: "Glances is installed automatically into CamStack embedded Python.",
|
|
44568
|
-
default: true,
|
|
44569
|
-
perNode: true
|
|
44570
|
-
}),
|
|
44571
|
-
this.field({
|
|
44572
|
-
type: "text",
|
|
44573
|
-
key: "glancesPath",
|
|
44574
|
-
label: "Glances binary override",
|
|
44575
|
-
description: "Optional executable override. Empty uses the automatically managed Python package.",
|
|
44576
|
-
placeholder: "glances",
|
|
44577
|
-
default: "",
|
|
44578
|
-
perNode: true
|
|
44579
|
-
}),
|
|
44580
|
-
this.field({
|
|
44581
|
-
type: "tags",
|
|
44582
|
-
key: "glancesArgs",
|
|
44583
|
-
label: "Glances arguments",
|
|
44584
|
-
description: "Exact arguments passed to Glances.",
|
|
44585
|
-
default: [],
|
|
44586
|
-
perNode: true
|
|
44587
|
-
}),
|
|
44588
|
-
this.field({
|
|
44685
|
+
return this.schema({ sections: [
|
|
44686
|
+
{
|
|
44687
|
+
id: "terminal",
|
|
44688
|
+
title: "Terminal",
|
|
44689
|
+
description: "Interactive terminal sessions in the Admin UI. Only pre-declared profiles can be opened; a free-form command is never accepted. Every setting below is per node — the values you see belong to the node selected above.",
|
|
44690
|
+
columns: 2,
|
|
44691
|
+
fields: [this.field({
|
|
44589
44692
|
type: "number",
|
|
44590
44693
|
key: "maxSessions",
|
|
44591
44694
|
label: "Max concurrent sessions",
|
|
@@ -44594,16 +44697,122 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44594
44697
|
step: 1,
|
|
44595
44698
|
default: 4,
|
|
44596
44699
|
perNode: true
|
|
44597
|
-
})
|
|
44598
|
-
|
|
44700
|
+
})]
|
|
44701
|
+
},
|
|
44702
|
+
{
|
|
44703
|
+
id: "terminal-btm",
|
|
44704
|
+
title: "BTM camera",
|
|
44705
|
+
description: "bottom (btm) — CPU, memory, network and process monitor.",
|
|
44706
|
+
columns: 2,
|
|
44707
|
+
fields: [
|
|
44708
|
+
this.field({
|
|
44709
|
+
type: "boolean",
|
|
44710
|
+
key: "btmEnabled",
|
|
44711
|
+
label: "Enabled",
|
|
44712
|
+
description: "Offer the BTM profile on this node.",
|
|
44713
|
+
default: true,
|
|
44714
|
+
perNode: true
|
|
44715
|
+
}),
|
|
44716
|
+
this.field({
|
|
44717
|
+
type: "text",
|
|
44718
|
+
key: "btmPath",
|
|
44719
|
+
label: "Binary",
|
|
44720
|
+
description: "Path to the `btm` (bottom) executable. Leave empty to resolve from PATH.",
|
|
44721
|
+
placeholder: "btm",
|
|
44722
|
+
default: "",
|
|
44723
|
+
perNode: true
|
|
44724
|
+
}),
|
|
44725
|
+
this.field({
|
|
44726
|
+
type: "tags",
|
|
44727
|
+
key: "btmArgs",
|
|
44728
|
+
label: "Arguments",
|
|
44729
|
+
description: "Exact arguments passed to btm. One tag per argv entry.",
|
|
44730
|
+
default: [],
|
|
44731
|
+
perNode: true,
|
|
44732
|
+
span: 2
|
|
44733
|
+
})
|
|
44734
|
+
]
|
|
44735
|
+
},
|
|
44736
|
+
{
|
|
44737
|
+
id: "terminal-top",
|
|
44738
|
+
title: "Top camera",
|
|
44739
|
+
description: "The operating system process and resource monitor.",
|
|
44740
|
+
columns: 2,
|
|
44741
|
+
fields: [
|
|
44742
|
+
this.field({
|
|
44743
|
+
type: "boolean",
|
|
44744
|
+
key: "topEnabled",
|
|
44745
|
+
label: "Enabled",
|
|
44746
|
+
description: "Offer the Top profile on this node.",
|
|
44747
|
+
default: true,
|
|
44748
|
+
perNode: true
|
|
44749
|
+
}),
|
|
44750
|
+
this.field({
|
|
44751
|
+
type: "text",
|
|
44752
|
+
key: "topPath",
|
|
44753
|
+
label: "Binary",
|
|
44754
|
+
placeholder: "top",
|
|
44755
|
+
default: "",
|
|
44756
|
+
perNode: true
|
|
44757
|
+
}),
|
|
44758
|
+
this.field({
|
|
44759
|
+
type: "tags",
|
|
44760
|
+
key: "topArgs",
|
|
44761
|
+
label: "Arguments",
|
|
44762
|
+
description: "Exact arguments passed to top. One tag per argv entry.",
|
|
44763
|
+
default: [],
|
|
44764
|
+
perNode: true,
|
|
44765
|
+
span: 2
|
|
44766
|
+
})
|
|
44767
|
+
]
|
|
44768
|
+
},
|
|
44769
|
+
{
|
|
44770
|
+
id: "terminal-glances",
|
|
44771
|
+
title: "Glances camera",
|
|
44772
|
+
description: "Cross-platform curses monitor, installed automatically into CamStack embedded Python. Glances is the most expensive built-in profile — it only runs while somebody is watching, but while it runs it costs real CPU. See the Arguments help below before widening it.",
|
|
44773
|
+
columns: 2,
|
|
44774
|
+
fields: [
|
|
44775
|
+
this.field({
|
|
44776
|
+
type: "boolean",
|
|
44777
|
+
key: "glancesEnabled",
|
|
44778
|
+
label: "Enabled",
|
|
44779
|
+
description: "Offer the Glances profile on this node.",
|
|
44780
|
+
default: true,
|
|
44781
|
+
perNode: true
|
|
44782
|
+
}),
|
|
44783
|
+
this.field({
|
|
44784
|
+
type: "text",
|
|
44785
|
+
key: "glancesPath",
|
|
44786
|
+
label: "Binary override",
|
|
44787
|
+
description: "Optional executable override. Empty uses the automatically managed Python package.",
|
|
44788
|
+
placeholder: "glances",
|
|
44789
|
+
default: "",
|
|
44790
|
+
perNode: true
|
|
44791
|
+
}),
|
|
44792
|
+
this.field({
|
|
44793
|
+
type: "tags",
|
|
44794
|
+
key: "glancesArgs",
|
|
44795
|
+
label: "Arguments",
|
|
44796
|
+
description: GLANCES_ARGS_DESCRIPTION,
|
|
44797
|
+
default: [...DEFAULT_GLANCES_ARGS],
|
|
44798
|
+
perNode: true,
|
|
44799
|
+
span: 2
|
|
44800
|
+
})
|
|
44801
|
+
]
|
|
44802
|
+
},
|
|
44803
|
+
{
|
|
44804
|
+
id: "terminal-shell",
|
|
44805
|
+
title: "Interactive shell",
|
|
44806
|
+
description: "The one profile that is genuinely a command surface. Off by default; turning it on grants command execution as the server user to every admin.",
|
|
44807
|
+
columns: 2,
|
|
44808
|
+
fields: [this.field({
|
|
44599
44809
|
type: "boolean",
|
|
44600
44810
|
key: "allowShell",
|
|
44601
44811
|
label: "Allow interactive shell",
|
|
44602
|
-
description: "Adds a \"Shell\" profile
|
|
44812
|
+
description: "Adds a \"Shell\" profile on this node.",
|
|
44603
44813
|
default: false,
|
|
44604
44814
|
perNode: true
|
|
44605
|
-
}),
|
|
44606
|
-
this.field({
|
|
44815
|
+
}), this.field({
|
|
44607
44816
|
type: "text",
|
|
44608
44817
|
key: "shellPath",
|
|
44609
44818
|
label: "Shell binary",
|
|
@@ -44611,89 +44820,90 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44611
44820
|
placeholder: "/bin/bash",
|
|
44612
44821
|
default: "",
|
|
44613
44822
|
perNode: true
|
|
44614
|
-
})
|
|
44615
|
-
|
|
44616
|
-
|
|
44617
|
-
|
|
44618
|
-
|
|
44619
|
-
|
|
44620
|
-
|
|
44621
|
-
|
|
44622
|
-
|
|
44623
|
-
|
|
44624
|
-
|
|
44625
|
-
|
|
44626
|
-
|
|
44627
|
-
|
|
44628
|
-
|
|
44629
|
-
|
|
44630
|
-
|
|
44631
|
-
|
|
44632
|
-
|
|
44633
|
-
|
|
44634
|
-
|
|
44635
|
-
|
|
44636
|
-
|
|
44637
|
-
|
|
44638
|
-
|
|
44639
|
-
|
|
44640
|
-
},
|
|
44641
|
-
itemFields: [
|
|
44642
|
-
{
|
|
44643
|
-
type: "boolean",
|
|
44644
|
-
key: "enabled",
|
|
44645
|
-
label: "Enabled",
|
|
44646
|
-
default: true
|
|
44647
|
-
},
|
|
44648
|
-
{
|
|
44649
|
-
type: "text",
|
|
44650
|
-
key: "profileId",
|
|
44651
|
-
label: "Profile ID",
|
|
44652
|
-
description: "Stable lowercase slug, for example gpu-monitor.",
|
|
44653
|
-
required: true
|
|
44654
|
-
},
|
|
44655
|
-
{
|
|
44656
|
-
type: "text",
|
|
44657
|
-
key: "label",
|
|
44658
|
-
label: "Display name",
|
|
44659
|
-
required: true
|
|
44660
|
-
},
|
|
44661
|
-
{
|
|
44662
|
-
type: "textarea",
|
|
44663
|
-
key: "description",
|
|
44664
|
-
label: "Description",
|
|
44665
|
-
rows: 2
|
|
44666
|
-
},
|
|
44667
|
-
{
|
|
44668
|
-
type: "text",
|
|
44669
|
-
key: "executable",
|
|
44670
|
-
label: "Executable",
|
|
44671
|
-
description: "Absolute path or a binary resolved from PATH.",
|
|
44672
|
-
required: true
|
|
44673
|
-
},
|
|
44674
|
-
{
|
|
44675
|
-
type: "tags",
|
|
44676
|
-
key: "args",
|
|
44677
|
-
label: "Arguments",
|
|
44678
|
-
description: "One exact process argument per tag.",
|
|
44679
|
-
maxTags: 64
|
|
44680
|
-
},
|
|
44681
|
-
{
|
|
44682
|
-
type: "text",
|
|
44683
|
-
key: "cwd",
|
|
44684
|
-
label: "Working directory",
|
|
44685
|
-
description: "Optional working directory for this profile."
|
|
44823
|
+
})]
|
|
44824
|
+
},
|
|
44825
|
+
{
|
|
44826
|
+
id: "terminal-profiles",
|
|
44827
|
+
title: "Custom profiles",
|
|
44828
|
+
description: "Enabled profiles are available templates on this node. Create a Terminal instance on the Terminal page to declare a camera; session requests only carry the profile ID and commands cannot be overridden by clients.",
|
|
44829
|
+
columns: 1,
|
|
44830
|
+
fields: [this.field({
|
|
44831
|
+
type: "editable-array",
|
|
44832
|
+
key: "customProfiles",
|
|
44833
|
+
label: "Profiles",
|
|
44834
|
+
perNode: true,
|
|
44835
|
+
default: [],
|
|
44836
|
+
maxRows: 32,
|
|
44837
|
+
addLabel: "Add profile",
|
|
44838
|
+
emptyMessage: "No custom profiles configured.",
|
|
44839
|
+
rowTitleTemplate: "{label} — {executable}",
|
|
44840
|
+
defaultItem: {
|
|
44841
|
+
enabled: true,
|
|
44842
|
+
profileId: "",
|
|
44843
|
+
label: "",
|
|
44844
|
+
description: "",
|
|
44845
|
+
executable: "",
|
|
44846
|
+
args: [],
|
|
44847
|
+
cwd: "",
|
|
44848
|
+
environment: []
|
|
44686
44849
|
},
|
|
44687
|
-
|
|
44688
|
-
|
|
44689
|
-
|
|
44690
|
-
|
|
44691
|
-
|
|
44692
|
-
|
|
44693
|
-
|
|
44694
|
-
|
|
44695
|
-
|
|
44696
|
-
|
|
44850
|
+
itemFields: [
|
|
44851
|
+
{
|
|
44852
|
+
type: "boolean",
|
|
44853
|
+
key: "enabled",
|
|
44854
|
+
label: "Enabled",
|
|
44855
|
+
default: true
|
|
44856
|
+
},
|
|
44857
|
+
{
|
|
44858
|
+
type: "text",
|
|
44859
|
+
key: "profileId",
|
|
44860
|
+
label: "Profile ID",
|
|
44861
|
+
description: "Stable lowercase slug, for example gpu-monitor.",
|
|
44862
|
+
required: true
|
|
44863
|
+
},
|
|
44864
|
+
{
|
|
44865
|
+
type: "text",
|
|
44866
|
+
key: "label",
|
|
44867
|
+
label: "Display name",
|
|
44868
|
+
required: true
|
|
44869
|
+
},
|
|
44870
|
+
{
|
|
44871
|
+
type: "textarea",
|
|
44872
|
+
key: "description",
|
|
44873
|
+
label: "Description",
|
|
44874
|
+
rows: 2
|
|
44875
|
+
},
|
|
44876
|
+
{
|
|
44877
|
+
type: "text",
|
|
44878
|
+
key: "executable",
|
|
44879
|
+
label: "Executable",
|
|
44880
|
+
description: "Absolute path or a binary resolved from PATH.",
|
|
44881
|
+
required: true
|
|
44882
|
+
},
|
|
44883
|
+
{
|
|
44884
|
+
type: "tags",
|
|
44885
|
+
key: "args",
|
|
44886
|
+
label: "Arguments",
|
|
44887
|
+
description: "One exact process argument per tag.",
|
|
44888
|
+
maxTags: 64
|
|
44889
|
+
},
|
|
44890
|
+
{
|
|
44891
|
+
type: "text",
|
|
44892
|
+
key: "cwd",
|
|
44893
|
+
label: "Working directory",
|
|
44894
|
+
description: "Optional working directory for this profile."
|
|
44895
|
+
},
|
|
44896
|
+
{
|
|
44897
|
+
type: "tags",
|
|
44898
|
+
key: "environment",
|
|
44899
|
+
label: "Environment",
|
|
44900
|
+
description: "Optional NAME=value entries merged into the process environment.",
|
|
44901
|
+
maxTags: 64
|
|
44902
|
+
}
|
|
44903
|
+
]
|
|
44904
|
+
})]
|
|
44905
|
+
}
|
|
44906
|
+
] });
|
|
44697
44907
|
}
|
|
44698
44908
|
};
|
|
44699
44909
|
//#endregion
|