feat: apply agent profile settings atomically

This commit is contained in:
Federico Jaramillo Martinez
2026-07-14 00:11:39 +02:00
parent adc2e297a4
commit 8b5ccc2fd9
33 changed files with 794 additions and 163 deletions
+9
View File
@@ -2,6 +2,15 @@ import type { ActiveAgentProfileDescriptor } from "./apiTypes.js";
export const ACTIVE_AGENT_PROFILE_SCHEMA_VERSION = 1 as const;
export function isPiCompanionCommand(command: string): boolean {
const name = command.split(/[\\/]/u).at(-1)?.toLowerCase() ?? command.toLowerCase();
return name.replace(/(?:\.[cm]?js|\.exe|\.cmd)$/iu, "") === "pi";
}
export function usesPiCodingAgentStateCompatibility(command: string): boolean {
return !command.includes("/") && !command.includes("\\") && isPiCompanionCommand(command);
}
const ACTIVE_AGENT_PROFILE_FIELDS = new Set([
"schemaVersion",
"revision",
+5
View File
@@ -11,6 +11,7 @@ export const PI_WEB_CAPABILITIES = {
workspaceFileSuggestions: "workspace.fileSuggestions",
piPackagesManage: "piPackages.manage",
selectedMachineSettings: "settings.selectedMachine",
agentProfileConfig: "settings.agentProfile",
} as const;
export type PiWebCapability = typeof PI_WEB_CAPABILITIES[keyof typeof PI_WEB_CAPABILITIES];
@@ -149,6 +150,8 @@ export interface PiPackageMutationResponse extends PiPackagesResponse {
removed?: boolean;
}
export type PiWebAgentDirEnvSource = "pi-web" | "pi-compatibility";
export interface PiWebConfigEnvOverrides {
host: boolean;
port: boolean;
@@ -157,6 +160,8 @@ export interface PiWebConfigEnvOverrides {
subsessions: boolean;
agentCommand: boolean;
agentDir: boolean;
/** The configured directory environment source, even when Pi compatibility is inactive for the desired command. */
agentDirSource?: PiWebAgentDirEnvSource;
agentSessionDir: boolean;
}
+4 -2
View File
@@ -5,13 +5,15 @@ describe("PI WEB capabilities", () => {
it("advertises web-only capabilities without requiring session daemon support", () => {
expect(WEB_RUNTIME_CAPABILITIES).toContain(PI_WEB_CAPABILITIES.piPackagesManage);
expect(WEB_RUNTIME_CAPABILITIES).toContain(PI_WEB_CAPABILITIES.selectedMachineSettings);
expect(WEB_RUNTIME_CAPABILITIES).toContain(PI_WEB_CAPABILITIES.agentProfileConfig);
expect(SESSIOND_RUNTIME_CAPABILITIES).not.toContain(PI_WEB_CAPABILITIES.piPackagesManage);
expect(SESSIOND_RUNTIME_CAPABILITIES).not.toContain(PI_WEB_CAPABILITIES.selectedMachineSettings);
expect(SESSIOND_RUNTIME_CAPABILITIES).not.toContain(PI_WEB_CAPABILITIES.agentProfileConfig);
expect(effectivePiWebCapabilities({
web: { available: true, capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings] },
web: { available: true, capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, PI_WEB_CAPABILITIES.agentProfileConfig] },
sessiond: { available: false, capabilities: [] },
})).toEqual([PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings]);
})).toEqual([PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, PI_WEB_CAPABILITIES.agentProfileConfig]);
});
it("requires web and session daemon support for authoritative session persistence", () => {
+2
View File
@@ -16,6 +16,7 @@ export const WEB_RUNTIME_CAPABILITIES = [
PI_WEB_CAPABILITIES.workspaceFileSuggestions,
PI_WEB_CAPABILITIES.piPackagesManage,
PI_WEB_CAPABILITIES.selectedMachineSettings,
PI_WEB_CAPABILITIES.agentProfileConfig,
] as const satisfies readonly PiWebCapability[];
export const SESSIOND_RUNTIME_CAPABILITIES = [
@@ -37,6 +38,7 @@ const EFFECTIVE_CAPABILITY_REQUIREMENTS = {
[PI_WEB_CAPABILITIES.workspaceFileSuggestions]: ["web"],
[PI_WEB_CAPABILITIES.piPackagesManage]: ["web"],
[PI_WEB_CAPABILITIES.selectedMachineSettings]: ["web"],
[PI_WEB_CAPABILITIES.agentProfileConfig]: ["web"],
} as const satisfies Record<PiWebCapability, readonly PiWebServiceComponent[]>;
export function isPiWebCapability(value: unknown): value is PiWebCapability {
+4 -4
View File
@@ -8,16 +8,16 @@ describe("PI WEB status parsing", () => {
packageName: "@jmfederico/pi-web",
generatedAt: "now",
components: {
web: { component: "web", label: "Web/UI", runtimeVersion: "1.0.0", available: true, capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, "future.capability"] },
web: { component: "web", label: "Web/UI", runtimeVersion: "1.0.0", available: true, capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, PI_WEB_CAPABILITIES.agentProfileConfig, "future.capability"] },
sessiond: { component: "sessiond", label: "Session daemon", runtimeVersion: "1.0.0", available: true, capabilities: ["future.sessiondCapability"] },
},
capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, "future.capability"],
capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, PI_WEB_CAPABILITIES.agentProfileConfig, "future.capability"],
})).toMatchObject({
components: {
web: { capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings] },
web: { capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, PI_WEB_CAPABILITIES.agentProfileConfig] },
sessiond: { capabilities: [] },
},
capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings],
capabilities: [PI_WEB_CAPABILITIES.piPackagesManage, PI_WEB_CAPABILITIES.selectedMachineSettings, PI_WEB_CAPABILITIES.agentProfileConfig],
});
});