Skip to content

Commit 3d06f1a

Browse files
committed
more fixes
1 parent c2dc2b1 commit 3d06f1a

23 files changed

Lines changed: 1053 additions & 102 deletions

File tree

DotPilot.Core/ChatSessions/Execution/AgentSessionService.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ public async ValueTask<Result<SessionTranscriptSnapshot>> CreateSessionAsync(
202202
return Result<SessionTranscriptSnapshot>.FailNotFound($"Agent '{command.AgentProfileId}' was not found.");
203203
}
204204

205-
var providerProfile = AgentSessionProviderCatalog.Get((AgentProviderKind)agent.ProviderKind);
206205
var now = timeProvider.GetUtcNow();
207206
var sessionId = SessionId.New();
208207
var session = new SessionRecord
@@ -217,10 +216,6 @@ public async ValueTask<Result<SessionTranscriptSnapshot>> CreateSessionAsync(
217216
dbContext.Sessions.Add(session);
218217
dbContext.SessionEntries.Add(CreateEntryRecord(sessionId, SessionStreamEntryKind.Status, StatusAuthor, SessionReadyText, now, accentLabel: StatusAccentLabel));
219218
await dbContext.SaveChangesAsync(cancellationToken);
220-
if (providerProfile.SupportsLiveExecution)
221-
{
222-
await runtimeConversationFactory.InitializeAsync(agent, sessionId, cancellationToken);
223-
}
224219

225220
AgentSessionServiceLog.SessionCreated(logger, sessionId, session.Title, command.AgentProfileId);
226221

DotPilot.Tests/AgentBuilder/Services/AgentPromptDraftGeneratorTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace DotPilot.Tests.AgentBuilder;
77

8+
[NonParallelizable]
89
public sealed class AgentPromptDraftGeneratorTests
910
{
1011
[Test]

DotPilot.Tests/AgentBuilder/ViewModels/AgentBuilderModelTests.cs

Lines changed: 145 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using DotPilot.Core.ChatSessions;
2+
using DotPilot.Core.AgentBuilder;
23
using DotPilot.Tests.Providers;
34
using Microsoft.Extensions.DependencyInjection;
45

56
namespace DotPilot.Tests.AgentBuilder;
67

8+
[NonParallelizable]
79
public sealed class AgentBuilderModelTests
810
{
911
[Test]
@@ -37,7 +39,9 @@ public async Task GenerateDraftAndSaveAgentUsesEnabledProviderModelWhenModelOver
3739
agent.Name == "Repository Reviewer Agent" &&
3840
agent.ProviderKind == AgentProviderKind.Codex &&
3941
agent.ModelName == "gpt-5.4");
40-
(await model.OperationMessage).Should().Be("Saved Repository Reviewer Agent using Codex.");
42+
workspace.Sessions.Should().Contain(session => session.Title == "Session with Repository Reviewer Agent");
43+
workspace.SelectedSessionId.Should().NotBeNull();
44+
fixture.RequestedRoutes.Should().Contain(ShellRoute.Chat);
4145
(await model.Builder)!.StatusMessage.Should().Contain("ready for local desktop execution");
4246
}
4347

@@ -47,8 +51,8 @@ public async Task BuilderProjectionReflectsSelectedProviderSuggestionAndVersion(
4751
await using var fixture = await CreateFixtureAsync();
4852
var model = ActivatorUtilities.CreateInstance<AgentBuilderModel>(fixture.Provider);
4953

50-
await model.SelectedProvider.UpdateAsync(
51-
_ => new AgentProviderOption(
54+
await model.HandleSelectedProviderChanged(
55+
new AgentProviderOption(
5256
AgentProviderKind.GitHubCopilot,
5357
"GitHub Copilot",
5458
"copilot",
@@ -123,6 +127,18 @@ public async Task HandleSelectedProviderChangedUpdatesModelSuggestionToTheChosen
123127

124128
await model.BuildManually(CancellationToken.None);
125129
(await model.ModelName).Should().Be("gpt-5");
130+
await model.SelectedProvider.UpdateAsync(
131+
_ => new AgentProviderOption(
132+
AgentProviderKind.Codex,
133+
"Codex",
134+
"codex",
135+
"Codex CLI is ready for local desktop execution.",
136+
"gpt-5",
137+
["gpt-5", "gpt-5.4"],
138+
"1.0.0",
139+
true),
140+
CancellationToken.None);
141+
await model.SelectedProviderKind.SetAsync(AgentProviderKind.Codex, CancellationToken.None);
126142

127143
await model.HandleSelectedProviderChanged(
128144
new AgentProviderOption(
@@ -158,6 +174,7 @@ await model.SelectedProvider.UpdateAsync(
158174
"1.0.0",
159175
true),
160176
CancellationToken.None);
177+
await model.SelectedProviderKind.SetAsync(AgentProviderKind.Codex, CancellationToken.None);
161178

162179
await model.HandleSelectedProviderChanged(
163180
new AgentProviderOption(
@@ -175,6 +192,89 @@ await model.HandleSelectedProviderChanged(
175192
(await model.SelectedProviderKind).Should().Be(AgentProviderKind.GitHubCopilot);
176193
}
177194

195+
[Test]
196+
public async Task BuilderProjectionUsesSelectedProviderKindWhenThePreviousProviderStateIsStale()
197+
{
198+
using var commandScope = CodexCliTestScope.Create(nameof(AgentBuilderModelTests));
199+
commandScope.WriteVersionCommand("codex", "codex version 1.0.0");
200+
commandScope.WriteCodexMetadata("gpt-5.4", "gpt-5.4", "gpt-5");
201+
commandScope.WriteVersionCommand("claude", "2.0.75 (Claude Code)");
202+
commandScope.WriteClaudeSettings("claude-opus-4-6");
203+
204+
await using var fixture = await CreateFixtureAsync();
205+
(await fixture.WorkspaceState.UpdateProviderAsync(
206+
new UpdateProviderPreferenceCommand(AgentProviderKind.Codex, true),
207+
CancellationToken.None)).ShouldSucceed();
208+
(await fixture.WorkspaceState.UpdateProviderAsync(
209+
new UpdateProviderPreferenceCommand(AgentProviderKind.ClaudeCode, true),
210+
CancellationToken.None)).ShouldSucceed();
211+
212+
var model = ActivatorUtilities.CreateInstance<AgentBuilderModel>(fixture.Provider);
213+
214+
await model.BuildManually(CancellationToken.None);
215+
await model.SelectedProvider.UpdateAsync(
216+
_ => new AgentProviderOption(
217+
AgentProviderKind.Debug,
218+
string.Empty,
219+
string.Empty,
220+
string.Empty,
221+
string.Empty,
222+
[],
223+
null,
224+
false),
225+
CancellationToken.None);
226+
await model.SelectedProviderKind.SetAsync(AgentProviderKind.ClaudeCode, CancellationToken.None);
227+
228+
var builder = await model.Builder;
229+
230+
builder.Should().NotBeNull();
231+
232+
builder!.ProviderDisplayName.Should().Be("Claude Code");
233+
builder.SuggestedModelName.Should().Be("claude-opus-4-6");
234+
(await model.SelectedProvider).Should().NotBeNull();
235+
(await model.SelectedProvider)!.Kind.Should().Be(AgentProviderKind.ClaudeCode);
236+
}
237+
238+
[Test]
239+
public async Task BuilderProjectionPrefersTheSelectedProviderWhenTheProviderKindStateIsStale()
240+
{
241+
using var commandScope = CodexCliTestScope.Create(nameof(AgentBuilderModelTests));
242+
commandScope.WriteVersionCommand("codex", "codex version 1.0.0");
243+
commandScope.WriteCodexMetadata("gpt-5.4", "gpt-5.4", "gpt-5");
244+
commandScope.WriteVersionCommand("claude", "2.0.75 (Claude Code)");
245+
commandScope.WriteClaudeSettings("claude-opus-4-6");
246+
247+
await using var fixture = await CreateFixtureAsync();
248+
(await fixture.WorkspaceState.UpdateProviderAsync(
249+
new UpdateProviderPreferenceCommand(AgentProviderKind.Codex, true),
250+
CancellationToken.None)).ShouldSucceed();
251+
(await fixture.WorkspaceState.UpdateProviderAsync(
252+
new UpdateProviderPreferenceCommand(AgentProviderKind.ClaudeCode, true),
253+
CancellationToken.None)).ShouldSucceed();
254+
255+
var model = ActivatorUtilities.CreateInstance<AgentBuilderModel>(fixture.Provider);
256+
257+
await model.BuildManually(CancellationToken.None);
258+
await model.SelectedProvider.UpdateAsync(
259+
_ => new AgentProviderOption(
260+
AgentProviderKind.ClaudeCode,
261+
"Claude Code",
262+
"claude",
263+
"Claude Code profile authoring is available.",
264+
"claude-opus-4-6",
265+
["claude-opus-4-6", "claude-sonnet-4-5"],
266+
"2.0.75",
267+
true),
268+
CancellationToken.None);
269+
await model.SelectedProviderKind.SetAsync(AgentProviderKind.Codex, CancellationToken.None);
270+
271+
var builder = await model.Builder;
272+
273+
builder.Should().NotBeNull();
274+
builder!.ProviderDisplayName.Should().Be("Claude Code");
275+
builder.SuggestedModelName.Should().Be("claude-opus-4-6");
276+
}
277+
178278
[Test]
179279
public async Task BuildManuallyAllowsChoosingASupportedModelBeforeSavingAgent()
180280
{
@@ -221,17 +321,30 @@ public async Task StartChatForAgentCreatesAndSelectsSessionForChosenCatalogAgent
221321
await model.GenerateAgentDraft(CancellationToken.None);
222322
await model.SaveAgent(CancellationToken.None);
223323

224-
var createdAgent = (await model.Agents)
324+
var workspace = (await fixture.WorkspaceState.GetWorkspaceAsync(CancellationToken.None)).ShouldSucceed();
325+
var createdAgentSummary = workspace.Agents
225326
.Should()
226327
.ContainSingle(agent => agent.Name == "Repository Reviewer Agent")
227328
.Which;
329+
var createdAgent = new AgentCatalogItem(
330+
createdAgentSummary.Id,
331+
"R",
332+
createdAgentSummary.Name,
333+
AgentSessionDefaults.CreateAgentDescription(createdAgentSummary.SystemPrompt),
334+
createdAgentSummary.ProviderDisplayName,
335+
createdAgentSummary.ModelName,
336+
false,
337+
"AgentCatalogStartChatButton_RepositoryReviewerAgent",
338+
new AgentCatalogStartChatRequest(createdAgentSummary.Id, createdAgentSummary.Name),
339+
null);
228340

229341
await model.StartChatForAgent(createdAgent, CancellationToken.None);
230342

231-
var workspace = (await fixture.WorkspaceState.GetWorkspaceAsync(CancellationToken.None)).ShouldSucceed();
343+
workspace = (await fixture.WorkspaceState.GetWorkspaceAsync(CancellationToken.None)).ShouldSucceed();
232344
workspace.Sessions.Should().Contain(session => session.Title == "Session with Repository Reviewer Agent");
233345
workspace.SelectedSessionId.Should().NotBeNull();
234-
(await model.OperationMessage).Should().Be("Started a session with Repository Reviewer Agent. Switch to Chat to continue.");
346+
fixture.RequestedRoutes.Should().Contain(ShellRoute.Chat);
347+
(await model.OperationMessage).Should().Be("Started a session with Repository Reviewer Agent.");
235348
}
236349

237350
private static async Task<TestFixture> CreateFixtureAsync()
@@ -243,21 +356,43 @@ private static async Task<TestFixture> CreateFixtureAsync()
243356
UseInMemoryDatabase = true,
244357
InMemoryDatabaseName = Guid.NewGuid().ToString("N"),
245358
});
359+
services.AddSingleton<WorkspaceProjectionNotifier>();
360+
services.AddSingleton<ShellNavigationNotifier>();
246361

247362
var provider = services.BuildServiceProvider();
248363
var workspaceState = provider.GetRequiredService<IAgentWorkspaceState>();
249-
return new TestFixture(provider, workspaceState);
364+
var navigationNotifier = provider.GetRequiredService<ShellNavigationNotifier>();
365+
return new TestFixture(provider, workspaceState, navigationNotifier);
250366
}
251367

252-
private sealed class TestFixture(ServiceProvider provider, IAgentWorkspaceState workspaceState) : IAsyncDisposable
368+
private sealed class TestFixture : IAsyncDisposable
253369
{
254-
public ServiceProvider Provider { get; } = provider;
370+
private readonly ShellNavigationNotifier navigationNotifier;
371+
private readonly List<ShellRoute> requestedRoutes = [];
372+
373+
public TestFixture(ServiceProvider provider, IAgentWorkspaceState workspaceState, ShellNavigationNotifier navigationNotifier)
374+
{
375+
Provider = provider;
376+
WorkspaceState = workspaceState;
377+
this.navigationNotifier = navigationNotifier;
378+
this.navigationNotifier.Requested += OnNavigationRequested;
379+
}
380+
381+
public ServiceProvider Provider { get; }
255382

256-
public IAgentWorkspaceState WorkspaceState { get; } = workspaceState;
383+
public IAgentWorkspaceState WorkspaceState { get; }
384+
385+
public IReadOnlyList<ShellRoute> RequestedRoutes => requestedRoutes;
257386

258387
public ValueTask DisposeAsync()
259388
{
389+
navigationNotifier.Requested -= OnNavigationRequested;
260390
return Provider.DisposeAsync();
261391
}
392+
393+
private void OnNavigationRequested(object? sender, ShellNavigationRequestedEventArgs e)
394+
{
395+
requestedRoutes.Add(e.Route);
396+
}
262397
}
263398
}

DotPilot.Tests/ChatSessions/Execution/AgentSessionServiceTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace DotPilot.Tests.ChatSessions;
1010

11+
[NonParallelizable]
1112
public sealed class AgentSessionServiceTests
1213
{
1314
private const int LegacyDefaultRole = 4;

DotPilot.Tests/Settings/ViewModels/SettingsModelTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace DotPilot.Tests.Settings;
66

7+
[NonParallelizable]
78
public sealed class SettingsModelTests
89
{
910
[Test]

0 commit comments

Comments
 (0)