Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
40fac3f
fix(coding-agent): avoid retrying delivered agent messages
snimu Aug 24, 2026
980d22d
Add the changelog fragment
snimu Aug 24, 2026
4d9aa20
fix(coding-agent): remove blanket RPC timeouts
snimu Aug 24, 2026
8e57ca7
fix(coding-agent): trust supervised session renames
snimu Aug 24, 2026
6fd14f2
fix(coding-agent): align RPC child lifecycle
snimu Aug 24, 2026
7369191
fix(coding-agent): single-source interactive queue state
snimu Aug 24, 2026
c38d47e
Merge remote-message-single-send into the stack
snimu Aug 24, 2026
a7e26e6
Merge remove-rpc-blanket-timeouts into the stack
snimu Aug 24, 2026
8ba6695
Merge supervised-rename-authority into the stack
snimu Aug 24, 2026
3881a53
fix(coding-agent): preserve queue selection after moves
snimu Aug 24, 2026
0bb6e44
fix(coding-agent): reject failed RPC prompts
snimu Aug 24, 2026
1ed6add
Merge remove-rpc-blanket-timeouts (prompt-failure fix) into the stack
snimu Aug 24, 2026
cf8fda3
fix(coding-agent): rely on queue events after mutations
snimu Aug 24, 2026
b4ad907
Merge supervised-rename-authority (stack update) into the stack
snimu Aug 24, 2026
bf98b51
test(coding-agent): update resync queue display harness
snimu Aug 24, 2026
3836e61
test(coding-agent): update snapshot queue display seams
snimu Aug 24, 2026
0338d32
fix(coding-agent): reconcile queue browsing on events
snimu Aug 24, 2026
f34b713
fix(coding-agent): cancel failed RPC event waits
snimu Aug 24, 2026
f504c64
Merge remove-rpc-blanket-timeouts (waiter cleanup) into the stack
snimu Aug 24, 2026
0519888
Merge supervised-rename-authority (waiter cleanup) into the stack
snimu Aug 24, 2026
34f36d9
Merge remote-tracking branch 'origin/main' into snimu/remote-message-…
snimu Aug 26, 2026
d9e1a86
Merge branch 'snimu/remote-message-single-send' into snimu/remove-rpc…
snimu Aug 26, 2026
1ff8125
Merge branch 'snimu/remove-rpc-blanket-timeouts' into snimu/supervise…
snimu Aug 26, 2026
d4d6e52
Merge branch 'snimu/supervised-rename-authority' into snimu/tui-queue…
snimu Aug 26, 2026
938b0a7
fix(coding-agent): retain queued edit after lost move
snimu Aug 26, 2026
29e994a
Merge remote-tracking branch 'origin/main' into snimu/remote-message-…
snimu Aug 27, 2026
6eb14d8
Merge branch 'snimu/remote-message-single-send' into snimu/remove-rpc…
snimu Aug 27, 2026
1cb0f22
Merge branch 'snimu/remove-rpc-blanket-timeouts' into snimu/supervise…
snimu Aug 27, 2026
384a702
Merge branch 'snimu/supervised-rename-authority' into snimu/tui-queue…
snimu Aug 27, 2026
20c2482
fix(coding-agent): reconcile queue selection after snapshots
snimu Aug 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fixed remote agent messages being delivered twice when the daemon request timed out or the response was lost: the message is now sent exactly once per call, and post-send failures surface as errors instead of triggering a resend.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Allowed long-running RPC commands and agent turns to complete without fixed client timeouts.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fixed queued-message editing so duplicate prompts always target the selected queue entry.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fixed supervised session renames failing after the supervisor approved an available name.
77 changes: 44 additions & 33 deletions packages/coding-agent/src/modes/daemon/daemon-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3988,7 +3988,7 @@ export class AgentDaemon {
if (!name) {
throw new Error("Session name cannot be empty");
}
await this.setStateSessionName(state, name);
await this.setStateSessionNameForCommand(state, name);
return success(command.id, "rename", summaryForActiveSession(state));
}

Expand All @@ -4002,7 +4002,7 @@ export class AgentDaemon {
throw new Error("Session name cannot be empty");
}
if (state) {
await this.setStateSessionName(state, name);
await this.setStateSessionNameForCommand(state, name);
} else {
const info = await readSessionInfo(command.sessionPath);
if (!info) throw new Error(`Session not found: ${command.sessionPath}`);
Expand Down Expand Up @@ -4898,7 +4898,7 @@ export class AgentDaemon {
if (!name) {
throw new Error("Session name cannot be empty");
}
await this.setStateSessionName(state, name);
await this.setStateSessionNameForCommand(state, name);
return success(command.id, "set_session_name");
}

Expand Down Expand Up @@ -5572,6 +5572,15 @@ export class AgentDaemon {
}
}

private setStateSessionNameForCommand(state: ActiveSessionState, name: string): Promise<void> {
return this.options.worker ? this.applyStateSessionName(state, name) : this.setStateSessionName(state, name);
}

private async applyStateSessionName(state: ActiveSessionState, name: string): Promise<void> {
state.runtime.session.setSessionName(name);
await this.appendRlmLedgerRenameForState(state, name);
}

private async setStateSessionName(state: ActiveSessionState, name: string): Promise<void> {
const normalizedName = name.trim();
if (!normalizedName) {
Expand All @@ -5594,8 +5603,7 @@ export class AgentDaemon {
},
async () => {
await this.assertStateSessionNameAvailable(state, normalizedName);
state.runtime.session.setSessionName(normalizedName);
await this.appendRlmLedgerRenameForState(state, normalizedName);
await this.applyStateSessionName(state, normalizedName);
},
);
}
Expand Down Expand Up @@ -5905,42 +5913,45 @@ export class AgentDaemon {
throw new Error(`Unknown active session: ${targetSelector}`);
}
const deadline = Date.now() + 30_000;
let client: DaemonClient | undefined;
let lastError: unknown;
while (Date.now() < deadline && !this.shuttingDown) {
const client = new DaemonClient(supervisorSocketPath);
let receivedResponse = false;
const candidate = new DaemonClient(supervisorSocketPath);
try {
await client.connect(1000);
await client.waitForHello(1000);
const response = await client.request(
{
type: "send_message",
targetActiveSessionId: targetSelector,
message,
fromActiveSessionId: fromState.activeSessionId,
agentOrigin: true,
},
30_000,
);
receivedResponse = true;
if (!response.success) {
throw deserializeDaemonError(response);
}
if (!response.data || typeof response.data !== "object") {
throw new Error("Supervisor returned an invalid agent-message receipt");
}
return response.data as AgentSessionMessageReceipt;
await candidate.connect(1000);
await candidate.waitForHello(1000);
client = candidate;
break;
} catch (error) {
lastError = error;
if (receivedResponse) {
throw error;
}
} finally {
client.close();
candidate.close();
}
await new Promise((resolveDelay) => setTimeout(resolveDelay, 250));
}
throw lastError instanceof Error ? lastError : new Error(`Unknown active session: ${targetSelector}`);
if (!client) {
throw lastError instanceof Error ? lastError : new Error(`Unknown active session: ${targetSelector}`);
}
try {
const response = await client.request(
{
type: "send_message",
targetActiveSessionId: targetSelector,
message,
fromActiveSessionId: fromState.activeSessionId,
agentOrigin: true,
},
30_000,
);
if (!response.success) {
throw deserializeDaemonError(response);
}
if (!response.data || typeof response.data !== "object") {
throw new Error("Supervisor returned an invalid agent-message receipt");
}
return response.data as AgentSessionMessageReceipt;
} finally {
client.close();
}
}

private async acceptAgentSessionMessage(
Expand Down
Loading
Loading