@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.js
CHANGED
|
@@ -7665,7 +7665,7 @@ var RecordingBandSchema = object({
|
|
|
7665
7665
|
postBufferSec: number().min(0).optional()
|
|
7666
7666
|
});
|
|
7667
7667
|
({
|
|
7668
|
-
preBufferSec:
|
|
7668
|
+
preBufferSec: 15,
|
|
7669
7669
|
postBufferSec: 30
|
|
7670
7670
|
}).postBufferSec * 1e3;
|
|
7671
7671
|
/**
|
|
@@ -13813,128 +13813,103 @@ var COCO_TO_MACRO = {
|
|
|
13813
13813
|
var AUDIO_MACRO_LABELS = [
|
|
13814
13814
|
{
|
|
13815
13815
|
id: "speech",
|
|
13816
|
-
name: "Speech"
|
|
13817
|
-
icon: "🗣️"
|
|
13816
|
+
name: "Speech"
|
|
13818
13817
|
},
|
|
13819
13818
|
{
|
|
13820
13819
|
id: "scream",
|
|
13821
|
-
name: "Scream / Shout"
|
|
13822
|
-
icon: "😱"
|
|
13820
|
+
name: "Scream / Shout"
|
|
13823
13821
|
},
|
|
13824
13822
|
{
|
|
13825
13823
|
id: "crying",
|
|
13826
|
-
name: "Crying / Baby"
|
|
13827
|
-
icon: "😢"
|
|
13824
|
+
name: "Crying / Baby"
|
|
13828
13825
|
},
|
|
13829
13826
|
{
|
|
13830
13827
|
id: "laughter",
|
|
13831
|
-
name: "Laughter"
|
|
13832
|
-
icon: "😂"
|
|
13828
|
+
name: "Laughter"
|
|
13833
13829
|
},
|
|
13834
13830
|
{
|
|
13835
13831
|
id: "music",
|
|
13836
|
-
name: "Music"
|
|
13837
|
-
icon: "🎵"
|
|
13832
|
+
name: "Music"
|
|
13838
13833
|
},
|
|
13839
13834
|
{
|
|
13840
13835
|
id: "dog",
|
|
13841
|
-
name: "Dog"
|
|
13842
|
-
icon: "🐕"
|
|
13836
|
+
name: "Dog"
|
|
13843
13837
|
},
|
|
13844
13838
|
{
|
|
13845
13839
|
id: "cat",
|
|
13846
|
-
name: "Cat"
|
|
13847
|
-
icon: "🐈"
|
|
13840
|
+
name: "Cat"
|
|
13848
13841
|
},
|
|
13849
13842
|
{
|
|
13850
13843
|
id: "bird",
|
|
13851
|
-
name: "Bird"
|
|
13852
|
-
icon: "🐦"
|
|
13844
|
+
name: "Bird"
|
|
13853
13845
|
},
|
|
13854
13846
|
{
|
|
13855
13847
|
id: "animal",
|
|
13856
|
-
name: "Animal (other)"
|
|
13857
|
-
icon: "🐾"
|
|
13848
|
+
name: "Animal (other)"
|
|
13858
13849
|
},
|
|
13859
13850
|
{
|
|
13860
13851
|
id: "alarm",
|
|
13861
|
-
name: "Alarm / Siren"
|
|
13862
|
-
icon: "🚨"
|
|
13852
|
+
name: "Alarm / Siren"
|
|
13863
13853
|
},
|
|
13864
13854
|
{
|
|
13865
13855
|
id: "doorbell",
|
|
13866
|
-
name: "Doorbell / Knock"
|
|
13867
|
-
icon: "🔔"
|
|
13856
|
+
name: "Doorbell / Knock"
|
|
13868
13857
|
},
|
|
13869
13858
|
{
|
|
13870
13859
|
id: "glass_breaking",
|
|
13871
|
-
name: "Glass Breaking"
|
|
13872
|
-
icon: "💥"
|
|
13860
|
+
name: "Glass Breaking"
|
|
13873
13861
|
},
|
|
13874
13862
|
{
|
|
13875
13863
|
id: "gunshot",
|
|
13876
|
-
name: "Gunshot / Explosion"
|
|
13877
|
-
icon: "💣"
|
|
13864
|
+
name: "Gunshot / Explosion"
|
|
13878
13865
|
},
|
|
13879
13866
|
{
|
|
13880
13867
|
id: "vehicle",
|
|
13881
|
-
name: "Vehicle"
|
|
13882
|
-
icon: "🚗"
|
|
13868
|
+
name: "Vehicle"
|
|
13883
13869
|
},
|
|
13884
13870
|
{
|
|
13885
13871
|
id: "siren",
|
|
13886
|
-
name: "Emergency Siren"
|
|
13887
|
-
icon: "🚑"
|
|
13872
|
+
name: "Emergency Siren"
|
|
13888
13873
|
},
|
|
13889
13874
|
{
|
|
13890
13875
|
id: "fire",
|
|
13891
|
-
name: "Fire / Smoke"
|
|
13892
|
-
icon: "🔥"
|
|
13876
|
+
name: "Fire / Smoke"
|
|
13893
13877
|
},
|
|
13894
13878
|
{
|
|
13895
13879
|
id: "water",
|
|
13896
|
-
name: "Water"
|
|
13897
|
-
icon: "💧"
|
|
13880
|
+
name: "Water"
|
|
13898
13881
|
},
|
|
13899
13882
|
{
|
|
13900
13883
|
id: "wind",
|
|
13901
|
-
name: "Wind / Weather"
|
|
13902
|
-
icon: "🌬️"
|
|
13884
|
+
name: "Wind / Weather"
|
|
13903
13885
|
},
|
|
13904
13886
|
{
|
|
13905
13887
|
id: "door",
|
|
13906
|
-
name: "Door"
|
|
13907
|
-
icon: "🚪"
|
|
13888
|
+
name: "Door"
|
|
13908
13889
|
},
|
|
13909
13890
|
{
|
|
13910
13891
|
id: "footsteps",
|
|
13911
|
-
name: "Footsteps"
|
|
13912
|
-
icon: "👣"
|
|
13892
|
+
name: "Footsteps"
|
|
13913
13893
|
},
|
|
13914
13894
|
{
|
|
13915
13895
|
id: "crowd",
|
|
13916
|
-
name: "Crowd / Chatter"
|
|
13917
|
-
icon: "👥"
|
|
13896
|
+
name: "Crowd / Chatter"
|
|
13918
13897
|
},
|
|
13919
13898
|
{
|
|
13920
13899
|
id: "telephone",
|
|
13921
|
-
name: "Telephone"
|
|
13922
|
-
icon: "📞"
|
|
13900
|
+
name: "Telephone"
|
|
13923
13901
|
},
|
|
13924
13902
|
{
|
|
13925
13903
|
id: "engine",
|
|
13926
|
-
name: "Engine / Motor"
|
|
13927
|
-
icon: "⚙️"
|
|
13904
|
+
name: "Engine / Motor"
|
|
13928
13905
|
},
|
|
13929
13906
|
{
|
|
13930
13907
|
id: "tools",
|
|
13931
|
-
name: "Tools / Construction"
|
|
13932
|
-
icon: "🔨"
|
|
13908
|
+
name: "Tools / Construction"
|
|
13933
13909
|
},
|
|
13934
13910
|
{
|
|
13935
13911
|
id: "silence",
|
|
13936
|
-
name: "Silence"
|
|
13937
|
-
icon: "🤫"
|
|
13912
|
+
name: "Silence"
|
|
13938
13913
|
}
|
|
13939
13914
|
];
|
|
13940
13915
|
var YAMNET_TO_MACRO = {
|
|
@@ -16436,7 +16411,7 @@ var TrackEnvelopeSchema = object({
|
|
|
16436
16411
|
* `snapshots[]` references — megabytes across a page of tracks. `slim`
|
|
16437
16412
|
* keeps every scalar the list surfaces actually render (ids, class(es),
|
|
16438
16413
|
* label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
|
|
16439
|
-
* zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
|
|
16414
|
+
* zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
|
|
16440
16415
|
* `snapshots` as EMPTY arrays — detail views re-fetch the full row via
|
|
16441
16416
|
* `getTrack`. Mirrors the event-store `projection` convention
|
|
16442
16417
|
* (`getObjectEvents` et al.).
|
|
@@ -16731,6 +16706,35 @@ var TrackSchema = object({
|
|
|
16731
16706
|
*/
|
|
16732
16707
|
hasFace: boolean().optional(),
|
|
16733
16708
|
/**
|
|
16709
|
+
* This track has a face row IN THE GALLERY: a crop **and** an embedding — a
|
|
16710
|
+
* face an operator could ASSIGN to an identity.
|
|
16711
|
+
*
|
|
16712
|
+
* The STRICT twin of {@link hasFace}, and the pair only earns its keep
|
|
16713
|
+
* because the two disagree. `hasFace` is stamped at the TOP of the face
|
|
16714
|
+
* branch, before every gate, and means no more than "a face detector produced
|
|
16715
|
+
* a face detail". This one is stamped at the single moment the gallery row
|
|
16716
|
+
* LANDS — after `FaceRecognizer.onTrackEnd` successfully persists it, i.e.
|
|
16717
|
+
* past the embedding-magnitude verdict, the `minFacePx` detection gate, the
|
|
16718
|
+
* candidate gate, the imageless-track drop (no crop was ever captured) and
|
|
16719
|
+
* the crop-store drop. Everything between the detector and that insert can
|
|
16720
|
+
* legitimately refuse the face, so a flag written any earlier promises the
|
|
16721
|
+
* operator something to assign and delivers nothing.
|
|
16722
|
+
*
|
|
16723
|
+
* **Independent of recognition.** A face collected but never auto-matched is
|
|
16724
|
+
* still assignable — it is in fact the face an operator most wants to reach —
|
|
16725
|
+
* so this is NOT gated on `recognizedIdentityId`. Recognition lands in
|
|
16726
|
+
* `subLabel`; this says only that the raw material exists.
|
|
16727
|
+
*
|
|
16728
|
+
* **Set once, never cleared.** A track that produced a gallery row produced
|
|
16729
|
+
* one; deleting the row later is the gallery's business, not this flag's.
|
|
16730
|
+
*
|
|
16731
|
+
* **Absent ≠ false**, the same rule as {@link hasFace}: every row written
|
|
16732
|
+
* before the column omits it, and so does every server that predates the
|
|
16733
|
+
* field. A consumer must test `=== true` and render nothing otherwise —
|
|
16734
|
+
* never infer "no assignable face".
|
|
16735
|
+
*/
|
|
16736
|
+
hasEmbeddedFace: boolean().optional(),
|
|
16737
|
+
/**
|
|
16734
16738
|
* This subject CONTAINS a folded rider — a person the rider-pairing step
|
|
16735
16739
|
* ([D34](../decisions/adr-0034.md)) removed from the frame BEFORE the tracker,
|
|
16736
16740
|
* so the passage is tracked once and as a VEHICLE.
|
|
@@ -18120,6 +18124,32 @@ var DetailResultSchema = object({
|
|
|
18120
18124
|
/** FRAME-space bbox (already mapped back from crop space). */
|
|
18121
18125
|
bbox: NativeCropBboxSchema.optional(),
|
|
18122
18126
|
embedding: string().optional(),
|
|
18127
|
+
/**
|
|
18128
|
+
* L2 magnitude of the RAW pre-normalization embedding. Additive and optional
|
|
18129
|
+
* so an older runner that does not send it degrades to "unmeasurable", which
|
|
18130
|
+
* the consuming gate treats as accept — never as reject.
|
|
18131
|
+
*/
|
|
18132
|
+
embeddingMagnitude: number().optional(),
|
|
18133
|
+
/**
|
|
18134
|
+
* Model that produced `embedding` — the SAME contract `labelModelId` has for
|
|
18135
|
+
* `label`, and for the same reason: the producing node is the only side that
|
|
18136
|
+
* knows which model actually ran, and re-deriving it downstream is exactly
|
|
18137
|
+
* the inference this model exists to forbid.
|
|
18138
|
+
*
|
|
18139
|
+
* Additive and optional, so a runner that predates it degrades to
|
|
18140
|
+
* "unmeasurable" rather than to a wrong answer — the consumer falls back to
|
|
18141
|
+
* its previous assumption instead of refusing.
|
|
18142
|
+
*
|
|
18143
|
+
* Its absence was not cosmetic. `FaceRecognizer` needs the probe's model id
|
|
18144
|
+
* to use `face-matcher`'s same-model gate (`sample.modelId !== probe.modelId`);
|
|
18145
|
+
* with nothing on the wire it took the id from the GALLERY, so the gate
|
|
18146
|
+
* compared the gallery against itself and could never fire. That turned the
|
|
18147
|
+
* one guard protecting the face feature space into a tautology, and it is
|
|
18148
|
+
* why swapping `face-embedding`'s model would NOT have stranded the enrolled
|
|
18149
|
+
* gallery as the catalog comment predicts — it would have scored the new
|
|
18150
|
+
* model's vectors against the old model's samples in one cosine space.
|
|
18151
|
+
*/
|
|
18152
|
+
embeddingModelId: string().optional(),
|
|
18123
18153
|
label: string().optional(),
|
|
18124
18154
|
/**
|
|
18125
18155
|
* The tier `label` occupies, copied VERBATIM from the producing step's
|
|
@@ -18995,6 +19025,12 @@ var CameraStatusSchema = object({
|
|
|
18995
19025
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
18996
19026
|
fetchedAt: number()
|
|
18997
19027
|
});
|
|
19028
|
+
var InferenceDeviceExclusionReasonSchema = _enum([
|
|
19029
|
+
"disabled",
|
|
19030
|
+
"unavailable",
|
|
19031
|
+
"cannot-host-camera-root",
|
|
19032
|
+
"accelerator-preferred"
|
|
19033
|
+
]);
|
|
18998
19034
|
var NodeInferenceDeviceSchema = object({
|
|
18999
19035
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
19000
19036
|
key: string(),
|
|
@@ -19025,7 +19061,17 @@ var NodeInferenceDeviceSchema = object({
|
|
|
19025
19061
|
* available per format; this is the stored selection that becomes the
|
|
19026
19062
|
* default for EVERY camera landing on this accelerator.
|
|
19027
19063
|
*/
|
|
19028
|
-
steps: record(string(), DeviceStepConfigSchema).optional()
|
|
19064
|
+
steps: record(string(), DeviceStepConfigSchema).optional(),
|
|
19065
|
+
/**
|
|
19066
|
+
* `null` when the device IS a camera-root candidate on this node; otherwise
|
|
19067
|
+
* the reason the dispatcher drops it. Computed by the SAME
|
|
19068
|
+
* `resolveInferenceDeviceEligibility` the dispatcher runs, so this view can
|
|
19069
|
+
* never disagree with the election — deriving it in the UI from
|
|
19070
|
+
* `enabled`/`available` would silently miss `cannot-host-camera-root` (needs
|
|
19071
|
+
* the node's model catalog) and `accelerator-preferred` (needs the node-wide
|
|
19072
|
+
* "an accelerator is serving" predicate).
|
|
19073
|
+
*/
|
|
19074
|
+
exclusion: InferenceDeviceExclusionReasonSchema.nullable()
|
|
19029
19075
|
});
|
|
19030
19076
|
var NodeInferenceDevicesSchema = object({
|
|
19031
19077
|
nodeId: string(),
|
|
@@ -19584,6 +19630,7 @@ var snapshotCapability = {
|
|
|
19584
19630
|
isBattery: boolean(),
|
|
19585
19631
|
reason: _enum([
|
|
19586
19632
|
"disabled",
|
|
19633
|
+
"offline",
|
|
19587
19634
|
"sleeping",
|
|
19588
19635
|
"unreachable",
|
|
19589
19636
|
"waking"
|
|
@@ -19673,9 +19720,17 @@ targets: array(object({
|
|
|
19673
19720
|
sleeping: boolean(),
|
|
19674
19721
|
/** Current device state rendered over the cached frame. State images
|
|
19675
19722
|
* remain authoritative even when their photographic background is
|
|
19676
|
-
* old; null means the link must carry a current camera frame.
|
|
19723
|
+
* old; null means the link must carry a current camera frame.
|
|
19724
|
+
*
|
|
19725
|
+
* **This is the ONLY source a surface may derive an inactive tile
|
|
19726
|
+
* from.** A client that reads a device's `online`/`disabled` flags and
|
|
19727
|
+
* draws its own verdict will disagree with the pixels it is painting
|
|
19728
|
+
* — the frame comes from here, and so must the sentence over it
|
|
19729
|
+
* (D190). Pair with `ageMs` for the age of the photograph behind the
|
|
19730
|
+
* state. */
|
|
19677
19731
|
stateReason: _enum([
|
|
19678
19732
|
"disabled",
|
|
19733
|
+
"offline",
|
|
19679
19734
|
"sleeping",
|
|
19680
19735
|
"unreachable",
|
|
19681
19736
|
"waking"
|
|
@@ -24014,7 +24069,12 @@ var ListResultSchema = object({
|
|
|
24014
24069
|
probedAt: number()
|
|
24015
24070
|
});
|
|
24016
24071
|
var PreferredSchema = LocalInterfaceSchema.nullable();
|
|
24017
|
-
|
|
24072
|
+
/**
|
|
24073
|
+
* Candidate base URL for the SDK to race on connect. Order matters —
|
|
24074
|
+
* the SDK should attempt these top-to-bottom with a short per-candidate
|
|
24075
|
+
* timeout (e.g. 1500ms) and cache the winner for the session.
|
|
24076
|
+
*/
|
|
24077
|
+
var ConnectionEndpointSchema = object({
|
|
24018
24078
|
/** Operator-facing label (e.g. "LAN — en0", "Public tunnel"). */
|
|
24019
24079
|
label: string(),
|
|
24020
24080
|
/** Fully-formed base URL with scheme + host + port. */
|
|
@@ -24057,7 +24117,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
|
|
|
24057
24117
|
* ordering between polls.
|
|
24058
24118
|
*/
|
|
24059
24119
|
priority: number()
|
|
24060
|
-
})
|
|
24120
|
+
});
|
|
24121
|
+
/**
|
|
24122
|
+
* Where the advertised local port came from. Ordered most → least
|
|
24123
|
+
* authoritative, and the whole point of returning it: a client must be able to
|
|
24124
|
+
* tell a FACT about the hub's socket from an echo of its own guess.
|
|
24125
|
+
*/
|
|
24126
|
+
var LocalPortSourceEnum = _enum([
|
|
24127
|
+
"server-config",
|
|
24128
|
+
"server-env",
|
|
24129
|
+
"caller-hint",
|
|
24130
|
+
"default"
|
|
24131
|
+
]);
|
|
24132
|
+
/** The port every LAN/loopback `baseUrl` in the same result was built with. */
|
|
24133
|
+
var AdvertisedLocalPortSchema = object({
|
|
24134
|
+
port: number().int().min(1).max(65535),
|
|
24135
|
+
source: LocalPortSourceEnum
|
|
24136
|
+
});
|
|
24137
|
+
var GetConnectionEndpointsResultSchema = object({
|
|
24138
|
+
endpoints: array(ConnectionEndpointSchema).readonly(),
|
|
24139
|
+
/**
|
|
24140
|
+
* The port the hub built the LAN/loopback URLs with, and where that number
|
|
24141
|
+
* came from.
|
|
24142
|
+
*
|
|
24143
|
+
* Returned rather than merely applied, because "the URL is right" and "the
|
|
24144
|
+
* client can KNOW the URL is right" are different properties. A client that
|
|
24145
|
+
* only sees a corrected URL cannot distinguish a hub that fixed the port from
|
|
24146
|
+
* a hub that echoed the port the client sent, so it cannot decide whether to
|
|
24147
|
+
* race the candidate or discard it. With `source` it can: anything but
|
|
24148
|
+
* `caller-hint` is the hub's own socket.
|
|
24149
|
+
*
|
|
24150
|
+
* Absent on hubs predating this field — a client that finds it missing is
|
|
24151
|
+
* talking to an echoing hub and must degrade exactly as it does for
|
|
24152
|
+
* `caller-hint`.
|
|
24153
|
+
*/
|
|
24154
|
+
localPort: AdvertisedLocalPortSchema
|
|
24155
|
+
});
|
|
24061
24156
|
/**
|
|
24062
24157
|
* The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
|
|
24063
24158
|
* AUTO (resolved from the candidate ranking at send time); `resolved` reports
|
|
@@ -24078,8 +24173,13 @@ var AllowedAddressesSchema = object({
|
|
|
24078
24173
|
*/
|
|
24079
24174
|
addresses: array(string()).readonly() });
|
|
24080
24175
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24081
|
-
/**
|
|
24082
|
-
|
|
24176
|
+
/**
|
|
24177
|
+
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
24178
|
+
* written against the echoing contract keep working; the hub uses it
|
|
24179
|
+
* only when it cannot read its own port, and says so via
|
|
24180
|
+
* `localPort.source === 'caller-hint'`.
|
|
24181
|
+
*/
|
|
24182
|
+
port: number().int().min(1).max(65535).optional(),
|
|
24083
24183
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
24084
24184
|
* candidate. Default `true`. */
|
|
24085
24185
|
includeLoopback: boolean().optional(),
|
|
@@ -37265,7 +37365,6 @@ var NC_AUDIO_DEFAULTS = {
|
|
|
37265
37365
|
hitPercent: 60,
|
|
37266
37366
|
samplingSeconds: 10
|
|
37267
37367
|
};
|
|
37268
|
-
new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
|
|
37269
37368
|
new Set(["devices", "classes"]);
|
|
37270
37369
|
NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
|
|
37271
37370
|
/**
|
|
@@ -37499,6 +37598,39 @@ TimelapseRuleInputSchema.extend({
|
|
|
37499
37598
|
createdAt: number(),
|
|
37500
37599
|
updatedAt: number()
|
|
37501
37600
|
});
|
|
37601
|
+
Object.freeze(Object.fromEntries([{
|
|
37602
|
+
stepId: "face-embedding",
|
|
37603
|
+
label: "Face recognition model",
|
|
37604
|
+
defaultModelId: "arcface-r100",
|
|
37605
|
+
indexName: "the enrolled face gallery",
|
|
37606
|
+
options: [
|
|
37607
|
+
{
|
|
37608
|
+
id: "arcface-r100",
|
|
37609
|
+
label: "ArcFace (ResNet34)"
|
|
37610
|
+
},
|
|
37611
|
+
{
|
|
37612
|
+
id: "auraface-r100",
|
|
37613
|
+
label: "AuraFace R100"
|
|
37614
|
+
},
|
|
37615
|
+
{
|
|
37616
|
+
id: "inception-resnet-v1",
|
|
37617
|
+
label: "Inception ResNet V1"
|
|
37618
|
+
}
|
|
37619
|
+
]
|
|
37620
|
+
}, {
|
|
37621
|
+
stepId: "clip-embedding",
|
|
37622
|
+
label: "Semantic search model",
|
|
37623
|
+
defaultModelId: "mobileclip-s1",
|
|
37624
|
+
indexName: "the object semantic-search index",
|
|
37625
|
+
options: [{
|
|
37626
|
+
id: "mobileclip-s1",
|
|
37627
|
+
label: "MobileCLIP S1"
|
|
37628
|
+
}, {
|
|
37629
|
+
id: "mobileclip-s2",
|
|
37630
|
+
label: "MobileCLIP S2"
|
|
37631
|
+
}]
|
|
37632
|
+
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
37633
|
+
string().min(1);
|
|
37502
37634
|
object({
|
|
37503
37635
|
/**
|
|
37504
37636
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -37519,10 +37651,21 @@ object({
|
|
|
37519
37651
|
*/
|
|
37520
37652
|
square: boolean()
|
|
37521
37653
|
});
|
|
37522
|
-
|
|
37654
|
+
/**
|
|
37655
|
+
* The convention in force when nobody has configured one — byte-for-byte the
|
|
37656
|
+
* behaviour of the pre-unification LIVE path (`DETAIL_CROP_PADDING_RATIO`).
|
|
37657
|
+
*/
|
|
37658
|
+
var DEFAULT_DETAIL_CROP_CONVENTION = {
|
|
37523
37659
|
paddingRatio: .15,
|
|
37524
37660
|
square: false
|
|
37525
|
-
}
|
|
37661
|
+
};
|
|
37662
|
+
Object.freeze({
|
|
37663
|
+
x: 0,
|
|
37664
|
+
y: 0,
|
|
37665
|
+
w: 1,
|
|
37666
|
+
h: 1
|
|
37667
|
+
});
|
|
37668
|
+
DEFAULT_DETAIL_CROP_CONVENTION.paddingRatio;
|
|
37526
37669
|
/**
|
|
37527
37670
|
* WHICH delivered frames the decode worker retains a native copy of.
|
|
37528
37671
|
*
|
|
@@ -44134,6 +44277,38 @@ var TerminalSessionManager = class {
|
|
|
44134
44277
|
* (`node-pty`) and should update via `camstack deploy` independently of the
|
|
44135
44278
|
* framework, exactly like the node-av decoder addon.
|
|
44136
44279
|
*/
|
|
44280
|
+
/**
|
|
44281
|
+
* Default argv for the Glances profile — deliberately EMPTY.
|
|
44282
|
+
*
|
|
44283
|
+
* Measured on the hub (2026-08-21, glances 4.5.6, embedded Python, a real pty
|
|
44284
|
+
* at the terminal camera's own 120x40 grid, CPU sampled from
|
|
44285
|
+
* /proc/<pid>/{utime,stime} so the number is the process's own and not the
|
|
44286
|
+
* box's contention):
|
|
44287
|
+
*
|
|
44288
|
+
* argv CPU (of one core)
|
|
44289
|
+
* (none — this default) 0.8 %
|
|
44290
|
+
* -t 3 0.7 %
|
|
44291
|
+
* -t 5 0.6 %
|
|
44292
|
+
* --disable-plugin processlist 0.7 %
|
|
44293
|
+
* --disable-plugin containers 0.9 %
|
|
44294
|
+
* --disable-plugin sensors 0.8 %
|
|
44295
|
+
* --disable-process 0.8 %
|
|
44296
|
+
* -t 3 --disable-plugin processlist,containers,sensors 0.5 %
|
|
44297
|
+
* -t 5 --disable-plugin processlist,containers,sensors 0.4 %
|
|
44298
|
+
*
|
|
44299
|
+
* Startup costs 0.19 core-seconds; steady state is 1.0 % of one core at 36 MB
|
|
44300
|
+
* RSS. The whole tuning range is worth ~0.4 % of ONE core out of 20 — below the
|
|
44301
|
+
* noise floor of a box that idles at 2.6 cores — while every entry that buys
|
|
44302
|
+
* something removes a panel the operator opened the camera to read. `-t` is
|
|
44303
|
+
* additionally counter-productive here: the terminal camera renders at 2 FPS
|
|
44304
|
+
* and glances already repaints every 2 s, so slowing glances only makes the
|
|
44305
|
+
* camera show stale numbers.
|
|
44306
|
+
*
|
|
44307
|
+
* So the default ships empty and the knob stays in front of the operator.
|
|
44308
|
+
* Anyone who does want to trade panels for CPU has the numbers above.
|
|
44309
|
+
*/
|
|
44310
|
+
var DEFAULT_GLANCES_ARGS = [];
|
|
44311
|
+
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.";
|
|
44137
44312
|
var DEFAULTS = {
|
|
44138
44313
|
btmPath: "",
|
|
44139
44314
|
btmEnabled: true,
|
|
@@ -44143,7 +44318,7 @@ var DEFAULTS = {
|
|
|
44143
44318
|
topArgs: [],
|
|
44144
44319
|
glancesEnabled: true,
|
|
44145
44320
|
glancesPath: "",
|
|
44146
|
-
glancesArgs:
|
|
44321
|
+
glancesArgs: DEFAULT_GLANCES_ARGS,
|
|
44147
44322
|
allowShell: false,
|
|
44148
44323
|
shellPath: "",
|
|
44149
44324
|
maxSessions: 4,
|
|
@@ -44530,85 +44705,13 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44530
44705
|
return this.instanceInfo(instance);
|
|
44531
44706
|
}
|
|
44532
44707
|
globalSettingsSchema() {
|
|
44533
|
-
return this.schema({ sections: [
|
|
44534
|
-
|
|
44535
|
-
|
|
44536
|
-
|
|
44537
|
-
|
|
44538
|
-
|
|
44539
|
-
this.field({
|
|
44540
|
-
type: "boolean",
|
|
44541
|
-
key: "btmEnabled",
|
|
44542
|
-
label: "Enable BTM camera",
|
|
44543
|
-
default: true,
|
|
44544
|
-
perNode: true
|
|
44545
|
-
}),
|
|
44546
|
-
this.field({
|
|
44547
|
-
type: "text",
|
|
44548
|
-
key: "btmPath",
|
|
44549
|
-
label: "BTM binary",
|
|
44550
|
-
description: "Path to the `btm` (bottom) executable. Leave empty to resolve from PATH.",
|
|
44551
|
-
placeholder: "btm",
|
|
44552
|
-
default: "",
|
|
44553
|
-
perNode: true
|
|
44554
|
-
}),
|
|
44555
|
-
this.field({
|
|
44556
|
-
type: "tags",
|
|
44557
|
-
key: "btmArgs",
|
|
44558
|
-
label: "BTM arguments",
|
|
44559
|
-
description: "Exact arguments passed to btm.",
|
|
44560
|
-
default: [],
|
|
44561
|
-
perNode: true
|
|
44562
|
-
}),
|
|
44563
|
-
this.field({
|
|
44564
|
-
type: "boolean",
|
|
44565
|
-
key: "topEnabled",
|
|
44566
|
-
label: "Enable Top camera",
|
|
44567
|
-
default: true,
|
|
44568
|
-
perNode: true
|
|
44569
|
-
}),
|
|
44570
|
-
this.field({
|
|
44571
|
-
type: "text",
|
|
44572
|
-
key: "topPath",
|
|
44573
|
-
label: "Top binary",
|
|
44574
|
-
placeholder: "top",
|
|
44575
|
-
default: "",
|
|
44576
|
-
perNode: true
|
|
44577
|
-
}),
|
|
44578
|
-
this.field({
|
|
44579
|
-
type: "tags",
|
|
44580
|
-
key: "topArgs",
|
|
44581
|
-
label: "Top arguments",
|
|
44582
|
-
description: "Exact arguments passed to top.",
|
|
44583
|
-
default: [],
|
|
44584
|
-
perNode: true
|
|
44585
|
-
}),
|
|
44586
|
-
this.field({
|
|
44587
|
-
type: "boolean",
|
|
44588
|
-
key: "glancesEnabled",
|
|
44589
|
-
label: "Enable Glances camera",
|
|
44590
|
-
description: "Glances is installed automatically into CamStack embedded Python.",
|
|
44591
|
-
default: true,
|
|
44592
|
-
perNode: true
|
|
44593
|
-
}),
|
|
44594
|
-
this.field({
|
|
44595
|
-
type: "text",
|
|
44596
|
-
key: "glancesPath",
|
|
44597
|
-
label: "Glances binary override",
|
|
44598
|
-
description: "Optional executable override. Empty uses the automatically managed Python package.",
|
|
44599
|
-
placeholder: "glances",
|
|
44600
|
-
default: "",
|
|
44601
|
-
perNode: true
|
|
44602
|
-
}),
|
|
44603
|
-
this.field({
|
|
44604
|
-
type: "tags",
|
|
44605
|
-
key: "glancesArgs",
|
|
44606
|
-
label: "Glances arguments",
|
|
44607
|
-
description: "Exact arguments passed to Glances.",
|
|
44608
|
-
default: [],
|
|
44609
|
-
perNode: true
|
|
44610
|
-
}),
|
|
44611
|
-
this.field({
|
|
44708
|
+
return this.schema({ sections: [
|
|
44709
|
+
{
|
|
44710
|
+
id: "terminal",
|
|
44711
|
+
title: "Terminal",
|
|
44712
|
+
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.",
|
|
44713
|
+
columns: 2,
|
|
44714
|
+
fields: [this.field({
|
|
44612
44715
|
type: "number",
|
|
44613
44716
|
key: "maxSessions",
|
|
44614
44717
|
label: "Max concurrent sessions",
|
|
@@ -44617,16 +44720,122 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44617
44720
|
step: 1,
|
|
44618
44721
|
default: 4,
|
|
44619
44722
|
perNode: true
|
|
44620
|
-
})
|
|
44621
|
-
|
|
44723
|
+
})]
|
|
44724
|
+
},
|
|
44725
|
+
{
|
|
44726
|
+
id: "terminal-btm",
|
|
44727
|
+
title: "BTM camera",
|
|
44728
|
+
description: "bottom (btm) — CPU, memory, network and process monitor.",
|
|
44729
|
+
columns: 2,
|
|
44730
|
+
fields: [
|
|
44731
|
+
this.field({
|
|
44732
|
+
type: "boolean",
|
|
44733
|
+
key: "btmEnabled",
|
|
44734
|
+
label: "Enabled",
|
|
44735
|
+
description: "Offer the BTM profile on this node.",
|
|
44736
|
+
default: true,
|
|
44737
|
+
perNode: true
|
|
44738
|
+
}),
|
|
44739
|
+
this.field({
|
|
44740
|
+
type: "text",
|
|
44741
|
+
key: "btmPath",
|
|
44742
|
+
label: "Binary",
|
|
44743
|
+
description: "Path to the `btm` (bottom) executable. Leave empty to resolve from PATH.",
|
|
44744
|
+
placeholder: "btm",
|
|
44745
|
+
default: "",
|
|
44746
|
+
perNode: true
|
|
44747
|
+
}),
|
|
44748
|
+
this.field({
|
|
44749
|
+
type: "tags",
|
|
44750
|
+
key: "btmArgs",
|
|
44751
|
+
label: "Arguments",
|
|
44752
|
+
description: "Exact arguments passed to btm. One tag per argv entry.",
|
|
44753
|
+
default: [],
|
|
44754
|
+
perNode: true,
|
|
44755
|
+
span: 2
|
|
44756
|
+
})
|
|
44757
|
+
]
|
|
44758
|
+
},
|
|
44759
|
+
{
|
|
44760
|
+
id: "terminal-top",
|
|
44761
|
+
title: "Top camera",
|
|
44762
|
+
description: "The operating system process and resource monitor.",
|
|
44763
|
+
columns: 2,
|
|
44764
|
+
fields: [
|
|
44765
|
+
this.field({
|
|
44766
|
+
type: "boolean",
|
|
44767
|
+
key: "topEnabled",
|
|
44768
|
+
label: "Enabled",
|
|
44769
|
+
description: "Offer the Top profile on this node.",
|
|
44770
|
+
default: true,
|
|
44771
|
+
perNode: true
|
|
44772
|
+
}),
|
|
44773
|
+
this.field({
|
|
44774
|
+
type: "text",
|
|
44775
|
+
key: "topPath",
|
|
44776
|
+
label: "Binary",
|
|
44777
|
+
placeholder: "top",
|
|
44778
|
+
default: "",
|
|
44779
|
+
perNode: true
|
|
44780
|
+
}),
|
|
44781
|
+
this.field({
|
|
44782
|
+
type: "tags",
|
|
44783
|
+
key: "topArgs",
|
|
44784
|
+
label: "Arguments",
|
|
44785
|
+
description: "Exact arguments passed to top. One tag per argv entry.",
|
|
44786
|
+
default: [],
|
|
44787
|
+
perNode: true,
|
|
44788
|
+
span: 2
|
|
44789
|
+
})
|
|
44790
|
+
]
|
|
44791
|
+
},
|
|
44792
|
+
{
|
|
44793
|
+
id: "terminal-glances",
|
|
44794
|
+
title: "Glances camera",
|
|
44795
|
+
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.",
|
|
44796
|
+
columns: 2,
|
|
44797
|
+
fields: [
|
|
44798
|
+
this.field({
|
|
44799
|
+
type: "boolean",
|
|
44800
|
+
key: "glancesEnabled",
|
|
44801
|
+
label: "Enabled",
|
|
44802
|
+
description: "Offer the Glances profile on this node.",
|
|
44803
|
+
default: true,
|
|
44804
|
+
perNode: true
|
|
44805
|
+
}),
|
|
44806
|
+
this.field({
|
|
44807
|
+
type: "text",
|
|
44808
|
+
key: "glancesPath",
|
|
44809
|
+
label: "Binary override",
|
|
44810
|
+
description: "Optional executable override. Empty uses the automatically managed Python package.",
|
|
44811
|
+
placeholder: "glances",
|
|
44812
|
+
default: "",
|
|
44813
|
+
perNode: true
|
|
44814
|
+
}),
|
|
44815
|
+
this.field({
|
|
44816
|
+
type: "tags",
|
|
44817
|
+
key: "glancesArgs",
|
|
44818
|
+
label: "Arguments",
|
|
44819
|
+
description: GLANCES_ARGS_DESCRIPTION,
|
|
44820
|
+
default: [...DEFAULT_GLANCES_ARGS],
|
|
44821
|
+
perNode: true,
|
|
44822
|
+
span: 2
|
|
44823
|
+
})
|
|
44824
|
+
]
|
|
44825
|
+
},
|
|
44826
|
+
{
|
|
44827
|
+
id: "terminal-shell",
|
|
44828
|
+
title: "Interactive shell",
|
|
44829
|
+
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.",
|
|
44830
|
+
columns: 2,
|
|
44831
|
+
fields: [this.field({
|
|
44622
44832
|
type: "boolean",
|
|
44623
44833
|
key: "allowShell",
|
|
44624
44834
|
label: "Allow interactive shell",
|
|
44625
|
-
description: "Adds a \"Shell\" profile
|
|
44835
|
+
description: "Adds a \"Shell\" profile on this node.",
|
|
44626
44836
|
default: false,
|
|
44627
44837
|
perNode: true
|
|
44628
|
-
}),
|
|
44629
|
-
this.field({
|
|
44838
|
+
}), this.field({
|
|
44630
44839
|
type: "text",
|
|
44631
44840
|
key: "shellPath",
|
|
44632
44841
|
label: "Shell binary",
|
|
@@ -44634,89 +44843,90 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44634
44843
|
placeholder: "/bin/bash",
|
|
44635
44844
|
default: "",
|
|
44636
44845
|
perNode: true
|
|
44637
|
-
})
|
|
44638
|
-
|
|
44639
|
-
|
|
44640
|
-
|
|
44641
|
-
|
|
44642
|
-
|
|
44643
|
-
|
|
44644
|
-
|
|
44645
|
-
|
|
44646
|
-
|
|
44647
|
-
|
|
44648
|
-
|
|
44649
|
-
|
|
44650
|
-
|
|
44651
|
-
|
|
44652
|
-
|
|
44653
|
-
|
|
44654
|
-
|
|
44655
|
-
|
|
44656
|
-
|
|
44657
|
-
|
|
44658
|
-
|
|
44659
|
-
|
|
44660
|
-
|
|
44661
|
-
|
|
44662
|
-
|
|
44663
|
-
},
|
|
44664
|
-
itemFields: [
|
|
44665
|
-
{
|
|
44666
|
-
type: "boolean",
|
|
44667
|
-
key: "enabled",
|
|
44668
|
-
label: "Enabled",
|
|
44669
|
-
default: true
|
|
44670
|
-
},
|
|
44671
|
-
{
|
|
44672
|
-
type: "text",
|
|
44673
|
-
key: "profileId",
|
|
44674
|
-
label: "Profile ID",
|
|
44675
|
-
description: "Stable lowercase slug, for example gpu-monitor.",
|
|
44676
|
-
required: true
|
|
44677
|
-
},
|
|
44678
|
-
{
|
|
44679
|
-
type: "text",
|
|
44680
|
-
key: "label",
|
|
44681
|
-
label: "Display name",
|
|
44682
|
-
required: true
|
|
44683
|
-
},
|
|
44684
|
-
{
|
|
44685
|
-
type: "textarea",
|
|
44686
|
-
key: "description",
|
|
44687
|
-
label: "Description",
|
|
44688
|
-
rows: 2
|
|
44689
|
-
},
|
|
44690
|
-
{
|
|
44691
|
-
type: "text",
|
|
44692
|
-
key: "executable",
|
|
44693
|
-
label: "Executable",
|
|
44694
|
-
description: "Absolute path or a binary resolved from PATH.",
|
|
44695
|
-
required: true
|
|
44696
|
-
},
|
|
44697
|
-
{
|
|
44698
|
-
type: "tags",
|
|
44699
|
-
key: "args",
|
|
44700
|
-
label: "Arguments",
|
|
44701
|
-
description: "One exact process argument per tag.",
|
|
44702
|
-
maxTags: 64
|
|
44703
|
-
},
|
|
44704
|
-
{
|
|
44705
|
-
type: "text",
|
|
44706
|
-
key: "cwd",
|
|
44707
|
-
label: "Working directory",
|
|
44708
|
-
description: "Optional working directory for this profile."
|
|
44846
|
+
})]
|
|
44847
|
+
},
|
|
44848
|
+
{
|
|
44849
|
+
id: "terminal-profiles",
|
|
44850
|
+
title: "Custom profiles",
|
|
44851
|
+
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.",
|
|
44852
|
+
columns: 1,
|
|
44853
|
+
fields: [this.field({
|
|
44854
|
+
type: "editable-array",
|
|
44855
|
+
key: "customProfiles",
|
|
44856
|
+
label: "Profiles",
|
|
44857
|
+
perNode: true,
|
|
44858
|
+
default: [],
|
|
44859
|
+
maxRows: 32,
|
|
44860
|
+
addLabel: "Add profile",
|
|
44861
|
+
emptyMessage: "No custom profiles configured.",
|
|
44862
|
+
rowTitleTemplate: "{label} — {executable}",
|
|
44863
|
+
defaultItem: {
|
|
44864
|
+
enabled: true,
|
|
44865
|
+
profileId: "",
|
|
44866
|
+
label: "",
|
|
44867
|
+
description: "",
|
|
44868
|
+
executable: "",
|
|
44869
|
+
args: [],
|
|
44870
|
+
cwd: "",
|
|
44871
|
+
environment: []
|
|
44709
44872
|
},
|
|
44710
|
-
|
|
44711
|
-
|
|
44712
|
-
|
|
44713
|
-
|
|
44714
|
-
|
|
44715
|
-
|
|
44716
|
-
|
|
44717
|
-
|
|
44718
|
-
|
|
44719
|
-
|
|
44873
|
+
itemFields: [
|
|
44874
|
+
{
|
|
44875
|
+
type: "boolean",
|
|
44876
|
+
key: "enabled",
|
|
44877
|
+
label: "Enabled",
|
|
44878
|
+
default: true
|
|
44879
|
+
},
|
|
44880
|
+
{
|
|
44881
|
+
type: "text",
|
|
44882
|
+
key: "profileId",
|
|
44883
|
+
label: "Profile ID",
|
|
44884
|
+
description: "Stable lowercase slug, for example gpu-monitor.",
|
|
44885
|
+
required: true
|
|
44886
|
+
},
|
|
44887
|
+
{
|
|
44888
|
+
type: "text",
|
|
44889
|
+
key: "label",
|
|
44890
|
+
label: "Display name",
|
|
44891
|
+
required: true
|
|
44892
|
+
},
|
|
44893
|
+
{
|
|
44894
|
+
type: "textarea",
|
|
44895
|
+
key: "description",
|
|
44896
|
+
label: "Description",
|
|
44897
|
+
rows: 2
|
|
44898
|
+
},
|
|
44899
|
+
{
|
|
44900
|
+
type: "text",
|
|
44901
|
+
key: "executable",
|
|
44902
|
+
label: "Executable",
|
|
44903
|
+
description: "Absolute path or a binary resolved from PATH.",
|
|
44904
|
+
required: true
|
|
44905
|
+
},
|
|
44906
|
+
{
|
|
44907
|
+
type: "tags",
|
|
44908
|
+
key: "args",
|
|
44909
|
+
label: "Arguments",
|
|
44910
|
+
description: "One exact process argument per tag.",
|
|
44911
|
+
maxTags: 64
|
|
44912
|
+
},
|
|
44913
|
+
{
|
|
44914
|
+
type: "text",
|
|
44915
|
+
key: "cwd",
|
|
44916
|
+
label: "Working directory",
|
|
44917
|
+
description: "Optional working directory for this profile."
|
|
44918
|
+
},
|
|
44919
|
+
{
|
|
44920
|
+
type: "tags",
|
|
44921
|
+
key: "environment",
|
|
44922
|
+
label: "Environment",
|
|
44923
|
+
description: "Optional NAME=value entries merged into the process environment.",
|
|
44924
|
+
maxTags: 64
|
|
44925
|
+
}
|
|
44926
|
+
]
|
|
44927
|
+
})]
|
|
44928
|
+
}
|
|
44929
|
+
] });
|
|
44720
44930
|
}
|
|
44721
44931
|
};
|
|
44722
44932
|
//#endregion
|