Merge remote-tracking branch 'origin/main' into pr-36-generic-agent-config

# Conflicts:
#	docs/config.html
#	docs/config.md
#	src/cli.test.ts
#	src/cli.ts
#	src/client/src/components/settings/SettingsSessiondPanel.ts
#	src/client/src/components/settings/settingsConfigDraft.test.ts
#	src/client/src/components/settings/settingsConfigDraft.ts
#	src/server/app.test.ts
#	src/server/app.ts
#	src/server/configRoutes.test.ts
#	src/server/configRoutes.ts
#	src/server/piWebPluginService.test.ts
#	src/server/piWebPluginService.ts
#	src/server/piWebStatus.test.ts
#	src/server/piWebStatus.ts
#	src/server/piWebStatusCache.ts
#	src/server/sessions/authService.test.ts
#	src/server/sessions/piSessionService.ts
#	src/server/sessions/sessionRoutes.test.ts
This commit is contained in:
Federico Jaramillo Martinez
2026-07-13 20:30:08 +02:00
289 changed files with 29164 additions and 6419 deletions
+45 -1
View File
@@ -2,7 +2,15 @@ import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { agentCommandForChecks, commandWithVersionCheck, isCliEntrypoint } from "./cli.js";
import {
agentCommandForChecks,
commandWithVersionCheck,
doctorExitCode,
isCliEntrypoint,
launchdRuntimeDetails,
regularFileExists,
serviceBackendForPlatform,
} from "./cli.js";
const originalShell = process.env["SHELL"];
const originalPiWebConfig = process.env["PI_WEB_CONFIG"];
@@ -66,6 +74,42 @@ describe("agentCommandForChecks", () => {
});
});
describe("native-service doctor CLI contracts", () => {
it("uses native services only on supported platforms", () => {
expect(serviceBackendForPlatform("linux")).toEqual({ kind: "systemd", label: "systemd user services" });
expect(serviceBackendForPlatform("darwin")).toEqual({ kind: "launchd", label: "LaunchAgents" });
expect(serviceBackendForPlatform("win32")).toBeUndefined();
});
it("fails doctor for general, native-plan, or node-pty failures", () => {
expect(doctorExitCode(true, true, true)).toBe(0);
expect(doctorExitCode(false, true, true)).toBe(1);
expect(doctorExitCode(true, false, true)).toBe(1);
expect(doctorExitCode(true, true, false)).toBe(1);
});
it("accepts only regular files as bundled entrypoints", () => {
const dir = mkdtempSync(join(tmpdir(), "pi-web-entrypoint-test-"));
try {
const file = join(dir, "entrypoint.js");
writeFileSync(file, "export {};\n");
expect(regularFileExists(file)).toBe(true);
expect(regularFileExists(dir)).toBe(false);
expect(regularFileExists(join(dir, "missing.js"))).toBe(false);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
it("surfaces launchd last exit code 127 in service status", () => {
expect(launchdRuntimeDetails("state = exited\nlast exit code = 127\n")).toEqual({
state: "exited",
detail: "exited (last exit code 127)",
pid: undefined,
});
});
});
describe("isCliEntrypoint", () => {
it("matches direct execution paths", () => {
expect(isCliEntrypoint("/tmp/pi-web-cli.js", "/tmp/pi-web-cli.js")).toBe(true);