feat: 配置 Webterm 默认恢复会话

This commit is contained in:
Codex
2026-07-11 04:17:13 +02:00
parent ce5c20f627
commit 8374757b1f
2 changed files with 35 additions and 1 deletions
+11
View File
@@ -34,6 +34,17 @@ targets:
- source: /root/webterm/scripts/host-shell.sh
target: /usr/local/bin/host-shell
readOnly: true
autoStartSessions:
- title: 决策中心
cwd: /root/unidesk
command: mycx resume 019f4937-9820-7b31-9178-344ae93d5a4c
cols: 100
rows: 30
- title: 71-FILTER
cwd: /root/unidesk
command: mycx resume 019f4b5f-b5ce-76b3-8ccb-508790e9662d
cols: 100
rows: 30
environment:
HOST: 0.0.0.0
PORT: "7681"
+24 -1
View File
@@ -41,6 +41,7 @@ interface WebtermTarget {
privileged: boolean;
pid: "host" | "container";
sourceMounts: Array<{ source: string; target: string; readOnly: boolean }>;
autoStartSessions: Array<{ title: string; cwd: string; command: string; cols: number; rows: number }>;
environment: Record<string, string>;
};
publicExposure: {
@@ -252,6 +253,7 @@ function parseTarget(record: Record<string, unknown>, path: string): WebtermTarg
const pk01 = recordField(exposure, "pk01", `${path}.publicExposure`);
const environment = parseEnvironment(recordField(runtime, "environment", `${path}.runtime`), `${path}.runtime.environment`);
const sourceMounts = parseSourceMounts(runtime.sourceMounts, `${path}.runtime.sourceMounts`);
const autoStartSessions = parseAutoStartSessions(runtime.autoStartSessions, `${path}.runtime.autoStartSessions`);
const target: WebtermTarget = {
id: stringField(record, "id", path),
enabled: booleanField(record, "enabled", path),
@@ -269,6 +271,7 @@ function parseTarget(record: Record<string, unknown>, path: string): WebtermTarg
privileged: booleanField(runtime, "privileged", `${path}.runtime`),
pid: parsePid(stringField(runtime, "pid", `${path}.runtime`), `${path}.runtime.pid`),
sourceMounts,
autoStartSessions,
environment,
},
publicExposure: {
@@ -306,7 +309,11 @@ function resolveTarget(targetId: string | null): WebtermTarget {
}
function renderCompose(target: WebtermTarget): string {
const envLines = Object.entries(target.runtime.environment)
const environment = {
...target.runtime.environment,
AUTO_START_SESSIONS_JSON: JSON.stringify(target.runtime.autoStartSessions),
};
const envLines = Object.entries(environment)
.map(([key, value]) => ` ${key}: ${quoteYaml(value)}`)
.join("\n");
const volumeLines = target.runtime.sourceMounts
@@ -378,6 +385,7 @@ function targetSummary(target: WebtermTarget): Record<string, unknown> {
composeProject: target.runtime.composeProject,
containerName: target.runtime.containerName,
image: target.runtime.image,
autoStartSessions: target.runtime.autoStartSessions.map((session) => session.title),
sourceMounts: target.runtime.sourceMounts.map((mount) => `${mount.source}->${mount.target}${mount.readOnly ? ":ro" : ""}`),
hostPort: target.runtime.hostPort,
containerPort: target.runtime.containerPort,
@@ -481,6 +489,21 @@ function parseSourceMounts(value: unknown, path: string): WebtermTarget["runtime
});
}
function parseAutoStartSessions(value: unknown, path: string): WebtermTarget["runtime"]["autoStartSessions"] {
if (!Array.isArray(value)) throw new Error(`${path} must be an array`);
return value.map((item, index) => {
const itemPath = `${path}[${index}]`;
const record = asRecord(item, itemPath);
return {
title: stringField(record, "title", itemPath),
cwd: stringField(record, "cwd", itemPath),
command: stringField(record, "command", itemPath),
cols: integerField(record, "cols", itemPath),
rows: integerField(record, "rows", itemPath),
};
});
}
function parseLiteral<T extends string>(value: string, expected: T, path: string): T {
if (value !== expected) throw new Error(`${path} must be ${expected}`);
return expected;