feat(interactive): worker launch-spec for embedded ConPTY sessions

Adds InteractiveLaunchSpecService + GetInteractiveLaunchSpec hub method that
prepares a task worktree (session-skills seeding, run env) and returns a
LaunchSpec {cwd,exe,args,env} for a UI-hosted ConPTY terminal. Reuses
ISessionSkillSeeder, TaskRunner.UnionSkillNames, and WindowsTerminalLauncher
resume-arg/resolve logic. Guards mirror ResumeTaskInTerminal; a never-run task
yields a fresh-start spec instead of an error.
This commit is contained in:
mika kuns
2026-07-23 16:47:15 +02:00
parent d91ad2d635
commit 1245e75902
11 changed files with 408 additions and 3 deletions
@@ -106,7 +106,12 @@ public sealed class WindowsTerminalLauncher : ITerminalLauncher
// Resumes a session by id in default (interactive) permission mode: the user drives
// tool approvals in the terminal, unlike planning which pins --permission-mode plan.
internal static string BuildResumeCommand(string claudePath, string claudeSessionId) =>
BuildPwshCommand(claudePath, new[] { "--resume", claudeSessionId });
BuildPwshCommand(claudePath, BuildResumeArgs(claudeSessionId));
// The raw claude CLI args for a --resume launch, shared with InteractiveLaunchSpecService
// (which needs the bare Exe/Args pair for a ConPTY host, not a wrapped pwsh command line).
internal static IReadOnlyList<string> BuildResumeArgs(string claudeSessionId) =>
new[] { "--resume", claudeSessionId };
// Builds the PowerShell command that launches an interactive planning session.
// Arg order matters: variadic flags (--allowedTools, --add-dir) come first; the
@@ -174,7 +179,9 @@ public sealed class WindowsTerminalLauncher : ITerminalLauncher
?? throw new TerminalLaunchException("Failed to start Windows Terminal process.");
}
private static string? Resolve(string pathOrName)
// Not private: reused by InteractiveLaunchSpecService to resolve the claude executable
// for a ConPTY-hosted launch spec the same way a wt-launched terminal resolves it.
internal static string? Resolve(string pathOrName)
{
if (File.Exists(pathOrName))
return pathOrName;