| 1 | namespace CascadeIDE.Features.Agent.Environment; |
| 2 | |
| 3 | /// <summary>Ephemeral substrate per run (ADR 0148 W4): temp dirs under LocalAppData.</summary> |
| 4 | public sealed class AgentSandboxManager |
| 5 | { |
| 6 | public string RunsRoot { get; } |
| 7 | |
| 8 | public AgentSandboxManager(string? runsRoot = null) |
| 9 | { |
| 10 | RunsRoot = runsRoot |
| 11 | ?? Path.Combine( |
| 12 | System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), |
| 13 | "CascadeIDE", |
| 14 | "agent-runs"); |
| 15 | } |
| 16 | |
| 17 | public AgentSandboxLease Prepare(string runId, AgentSandboxProfile profile, string? workspaceRoot = null) |
| 18 | { |
| 19 | var runDir = Path.Combine(RunsRoot, runId); |
| 20 | Directory.CreateDirectory(RunsRoot); |
| 21 | |
| 22 | switch (profile) |
| 23 | { |
| 24 | case AgentSandboxProfile.AgentEphemeral: |
| 25 | if (Directory.Exists(runDir)) |
| 26 | Directory.Delete(runDir, recursive: true); |
| 27 | Directory.CreateDirectory(runDir); |
| 28 | Directory.CreateDirectory(Path.Combine(runDir, "temp")); |
| 29 | break; |
| 30 | |
| 31 | case AgentSandboxProfile.AgentWorktree: |
| 32 | Directory.CreateDirectory(runDir); |
| 33 | break; |
| 34 | |
| 35 | default: |
| 36 | Directory.CreateDirectory(runDir); |
| 37 | break; |
| 38 | } |
| 39 | |
| 40 | AgentSandboxSubstrateBundle? substrate = profile == AgentSandboxProfile.AgentEphemeral |
| 41 | ? AgentSandboxSubstrate.Allocate(runDir) |
| 42 | : null; |
| 43 | |
| 44 | return new AgentSandboxLease(runId, profile, runDir, workspaceRoot, substrate); |
| 45 | } |
| 46 | |
| 47 | public AgentSandboxSubstrateBundle RecreateSubstrateBeforeTests(AgentSandboxLease lease) |
| 48 | { |
| 49 | if (lease.Profile != AgentSandboxProfile.AgentEphemeral) |
| 50 | return lease.Substrate ?? AgentSandboxSubstrate.Allocate(lease.RunDirectory); |
| 51 | |
| 52 | var substrate = Path.Combine(lease.RunDirectory, "substrate"); |
| 53 | if (Directory.Exists(substrate)) |
| 54 | Directory.Delete(substrate, recursive: true); |
| 55 | Directory.CreateDirectory(Path.Combine(lease.RunDirectory, "temp")); |
| 56 | return AgentSandboxSubstrate.Allocate(lease.RunDirectory); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | public sealed record AgentSandboxLease( |
| 61 | string RunId, |
| 62 | AgentSandboxProfile Profile, |
| 63 | string RunDirectory, |
| 64 | string? WorkspaceRoot, |
| 65 | AgentSandboxSubstrateBundle? Substrate = null); |
| 66 | |