diff --git a/config/platform-infra/webterm.yaml b/config/platform-infra/webterm.yaml index b1cb181d..874b61da 100644 --- a/config/platform-infra/webterm.yaml +++ b/config/platform-infra/webterm.yaml @@ -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" diff --git a/scripts/src/platform-infra-webterm.ts b/scripts/src/platform-infra-webterm.ts index 495e366e..3893dc7d 100644 --- a/scripts/src/platform-infra-webterm.ts +++ b/scripts/src/platform-infra-webterm.ts @@ -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; }; publicExposure: { @@ -252,6 +253,7 @@ function parseTarget(record: Record, 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, 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 { 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(value: string, expected: T, path: string): T { if (value !== expected) throw new Error(`${path} must be ${expected}`); return expected;