Skip to content

Commit 11b3b01

Browse files
OpenSource03claude
andcommitted
feat: background agent stop, transcript viewer, and live progress
- Add stop button for running background agents via SDK stopTask - Agent transcript viewer modal reads JSONL output files - AI-generated progress summaries from agentProgressSummaries SDK option - Real-time current tool indicator from tool_progress events - Eager agent registration from task_started with pending→confirmed flow - "Stopping" status state with optimistic UI update Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f95eaf9 commit 11b3b01

15 files changed

+768
-104
lines changed

electron/src/ipc/claude-sessions.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BrowserWindow, ipcMain } from "electron";
22
import crypto from "crypto";
3+
import fs from "fs";
34
import os from "os";
45
import { log } from "../lib/logger";
56
import { safeSend } from "../lib/safe-send";
@@ -555,6 +556,7 @@ async function restartSession(
555556
canUseTool,
556557
settingSources: ["user", "project", "local"],
557558
pathToClaudeCodeExecutable: cliPath,
559+
agentProgressSummaries: true,
558560
...fileCheckpointOptions(),
559561
resume: sessionId,
560562
stderr: (data: string) => {
@@ -652,6 +654,7 @@ export function register(getMainWindow: () => BrowserWindow | null): void {
652654
canUseTool,
653655
settingSources: ["user", "project", "local"],
654656
pathToClaudeCodeExecutable: cliPath,
657+
agentProgressSummaries: true,
655658
...fileCheckpointOptions(),
656659
stderr: (data: string) => {
657660
const trimmed = data.trim();
@@ -899,6 +902,39 @@ export function register(getMainWindow: () => BrowserWindow | null): void {
899902
return { ok: true };
900903
});
901904

905+
ipcMain.handle("claude:stop-task", async (_event, { sessionId, taskId }: { sessionId: string; taskId: string }) => {
906+
const session = sessions.get(sessionId);
907+
if (!session?.queryHandle?.stopTask) {
908+
return { error: "No active session or stopTask not supported" };
909+
}
910+
try {
911+
await session.queryHandle.stopTask(taskId);
912+
log("STOP_TASK", `session=${sessionId.slice(0, 8)} task=${taskId}`);
913+
return { ok: true };
914+
} catch (err) {
915+
const errMsg = reportError("STOP_TASK_ERR", err, { engine: "claude", sessionId, taskId });
916+
return { error: errMsg };
917+
}
918+
});
919+
920+
ipcMain.handle("claude:read-agent-output", async (_event, { outputFile }: { outputFile: string }) => {
921+
try {
922+
const content = await fs.promises.readFile(outputFile, "utf-8");
923+
const lines = content
924+
.split("\n")
925+
.filter(Boolean)
926+
.map((line) => {
927+
try { return JSON.parse(line); }
928+
catch { return null; }
929+
})
930+
.filter(Boolean);
931+
return { messages: lines };
932+
} catch (err) {
933+
const errMsg = reportError("READ_AGENT_OUTPUT_ERR", err, { outputFile });
934+
return { error: errMsg };
935+
}
936+
});
937+
902938
ipcMain.handle("claude:revert-files", async (_event, { sessionId, checkpointId }: { sessionId: string; checkpointId: string }) => {
903939
const session = sessions.get(sessionId);
904940
if (!session?.queryHandle?.rewindFiles) {

electron/src/preload.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ contextBridge.exposeInMainWorld("claude", {
4848
stop: (sessionId: string, reason?: string) =>
4949
ipcRenderer.invoke("claude:stop", { sessionId, reason }),
5050
interrupt: (sessionId: string) => ipcRenderer.invoke("claude:interrupt", sessionId),
51+
stopTask: (sessionId: string, taskId: string) =>
52+
ipcRenderer.invoke("claude:stop-task", { sessionId, taskId }),
53+
readAgentOutput: (outputFile: string) =>
54+
ipcRenderer.invoke("claude:read-agent-output", { outputFile }),
5155
log: (label: string, data: unknown) => ipcRenderer.send("claude:log", label, data),
5256
onEvent: (callback: (data: unknown) => void) => {
5357
const listener = (_event: IpcRendererEvent, data: unknown) => callback(data);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "harnss",
3-
"version": "0.21.3",
3+
"version": "0.21.4",
44
"productName": "Harnss",
55
"description": "Harness your AI coding agents — one desktop app for Claude Code, Codex, and any ACP agent",
66
"author": {

0 commit comments

Comments
 (0)