@camstack/addon-terminal 0.1.29 → 0.1.30
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 +219 -22
- package/dist/addon.mjs +219 -22
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -20032,7 +20032,12 @@ var TerminalSessionInfoSchema = object({
|
|
|
20032
20032
|
var TerminalProfileInfoSchema = object({
|
|
20033
20033
|
profileId: string(),
|
|
20034
20034
|
label: string(),
|
|
20035
|
-
description: string().optional()
|
|
20035
|
+
description: string().optional(),
|
|
20036
|
+
/** Spawn defaults the instance form copies on create. */
|
|
20037
|
+
executable: string().optional(),
|
|
20038
|
+
args: array(string()).readonly().optional(),
|
|
20039
|
+
cwd: string().optional(),
|
|
20040
|
+
environment: array(string()).readonly().optional()
|
|
20036
20041
|
});
|
|
20037
20042
|
/**
|
|
20038
20043
|
* A durable operator-created Terminal instance. Profiles are templates; only
|
|
@@ -20045,7 +20050,11 @@ var TerminalInstanceInfoSchema = object({
|
|
|
20045
20050
|
profileId: string(),
|
|
20046
20051
|
profileLabel: string(),
|
|
20047
20052
|
name: string(),
|
|
20048
|
-
enabled: boolean()
|
|
20053
|
+
enabled: boolean(),
|
|
20054
|
+
executable: string(),
|
|
20055
|
+
args: array(string()).readonly(),
|
|
20056
|
+
cwd: string(),
|
|
20057
|
+
environment: array(string()).readonly()
|
|
20049
20058
|
});
|
|
20050
20059
|
var TerminalLegacyCameraSchema = object({
|
|
20051
20060
|
stableId: string(),
|
|
@@ -20091,7 +20100,22 @@ var terminalSessionCapability = {
|
|
|
20091
20100
|
createInstance: method(object({
|
|
20092
20101
|
targetNodeId: string().min(1),
|
|
20093
20102
|
profileId: string().min(1),
|
|
20094
|
-
name: string().trim().min(1).max(160).optional()
|
|
20103
|
+
name: string().trim().min(1).max(160).optional(),
|
|
20104
|
+
executable: string().max(1024).optional(),
|
|
20105
|
+
args: array(string().max(2048)).max(64).optional(),
|
|
20106
|
+
cwd: string().max(1024).optional(),
|
|
20107
|
+
environment: array(string().max(4096)).max(64).optional()
|
|
20108
|
+
}), TerminalInstanceInfoSchema, {
|
|
20109
|
+
kind: "mutation",
|
|
20110
|
+
auth: "admin"
|
|
20111
|
+
}),
|
|
20112
|
+
updateInstance: method(object({
|
|
20113
|
+
instanceId: string().min(1),
|
|
20114
|
+
name: string().trim().min(1).max(160).optional(),
|
|
20115
|
+
executable: string().max(1024).optional(),
|
|
20116
|
+
args: array(string().max(2048)).max(64).optional(),
|
|
20117
|
+
cwd: string().max(1024).optional(),
|
|
20118
|
+
environment: array(string().max(4096)).max(64).optional()
|
|
20095
20119
|
}), TerminalInstanceInfoSchema, {
|
|
20096
20120
|
kind: "mutation",
|
|
20097
20121
|
auth: "admin"
|
|
@@ -20126,7 +20150,11 @@ var terminalSessionCapability = {
|
|
|
20126
20150
|
openSession: method(object({
|
|
20127
20151
|
profileId: string(),
|
|
20128
20152
|
cols: number().int().positive(),
|
|
20129
|
-
rows: number().int().positive()
|
|
20153
|
+
rows: number().int().positive(),
|
|
20154
|
+
executable: string().max(1024).optional(),
|
|
20155
|
+
args: array(string().max(2048)).max(64).optional(),
|
|
20156
|
+
cwd: string().max(1024).optional(),
|
|
20157
|
+
environment: array(string().max(4096)).max(64).optional()
|
|
20130
20158
|
}), TerminalSessionInfoSchema, {
|
|
20131
20159
|
kind: "mutation",
|
|
20132
20160
|
auth: "admin"
|
|
@@ -24181,6 +24209,20 @@ var AllowedAddressesSchema = object({
|
|
|
24181
24209
|
* Network Addresses admin page and persisted by the addon.
|
|
24182
24210
|
*/
|
|
24183
24211
|
addresses: array(string()).readonly() });
|
|
24212
|
+
var TlsStatusSchema = object({
|
|
24213
|
+
mode: _enum([
|
|
24214
|
+
"generated",
|
|
24215
|
+
"uploaded",
|
|
24216
|
+
"disabled"
|
|
24217
|
+
]),
|
|
24218
|
+
leafFingerprintSha256: string().nullable(),
|
|
24219
|
+
caFingerprintSha256: string().nullable(),
|
|
24220
|
+
validTo: string().nullable(),
|
|
24221
|
+
sans: array(string()),
|
|
24222
|
+
caCertPem: string().nullable(),
|
|
24223
|
+
reissueError: string().nullable(),
|
|
24224
|
+
restartRequired: boolean()
|
|
24225
|
+
});
|
|
24184
24226
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24185
24227
|
/**
|
|
24186
24228
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -24200,7 +24242,20 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
24200
24242
|
* to avoid mixed-content blocks in the browser. The public
|
|
24201
24243
|
* tunnel always emits `https://` regardless. */
|
|
24202
24244
|
scheme: _enum(["http", "https"]).optional()
|
|
24203
|
-
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" })
|
|
24245
|
+
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
|
|
24246
|
+
kind: "mutation",
|
|
24247
|
+
auth: "admin"
|
|
24248
|
+
}), method(object({
|
|
24249
|
+
certPem: string().min(1),
|
|
24250
|
+
keyPem: string().min(1),
|
|
24251
|
+
caPem: string().optional()
|
|
24252
|
+
}), TlsStatusSchema, {
|
|
24253
|
+
kind: "mutation",
|
|
24254
|
+
auth: "admin"
|
|
24255
|
+
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
24256
|
+
kind: "mutation",
|
|
24257
|
+
auth: "admin"
|
|
24258
|
+
});
|
|
24204
24259
|
var LockControlStatusSchema = object({
|
|
24205
24260
|
/** Lifecycle state of the lock. `jammed` means the motor reported
|
|
24206
24261
|
* failure to reach the target — operator intervention required. */
|
|
@@ -32225,6 +32280,12 @@ Object.freeze({
|
|
|
32225
32280
|
addonId: null,
|
|
32226
32281
|
access: "create"
|
|
32227
32282
|
},
|
|
32283
|
+
"localNetwork.downloadCa": {
|
|
32284
|
+
capName: "local-network",
|
|
32285
|
+
capScope: "system",
|
|
32286
|
+
addonId: null,
|
|
32287
|
+
access: "view"
|
|
32288
|
+
},
|
|
32228
32289
|
"localNetwork.getAllowedAddresses": {
|
|
32229
32290
|
capName: "local-network",
|
|
32230
32291
|
capScope: "system",
|
|
@@ -32249,18 +32310,36 @@ Object.freeze({
|
|
|
32249
32310
|
addonId: null,
|
|
32250
32311
|
access: "view"
|
|
32251
32312
|
},
|
|
32313
|
+
"localNetwork.getTlsStatus": {
|
|
32314
|
+
capName: "local-network",
|
|
32315
|
+
capScope: "system",
|
|
32316
|
+
addonId: null,
|
|
32317
|
+
access: "view"
|
|
32318
|
+
},
|
|
32252
32319
|
"localNetwork.list": {
|
|
32253
32320
|
capName: "local-network",
|
|
32254
32321
|
capScope: "system",
|
|
32255
32322
|
addonId: null,
|
|
32256
32323
|
access: "view"
|
|
32257
32324
|
},
|
|
32325
|
+
"localNetwork.regenerateCertificate": {
|
|
32326
|
+
capName: "local-network",
|
|
32327
|
+
capScope: "system",
|
|
32328
|
+
addonId: null,
|
|
32329
|
+
access: "create"
|
|
32330
|
+
},
|
|
32258
32331
|
"localNetwork.resetAllowlistToBestMatch": {
|
|
32259
32332
|
capName: "local-network",
|
|
32260
32333
|
capScope: "system",
|
|
32261
32334
|
addonId: null,
|
|
32262
32335
|
access: "delete"
|
|
32263
32336
|
},
|
|
32337
|
+
"localNetwork.revertToGeneratedCertificate": {
|
|
32338
|
+
capName: "local-network",
|
|
32339
|
+
capScope: "system",
|
|
32340
|
+
addonId: null,
|
|
32341
|
+
access: "create"
|
|
32342
|
+
},
|
|
32264
32343
|
"localNetwork.setAllowedAddresses": {
|
|
32265
32344
|
capName: "local-network",
|
|
32266
32345
|
capScope: "system",
|
|
@@ -32273,6 +32352,12 @@ Object.freeze({
|
|
|
32273
32352
|
addonId: null,
|
|
32274
32353
|
access: "create"
|
|
32275
32354
|
},
|
|
32355
|
+
"localNetwork.uploadCertificate": {
|
|
32356
|
+
capName: "local-network",
|
|
32357
|
+
capScope: "system",
|
|
32358
|
+
addonId: null,
|
|
32359
|
+
access: "create"
|
|
32360
|
+
},
|
|
32276
32361
|
"lockControl.lock": {
|
|
32277
32362
|
capName: "lock-control",
|
|
32278
32363
|
capScope: "device",
|
|
@@ -35153,6 +35238,12 @@ Object.freeze({
|
|
|
35153
35238
|
addonId: null,
|
|
35154
35239
|
access: "create"
|
|
35155
35240
|
},
|
|
35241
|
+
"terminalSession.updateInstance": {
|
|
35242
|
+
capName: "terminal-session",
|
|
35243
|
+
capScope: "system",
|
|
35244
|
+
addonId: null,
|
|
35245
|
+
access: "create"
|
|
35246
|
+
},
|
|
35156
35247
|
"terminalSession.writeInput": {
|
|
35157
35248
|
capName: "terminal-session",
|
|
35158
35249
|
capScope: "system",
|
|
@@ -37640,6 +37731,35 @@ Object.freeze(Object.fromEntries([{
|
|
|
37640
37731
|
}]
|
|
37641
37732
|
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
37642
37733
|
string().min(1);
|
|
37734
|
+
var CLUSTER_STEP_SETTING_FIELDS = [{
|
|
37735
|
+
stepId: "face-embedding",
|
|
37736
|
+
key: "minLandmarkFaceSize",
|
|
37737
|
+
label: "Min face size for recognition (detection px)",
|
|
37738
|
+
description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
|
|
37739
|
+
type: "slider",
|
|
37740
|
+
min: 0,
|
|
37741
|
+
max: 64,
|
|
37742
|
+
step: 2,
|
|
37743
|
+
default: 24
|
|
37744
|
+
}];
|
|
37745
|
+
function clusterStepSettingKey(stepId, fieldKey) {
|
|
37746
|
+
return `clusterStepSetting:${stepId}:${fieldKey}`;
|
|
37747
|
+
}
|
|
37748
|
+
var ClusterSettingNumberSchema = number().finite();
|
|
37749
|
+
function readClusterStepSettings(config) {
|
|
37750
|
+
const out = {};
|
|
37751
|
+
for (const field of CLUSTER_STEP_SETTING_FIELDS) {
|
|
37752
|
+
const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
|
|
37753
|
+
const value = parsed.success ? parsed.data : field.default;
|
|
37754
|
+
const existing = out[field.stepId] ?? {};
|
|
37755
|
+
out[field.stepId] = {
|
|
37756
|
+
...existing,
|
|
37757
|
+
[field.key]: value
|
|
37758
|
+
};
|
|
37759
|
+
}
|
|
37760
|
+
return out;
|
|
37761
|
+
}
|
|
37762
|
+
readClusterStepSettings({});
|
|
37643
37763
|
object({
|
|
37644
37764
|
/**
|
|
37645
37765
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -43347,7 +43467,8 @@ var TerminalCameraRelay = class {
|
|
|
43347
43467
|
const opening = this.api.openSession(state.nodeId, {
|
|
43348
43468
|
profileId: state.profileId,
|
|
43349
43469
|
cols: 120,
|
|
43350
|
-
rows: 40
|
|
43470
|
+
rows: 40,
|
|
43471
|
+
instanceId: state.instanceId
|
|
43351
43472
|
});
|
|
43352
43473
|
state.openPromise = opening;
|
|
43353
43474
|
try {
|
|
@@ -43734,8 +43855,25 @@ var TerminalInstanceSchema = object({
|
|
|
43734
43855
|
profileId: string().min(1).max(64),
|
|
43735
43856
|
profileLabel: string().min(1).max(120),
|
|
43736
43857
|
name: string().min(1).max(160),
|
|
43737
|
-
enabled: boolean()
|
|
43858
|
+
enabled: boolean(),
|
|
43859
|
+
executable: string().max(1024).default(""),
|
|
43860
|
+
args: array(string().max(2048)).max(64).default([]),
|
|
43861
|
+
cwd: string().max(1024).default(""),
|
|
43862
|
+
environment: array(string().max(4096)).max(64).default([])
|
|
43738
43863
|
});
|
|
43864
|
+
function environmentEntriesToRecord(entries) {
|
|
43865
|
+
const out = {};
|
|
43866
|
+
for (const entry of entries) {
|
|
43867
|
+
const eq = entry.indexOf("=");
|
|
43868
|
+
if (eq <= 0) continue;
|
|
43869
|
+
out[entry.slice(0, eq)] = entry.slice(eq + 1);
|
|
43870
|
+
}
|
|
43871
|
+
return out;
|
|
43872
|
+
}
|
|
43873
|
+
function environmentRecordToEntries(env) {
|
|
43874
|
+
if (env === void 0) return [];
|
|
43875
|
+
return Object.entries(env).map(([name, value]) => `${name}=${value}`);
|
|
43876
|
+
}
|
|
43739
43877
|
/**
|
|
43740
43878
|
* Config is operator-writable, so malformed or duplicate rows are ignored
|
|
43741
43879
|
* rather than allowed to make declaration reconciliation destructive.
|
|
@@ -43999,7 +44137,11 @@ var TerminalSessionManager = class {
|
|
|
43999
44137
|
return this.profiles.map((p) => ({
|
|
44000
44138
|
profileId: p.profileId,
|
|
44001
44139
|
label: p.label,
|
|
44002
|
-
...p.description !== void 0 ? { description: p.description } : {}
|
|
44140
|
+
...p.description !== void 0 ? { description: p.description } : {},
|
|
44141
|
+
executable: p.file,
|
|
44142
|
+
args: [...p.args],
|
|
44143
|
+
cwd: p.cwd ?? "",
|
|
44144
|
+
environment: environmentRecordToEntries(p.env)
|
|
44003
44145
|
}));
|
|
44004
44146
|
}
|
|
44005
44147
|
setInstanceControl(control) {
|
|
@@ -44011,6 +44153,9 @@ var TerminalSessionManager = class {
|
|
|
44011
44153
|
async createInstance(input) {
|
|
44012
44154
|
return this.requireInstanceControl().createInstance(input);
|
|
44013
44155
|
}
|
|
44156
|
+
async updateInstance(input) {
|
|
44157
|
+
return this.requireInstanceControl().updateInstance(input);
|
|
44158
|
+
}
|
|
44014
44159
|
async deleteInstance(input) {
|
|
44015
44160
|
await this.requireInstanceControl().deleteInstance(input);
|
|
44016
44161
|
}
|
|
@@ -44033,24 +44178,29 @@ var TerminalSessionManager = class {
|
|
|
44033
44178
|
const cols = clampDimension(input.cols, MAX_COLS);
|
|
44034
44179
|
const rows = clampDimension(input.rows, MAX_ROWS);
|
|
44035
44180
|
const sessionId = this.mintId();
|
|
44181
|
+
const file = input.executable?.trim() || profile.file;
|
|
44182
|
+
const args = input.args !== void 0 ? [...input.args] : [...profile.args];
|
|
44183
|
+
const cwd = input.cwd?.trim() || profile.cwd || this.opts.cwd;
|
|
44184
|
+
const env = {
|
|
44185
|
+
...this.opts.env,
|
|
44186
|
+
...profile.env,
|
|
44187
|
+
...environmentEntriesToRecord(input.environment ?? [])
|
|
44188
|
+
};
|
|
44036
44189
|
const executable = [{
|
|
44037
|
-
file
|
|
44038
|
-
args
|
|
44039
|
-
}, ...profile.fallbacks ?? []].map((candidate) => ({
|
|
44190
|
+
file,
|
|
44191
|
+
args
|
|
44192
|
+
}, ...input.executable?.trim() ? [] : profile.fallbacks ?? []].map((candidate) => ({
|
|
44040
44193
|
...candidate,
|
|
44041
44194
|
resolvedFile: this.resolveBinary(candidate.file)
|
|
44042
44195
|
})).find((candidate) => candidate.resolvedFile !== null);
|
|
44043
|
-
if (executable === void 0) throw new Error(`Terminal profile '${profile.profileId}' cannot start: executable '${
|
|
44196
|
+
if (executable === void 0) throw new Error(`Terminal profile '${profile.profileId}' cannot start: executable '${file}' was not found on PATH. Install it in the server image or set its path in Terminal settings.`);
|
|
44044
44197
|
const pty = this.opts.spawn({
|
|
44045
44198
|
file: executable.resolvedFile,
|
|
44046
44199
|
args: executable.args,
|
|
44047
44200
|
cols,
|
|
44048
44201
|
rows,
|
|
44049
|
-
...
|
|
44050
|
-
...
|
|
44051
|
-
...this.opts.env,
|
|
44052
|
-
...profile.env
|
|
44053
|
-
} } : {}
|
|
44202
|
+
...cwd !== void 0 && cwd !== "" ? { cwd } : {},
|
|
44203
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
44054
44204
|
});
|
|
44055
44205
|
const screen = this.opts.screenFactory(cols, rows);
|
|
44056
44206
|
const info = {
|
|
@@ -44148,7 +44298,7 @@ var TerminalSessionManager = class {
|
|
|
44148
44298
|
const oldestSeq = session.output[0]?.seq ?? session.nextSeq;
|
|
44149
44299
|
if (input.afterSeq === 0 || input.afterSeq < oldestSeq - 1 || input.afterSeq > cursor) {
|
|
44150
44300
|
await session.screen.flush();
|
|
44151
|
-
const exit =
|
|
44301
|
+
const exit = session.output.toReversed().find((event) => event.kind === "exit");
|
|
44152
44302
|
return {
|
|
44153
44303
|
cursor,
|
|
44154
44304
|
reset: true,
|
|
@@ -44392,7 +44542,21 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44392
44542
|
const localNodeId = declarationOwnerNodeId(this.ctx.kernel.localNodeId);
|
|
44393
44543
|
const cameraRelay = new TerminalCameraRelay({
|
|
44394
44544
|
listProfiles: (nodeId) => nodeId === localNodeId ? manager.listProfiles() : this.ctx.api.terminalSession.listProfiles.query(void 0, nodePin(nodeId)),
|
|
44395
|
-
openSession: (nodeId, input) =>
|
|
44545
|
+
openSession: (nodeId, input) => {
|
|
44546
|
+
const instance = input.instanceId ? this.terminalInstances().find((row) => row.id === input.instanceId) : void 0;
|
|
44547
|
+
const payload = {
|
|
44548
|
+
profileId: input.profileId,
|
|
44549
|
+
cols: input.cols,
|
|
44550
|
+
rows: input.rows,
|
|
44551
|
+
...instance ? {
|
|
44552
|
+
...instance.executable ? { executable: instance.executable } : {},
|
|
44553
|
+
...instance.args.length > 0 ? { args: [...instance.args] } : {},
|
|
44554
|
+
...instance.cwd ? { cwd: instance.cwd } : {},
|
|
44555
|
+
...instance.environment.length > 0 ? { environment: [...instance.environment] } : {}
|
|
44556
|
+
} : {}
|
|
44557
|
+
};
|
|
44558
|
+
return nodeId === localNodeId ? manager.openSession(payload) : this.ctx.api.terminalSession.openSession.mutate(payload, nodePin(nodeId));
|
|
44559
|
+
},
|
|
44396
44560
|
pullOutput: (nodeId, input) => nodeId === localNodeId ? manager.pullOutput(input) : this.ctx.api.terminalSession.pullOutput.mutate(input, nodePin(nodeId)),
|
|
44397
44561
|
closeSession: async (nodeId, sessionId) => {
|
|
44398
44562
|
if (nodeId === localNodeId) await manager.close({ sessionId });
|
|
@@ -44597,6 +44761,7 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44597
44761
|
return {
|
|
44598
44762
|
listInstances: async () => this.terminalInstances().map((instance) => this.instanceInfo(instance)),
|
|
44599
44763
|
createInstance: async (input) => this.createTerminalInstance(input),
|
|
44764
|
+
updateInstance: async (input) => this.updateTerminalInstance(input),
|
|
44600
44765
|
deleteInstance: async ({ instanceId }) => this.deleteTerminalInstance(instanceId),
|
|
44601
44766
|
setInstanceEnabled: async ({ instanceId, enabled }) => this.setTerminalInstanceEnabled(instanceId, enabled),
|
|
44602
44767
|
listLegacyCameras: async () => this.listLegacyTerminalCameras(),
|
|
@@ -44616,7 +44781,11 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44616
44781
|
profileId: instance.profileId,
|
|
44617
44782
|
profileLabel: instance.profileLabel,
|
|
44618
44783
|
name: instance.name,
|
|
44619
|
-
enabled: instance.enabled
|
|
44784
|
+
enabled: instance.enabled,
|
|
44785
|
+
executable: instance.executable,
|
|
44786
|
+
args: instance.args,
|
|
44787
|
+
cwd: instance.cwd,
|
|
44788
|
+
environment: instance.environment
|
|
44620
44789
|
};
|
|
44621
44790
|
}
|
|
44622
44791
|
replaceTerminalCameraTombstones(stableIds) {
|
|
@@ -44644,11 +44813,35 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44644
44813
|
profileId: profile.profileId,
|
|
44645
44814
|
profileLabel: profile.label,
|
|
44646
44815
|
name,
|
|
44647
|
-
enabled: true
|
|
44816
|
+
enabled: true,
|
|
44817
|
+
executable: input.executable?.trim() || profile.executable || "",
|
|
44818
|
+
args: input.args ? [...input.args] : [...profile.args ?? []],
|
|
44819
|
+
cwd: input.cwd?.trim() || profile.cwd || "",
|
|
44820
|
+
environment: input.environment ? [...input.environment] : [...profile.environment ?? []]
|
|
44648
44821
|
};
|
|
44649
44822
|
await this.updateGlobalSettings({ terminalInstances: [...this.config.terminalInstances, instance] });
|
|
44650
44823
|
return this.instanceInfo(instance);
|
|
44651
44824
|
}
|
|
44825
|
+
async updateTerminalInstance(input) {
|
|
44826
|
+
const updated = await this.instanceMutationQueue.run(() => this.updateTerminalInstanceUnlocked(input));
|
|
44827
|
+
await this.cameraRelay?.closeInstance(updated.instanceId);
|
|
44828
|
+
await this.reconcileTerminalCameras();
|
|
44829
|
+
return updated;
|
|
44830
|
+
}
|
|
44831
|
+
async updateTerminalInstanceUnlocked(input) {
|
|
44832
|
+
const instance = this.terminalInstances().find((candidate) => candidate.id === input.instanceId);
|
|
44833
|
+
if (!instance) throw new Error(`No such Terminal instance: ${input.instanceId}`);
|
|
44834
|
+
const updated = {
|
|
44835
|
+
...instance,
|
|
44836
|
+
...input.name !== void 0 ? { name: input.name.trim() } : {},
|
|
44837
|
+
...input.executable !== void 0 ? { executable: input.executable.trim() } : {},
|
|
44838
|
+
...input.args !== void 0 ? { args: [...input.args] } : {},
|
|
44839
|
+
...input.cwd !== void 0 ? { cwd: input.cwd.trim() } : {},
|
|
44840
|
+
...input.environment !== void 0 ? { environment: [...input.environment] } : {}
|
|
44841
|
+
};
|
|
44842
|
+
await this.updateGlobalSettings({ terminalInstances: this.config.terminalInstances.map((candidate) => candidate.id === input.instanceId ? updated : candidate) });
|
|
44843
|
+
return this.instanceInfo(updated);
|
|
44844
|
+
}
|
|
44652
44845
|
async deleteTerminalInstance(instanceId) {
|
|
44653
44846
|
await this.instanceMutationQueue.run(() => this.deleteTerminalInstanceUnlocked(instanceId));
|
|
44654
44847
|
await this.reconcileTerminalCameras();
|
|
@@ -44708,7 +44901,11 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44708
44901
|
profileId: "monitor",
|
|
44709
44902
|
profileLabel: legacy.profileLabel,
|
|
44710
44903
|
name: requestedName?.trim() || legacy.name,
|
|
44711
|
-
enabled: true
|
|
44904
|
+
enabled: true,
|
|
44905
|
+
executable: "",
|
|
44906
|
+
args: [],
|
|
44907
|
+
cwd: "",
|
|
44908
|
+
environment: []
|
|
44712
44909
|
};
|
|
44713
44910
|
await this.updateGlobalSettings({ terminalInstances: [...this.config.terminalInstances, instance] });
|
|
44714
44911
|
return this.instanceInfo(instance);
|
package/dist/addon.mjs
CHANGED
|
@@ -20009,7 +20009,12 @@ var TerminalSessionInfoSchema = object({
|
|
|
20009
20009
|
var TerminalProfileInfoSchema = object({
|
|
20010
20010
|
profileId: string(),
|
|
20011
20011
|
label: string(),
|
|
20012
|
-
description: string().optional()
|
|
20012
|
+
description: string().optional(),
|
|
20013
|
+
/** Spawn defaults the instance form copies on create. */
|
|
20014
|
+
executable: string().optional(),
|
|
20015
|
+
args: array(string()).readonly().optional(),
|
|
20016
|
+
cwd: string().optional(),
|
|
20017
|
+
environment: array(string()).readonly().optional()
|
|
20013
20018
|
});
|
|
20014
20019
|
/**
|
|
20015
20020
|
* A durable operator-created Terminal instance. Profiles are templates; only
|
|
@@ -20022,7 +20027,11 @@ var TerminalInstanceInfoSchema = object({
|
|
|
20022
20027
|
profileId: string(),
|
|
20023
20028
|
profileLabel: string(),
|
|
20024
20029
|
name: string(),
|
|
20025
|
-
enabled: boolean()
|
|
20030
|
+
enabled: boolean(),
|
|
20031
|
+
executable: string(),
|
|
20032
|
+
args: array(string()).readonly(),
|
|
20033
|
+
cwd: string(),
|
|
20034
|
+
environment: array(string()).readonly()
|
|
20026
20035
|
});
|
|
20027
20036
|
var TerminalLegacyCameraSchema = object({
|
|
20028
20037
|
stableId: string(),
|
|
@@ -20068,7 +20077,22 @@ var terminalSessionCapability = {
|
|
|
20068
20077
|
createInstance: method(object({
|
|
20069
20078
|
targetNodeId: string().min(1),
|
|
20070
20079
|
profileId: string().min(1),
|
|
20071
|
-
name: string().trim().min(1).max(160).optional()
|
|
20080
|
+
name: string().trim().min(1).max(160).optional(),
|
|
20081
|
+
executable: string().max(1024).optional(),
|
|
20082
|
+
args: array(string().max(2048)).max(64).optional(),
|
|
20083
|
+
cwd: string().max(1024).optional(),
|
|
20084
|
+
environment: array(string().max(4096)).max(64).optional()
|
|
20085
|
+
}), TerminalInstanceInfoSchema, {
|
|
20086
|
+
kind: "mutation",
|
|
20087
|
+
auth: "admin"
|
|
20088
|
+
}),
|
|
20089
|
+
updateInstance: method(object({
|
|
20090
|
+
instanceId: string().min(1),
|
|
20091
|
+
name: string().trim().min(1).max(160).optional(),
|
|
20092
|
+
executable: string().max(1024).optional(),
|
|
20093
|
+
args: array(string().max(2048)).max(64).optional(),
|
|
20094
|
+
cwd: string().max(1024).optional(),
|
|
20095
|
+
environment: array(string().max(4096)).max(64).optional()
|
|
20072
20096
|
}), TerminalInstanceInfoSchema, {
|
|
20073
20097
|
kind: "mutation",
|
|
20074
20098
|
auth: "admin"
|
|
@@ -20103,7 +20127,11 @@ var terminalSessionCapability = {
|
|
|
20103
20127
|
openSession: method(object({
|
|
20104
20128
|
profileId: string(),
|
|
20105
20129
|
cols: number().int().positive(),
|
|
20106
|
-
rows: number().int().positive()
|
|
20130
|
+
rows: number().int().positive(),
|
|
20131
|
+
executable: string().max(1024).optional(),
|
|
20132
|
+
args: array(string().max(2048)).max(64).optional(),
|
|
20133
|
+
cwd: string().max(1024).optional(),
|
|
20134
|
+
environment: array(string().max(4096)).max(64).optional()
|
|
20107
20135
|
}), TerminalSessionInfoSchema, {
|
|
20108
20136
|
kind: "mutation",
|
|
20109
20137
|
auth: "admin"
|
|
@@ -24158,6 +24186,20 @@ var AllowedAddressesSchema = object({
|
|
|
24158
24186
|
* Network Addresses admin page and persisted by the addon.
|
|
24159
24187
|
*/
|
|
24160
24188
|
addresses: array(string()).readonly() });
|
|
24189
|
+
var TlsStatusSchema = object({
|
|
24190
|
+
mode: _enum([
|
|
24191
|
+
"generated",
|
|
24192
|
+
"uploaded",
|
|
24193
|
+
"disabled"
|
|
24194
|
+
]),
|
|
24195
|
+
leafFingerprintSha256: string().nullable(),
|
|
24196
|
+
caFingerprintSha256: string().nullable(),
|
|
24197
|
+
validTo: string().nullable(),
|
|
24198
|
+
sans: array(string()),
|
|
24199
|
+
caCertPem: string().nullable(),
|
|
24200
|
+
reissueError: string().nullable(),
|
|
24201
|
+
restartRequired: boolean()
|
|
24202
|
+
});
|
|
24161
24203
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
24162
24204
|
/**
|
|
24163
24205
|
* LEGACY HINT — do not send from new code. Kept optional so clients
|
|
@@ -24177,7 +24219,20 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
24177
24219
|
* to avoid mixed-content blocks in the browser. The public
|
|
24178
24220
|
* tunnel always emits `https://` regardless. */
|
|
24179
24221
|
scheme: _enum(["http", "https"]).optional()
|
|
24180
|
-
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" })
|
|
24222
|
+
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
|
|
24223
|
+
kind: "mutation",
|
|
24224
|
+
auth: "admin"
|
|
24225
|
+
}), method(object({
|
|
24226
|
+
certPem: string().min(1),
|
|
24227
|
+
keyPem: string().min(1),
|
|
24228
|
+
caPem: string().optional()
|
|
24229
|
+
}), TlsStatusSchema, {
|
|
24230
|
+
kind: "mutation",
|
|
24231
|
+
auth: "admin"
|
|
24232
|
+
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
24233
|
+
kind: "mutation",
|
|
24234
|
+
auth: "admin"
|
|
24235
|
+
});
|
|
24181
24236
|
var LockControlStatusSchema = object({
|
|
24182
24237
|
/** Lifecycle state of the lock. `jammed` means the motor reported
|
|
24183
24238
|
* failure to reach the target — operator intervention required. */
|
|
@@ -32202,6 +32257,12 @@ Object.freeze({
|
|
|
32202
32257
|
addonId: null,
|
|
32203
32258
|
access: "create"
|
|
32204
32259
|
},
|
|
32260
|
+
"localNetwork.downloadCa": {
|
|
32261
|
+
capName: "local-network",
|
|
32262
|
+
capScope: "system",
|
|
32263
|
+
addonId: null,
|
|
32264
|
+
access: "view"
|
|
32265
|
+
},
|
|
32205
32266
|
"localNetwork.getAllowedAddresses": {
|
|
32206
32267
|
capName: "local-network",
|
|
32207
32268
|
capScope: "system",
|
|
@@ -32226,18 +32287,36 @@ Object.freeze({
|
|
|
32226
32287
|
addonId: null,
|
|
32227
32288
|
access: "view"
|
|
32228
32289
|
},
|
|
32290
|
+
"localNetwork.getTlsStatus": {
|
|
32291
|
+
capName: "local-network",
|
|
32292
|
+
capScope: "system",
|
|
32293
|
+
addonId: null,
|
|
32294
|
+
access: "view"
|
|
32295
|
+
},
|
|
32229
32296
|
"localNetwork.list": {
|
|
32230
32297
|
capName: "local-network",
|
|
32231
32298
|
capScope: "system",
|
|
32232
32299
|
addonId: null,
|
|
32233
32300
|
access: "view"
|
|
32234
32301
|
},
|
|
32302
|
+
"localNetwork.regenerateCertificate": {
|
|
32303
|
+
capName: "local-network",
|
|
32304
|
+
capScope: "system",
|
|
32305
|
+
addonId: null,
|
|
32306
|
+
access: "create"
|
|
32307
|
+
},
|
|
32235
32308
|
"localNetwork.resetAllowlistToBestMatch": {
|
|
32236
32309
|
capName: "local-network",
|
|
32237
32310
|
capScope: "system",
|
|
32238
32311
|
addonId: null,
|
|
32239
32312
|
access: "delete"
|
|
32240
32313
|
},
|
|
32314
|
+
"localNetwork.revertToGeneratedCertificate": {
|
|
32315
|
+
capName: "local-network",
|
|
32316
|
+
capScope: "system",
|
|
32317
|
+
addonId: null,
|
|
32318
|
+
access: "create"
|
|
32319
|
+
},
|
|
32241
32320
|
"localNetwork.setAllowedAddresses": {
|
|
32242
32321
|
capName: "local-network",
|
|
32243
32322
|
capScope: "system",
|
|
@@ -32250,6 +32329,12 @@ Object.freeze({
|
|
|
32250
32329
|
addonId: null,
|
|
32251
32330
|
access: "create"
|
|
32252
32331
|
},
|
|
32332
|
+
"localNetwork.uploadCertificate": {
|
|
32333
|
+
capName: "local-network",
|
|
32334
|
+
capScope: "system",
|
|
32335
|
+
addonId: null,
|
|
32336
|
+
access: "create"
|
|
32337
|
+
},
|
|
32253
32338
|
"lockControl.lock": {
|
|
32254
32339
|
capName: "lock-control",
|
|
32255
32340
|
capScope: "device",
|
|
@@ -35130,6 +35215,12 @@ Object.freeze({
|
|
|
35130
35215
|
addonId: null,
|
|
35131
35216
|
access: "create"
|
|
35132
35217
|
},
|
|
35218
|
+
"terminalSession.updateInstance": {
|
|
35219
|
+
capName: "terminal-session",
|
|
35220
|
+
capScope: "system",
|
|
35221
|
+
addonId: null,
|
|
35222
|
+
access: "create"
|
|
35223
|
+
},
|
|
35133
35224
|
"terminalSession.writeInput": {
|
|
35134
35225
|
capName: "terminal-session",
|
|
35135
35226
|
capScope: "system",
|
|
@@ -37617,6 +37708,35 @@ Object.freeze(Object.fromEntries([{
|
|
|
37617
37708
|
}]
|
|
37618
37709
|
}].map((s) => [s.stepId, s.defaultModelId])));
|
|
37619
37710
|
string().min(1);
|
|
37711
|
+
var CLUSTER_STEP_SETTING_FIELDS = [{
|
|
37712
|
+
stepId: "face-embedding",
|
|
37713
|
+
key: "minLandmarkFaceSize",
|
|
37714
|
+
label: "Min face size for recognition (detection px)",
|
|
37715
|
+
description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
|
|
37716
|
+
type: "slider",
|
|
37717
|
+
min: 0,
|
|
37718
|
+
max: 64,
|
|
37719
|
+
step: 2,
|
|
37720
|
+
default: 24
|
|
37721
|
+
}];
|
|
37722
|
+
function clusterStepSettingKey(stepId, fieldKey) {
|
|
37723
|
+
return `clusterStepSetting:${stepId}:${fieldKey}`;
|
|
37724
|
+
}
|
|
37725
|
+
var ClusterSettingNumberSchema = number().finite();
|
|
37726
|
+
function readClusterStepSettings(config) {
|
|
37727
|
+
const out = {};
|
|
37728
|
+
for (const field of CLUSTER_STEP_SETTING_FIELDS) {
|
|
37729
|
+
const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
|
|
37730
|
+
const value = parsed.success ? parsed.data : field.default;
|
|
37731
|
+
const existing = out[field.stepId] ?? {};
|
|
37732
|
+
out[field.stepId] = {
|
|
37733
|
+
...existing,
|
|
37734
|
+
[field.key]: value
|
|
37735
|
+
};
|
|
37736
|
+
}
|
|
37737
|
+
return out;
|
|
37738
|
+
}
|
|
37739
|
+
readClusterStepSettings({});
|
|
37620
37740
|
object({
|
|
37621
37741
|
/**
|
|
37622
37742
|
* Fraction of the box's own size added on EACH side before cutting.
|
|
@@ -43324,7 +43444,8 @@ var TerminalCameraRelay = class {
|
|
|
43324
43444
|
const opening = this.api.openSession(state.nodeId, {
|
|
43325
43445
|
profileId: state.profileId,
|
|
43326
43446
|
cols: 120,
|
|
43327
|
-
rows: 40
|
|
43447
|
+
rows: 40,
|
|
43448
|
+
instanceId: state.instanceId
|
|
43328
43449
|
});
|
|
43329
43450
|
state.openPromise = opening;
|
|
43330
43451
|
try {
|
|
@@ -43711,8 +43832,25 @@ var TerminalInstanceSchema = object({
|
|
|
43711
43832
|
profileId: string().min(1).max(64),
|
|
43712
43833
|
profileLabel: string().min(1).max(120),
|
|
43713
43834
|
name: string().min(1).max(160),
|
|
43714
|
-
enabled: boolean()
|
|
43835
|
+
enabled: boolean(),
|
|
43836
|
+
executable: string().max(1024).default(""),
|
|
43837
|
+
args: array(string().max(2048)).max(64).default([]),
|
|
43838
|
+
cwd: string().max(1024).default(""),
|
|
43839
|
+
environment: array(string().max(4096)).max(64).default([])
|
|
43715
43840
|
});
|
|
43841
|
+
function environmentEntriesToRecord(entries) {
|
|
43842
|
+
const out = {};
|
|
43843
|
+
for (const entry of entries) {
|
|
43844
|
+
const eq = entry.indexOf("=");
|
|
43845
|
+
if (eq <= 0) continue;
|
|
43846
|
+
out[entry.slice(0, eq)] = entry.slice(eq + 1);
|
|
43847
|
+
}
|
|
43848
|
+
return out;
|
|
43849
|
+
}
|
|
43850
|
+
function environmentRecordToEntries(env) {
|
|
43851
|
+
if (env === void 0) return [];
|
|
43852
|
+
return Object.entries(env).map(([name, value]) => `${name}=${value}`);
|
|
43853
|
+
}
|
|
43716
43854
|
/**
|
|
43717
43855
|
* Config is operator-writable, so malformed or duplicate rows are ignored
|
|
43718
43856
|
* rather than allowed to make declaration reconciliation destructive.
|
|
@@ -43976,7 +44114,11 @@ var TerminalSessionManager = class {
|
|
|
43976
44114
|
return this.profiles.map((p) => ({
|
|
43977
44115
|
profileId: p.profileId,
|
|
43978
44116
|
label: p.label,
|
|
43979
|
-
...p.description !== void 0 ? { description: p.description } : {}
|
|
44117
|
+
...p.description !== void 0 ? { description: p.description } : {},
|
|
44118
|
+
executable: p.file,
|
|
44119
|
+
args: [...p.args],
|
|
44120
|
+
cwd: p.cwd ?? "",
|
|
44121
|
+
environment: environmentRecordToEntries(p.env)
|
|
43980
44122
|
}));
|
|
43981
44123
|
}
|
|
43982
44124
|
setInstanceControl(control) {
|
|
@@ -43988,6 +44130,9 @@ var TerminalSessionManager = class {
|
|
|
43988
44130
|
async createInstance(input) {
|
|
43989
44131
|
return this.requireInstanceControl().createInstance(input);
|
|
43990
44132
|
}
|
|
44133
|
+
async updateInstance(input) {
|
|
44134
|
+
return this.requireInstanceControl().updateInstance(input);
|
|
44135
|
+
}
|
|
43991
44136
|
async deleteInstance(input) {
|
|
43992
44137
|
await this.requireInstanceControl().deleteInstance(input);
|
|
43993
44138
|
}
|
|
@@ -44010,24 +44155,29 @@ var TerminalSessionManager = class {
|
|
|
44010
44155
|
const cols = clampDimension(input.cols, MAX_COLS);
|
|
44011
44156
|
const rows = clampDimension(input.rows, MAX_ROWS);
|
|
44012
44157
|
const sessionId = this.mintId();
|
|
44158
|
+
const file = input.executable?.trim() || profile.file;
|
|
44159
|
+
const args = input.args !== void 0 ? [...input.args] : [...profile.args];
|
|
44160
|
+
const cwd = input.cwd?.trim() || profile.cwd || this.opts.cwd;
|
|
44161
|
+
const env = {
|
|
44162
|
+
...this.opts.env,
|
|
44163
|
+
...profile.env,
|
|
44164
|
+
...environmentEntriesToRecord(input.environment ?? [])
|
|
44165
|
+
};
|
|
44013
44166
|
const executable = [{
|
|
44014
|
-
file
|
|
44015
|
-
args
|
|
44016
|
-
}, ...profile.fallbacks ?? []].map((candidate) => ({
|
|
44167
|
+
file,
|
|
44168
|
+
args
|
|
44169
|
+
}, ...input.executable?.trim() ? [] : profile.fallbacks ?? []].map((candidate) => ({
|
|
44017
44170
|
...candidate,
|
|
44018
44171
|
resolvedFile: this.resolveBinary(candidate.file)
|
|
44019
44172
|
})).find((candidate) => candidate.resolvedFile !== null);
|
|
44020
|
-
if (executable === void 0) throw new Error(`Terminal profile '${profile.profileId}' cannot start: executable '${
|
|
44173
|
+
if (executable === void 0) throw new Error(`Terminal profile '${profile.profileId}' cannot start: executable '${file}' was not found on PATH. Install it in the server image or set its path in Terminal settings.`);
|
|
44021
44174
|
const pty = this.opts.spawn({
|
|
44022
44175
|
file: executable.resolvedFile,
|
|
44023
44176
|
args: executable.args,
|
|
44024
44177
|
cols,
|
|
44025
44178
|
rows,
|
|
44026
|
-
...
|
|
44027
|
-
...
|
|
44028
|
-
...this.opts.env,
|
|
44029
|
-
...profile.env
|
|
44030
|
-
} } : {}
|
|
44179
|
+
...cwd !== void 0 && cwd !== "" ? { cwd } : {},
|
|
44180
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
44031
44181
|
});
|
|
44032
44182
|
const screen = this.opts.screenFactory(cols, rows);
|
|
44033
44183
|
const info = {
|
|
@@ -44125,7 +44275,7 @@ var TerminalSessionManager = class {
|
|
|
44125
44275
|
const oldestSeq = session.output[0]?.seq ?? session.nextSeq;
|
|
44126
44276
|
if (input.afterSeq === 0 || input.afterSeq < oldestSeq - 1 || input.afterSeq > cursor) {
|
|
44127
44277
|
await session.screen.flush();
|
|
44128
|
-
const exit =
|
|
44278
|
+
const exit = session.output.toReversed().find((event) => event.kind === "exit");
|
|
44129
44279
|
return {
|
|
44130
44280
|
cursor,
|
|
44131
44281
|
reset: true,
|
|
@@ -44369,7 +44519,21 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44369
44519
|
const localNodeId = declarationOwnerNodeId(this.ctx.kernel.localNodeId);
|
|
44370
44520
|
const cameraRelay = new TerminalCameraRelay({
|
|
44371
44521
|
listProfiles: (nodeId) => nodeId === localNodeId ? manager.listProfiles() : this.ctx.api.terminalSession.listProfiles.query(void 0, nodePin(nodeId)),
|
|
44372
|
-
openSession: (nodeId, input) =>
|
|
44522
|
+
openSession: (nodeId, input) => {
|
|
44523
|
+
const instance = input.instanceId ? this.terminalInstances().find((row) => row.id === input.instanceId) : void 0;
|
|
44524
|
+
const payload = {
|
|
44525
|
+
profileId: input.profileId,
|
|
44526
|
+
cols: input.cols,
|
|
44527
|
+
rows: input.rows,
|
|
44528
|
+
...instance ? {
|
|
44529
|
+
...instance.executable ? { executable: instance.executable } : {},
|
|
44530
|
+
...instance.args.length > 0 ? { args: [...instance.args] } : {},
|
|
44531
|
+
...instance.cwd ? { cwd: instance.cwd } : {},
|
|
44532
|
+
...instance.environment.length > 0 ? { environment: [...instance.environment] } : {}
|
|
44533
|
+
} : {}
|
|
44534
|
+
};
|
|
44535
|
+
return nodeId === localNodeId ? manager.openSession(payload) : this.ctx.api.terminalSession.openSession.mutate(payload, nodePin(nodeId));
|
|
44536
|
+
},
|
|
44373
44537
|
pullOutput: (nodeId, input) => nodeId === localNodeId ? manager.pullOutput(input) : this.ctx.api.terminalSession.pullOutput.mutate(input, nodePin(nodeId)),
|
|
44374
44538
|
closeSession: async (nodeId, sessionId) => {
|
|
44375
44539
|
if (nodeId === localNodeId) await manager.close({ sessionId });
|
|
@@ -44574,6 +44738,7 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44574
44738
|
return {
|
|
44575
44739
|
listInstances: async () => this.terminalInstances().map((instance) => this.instanceInfo(instance)),
|
|
44576
44740
|
createInstance: async (input) => this.createTerminalInstance(input),
|
|
44741
|
+
updateInstance: async (input) => this.updateTerminalInstance(input),
|
|
44577
44742
|
deleteInstance: async ({ instanceId }) => this.deleteTerminalInstance(instanceId),
|
|
44578
44743
|
setInstanceEnabled: async ({ instanceId, enabled }) => this.setTerminalInstanceEnabled(instanceId, enabled),
|
|
44579
44744
|
listLegacyCameras: async () => this.listLegacyTerminalCameras(),
|
|
@@ -44593,7 +44758,11 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44593
44758
|
profileId: instance.profileId,
|
|
44594
44759
|
profileLabel: instance.profileLabel,
|
|
44595
44760
|
name: instance.name,
|
|
44596
|
-
enabled: instance.enabled
|
|
44761
|
+
enabled: instance.enabled,
|
|
44762
|
+
executable: instance.executable,
|
|
44763
|
+
args: instance.args,
|
|
44764
|
+
cwd: instance.cwd,
|
|
44765
|
+
environment: instance.environment
|
|
44597
44766
|
};
|
|
44598
44767
|
}
|
|
44599
44768
|
replaceTerminalCameraTombstones(stableIds) {
|
|
@@ -44621,11 +44790,35 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44621
44790
|
profileId: profile.profileId,
|
|
44622
44791
|
profileLabel: profile.label,
|
|
44623
44792
|
name,
|
|
44624
|
-
enabled: true
|
|
44793
|
+
enabled: true,
|
|
44794
|
+
executable: input.executable?.trim() || profile.executable || "",
|
|
44795
|
+
args: input.args ? [...input.args] : [...profile.args ?? []],
|
|
44796
|
+
cwd: input.cwd?.trim() || profile.cwd || "",
|
|
44797
|
+
environment: input.environment ? [...input.environment] : [...profile.environment ?? []]
|
|
44625
44798
|
};
|
|
44626
44799
|
await this.updateGlobalSettings({ terminalInstances: [...this.config.terminalInstances, instance] });
|
|
44627
44800
|
return this.instanceInfo(instance);
|
|
44628
44801
|
}
|
|
44802
|
+
async updateTerminalInstance(input) {
|
|
44803
|
+
const updated = await this.instanceMutationQueue.run(() => this.updateTerminalInstanceUnlocked(input));
|
|
44804
|
+
await this.cameraRelay?.closeInstance(updated.instanceId);
|
|
44805
|
+
await this.reconcileTerminalCameras();
|
|
44806
|
+
return updated;
|
|
44807
|
+
}
|
|
44808
|
+
async updateTerminalInstanceUnlocked(input) {
|
|
44809
|
+
const instance = this.terminalInstances().find((candidate) => candidate.id === input.instanceId);
|
|
44810
|
+
if (!instance) throw new Error(`No such Terminal instance: ${input.instanceId}`);
|
|
44811
|
+
const updated = {
|
|
44812
|
+
...instance,
|
|
44813
|
+
...input.name !== void 0 ? { name: input.name.trim() } : {},
|
|
44814
|
+
...input.executable !== void 0 ? { executable: input.executable.trim() } : {},
|
|
44815
|
+
...input.args !== void 0 ? { args: [...input.args] } : {},
|
|
44816
|
+
...input.cwd !== void 0 ? { cwd: input.cwd.trim() } : {},
|
|
44817
|
+
...input.environment !== void 0 ? { environment: [...input.environment] } : {}
|
|
44818
|
+
};
|
|
44819
|
+
await this.updateGlobalSettings({ terminalInstances: this.config.terminalInstances.map((candidate) => candidate.id === input.instanceId ? updated : candidate) });
|
|
44820
|
+
return this.instanceInfo(updated);
|
|
44821
|
+
}
|
|
44629
44822
|
async deleteTerminalInstance(instanceId) {
|
|
44630
44823
|
await this.instanceMutationQueue.run(() => this.deleteTerminalInstanceUnlocked(instanceId));
|
|
44631
44824
|
await this.reconcileTerminalCameras();
|
|
@@ -44685,7 +44878,11 @@ var TerminalAddon = class extends BaseAddon {
|
|
|
44685
44878
|
profileId: "monitor",
|
|
44686
44879
|
profileLabel: legacy.profileLabel,
|
|
44687
44880
|
name: requestedName?.trim() || legacy.name,
|
|
44688
|
-
enabled: true
|
|
44881
|
+
enabled: true,
|
|
44882
|
+
executable: "",
|
|
44883
|
+
args: [],
|
|
44884
|
+
cwd: "",
|
|
44885
|
+
environment: []
|
|
44689
44886
|
};
|
|
44690
44887
|
await this.updateGlobalSettings({ terminalInstances: [...this.config.terminalInstances, instance] });
|
|
44691
44888
|
return this.instanceInfo(instance);
|