From 69a531bd8b7badbb61f91c358f7da17bf20c082f Mon Sep 17 00:00:00 2001 From: MocA-Love <64681295+MocA-Love@users.noreply.github.com> Date: Fri, 17 Apr 2026 07:32:50 +0900 Subject: [PATCH] =?UTF-8?q?fix(desktop):=20done=20=E7=8A=B6=E6=85=8B?= =?UTF-8?q?=E3=81=AE=E3=82=BF=E3=82=B9=E3=82=AF=E3=81=AB=E3=83=A1=E3=83=83?= =?UTF-8?q?=E3=82=BB=E3=83=BC=E3=82=B8=E9=80=81=E4=BF=A1=E3=81=A7=E5=86=8D?= =?UTF-8?q?=E9=96=8B=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - start 許可リストに `done` を追加し、手動 Start でも再開可能に - sendInput で done/failed/aborted/escalated かつ claudeSessionId 有のときに 自動的に preparing へ遷移して supervisor.start を呼び、メッセージ送信だけで 過去セッションを `--resume` で継続するようにした - UI: done 済みかつ claudeSessionId 有の場合に Start ボタンを表示 - UI: フッターのヒントに「完了済み/失敗のタスクへ送ると再開される」旨を追記 Closes #241 --- .../src/main/todo-agent/trpc-router.ts | 41 ++++++++++++++++++- .../todo-agent/TodoManager/TodoManager.tsx | 7 +++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/main/todo-agent/trpc-router.ts b/apps/desktop/src/main/todo-agent/trpc-router.ts index 8b66b88480f..b0ca89e7f4d 100644 --- a/apps/desktop/src/main/todo-agent/trpc-router.ts +++ b/apps/desktop/src/main/todo-agent/trpc-router.ts @@ -179,7 +179,12 @@ export const createTodoAgentRouter = () => { // Allow manual "wake now" on a ScheduleWakeup-paused // session — the user should not have to wait out the // delay if they already have the context they wanted. - session.status !== "waiting" + session.status !== "waiting" && + // Allow resuming a completed session so the user can send + // follow-up messages. The supervisor detects the existing + // `claudeSessionId` and issues `--resume` to continue the + // prior conversation rather than starting fresh. + session.status !== "done" ) { throw new TRPCError({ code: "PRECONDITION_FAILED", @@ -410,11 +415,43 @@ export const createTodoAgentRouter = () => { * Queue a user intervention for the next turn. Headless mode * cannot inject text mid-stream, so interventions land at the * next iteration boundary. + * + * Sending a message to a terminal session (done/failed/aborted/ + * escalated) that still has a `claudeSessionId` auto-resumes the + * conversation: the message is buffered, the row flips to + * `preparing`, and the supervisor reruns with `--resume `. + * Without this, the queued message would sit unread until the + * user manually clicked Start — the exact friction #241 called + * out for the `done` case. */ sendInput: publicProcedure .input(todoSendInputSchema) .mutation(({ input }) => { - getTodoSupervisor().queueIntervention(input.sessionId, input.data); + const store = getTodoSessionStore(); + const session = store.get(input.sessionId); + if (!session) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "セッションが見つかりません", + }); + } + const supervisor = getTodoSupervisor(); + supervisor.queueIntervention(input.sessionId, input.data); + + const isTerminal = + session.status === "done" || + session.status === "failed" || + session.status === "aborted" || + session.status === "escalated"; + if (isTerminal && session.claudeSessionId) { + store.update(input.sessionId, { + status: "preparing", + phase: "preparing", + waitingUntil: null, + waitingReason: null, + }); + void supervisor.start(input.sessionId); + } return { ok: true }; }), diff --git a/apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx b/apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx index 8ce448d2ab0..79c0c961d35 100644 --- a/apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx +++ b/apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx @@ -977,7 +977,10 @@ function SessionDetail({ session, onDeleted }: SessionDetailProps) { session.status === "aborted" || session.status === "escalated" || // Manual "wake now" overrides the remaining ScheduleWakeup delay. - session.status === "waiting"; + session.status === "waiting" || + // Resume a completed session — supervisor issues `--resume` so the + // next turn continues the same Claude conversation. + (session.status === "done" && session.claudeSessionId != null); const isRunning = session.status === "preparing" || session.status === "running" || @@ -1581,7 +1584,7 @@ function SessionDetail({ session, onDeleted }: SessionDetailProps) { ) : ( <> ヒント: - 実行中でもメッセージを送ると、現在のターンを中断して即座に割り込みます。 + 実行中でもメッセージを送ると、現在のターンを中断して即座に割り込みます。完了済み/失敗のタスクに送ると、過去のセッションを再開して続きから対話します。 )}