Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
437 changes: 436 additions & 1 deletion dotnet/src/Generated/Rpc.cs

Large diffs are not rendered by default.

81 changes: 80 additions & 1 deletion dotnet/src/Generated/SessionEvents.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dotnet/test/Harness/E2ETestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public IReadOnlyDictionary<string, string> GetEnvironment()
.ToDictionary(e => (string)e.Key, e => e.Value?.ToString());

env["COPILOT_API_URL"] = ProxyUrl;
env["COPILOT_HOME"] = HomeDir;
env["XDG_CONFIG_HOME"] = HomeDir;
env["XDG_STATE_HOME"] = HomeDir;

Expand Down
29 changes: 20 additions & 9 deletions dotnet/test/SessionFsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SessionFsTests(E2ETestFixture fixture, ITestOutputHelper output)
private static readonly SessionFsConfig SessionFsConfig = new()
{
InitialCwd = "/",
SessionStatePath = "/session-state",
SessionStatePath = CreateSessionStatePath(),
Conventions = SessionFsSetProviderConventions.Posix,
};

Expand All @@ -38,7 +38,7 @@ public async Task Should_Route_File_Operations_Through_The_Session_Fs_Provider()
Assert.Contains("300", msg?.Data.Content ?? string.Empty);
await session.DisposeAsync();

var eventsPath = GetStoredPath(providerRoot, session.SessionId, "/session-state/events.jsonl");
var eventsPath = GetStoredPath(providerRoot, session.SessionId, $"{SessionFsConfig.SessionStatePath}/events.jsonl");
await WaitForConditionAsync(() => File.Exists(eventsPath));
var content = await ReadAllTextSharedAsync(eventsPath);
Assert.Contains("300", content);
Expand Down Expand Up @@ -69,7 +69,7 @@ public async Task Should_Load_Session_Data_From_Fs_Provider_On_Resume()
Assert.Contains("100", msg?.Data.Content ?? string.Empty);
await session1.DisposeAsync();

var eventsPath = GetStoredPath(providerRoot, sessionId, "/session-state/events.jsonl");
var eventsPath = GetStoredPath(providerRoot, sessionId, $"{SessionFsConfig.SessionStatePath}/events.jsonl");
await WaitForConditionAsync(() => File.Exists(eventsPath));

var session2 = await client.ResumeSessionAsync(sessionId, new ResumeSessionConfig
Expand Down Expand Up @@ -165,11 +165,11 @@ await session.SendAndWaitAsync(new MessageOptions
var messages = await session.GetMessagesAsync();
var toolResult = FindToolCallResult(messages, "get_big_string");
Assert.NotNull(toolResult);
Assert.Contains("/session-state/temp/", toolResult);
Assert.Contains($"{SessionFsConfig.SessionStatePath}/temp/", toolResult);

var match = System.Text.RegularExpressions.Regex.Match(
toolResult!,
@"([/\\]session-state[/\\]temp[/\\][^\s]+)");
$"({System.Text.RegularExpressions.Regex.Escape(SessionFsConfig.SessionStatePath)}/temp/[^\\s]+)");
Assert.True(match.Success);

var fileContent = await ReadAllTextSharedAsync(GetStoredPath(providerRoot, session.SessionId, match.Groups[1].Value));
Expand Down Expand Up @@ -206,7 +206,7 @@ public async Task Should_Succeed_With_Compaction_While_Using_SessionFs()

await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2+2?" });

var eventsPath = GetStoredPath(providerRoot, session.SessionId, "/session-state/events.jsonl");
var eventsPath = GetStoredPath(providerRoot, session.SessionId, $"{SessionFsConfig.SessionStatePath}/events.jsonl");
await WaitForConditionAsync(() => File.Exists(eventsPath), TimeSpan.FromSeconds(30));
var contentBefore = await ReadAllTextSharedAsync(eventsPath);
Assert.DoesNotContain("checkpointNumber", contentBefore);
Expand Down Expand Up @@ -244,13 +244,13 @@ public async Task Should_Write_Workspace_Metadata_Via_SessionFs()
Assert.Contains("56", msg?.Data.Content ?? string.Empty);

// WorkspaceManager should have created workspace.yaml via sessionFs
var workspaceYamlPath = GetStoredPath(providerRoot, session.SessionId, "/session-state/workspace.yaml");
var workspaceYamlPath = GetStoredPath(providerRoot, session.SessionId, $"{SessionFsConfig.SessionStatePath}/workspace.yaml");
await WaitForConditionAsync(() => File.Exists(workspaceYamlPath));
var yaml = await ReadAllTextSharedAsync(workspaceYamlPath);
Assert.Contains("id:", yaml);

// Checkpoint index should also exist
var indexPath = GetStoredPath(providerRoot, session.SessionId, "/session-state/checkpoints/index.md");
var indexPath = GetStoredPath(providerRoot, session.SessionId, $"{SessionFsConfig.SessionStatePath}/checkpoints/index.md");
await WaitForConditionAsync(() => File.Exists(indexPath));

await session.DisposeAsync();
Expand Down Expand Up @@ -278,7 +278,7 @@ public async Task Should_Persist_Plan_Md_Via_SessionFs()
await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2 + 3?" });
await session.Rpc.Plan.UpdateAsync("# Test Plan\n\nThis is a test.");

var planPath = GetStoredPath(providerRoot, session.SessionId, "/session-state/plan.md");
var planPath = GetStoredPath(providerRoot, session.SessionId, $"{SessionFsConfig.SessionStatePath}/plan.md");
await WaitForConditionAsync(() => File.Exists(planPath));
var content = await ReadAllTextSharedAsync(planPath);
Assert.Contains("# Test Plan", content);
Expand Down Expand Up @@ -323,6 +323,17 @@ private CopilotClient CreateSessionFsClient(string providerRoot, bool useStdio =
private static string CreateProviderRoot()
=> Path.Join(Path.GetTempPath(), $"copilot-sessionfs-{Guid.NewGuid():N}");

private static string CreateSessionStatePath()
{
if (OperatingSystem.IsWindows())
{
return "/session-state";
}

return Path.Join(Path.GetTempPath(), $"copilot-sessionfs-state-{Guid.NewGuid():N}", "session-state")
.Replace(Path.DirectorySeparatorChar, '/');
}

private static string GetStoredPath(string providerRoot, string sessionId, string sessionPath)
{
var safeSessionId = NormalizeRelativePathSegment(sessionId, nameof(sessionId));
Expand Down
42 changes: 41 additions & 1 deletion go/generated_session_events.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading