forked from admin/VolcanicAgenticCore
fix(claude-code): /claude-code-login reports the outcome of a login it joined
This commit is contained in:
@@ -8,7 +8,8 @@ namespace Volcanic.AgenticCore.Extensions.ClaudeCode;
|
||||
/// <c>/claude-code-login</c>: signs the <c>claude</c> CLI in (again) through the current session's own UI, with no
|
||||
/// owner redirect - whoever runs the command is already allow-listed and at the keyboard. Also useful to switch
|
||||
/// accounts or refresh a session that hasn't expired yet. The outcome is reported by <see cref="ClaudeCodeApi.LoginThroughAsync"/>
|
||||
/// through that same UI.
|
||||
/// through that same UI; when the command joins a login already running elsewhere (whose UI is another chat), it
|
||||
/// reports that login's outcome here itself.
|
||||
/// </summary>
|
||||
public static class LoginCommand
|
||||
{
|
||||
@@ -29,9 +30,17 @@ public static class LoginCommand
|
||||
return;
|
||||
}
|
||||
var ui = ctx.Ui;
|
||||
await (claude.Options.Coordinator ?? ClaudeLoginCoordinator.Shared)
|
||||
.EnsureLoggedInAsync(flowCt => claude.RunLoginFlowAsync(_ => Task.FromResult<IUserInterface?>(ui), flowCt), ct)
|
||||
var drivenHere = false;
|
||||
var outcome = await (claude.Options.Coordinator ?? ClaudeLoginCoordinator.Shared)
|
||||
.EnsureLoggedInAsync(flowCt =>
|
||||
{
|
||||
drivenHere = true;
|
||||
return claude.RunLoginFlowAsync(_ => Task.FromResult<IUserInterface?>(ui), flowCt);
|
||||
}, ct)
|
||||
.ConfigureAwait(false);
|
||||
if (drivenHere) return;
|
||||
if (outcome.Success) ui.Notify("A Claude Code login was already in progress elsewhere; it succeeded ✓");
|
||||
else ui.Notify($"A Claude Code login was already in progress elsewhere; it failed: {outcome.Error}", NotifyKind.Error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,10 +106,10 @@ public class LoginCommandTests : IDisposable
|
||||
return script;
|
||||
}
|
||||
|
||||
private ClaudeCodeApi Claude(string claudePath) => new(new SessionRegistry(), new ClaudeCodeApiOptions
|
||||
private ClaudeCodeApi Claude(string claudePath, ClaudeLoginCoordinator? coordinator = null) => new(new SessionRegistry(), new ClaudeCodeApiOptions
|
||||
{
|
||||
ClaudePath = claudePath,
|
||||
Coordinator = new ClaudeLoginCoordinator(),
|
||||
Coordinator = coordinator ?? new ClaudeLoginCoordinator(),
|
||||
GetEnv = _ => null,
|
||||
ParentEnvironment = new Dictionary<string, string?> { ["PATH"] = Environment.GetEnvironmentVariable("PATH") },
|
||||
});
|
||||
@@ -142,4 +142,35 @@ public class LoginCommandTests : IDisposable
|
||||
Assert.Contains(ui.Notes, n => n.Message.Contains("login complete"));
|
||||
Assert.Empty(api.Sent);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task Joining_a_login_driven_elsewhere_reports_its_outcome_here(bool success)
|
||||
{
|
||||
var coordinator = new ClaudeLoginCoordinator();
|
||||
var gate = new TaskCompletionSource<LoginOutcome>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var elsewhere = coordinator.EnsureLoggedInAsync(_ => gate.Task, CancellationToken.None);
|
||||
var command = LoginCommand.Create(new FakeExtensionApi(), Claude("/nonexistent/claude", coordinator));
|
||||
var ui = new RecordingUi("never-asked");
|
||||
|
||||
var running = command.Handler("", new FakeContext(ui), CancellationToken.None);
|
||||
gate.SetResult(success ? LoginOutcome.Ok : LoginOutcome.Failed("no code was entered"));
|
||||
await running.WaitAsync(TimeSpan.FromSeconds(10));
|
||||
await elsewhere;
|
||||
|
||||
Assert.Empty(ui.Questions); // the other flow's UI drove the login
|
||||
var (message, kind) = Assert.Single(ui.Notes);
|
||||
Assert.Contains("already in progress elsewhere", message);
|
||||
if (success)
|
||||
{
|
||||
Assert.Contains("succeeded", message);
|
||||
Assert.Equal(NotifyKind.Info, kind);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Contains("failed: no code was entered", message);
|
||||
Assert.Equal(NotifyKind.Error, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user