Forge
csharpdeeb25a2
1namespace CascadeIDE.Features.Agent.Environment;
2
3/// <summary>Ephemeral substrate per run (ADR 0148 W4): temp dirs under LocalAppData.</summary>
4public 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
60public sealed record AgentSandboxLease(
61 string RunId,
62 AgentSandboxProfile Profile,
63 string RunDirectory,
64 string? WorkspaceRoot,
65 AgentSandboxSubstrateBundle? Substrate = null);
66
View only · write via MCP/CIDE