


























@@ -31,7 +31,15 @@ const resolveGatewayAuthMock = vi.hoisted(() =>
3131const resolveSecretRefValuesMock = vi.hoisted(() => vi.fn());
3232const randomTokenMock = vi.hoisted(() => vi.fn(() => "generated-token"));
3333const createInstallPlanFixture = vi.hoisted(() => {
34-return async (params?: { wrapperPath?: string; env?: Record<string, string | undefined> }) => {
34+return async (params?: {
35+wrapperPath?: string;
36+env?: Record<string, string | undefined>;
37+}): Promise<{
38+programArguments: string[];
39+workingDirectory: string;
40+environment: Record<string, string | undefined>;
41+environmentValueSources?: Record<string, string | undefined>;
42+}> => {
3543const environment: Record<string, string | undefined> = {};
3644if (params?.wrapperPath || params?.env?.OPENCLAW_WRAPPER) {
3745environment.OPENCLAW_WRAPPER = params.wrapperPath ?? params.env?.OPENCLAW_WRAPPER;
@@ -48,7 +56,7 @@ const createInstallPlanFixture = vi.hoisted(() => {
4856const buildGatewayInstallPlanMock = vi.hoisted(() => vi.fn(createInstallPlanFixture));
4957const parsePortMock = vi.hoisted(() => vi.fn(() => null));
5058const isGatewayDaemonRuntimeMock = vi.hoisted(() => vi.fn(() => true));
51-const installDaemonServiceAndEmitMock = vi.hoisted(() => vi.fn(async () => {}));
59+const installDaemonServiceAndEmitMock = vi.hoisted(() => vi.fn(async (_params?: unknown) => {}));
52605361const actionState = vi.hoisted(() => ({
5462warnings: [] as string[],
@@ -224,6 +232,7 @@ describe("runDaemonInstall", () => {
224232installDaemonServiceAndEmitMock.mockReset();
225233service.isLoaded.mockReset();
226234service.stage.mockReset();
235+service.install.mockReset();
227236service.readCommand.mockReset();
228237resetRuntimeCapture();
229238actionState.warnings.length = 0;
@@ -254,6 +263,7 @@ describe("runDaemonInstall", () => {
254263installDaemonServiceAndEmitMock.mockResolvedValue(undefined);
255264service.isLoaded.mockResolvedValue(false);
256265service.stage.mockResolvedValue(undefined);
266+service.install.mockResolvedValue(undefined);
257267service.readCommand.mockResolvedValue(null);
258268resolveNodeStartupTlsEnvironmentMock.mockReturnValue({
259269NODE_EXTRA_CA_CERTS: undefined,
@@ -296,6 +306,35 @@ describe("runDaemonInstall", () => {
296306).toBe(true);
297307});
298308309+it("passes service environment value sources through to service install", async () => {
310+buildGatewayInstallPlanMock.mockResolvedValueOnce({
311+programArguments: ["openclaw", "gateway", "run"],
312+workingDirectory: "/tmp",
313+environment: {
314+OPENROUTER_API_KEY: "or-operator-key",
315+},
316+environmentValueSources: {
317+OPENROUTER_API_KEY: "file",
318+},
319+});
320+installDaemonServiceAndEmitMock.mockImplementationOnce(async (params?: unknown) => {
321+await (params as { install: () => Promise<void> }).install();
322+});
323+324+await runDaemonInstall({ json: true });
325+326+expect(service.install).toHaveBeenCalledWith(
327+expect.objectContaining({
328+environment: {
329+OPENROUTER_API_KEY: "or-operator-key",
330+},
331+environmentValueSources: {
332+OPENROUTER_API_KEY: "file",
333+},
334+}),
335+);
336+});
337+299338it("does not treat env-template gateway.auth.token as plaintext during install", async () => {
300339loadConfigMock.mockReturnValue({
301340gateway: { auth: { mode: "token", token: "${OPENCLAW_GATEWAY_TOKEN}" } },
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。