Skip to content

Sub-task 3: SessionOrchestrator — YOLO 模式下調用 setSessionMode() #267

Description

@bot0419

概述

SessionOrchestrator 的所有 5 種 Session 類型流程中,於 setSessionModel() 之後加入 setSessionMode() 調用,使 OpenCode 在 YOLO 模式下切換至 yolo Agent。

父議題#264
依賴#268(需要 AgentConnector.setSessionMode()getSessionModeOverride() 已實作)

背景

SessionOrchestrator 是所有 Session 類型的入口點。每種 Session 類型都有獨立的方法來建立 Agent 連線、設定模型、發送 prompt。目前的流程為:

const connector = this.createConnector({ agentConfig, ... });
await connector.connect();
const sessionId = await connector.createSession(mcpServers);
await connector.setSessionModel(sessionId, model);
// ← 此處需新增 setSessionMode()
const response = await connector.prompt(sessionId, assembledContext);

需要在 setSessionModel() 之後、prompt() 之前插入 Mode 切換邏輯。

實作步驟

步驟 1:在 5 種 Session 流程中加入 Mode 切換

SessionOrchestrator 有 5 個方法需要修改,每個方法在 setSessionModel() 之後加入:

// Import the new function
import { getSessionModeOverride } from "@acp/agent-factory.ts";

// After setSessionModel(), add mode override:
const modeOverride = getSessionModeOverride(agentType, yolo);
if (modeOverride) {
  await connector.setSessionMode(sessionId, modeOverride);
}

以下是 5 個需要修改的方法及其位置(行號為參考,實際可能因程式碼變更而偏移):

1. processMessage()(一般訊息)

// 尋找 connector.setSessionModel() 呼叫處
await connector.setSessionModel(sessionId, model);

// 在其後加入:
const modeOverride = getSessionModeOverride(agentType, yoloDecision.enabled);
if (modeOverride) {
  await connector.setSessionMode(sessionId, modeOverride);
}

注意:此方法中的 YOLO 狀態來自 yoloDecision.enabled(逐頻道 YOLO 判定結果)。

2. processSpontaneousPost()(自發性發文)

await connector.setSessionModel(sessionId, model);

const modeOverride = getSessionModeOverride(agentType, this.yolo);
if (modeOverride) {
  await connector.setSessionMode(sessionId, modeOverride);
}

注意:自發性發文使用全域 this.yolo,因為沒有特定頻道觸發。

3. processChannelLurkMessage()(頻道潛伏回覆)

await connector.setSessionModel(sessionId, model);

const modeOverride = getSessionModeOverride(agentType, yoloDecision.enabled);
if (modeOverride) {
  await connector.setSessionMode(sessionId, modeOverride);
}

注意:此方法有頻道設定,因此使用 yoloDecision.enabled

4. processSelfResearch()(自我研究)

await connector.setSessionModel(sessionId, model);

const modeOverride = getSessionModeOverride(agentType, this.yolo);
if (modeOverride) {
  await connector.setSessionMode(sessionId, modeOverride);
}

注意:自我研究使用全域 this.yolo

5. processMemoryMaintenance()(記憶維護)

await connector.setSessionModel(sessionId, model);

const modeOverride = getSessionModeOverride(agentType, this.yolo);
if (modeOverride) {
  await connector.setSessionMode(sessionId, modeOverride);
}

注意:記憶維護使用全域 this.yolo

步驟 2:確認 Import 語句

src/core/session-orchestrator.ts 的 import 區塊中,確認已 import getSessionModeOverride

import {
  createAgentConfig,
  getDefaultAgentType,
  getRetryPromptStrategy,
  getSessionModeOverride,  // ← 新增
} from "@acp/agent-factory.ts";

步驟 3:考量錯誤處理

setSessionMode() 可能在以下情況失敗:

  • Agent 不支援 Mode 切換
  • 指定的 Mode ID 不存在

建議處理方式:讓錯誤自然向上傳播。如果 Mode 切換失敗,Session 應該失敗(因為在錯誤的權限模式下執行 Agent 可能產生非預期結果)。這與 setSessionModel() 失敗的處理一致。

測試策略

tests/core/session-orchestrator.test.ts

新增以下測試案例(建議使用 sanitizeResources: false, sanitizeOps: false):

Deno.test({
  name: "SessionOrchestrator - processMessage - calls setSessionMode for opencode yolo",
  sanitizeResources: false,
  sanitizeOps: false,
  fn: async () => {
    // 1. 設定 agentType = "opencode", yolo = true
    // 2. Mock connector,驗證 setSessionMode 被呼叫
    // 3. 斷言 setSessionMode("yolo") 被呼叫且在 setSessionModel 之後
  },
});

Deno.test({
  name: "SessionOrchestrator - processMessage - does not call setSessionMode for copilot yolo",
  sanitizeResources: false,
  sanitizeOps: false,
  fn: async () => {
    // 1. 設定 agentType = "copilot", yolo = true
    // 2. Mock connector,驗證 setSessionMode 未被呼叫
  },
});

Deno.test({
  name: "SessionOrchestrator - processMessage - does not call setSessionMode for opencode non-yolo",
  sanitizeResources: false,
  sanitizeOps: false,
  fn: async () => {
    // 1. 設定 agentType = "opencode", yolo = false
    // 2. Mock connector,驗證 setSessionMode 未被呼叫
  },
});

// 類似的測試應覆蓋其他 4 種 Session 類型

測試覆蓋重點

場景 預期行為
OpenCode + YOLO 呼叫 setSessionMode("yolo")
OpenCode + 非 YOLO 不呼叫 setSessionMode()
Copilot + YOLO 不呼叫 setSessionMode()
Gemini + YOLO 不呼叫 setSessionMode()
5 種 Session 類型各自測試 確保無遺漏

相關檔案

檔案 修改類型
src/core/session-orchestrator.ts 在 5 處加入 setSessionMode() 調用 + import
tests/core/session-orchestrator.test.ts 新增測試案例

注意事項

  • 請仔細識別各方法中的 YOLO 狀態來源(yoloDecision.enabled vs this.yolo),使用錯誤的來源會導致權限邏輯不一致
  • setSessionMode() 應在 setSessionModel() 之後、prompt() 之前呼叫
  • 若未來新增第 6 種 Session 類型,也需要加入相同的 Mode 切換邏輯

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions