@camstack/addon-terminal 0.1.27 → 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 +300 -172
- package/dist/addon.mjs +300 -172
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -19025,6 +19025,12 @@ var CameraStatusSchema = object({
|
|
|
19025
19025
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
19026
19026
|
fetchedAt: number()
|
|
19027
19027
|
});
|
|
19028
|
+
var InferenceDeviceExclusionReasonSchema = _enum([
|
|
19029
|
+
"disabled",
|
|
19030
|
+
"unavailable",
|
|
19031
|
+
"cannot-host-camera-root",
|
|
19032
|
+
"accelerator-preferred"
|
|
19033
|
+
]);
|
|
19028
19034
|
var NodeInferenceDeviceSchema = object({
|
|
19029
19035
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
19030
19036
|
key: string(),
|
|
@@ -19055,7 +19061,17 @@ var NodeInferenceDeviceSchema = object({
|
|
|
19055
19061
|
* available per format; this is the stored selection that becomes the
|
|
19056
19062
|
* default for EVERY camera landing on this accelerator.
|
|
19057
19063
|
*/
|
|
19058
|
-
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()
|
|
19059
19075
|
});
|
|
19060
19076
|
var NodeInferenceDevicesSchema = object({
|
|
19061
19077
|
nodeId: string(),
|
|
@@ -24053,7 +24069,12 @@ var ListResultSchema = object({
|
|
|
24053
24069
|
probedAt: number()
|
|
24054
24070
|
});
|
|
24055
24071
|
var PreferredSchema = LocalInterfaceSchema.nullable();
|
|
24056
|
-
|
|
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({
|
|
24057
24078
|
/** Operator-facing label (e.g. "LAN — en0", "Public tunnel"). */
|
|
24058
24079
|
label: string(),
|
|
24059
24080
|
/** Fully-formed base URL with scheme + host + port. */
|
|
@@ -24096,7 +24117,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
|
|
|
24096
24117
|
* ordering between polls.
|
|
24097
24118
|
*/
|
|
24098
24119
|
priority: number()
|
|
24099
|
-
})
|
|
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
|
+
});
|
|
24100
24156
|
/**
|
|
24101
24157
|
* The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
|
|
24102
24158
|
* AUTO (resolved from the candidate ranking at send time); `resolved` reports
|
|
@@ -24117,8 +24173,13 @@ var AllowedAddressesSchema = object({
|
|
|
24117
24173
|
*/
|
|
24118
24174
|
addresses: array(string()).readonly() });
|
|
24119
24175
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24120
|
-
/**
|
|
24121
|
-
|
|
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(),
|
|
24122
24183
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
24123
24184
|
* candidate. Default `true`. */
|
|
24124
24185
|
includeLoopback: boolean().optional(),
|
|
@@ -44216,6 +44277,38 @@ var TerminalSessionManager = class {
|
|
|
44216
44277
|
* (`node-pty`) and should update via `camstack deploy` independently of the
|
|
44217
44278
|
* framework, exactly like the node-av decoder addon.
|
|
44218
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.";
|
|
44219
44312
|
var DEFAULTS = {
|
|
44220
44313
|
btmPath: "",
|
|
44221
44314
|
btmEnabled: true,
|
|
@@ -44225,7 +44318,7 @@ var DEFAULTS = {
|
|
|
44225
44318
|
topArgs: [],
|
|
44226
44319
|
glancesEnabled: true,
|
|
44227
44320
|
glancesPath: "",
|
|
44228
|
-
glancesArgs:
|
|
44321
|
+
glancesArgs: DEFAULT_GLANCES_ARGS,
|
|
44229
44322
|
allowShell: false,
|
|
44230
44323
|
shellPath: "",
|
|
44231
44324
|
maxSessions: 4,
|
|
@@ -44612,85 +44705,13 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44612
44705
|
return this.instanceInfo(instance);
|
|
44613
44706
|
}
|
|
44614
44707
|
globalSettingsSchema() {
|
|
44615
|
-
return this.schema({ sections: [
|
|
44616
|
-
|
|
44617
|
-
|
|
44618
|
-
|
|
44619
|
-
|
|
44620
|
-
|
|
44621
|
-
this.field({
|
|
44622
|
-
type: "boolean",
|
|
44623
|
-
key: "btmEnabled",
|
|
44624
|
-
label: "Enable BTM camera",
|
|
44625
|
-
default: true,
|
|
44626
|
-
perNode: true
|
|
44627
|
-
}),
|
|
44628
|
-
this.field({
|
|
44629
|
-
type: "text",
|
|
44630
|
-
key: "btmPath",
|
|
44631
|
-
label: "BTM binary",
|
|
44632
|
-
description: "Path to the `btm` (bottom) executable. Leave empty to resolve from PATH.",
|
|
44633
|
-
placeholder: "btm",
|
|
44634
|
-
default: "",
|
|
44635
|
-
perNode: true
|
|
44636
|
-
}),
|
|
44637
|
-
this.field({
|
|
44638
|
-
type: "tags",
|
|
44639
|
-
key: "btmArgs",
|
|
44640
|
-
label: "BTM arguments",
|
|
44641
|
-
description: "Exact arguments passed to btm.",
|
|
44642
|
-
default: [],
|
|
44643
|
-
perNode: true
|
|
44644
|
-
}),
|
|
44645
|
-
this.field({
|
|
44646
|
-
type: "boolean",
|
|
44647
|
-
key: "topEnabled",
|
|
44648
|
-
label: "Enable Top camera",
|
|
44649
|
-
default: true,
|
|
44650
|
-
perNode: true
|
|
44651
|
-
}),
|
|
44652
|
-
this.field({
|
|
44653
|
-
type: "text",
|
|
44654
|
-
key: "topPath",
|
|
44655
|
-
label: "Top binary",
|
|
44656
|
-
placeholder: "top",
|
|
44657
|
-
default: "",
|
|
44658
|
-
perNode: true
|
|
44659
|
-
}),
|
|
44660
|
-
this.field({
|
|
44661
|
-
type: "tags",
|
|
44662
|
-
key: "topArgs",
|
|
44663
|
-
label: "Top arguments",
|
|
44664
|
-
description: "Exact arguments passed to top.",
|
|
44665
|
-
default: [],
|
|
44666
|
-
perNode: true
|
|
44667
|
-
}),
|
|
44668
|
-
this.field({
|
|
44669
|
-
type: "boolean",
|
|
44670
|
-
key: "glancesEnabled",
|
|
44671
|
-
label: "Enable Glances camera",
|
|
44672
|
-
description: "Glances is installed automatically into CamStack embedded Python.",
|
|
44673
|
-
default: true,
|
|
44674
|
-
perNode: true
|
|
44675
|
-
}),
|
|
44676
|
-
this.field({
|
|
44677
|
-
type: "text",
|
|
44678
|
-
key: "glancesPath",
|
|
44679
|
-
label: "Glances binary override",
|
|
44680
|
-
description: "Optional executable override. Empty uses the automatically managed Python package.",
|
|
44681
|
-
placeholder: "glances",
|
|
44682
|
-
default: "",
|
|
44683
|
-
perNode: true
|
|
44684
|
-
}),
|
|
44685
|
-
this.field({
|
|
44686
|
-
type: "tags",
|
|
44687
|
-
key: "glancesArgs",
|
|
44688
|
-
label: "Glances arguments",
|
|
44689
|
-
description: "Exact arguments passed to Glances.",
|
|
44690
|
-
default: [],
|
|
44691
|
-
perNode: true
|
|
44692
|
-
}),
|
|
44693
|
-
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({
|
|
44694
44715
|
type: "number",
|
|
44695
44716
|
key: "maxSessions",
|
|
44696
44717
|
label: "Max concurrent sessions",
|
|
@@ -44699,16 +44720,122 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44699
44720
|
step: 1,
|
|
44700
44721
|
default: 4,
|
|
44701
44722
|
perNode: true
|
|
44702
|
-
})
|
|
44703
|
-
|
|
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({
|
|
44704
44832
|
type: "boolean",
|
|
44705
44833
|
key: "allowShell",
|
|
44706
44834
|
label: "Allow interactive shell",
|
|
44707
|
-
description: "Adds a \"Shell\" profile
|
|
44835
|
+
description: "Adds a \"Shell\" profile on this node.",
|
|
44708
44836
|
default: false,
|
|
44709
44837
|
perNode: true
|
|
44710
|
-
}),
|
|
44711
|
-
this.field({
|
|
44838
|
+
}), this.field({
|
|
44712
44839
|
type: "text",
|
|
44713
44840
|
key: "shellPath",
|
|
44714
44841
|
label: "Shell binary",
|
|
@@ -44716,89 +44843,90 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44716
44843
|
placeholder: "/bin/bash",
|
|
44717
44844
|
default: "",
|
|
44718
44845
|
perNode: true
|
|
44719
|
-
})
|
|
44720
|
-
|
|
44721
|
-
|
|
44722
|
-
|
|
44723
|
-
|
|
44724
|
-
|
|
44725
|
-
|
|
44726
|
-
|
|
44727
|
-
|
|
44728
|
-
|
|
44729
|
-
|
|
44730
|
-
|
|
44731
|
-
|
|
44732
|
-
|
|
44733
|
-
|
|
44734
|
-
|
|
44735
|
-
|
|
44736
|
-
|
|
44737
|
-
|
|
44738
|
-
|
|
44739
|
-
|
|
44740
|
-
|
|
44741
|
-
|
|
44742
|
-
|
|
44743
|
-
|
|
44744
|
-
|
|
44745
|
-
},
|
|
44746
|
-
itemFields: [
|
|
44747
|
-
{
|
|
44748
|
-
type: "boolean",
|
|
44749
|
-
key: "enabled",
|
|
44750
|
-
label: "Enabled",
|
|
44751
|
-
default: true
|
|
44752
|
-
},
|
|
44753
|
-
{
|
|
44754
|
-
type: "text",
|
|
44755
|
-
key: "profileId",
|
|
44756
|
-
label: "Profile ID",
|
|
44757
|
-
description: "Stable lowercase slug, for example gpu-monitor.",
|
|
44758
|
-
required: true
|
|
44759
|
-
},
|
|
44760
|
-
{
|
|
44761
|
-
type: "text",
|
|
44762
|
-
key: "label",
|
|
44763
|
-
label: "Display name",
|
|
44764
|
-
required: true
|
|
44765
|
-
},
|
|
44766
|
-
{
|
|
44767
|
-
type: "textarea",
|
|
44768
|
-
key: "description",
|
|
44769
|
-
label: "Description",
|
|
44770
|
-
rows: 2
|
|
44771
|
-
},
|
|
44772
|
-
{
|
|
44773
|
-
type: "text",
|
|
44774
|
-
key: "executable",
|
|
44775
|
-
label: "Executable",
|
|
44776
|
-
description: "Absolute path or a binary resolved from PATH.",
|
|
44777
|
-
required: true
|
|
44778
|
-
},
|
|
44779
|
-
{
|
|
44780
|
-
type: "tags",
|
|
44781
|
-
key: "args",
|
|
44782
|
-
label: "Arguments",
|
|
44783
|
-
description: "One exact process argument per tag.",
|
|
44784
|
-
maxTags: 64
|
|
44785
|
-
},
|
|
44786
|
-
{
|
|
44787
|
-
type: "text",
|
|
44788
|
-
key: "cwd",
|
|
44789
|
-
label: "Working directory",
|
|
44790
|
-
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: []
|
|
44791
44872
|
},
|
|
44792
|
-
|
|
44793
|
-
|
|
44794
|
-
|
|
44795
|
-
|
|
44796
|
-
|
|
44797
|
-
|
|
44798
|
-
|
|
44799
|
-
|
|
44800
|
-
|
|
44801
|
-
|
|
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
|
+
] });
|
|
44802
44930
|
}
|
|
44803
44931
|
};
|
|
44804
44932
|
//#endregion
|
package/dist/addon.mjs
CHANGED
|
@@ -19002,6 +19002,12 @@ var CameraStatusSchema = object({
|
|
|
19002
19002
|
/** Unix timestamp (ms) when this snapshot was composed server-side. */
|
|
19003
19003
|
fetchedAt: number()
|
|
19004
19004
|
});
|
|
19005
|
+
var InferenceDeviceExclusionReasonSchema = _enum([
|
|
19006
|
+
"disabled",
|
|
19007
|
+
"unavailable",
|
|
19008
|
+
"cannot-host-camera-root",
|
|
19009
|
+
"accelerator-preferred"
|
|
19010
|
+
]);
|
|
19005
19011
|
var NodeInferenceDeviceSchema = object({
|
|
19006
19012
|
/** Stable per-node device key, e.g. `openvino:npu`, `edgetpu:usb`, `cpu`. */
|
|
19007
19013
|
key: string(),
|
|
@@ -19032,7 +19038,17 @@ var NodeInferenceDeviceSchema = object({
|
|
|
19032
19038
|
* available per format; this is the stored selection that becomes the
|
|
19033
19039
|
* default for EVERY camera landing on this accelerator.
|
|
19034
19040
|
*/
|
|
19035
|
-
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()
|
|
19036
19052
|
});
|
|
19037
19053
|
var NodeInferenceDevicesSchema = object({
|
|
19038
19054
|
nodeId: string(),
|
|
@@ -24030,7 +24046,12 @@ var ListResultSchema = object({
|
|
|
24030
24046
|
probedAt: number()
|
|
24031
24047
|
});
|
|
24032
24048
|
var PreferredSchema = LocalInterfaceSchema.nullable();
|
|
24033
|
-
|
|
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({
|
|
24034
24055
|
/** Operator-facing label (e.g. "LAN — en0", "Public tunnel"). */
|
|
24035
24056
|
label: string(),
|
|
24036
24057
|
/** Fully-formed base URL with scheme + host + port. */
|
|
@@ -24073,7 +24094,42 @@ var GetConnectionEndpointsResultSchema = object({ endpoints: array(object({
|
|
|
24073
24094
|
* ordering between polls.
|
|
24074
24095
|
*/
|
|
24075
24096
|
priority: number()
|
|
24076
|
-
})
|
|
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
|
+
});
|
|
24077
24133
|
/**
|
|
24078
24134
|
* The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
|
|
24079
24135
|
* AUTO (resolved from the candidate ranking at send time); `resolved` reports
|
|
@@ -24094,8 +24150,13 @@ var AllowedAddressesSchema = object({
|
|
|
24094
24150
|
*/
|
|
24095
24151
|
addresses: array(string()).readonly() });
|
|
24096
24152
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24097
|
-
/**
|
|
24098
|
-
|
|
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(),
|
|
24099
24160
|
/** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
|
|
24100
24161
|
* candidate. Default `true`. */
|
|
24101
24162
|
includeLoopback: boolean().optional(),
|
|
@@ -44193,6 +44254,38 @@ var TerminalSessionManager = class {
|
|
|
44193
44254
|
* (`node-pty`) and should update via `camstack deploy` independently of the
|
|
44194
44255
|
* framework, exactly like the node-av decoder addon.
|
|
44195
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.";
|
|
44196
44289
|
var DEFAULTS = {
|
|
44197
44290
|
btmPath: "",
|
|
44198
44291
|
btmEnabled: true,
|
|
@@ -44202,7 +44295,7 @@ var DEFAULTS = {
|
|
|
44202
44295
|
topArgs: [],
|
|
44203
44296
|
glancesEnabled: true,
|
|
44204
44297
|
glancesPath: "",
|
|
44205
|
-
glancesArgs:
|
|
44298
|
+
glancesArgs: DEFAULT_GLANCES_ARGS,
|
|
44206
44299
|
allowShell: false,
|
|
44207
44300
|
shellPath: "",
|
|
44208
44301
|
maxSessions: 4,
|
|
@@ -44589,85 +44682,13 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44589
44682
|
return this.instanceInfo(instance);
|
|
44590
44683
|
}
|
|
44591
44684
|
globalSettingsSchema() {
|
|
44592
|
-
return this.schema({ sections: [
|
|
44593
|
-
|
|
44594
|
-
|
|
44595
|
-
|
|
44596
|
-
|
|
44597
|
-
|
|
44598
|
-
this.field({
|
|
44599
|
-
type: "boolean",
|
|
44600
|
-
key: "btmEnabled",
|
|
44601
|
-
label: "Enable BTM camera",
|
|
44602
|
-
default: true,
|
|
44603
|
-
perNode: true
|
|
44604
|
-
}),
|
|
44605
|
-
this.field({
|
|
44606
|
-
type: "text",
|
|
44607
|
-
key: "btmPath",
|
|
44608
|
-
label: "BTM binary",
|
|
44609
|
-
description: "Path to the `btm` (bottom) executable. Leave empty to resolve from PATH.",
|
|
44610
|
-
placeholder: "btm",
|
|
44611
|
-
default: "",
|
|
44612
|
-
perNode: true
|
|
44613
|
-
}),
|
|
44614
|
-
this.field({
|
|
44615
|
-
type: "tags",
|
|
44616
|
-
key: "btmArgs",
|
|
44617
|
-
label: "BTM arguments",
|
|
44618
|
-
description: "Exact arguments passed to btm.",
|
|
44619
|
-
default: [],
|
|
44620
|
-
perNode: true
|
|
44621
|
-
}),
|
|
44622
|
-
this.field({
|
|
44623
|
-
type: "boolean",
|
|
44624
|
-
key: "topEnabled",
|
|
44625
|
-
label: "Enable Top camera",
|
|
44626
|
-
default: true,
|
|
44627
|
-
perNode: true
|
|
44628
|
-
}),
|
|
44629
|
-
this.field({
|
|
44630
|
-
type: "text",
|
|
44631
|
-
key: "topPath",
|
|
44632
|
-
label: "Top binary",
|
|
44633
|
-
placeholder: "top",
|
|
44634
|
-
default: "",
|
|
44635
|
-
perNode: true
|
|
44636
|
-
}),
|
|
44637
|
-
this.field({
|
|
44638
|
-
type: "tags",
|
|
44639
|
-
key: "topArgs",
|
|
44640
|
-
label: "Top arguments",
|
|
44641
|
-
description: "Exact arguments passed to top.",
|
|
44642
|
-
default: [],
|
|
44643
|
-
perNode: true
|
|
44644
|
-
}),
|
|
44645
|
-
this.field({
|
|
44646
|
-
type: "boolean",
|
|
44647
|
-
key: "glancesEnabled",
|
|
44648
|
-
label: "Enable Glances camera",
|
|
44649
|
-
description: "Glances is installed automatically into CamStack embedded Python.",
|
|
44650
|
-
default: true,
|
|
44651
|
-
perNode: true
|
|
44652
|
-
}),
|
|
44653
|
-
this.field({
|
|
44654
|
-
type: "text",
|
|
44655
|
-
key: "glancesPath",
|
|
44656
|
-
label: "Glances binary override",
|
|
44657
|
-
description: "Optional executable override. Empty uses the automatically managed Python package.",
|
|
44658
|
-
placeholder: "glances",
|
|
44659
|
-
default: "",
|
|
44660
|
-
perNode: true
|
|
44661
|
-
}),
|
|
44662
|
-
this.field({
|
|
44663
|
-
type: "tags",
|
|
44664
|
-
key: "glancesArgs",
|
|
44665
|
-
label: "Glances arguments",
|
|
44666
|
-
description: "Exact arguments passed to Glances.",
|
|
44667
|
-
default: [],
|
|
44668
|
-
perNode: true
|
|
44669
|
-
}),
|
|
44670
|
-
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({
|
|
44671
44692
|
type: "number",
|
|
44672
44693
|
key: "maxSessions",
|
|
44673
44694
|
label: "Max concurrent sessions",
|
|
@@ -44676,16 +44697,122 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44676
44697
|
step: 1,
|
|
44677
44698
|
default: 4,
|
|
44678
44699
|
perNode: true
|
|
44679
|
-
})
|
|
44680
|
-
|
|
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({
|
|
44681
44809
|
type: "boolean",
|
|
44682
44810
|
key: "allowShell",
|
|
44683
44811
|
label: "Allow interactive shell",
|
|
44684
|
-
description: "Adds a \"Shell\" profile
|
|
44812
|
+
description: "Adds a \"Shell\" profile on this node.",
|
|
44685
44813
|
default: false,
|
|
44686
44814
|
perNode: true
|
|
44687
|
-
}),
|
|
44688
|
-
this.field({
|
|
44815
|
+
}), this.field({
|
|
44689
44816
|
type: "text",
|
|
44690
44817
|
key: "shellPath",
|
|
44691
44818
|
label: "Shell binary",
|
|
@@ -44693,89 +44820,90 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44693
44820
|
placeholder: "/bin/bash",
|
|
44694
44821
|
default: "",
|
|
44695
44822
|
perNode: true
|
|
44696
|
-
})
|
|
44697
|
-
|
|
44698
|
-
|
|
44699
|
-
|
|
44700
|
-
|
|
44701
|
-
|
|
44702
|
-
|
|
44703
|
-
|
|
44704
|
-
|
|
44705
|
-
|
|
44706
|
-
|
|
44707
|
-
|
|
44708
|
-
|
|
44709
|
-
|
|
44710
|
-
|
|
44711
|
-
|
|
44712
|
-
|
|
44713
|
-
|
|
44714
|
-
|
|
44715
|
-
|
|
44716
|
-
|
|
44717
|
-
|
|
44718
|
-
|
|
44719
|
-
|
|
44720
|
-
|
|
44721
|
-
|
|
44722
|
-
},
|
|
44723
|
-
itemFields: [
|
|
44724
|
-
{
|
|
44725
|
-
type: "boolean",
|
|
44726
|
-
key: "enabled",
|
|
44727
|
-
label: "Enabled",
|
|
44728
|
-
default: true
|
|
44729
|
-
},
|
|
44730
|
-
{
|
|
44731
|
-
type: "text",
|
|
44732
|
-
key: "profileId",
|
|
44733
|
-
label: "Profile ID",
|
|
44734
|
-
description: "Stable lowercase slug, for example gpu-monitor.",
|
|
44735
|
-
required: true
|
|
44736
|
-
},
|
|
44737
|
-
{
|
|
44738
|
-
type: "text",
|
|
44739
|
-
key: "label",
|
|
44740
|
-
label: "Display name",
|
|
44741
|
-
required: true
|
|
44742
|
-
},
|
|
44743
|
-
{
|
|
44744
|
-
type: "textarea",
|
|
44745
|
-
key: "description",
|
|
44746
|
-
label: "Description",
|
|
44747
|
-
rows: 2
|
|
44748
|
-
},
|
|
44749
|
-
{
|
|
44750
|
-
type: "text",
|
|
44751
|
-
key: "executable",
|
|
44752
|
-
label: "Executable",
|
|
44753
|
-
description: "Absolute path or a binary resolved from PATH.",
|
|
44754
|
-
required: true
|
|
44755
|
-
},
|
|
44756
|
-
{
|
|
44757
|
-
type: "tags",
|
|
44758
|
-
key: "args",
|
|
44759
|
-
label: "Arguments",
|
|
44760
|
-
description: "One exact process argument per tag.",
|
|
44761
|
-
maxTags: 64
|
|
44762
|
-
},
|
|
44763
|
-
{
|
|
44764
|
-
type: "text",
|
|
44765
|
-
key: "cwd",
|
|
44766
|
-
label: "Working directory",
|
|
44767
|
-
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: []
|
|
44768
44849
|
},
|
|
44769
|
-
|
|
44770
|
-
|
|
44771
|
-
|
|
44772
|
-
|
|
44773
|
-
|
|
44774
|
-
|
|
44775
|
-
|
|
44776
|
-
|
|
44777
|
-
|
|
44778
|
-
|
|
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
|
+
] });
|
|
44779
44907
|
}
|
|
44780
44908
|
};
|
|
44781
44909
|
//#endregion
|