Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
59 changes: 59 additions & 0 deletions apps/desktop/src/main/services/chat/agentChatService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ type ManagedChatSession = {
autoTitleSeed: string | null;
autoTitleStage: "none" | "initial" | "final";
autoTitleInFlight: boolean;
manuallyNamed: boolean;
summaryInFlight: boolean;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
activeAssistantMessageId: string | null;
lastActivitySignature: string | null;
Expand Down Expand Up @@ -2844,6 +2845,7 @@ export function createAgentChatService(args: {
): Promise<void> => {
const config = resolveChatConfig();
if (!config.autoTitleEnabled) return;
if (managed.manuallyNamed) return;
if (managed.autoTitleInFlight) return;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (args.stage === "initial" && managed.autoTitleStage !== "none") return;
if (args.stage === "final") {
Expand Down Expand Up @@ -4121,6 +4123,7 @@ export function createAgentChatService(args: {
autoTitleSeed: null,
autoTitleStage: hasCustomChatSessionTitle(row.title, provider) ? "initial" : "none",
autoTitleInFlight: false,
manuallyNamed: false,
Comment thread
arul28 marked this conversation as resolved.
Outdated
summaryInFlight: false,
continuitySummary: persisted?.continuitySummary ?? null,
continuitySummaryUpdatedAt: persisted?.continuitySummaryUpdatedAt ?? null,
Expand Down Expand Up @@ -7303,6 +7306,13 @@ export function createAgentChatService(args: {
return;
}

// Apply permission mode before the first interaction so the session
// starts with the correct approval behaviour selected in the rebase tab.
const initialPermissionMode = resolveClaudeTurnPermissionMode(managed);
if (typeof runtime.v2Session.setPermissionMode === "function") {
await runtime.v2Session.setPermissionMode(initialPermissionMode);
}

await runtime.v2Session.send("System initialization check. Respond with only the word READY.");
for await (const msg of runtime.v2Session.stream()) {
if (runtime.v2WarmupCancelled) break;
Expand Down Expand Up @@ -7456,6 +7466,7 @@ export function createAgentChatService(args: {
autoTitleSeed: null,
autoTitleStage: "none",
autoTitleInFlight: false,
manuallyNamed: false,
summaryInFlight: false,
continuitySummary: null,
continuitySummaryUpdatedAt: null,
Expand Down Expand Up @@ -7613,11 +7624,13 @@ export function createAgentChatService(args: {
automationId,
automationRunId,
computerUse,
requestedCwd,
}: AgentChatCreateArgs): Promise<AgentChatSession> => {
const launchContext = resolveLaneLaunchContext({
laneService,
laneId,
purpose: "start this chat",
requestedCwd,
});
const sessionId = randomUUID();
const startedAt = nowIso();
Expand Down Expand Up @@ -7763,6 +7776,7 @@ export function createAgentChatService(args: {
autoTitleSeed: null,
autoTitleStage: "none",
autoTitleInFlight: false,
manuallyNamed: false,
summaryInFlight: false,
continuitySummary: null,
continuitySummaryUpdatedAt: null,
Expand Down Expand Up @@ -8113,6 +8127,14 @@ export function createAgentChatService(args: {
if (reasoningEffort) {
managed.session.reasoningEffort = normalizeReasoningEffort(reasoningEffort);
}
// Re-sync permission mode so mid-session changes take effect on this turn.
if (managed.runtime?.kind === "unified") {
const chatConfig = resolveChatConfig();
managed.runtime.permissionMode = resolveSessionUnifiedPermissionMode(
managed.session,
chatConfig.unifiedPermissionMode,
);
}
Comment thread
arul28 marked this conversation as resolved.
await runTurn(managed, {
promptText,
displayText: visibleText,
Expand All @@ -8133,6 +8155,20 @@ export function createAgentChatService(args: {
managed.session.reasoningEffort = DEFAULT_REASONING_EFFORT;
}

// Re-sync codex approval policy so mid-session changes take effect on this turn.
if (runtime.threadResumed) {
const prevApproval = managed.session.codexApprovalPolicy;
const prevSandbox = managed.session.codexSandbox;
resolveCodexThreadParams(managed);
if (
managed.session.codexApprovalPolicy !== prevApproval
|| managed.session.codexSandbox !== prevSandbox
) {
// Policy drifted — force a re-resume so the codex server picks up the new settings.
runtime.threadResumed = false;
}
}

if (!runtime.threadResumed) {
const threadIdToResume = managed.session.threadId || readPersistedState(sessionId)?.threadId;
const { codexPolicy, mcpServers } = resolveCodexThreadParams(managed);
Expand Down Expand Up @@ -8487,6 +8523,11 @@ export function createAgentChatService(args: {
await startFreshCodexThread(managed, runtime, codexPolicy, mcpServers);
}
}
// Re-sync codex approval policy from persisted/config settings
managed.session.codexApprovalPolicy = persisted?.codexApprovalPolicy ?? managed.session.codexApprovalPolicy;
managed.session.codexSandbox = persisted?.codexSandbox ?? managed.session.codexSandbox;
managed.session.codexConfigSource = persisted?.codexConfigSource ?? managed.session.codexConfigSource;
managed.session.permissionMode = syncLegacyPermissionMode(managed.session) ?? managed.session.permissionMode;
} else if (managed.runtime?.kind === "unified" || (managed.session.modelId && !providerResolver.isModelCliWrapped(managed.session.modelId))) {
// Unified runtime resume — re-resolve the model
const result = await startUnifiedSession(managed);
Expand All @@ -8509,11 +8550,21 @@ export function createAgentChatService(args: {
}
// Fallthrough to Claude — SDK manages history via sdkSessionId
ensureClaudeSessionRuntime(managed);
// Re-sync permission mode from persisted/config settings
const fallbackPermMode = resolveClaudeTurnPermissionMode(managed);
if (managed.runtime?.kind === "claude" && managed.runtime.v2Session && typeof managed.runtime.v2Session.setPermissionMode === "function") {
await managed.runtime.v2Session.setPermissionMode(fallbackPermMode);
}
sessionService.setResumeCommand(sessionId, `chat:claude:${sessionId}`);
}
} else {
// Claude — SDK manages history via sdkSessionId
ensureClaudeSessionRuntime(managed);
// Re-sync permission mode from persisted/config settings
const claudePermMode = resolveClaudeTurnPermissionMode(managed);
if (managed.runtime?.kind === "claude" && managed.runtime.v2Session && typeof managed.runtime.v2Session.setPermissionMode === "function") {
await managed.runtime.v2Session.setPermissionMode(claudePermMode);
}
sessionService.setResumeCommand(sessionId, `chat:claude:${sessionId}`);
}

Expand Down Expand Up @@ -8948,6 +8999,7 @@ export function createAgentChatService(args: {
const updateSession = async ({
sessionId,
title,
manuallyNamed,
modelId,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
reasoningEffort,
interactionMode,
Expand Down Expand Up @@ -9161,6 +9213,13 @@ export function createAgentChatService(args: {
sessionId,
title: normalizedTitle.length ? normalizedTitle : defaultChatSessionTitle(managed.session.provider),
});
if (manuallyNamed === true) {
managed.manuallyNamed = true;
}
}
// Allow resetting manuallyNamed independently when no title change is provided
if (manuallyNamed !== undefined && title === undefined) {
managed.manuallyNamed = manuallyNamed;
}

persistChatState(managed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,14 @@ export function createGitOperationsService({
} else if (normalizedBehind > 0 && normalizedAhead === 0) {
recommendedAction = "pull";
} else if (diverged) {
recommendedAction = "pull";
// Check if the remote tip is an ancestor of local HEAD — if NOT, the
// local history was rewritten (e.g. rebase) and a force-push is needed
// instead of a pull.
const mergeBaseRes = await runGit(["merge-base", "--is-ancestor", upstreamRef, "HEAD"], {
cwd: lane.worktreePath,
timeoutMs: 5_000
});
recommendedAction = mergeBaseRes.exitCode === 0 ? "push" : "force_push_lease";
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Comment thread
arul28 marked this conversation as resolved.
Outdated
}

return {
Expand Down
Loading
Loading