fix(orchestration): wire Heavy Brain mode, fix project grouping and relay display#134
fix(orchestration): wire Heavy Brain mode, fix project grouping and relay display#134
Conversation
Add complete multi-engine task orchestration infrastructure: - Backend orchestrator service with DAG-based parallel execution, team worktree isolation, and result aggregation via sendMessage - Role-based engine assignment (explorer/researcher/reviewer/designer/coder) inspired by oh-my-opencode-slim - Frontend orchestration store, gateway API integration, and WS event handling - UI components: plan confirmation, DAG execution visualization, result cards, subtask editor with role selection - Sidebar team grouping with parent/child visual distinction and team worktree filtering - Chat.tsx integration: team task creation, orchestration flow interception, state restoration on refresh Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Upgrade @github/copilot-sdk from 0.2.0 to 0.2.2 - Switch default theme from "system" to "dark" for a more consistent first-launch experience with the upcoming team orchestration UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…llapse - Streamline TeamPlanCard layout and spacing - Fix SubtaskEditor collapse/expand behavior Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ection
- Persist orchestration runs to disk so team state survives restart
- Move team worktree creation to frontend; backend accepts worktreeInfo
in OrchestrationCreateRequest and reuses it for all subtask sessions
- Dispatch subtasks via worktreeId (team worktree name) so all child
sessions share the same working tree
- Extract result summary directly from engine response text parts
- Add autoDetectTeams() to recover team grouping from worktreeId pattern
("team-*") when a run is not yet in the orchestration store
- Allow team-* worktree creation even when global worktree toggle is off
- Add updateRoleMappings/getRoleMappings helpers backed by settings.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Settings - Add Role → Engine mapping editor with per-role engine selection, persisted to settings.json via updateRoleMappings() - Split Experimental section: stable Features (workspace, scheduled tasks, worktree) vs Experimental (team orchestration) - Fix SolidJS <select value> not syncing when <For> options load asynchronously by applying the ref+createEffect pattern already used by the model selector in the same file Chat page - Separate orchestrator Dashboard vs Chat views via a pill-style tab bar (macOS segmented control look); default to Dashboard - Auto-switch to Dashboard when a new team run is created - Reset to Dashboard on session switch - New team task flow creates the team worktree on the frontend and passes worktreeInfo to the backend - Refresh path runs autoDetectTeams to recover stale team sessions Sidebar - Add delete button on team worktree header that removes all sessions in the team (clears the "stale Team mo2* entries" use case) i18n / styles - en/zh/ru strings for team orchestration, role labels, and settings - CSS-based tooltip workaround for Electron + macOS hiddenInset title bar (native title tooltips don't fire reliably on hover-revealed buttons) - Session store exposes teamOrchestrationEnabled flag Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement cross-engine agent team orchestration with two modes: - Light Brain: deterministic DAG planning + parallel execution - Heavy Brain: LLM orchestrator loop with dynamic task dispatch Includes StructuredOutputSkill framework for format-safe LLM output, DAG executor with topological scheduling, gateway integration, minimal frontend with team trigger button and status bar. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement the agent-team hardening roadmap: DAG-aware heavy execution, real cancellation, planner engine selection, persisted run recovery, inactivity guardrails, minimal observability UI, and protocol-level test coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a managed server restart flow that preserves the existing quick tunnel when possible, expose it via package scripts, document the behavior, and cover the shell workflow with unit tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Deduplicate team runs by id in the team store, cover the create-plus-notification race with tests, remove the duplicate relay notice, and move long final results out of the status card into a separate result panel. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Phase 0 of the Agent Team consolidation plan: bring fridayliu's Light/Heavy Brain orchestration (electron/main/services/agent-team/*) onto PR #117's team orchestration base while preserving authorship on both sides via a merge commit. Conflict resolution strategy: - ws-server.ts: keep both orchestratorService (PR #117) and agentTeamService wired in parallel; orchestration handlers will be absorbed in later phases. - gateway-api.ts / gateway-client.ts: take union of Orchestration* and Team* method groups, types, and notification bindings. - types/unified.ts: keep both ORCHESTRATION_* and TEAM_* request/ notification constants. - Chat.tsx: run PR #117's isTeamParentSession interception first, then fridayliu's activeHeavyRelayRun relay; rename duplicate handleTeamSend to handleOrchestrationSend to disambiguate. No behavioral change expected beyond the sum of both branches. Typecheck passes, all 2312 unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ng gateway Extend unified types and gateway protocol to support concepts absorbed from PR #117 (orchestrator-service) into the agent-team module: Types (src/types/unified.ts) - TaskNode: add role?, modelId?, needsWorktree?, duration? - TeamRun: add teamWorktreeName?, teamWorktreeDir?, roleMappings? - TeamRunStatus: add 'awaiting-confirmation' - TeamCreateRequest: add roleMappings?, teamWorktreeInfo?, requirePlanConfirmation? - New requests: TeamConfirmPlanRequest, TeamUpdateRoleMappingsRequest, TeamGetRoleMappingsResponse - New gateway request keys: TEAM_CONFIRM_PLAN, TEAM_GET_ROLE_MAPPINGS, TEAM_UPDATE_ROLE_MAPPINGS AgentTeamService (electron/main/services/agent-team/index.ts) - DEFAULT_ROLE_MAPPINGS (5 roles adapted from PR #117) - awaitPlanConfirmation(runId): promise-based gate for Light Brain to pause after DAG generation - confirmPlan(runId, tasks): resolve gate from gateway handler - getRoleMappings / updateRoleMappings backed by settings.json via loadSettings/saveSettings (team.roleMappings key) - resolveRole(role, fallback): role → {engineType, modelId} - Pending confirmations rejected on cleanup to avoid hangs Gateway (ws-server, gateway-api, gateway-client) - Wire TEAM_CONFIRM_PLAN / TEAM_GET_ROLE_MAPPINGS / TEAM_UPDATE_ROLE_MAPPINGS end-to-end (ws handler + client request + api facade) The LightBrain/HeavyBrain orchestrators do not yet call awaitPlanConfirmation or resolveRole — that wiring lands in Phase 2 (t2-role, t2-confirm). The gate / resolver methods are in place so the protocol surface is stable for frontend work in Phase 3. Verified: npm run typecheck clean; bun run test:unit 70/70 files, 2312/2312 tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wire the Phase 1 types/gateway plumbing into the orchestrator runtime so the concepts that used to live in orchestrator-service.ts (PR #117) are now executed by the unified Light/Heavy brain pipeline. TaskExecutor - new optional RoleResolver type + constructor param - executeAttempt() resolves task.role → {engineType, modelId} before session creation, only when task.engineType is not already set (explicit engineType from the planner still wins) LightBrainOrchestrator - two new optional constructor params: resolveRole, awaitPlanConfirmation - new 'Phase 1.5' between planning and execution: if teamRun.requirePlanConfirmation is true and awaitPlanConfirmation is provided, set status to 'awaiting-confirmation' and block until the gateway resolves the gate via TEAM_CONFIRM_PLAN. User-edited tasks replace the auto-generated DAG before execution. - If the gate rejects (run cancelled mid-confirmation), mark run failed cleanly instead of crashing. - TaskExecutor is now constructed with resolveRole. HeavyBrainOrchestrator - new optional resolveRole constructor param (threaded into TaskExecutor). - Concurrency limit arg moves from 3rd to 4th position; updated call site in the one test that used it. AgentTeamService (createRun / executeRun) - TeamRun snapshot now carries roleMappings, teamWorktreeName/Dir (from teamWorktreeInfo), and requirePlanConfirmation (default: light=on, heavy=off). - executeRun injects resolveRole + awaitPlanConfirmation into the orchestrators from Phase 1 helpers. Types - TeamRun gains requirePlanConfirmation? to mirror TeamCreateRequest so the run snapshot is self-describing (needed by LightBrain runtime and by frontend to know whether to render the plan-confirm card). Verified: npm run typecheck clean; bun run test:unit 70/70 files, 2312/2312 tests passing (1 test updated for HeavyBrain constructor signature change). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract the inline team run card from Chat.tsx (~200 lines) into a dedicated component in src/components/team/, shrinking Chat.tsx and adding the user-facing plan confirmation action for the new 'awaiting-confirmation' status. New files - src/components/team/TeamRunCard.tsx — renders a TeamRun with its tasks, final result, cancel button, and (when status is 'awaiting-confirmation') a 'Confirm & execute' button that calls gateway.confirmTeamPlan. - src/components/team/team-run-helpers.ts — status label / color / icon helpers extracted from Chat.tsx, bound to the shared LocaleDict. i18n - New keys teamRunAwaitingConfirmation / teamRunConfirmPlan / teamRunEditPlan added to en / zh / ru (keep all locales in sync). Chat.tsx - Import TeamRunCard and use it instead of the inline JSX block. - New handleConfirmTeamPlan handler that forwards to gateway.confirmTeamPlan. - Remove now-duplicate helper functions (isTerminalTeamRun, getTeamRunStatusColor, getTeamRunStatusLabel, getTeamRunModeLabel, getTeamTaskStatusIcon, getTeamTaskStatusColor). Net effect: Chat.tsx goes from 3099 → 2931 lines; the user can now actually act on the Phase 2 'awaiting-confirmation' gate. The PR #117 OrchestrationCards components are left untouched — they will be removed in a later step together with orchestrator-service.ts once the new team flow fully replaces them. Verified: npm run typecheck clean; bun run test:unit 70/70 files, 2312/2312 tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add 10 unit tests covering the Phase 2 behaviors wired in 9e1c163. TaskExecutor (4 new cases) - Resolves task.role to engineType + modelId via injected RoleResolver - Preserves explicit task.engineType when both role and engineType set - Falls back to defaultEngineType when RoleResolver returns null LightBrainOrchestrator (2 new cases) - Pauses at 'awaiting-confirmation' when requirePlanConfirmation is true; resumes with user-edited tasks; replaces auto-generated DAG - Marks run 'failed' cleanly when awaitPlanConfirmation rejects (e.g. cancelled run) and never spawns worker sessions AgentTeamService (4 new cases, two new describe blocks) - role mappings: - getRoleMappings() returns DEFAULT_ROLE_MAPPINGS when nothing persisted - updateRoleMappings() persists to settings.json under team.roleMappings and reloads identically - resolveRole() maps known roles and falls back on unknown - plan confirmation gate: - awaitPlanConfirmation() resolves when confirmPlan() fires - confirmPlan() throws for unknown runId Verified: npm run typecheck clean; bun run test:unit 70/70 files, 2322/2322 tests passing (was 2312, +10). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…esign Adds docs/agent-team.md covering the architecture after merging PR #117 and fridayliu/feat/agentteam: - Two-brain split (Light one-shot planner vs Heavy persistent orchestrator) with shared DAG executor, TaskExecutor, and guardrails. - Plan-confirmation flow: awaiting-confirmation gate, TEAM_CONFIRM_PLAN gateway call, user-edited DAG resumption. - Role resolution: DEFAULT_ROLE_MAPPINGS, persistence via settings.json team.roleMappings, resolution order (explicit engineType > role > default). - Team worktree: current type coverage and planned DAGExecutor enforcement; read-only roles opt out; team-* worktree name whitelist. - Service coexistence: PR #117 orchestrator-service and fridayliu agent-team ship side-by-side. - Gateway key reference table. - Pointer to unit test layout. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tion Ports PR #117's aggregateResults pattern into the merged Light/Heavy brain pipeline. After a run reaches a terminal state (completed or failed), AgentTeamService.relayResultsToParentSession() sends the aggregated finalResult + failed-task list as a user message to the parent session, letting the parent engine summarize for the user. Changes - src/types/unified.ts: TeamRun and TeamCreateRequest both gain 'aggregateToParent?: boolean' (default true when parent exists). - electron/main/services/agent-team/index.ts: - createRun() populates aggregateToParent from request (default true). - executeRun() calls relayResultsToParentSession() after orchestrator completes but before cleanup so the emitRunUpdated finalizes state. - New private relayResultsToParentSession(): - No-ops when no parentSessionId / no engineManager / no finalResult - No-ops when aggregateToParent === false - Only relays for 'completed' or 'failed' status - Builds a prompt with header + aggregated task results + failed tasks section, asks parent engine for a concise summary. - Try/catch swallows failures with a warn log so a broken parent session never aborts the team run state. Tests (+3) - tests/unit/electron/services/agent-team/index.test.ts: three new cases under 'result aggregation to parent session': - Relays to parentSessionId after light run completes; prompt contains task descriptions and results. - Skips when aggregateToParent=false. - Skips when parentSessionId is missing. Verified: npm run typecheck clean; bun run test:unit 2325/2325 (was 2322). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cutor
Completes t2-worktree: DAGExecutor.runSingleTask now routes
write-capable tasks into the run's shared team worktree so sibling
tasks see each other's edits, while keeping read-only tasks on the
primary directory to avoid worktree contention.
Routing rules in DAGExecutor.runSingleTask():
- Read-only detection = task.needsWorktree === false, OR
run.roleMappings entry for task.role has readOnly === true.
- If run.teamWorktreeDir is set AND task is write-capable:
directory = run.teamWorktreeDir
defaultWorktreeId = run.teamWorktreeName (fallback run.worktreeId)
- Otherwise (read-only or no team worktree):
directory = this.directory (run's primary dir)
defaultWorktreeId = run.worktreeId
This is a pure routing change — TaskExecutor already respects the
directory + defaultWorktreeId it is handed; no changes there.
Tests (+4, new 'team worktree routing' describe):
- Routes write-capable tasks into teamWorktreeDir.
- Keeps read-only (needsWorktree=false) tasks in primary directory.
- Treats read-only role mapping (roleMappings[].readOnly) as read-only.
- Falls back to run.directory / worktreeId when teamWorktreeDir unset.
Verified: npm run typecheck clean; bun run test:unit 2329/2329 (was 2325).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Completes t3-settings-ui by wiring the existing PR #117 role-engine mapping editor (Settings → Team Orchestration) so every edit mirrors to the Light/Heavy brain's AgentTeamService in addition to the legacy orchestrator-service. Change - src/stores/orchestration.ts: updateRoleMappings() now calls gateway.updateTeamRoleMappings(mappings) in addition to updating orchestrationStore and saveSetting(). The gateway call is fire-and- forget with a warn log on failure so UI responsiveness is unaffected. Result: users editing role→engine mappings in Settings now affect BOTH orchestration flows. The AgentTeamService persists the update to settings.json under 'team.roleMappings' and resolveRole() picks it up on the next task dispatch. No UI changes were needed — the existing Settings section already renders roleMappings from orchestrationStore; we simply added the second write target in the shared update function. Verified: npm run typecheck clean; bun run test:unit 2329/2329. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ridge Completes t3-sidebar: bridges AgentTeamService team runs into the orchestration sidebar-grouping registry (originally added by PR #117) so child sessions spawned by Light/Heavy brain tasks collapse under their parent session in SessionSidebar, matching the UX of PR #117's orchestrator-service flow. Changes - src/stores/orchestration.ts: new associateChildSession(teamId, sessionId) helper that maps a child session into an existing team. - src/pages/Chat.tsx: wraps connectTeamHandlers() so every TeamRun update triggers bridgeToSidebar(): registerTeam(teamId, parentSessionId, worktreeInfo?) associateRunWithTeam(teamId, runId) associateChildSession(teamId, task.sessionId) for every task.sessionId teamId reuses any existing one for the parent session, falling back to the run.id. Idempotent; safe to call on every update so tasks tagged late in the run still get grouped. - Not placed inside stores/team.ts to avoid coupling its module imports with the orchestration store; the team test mock uses a single createStore container shared across modules, which would break if orchestration were imported at module load. No new tests — this is pure UI glue over existing registry helpers; orchestration + team store behavior is already covered. Verified: npm run typecheck clean; bun run test:unit 2329/2329 (no regressions). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…grouping Updates docs/agent-team.md now that the previously-planned behaviors have landed: - Team Worktree: replaced the 'planned' section with the actual routing rules used by DAGExecutor.runSingleTask() (write tasks vs read-only tasks, role.readOnly detection, fallback when teamWorktreeDir is unset). - New 'Result Aggregation to Parent' section describing relayResultsToParentSession() and the aggregateToParent gate. - New 'Sidebar Grouping' section describing the Chat.tsx bridge that reuses PR #117's orchestration registry for AgentTeamService runs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Unify on a single Orchestration naming convention across backend, gateway, frontend, tests, and docs, while keeping PR #117's role-based UI and fridayliu's Light/Heavy Brain DAG executor backend. Backend: - Move electron/main/services/agent-team/ -> orchestration/ - Delete orchestrator-service.ts (concepts already absorbed by LightBrain, role resolution, plan confirmation, and team-worktree routing) - Rename identifiers: AgentTeamService -> OrchestrationService, TeamRun -> OrchestrationRun, TaskNode -> OrchestrationSubtask, run.tasks -> run.subtasks, originalPrompt -> prompt, result/finalResult -> resultSummary, status 'planning' -> 'decomposing', 'awaiting-confirmation' -> 'confirming' - Persistence file agent-team-runs.json -> orchestration-runs.json - Log scope agent-team -> orchestration Gateway protocol: - Collapse all TEAM_* keys under ORCHESTRATION_* namespace and add GET, SEND_MESSAGE, GET_ROLE_MAPPINGS, UPDATE_ROLE_MAPPINGS - Replace team.run.updated / team.task.updated notifications with orchestration.updated / orchestration.subtask.updated Frontend: - Delete src/stores/team.ts, src/components/team/ (TeamRunCard etc.) - Keep PR #117 UI components under src/components/orchestration/ (OrchestrationCards, TeamPlanCard, TeamResultCard, TeamExecutionCard, SubtaskEditor) rebound to unified Orchestration* types - Strip ~150 lines of inline team* flow from Chat.tsx and route through orchestrationStore + gateway.sendOrchestrationMessage / confirmOrchestrationPlan - Rename settings key team.roleMappings -> orchestration.roleMappings - Rename i18n keys teamRun* -> orchestrationRun*, teamRelay* -> orchestrationRelay*, teamMessageRelayFailed -> orchestrationMessageRelayFailed - Update user-facing English/Chinese/Russian strings Tests / docs: - Move tests/unit/electron/services/agent-team/ -> orchestration/ - Update ws-server.test.ts + gateway-api.test.ts mocks and assertions - Rename docs/agent-team.md -> docs/orchestration.md and update prose All 2320 unit tests pass; typecheck clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…elay display - Wire Heavy Brain UI: pass mode from PromptInput team menu through handleOrchestrationSend to gateway.createOrchestration. Show team menu (Light/Heavy choice) only on team parent sessions before first run; revert to normal send button after. - Fix project grouping after refresh: pass worktreeId and parentDirectory from the team session to OrchestrationCreateRequest so child sessions inherit correct project association. Fix DAG executor to always pass parent project dir (not resolved worktree dir) to createSession — prevents resolveProjectId from deriving wrong project name. - Fix relay message display: add internal flag to ConversationMessage and UnifiedMessage. Mark orchestration relay user messages as internal so SessionTurn hides the user bubble while preserving turn structure. Suppress engine-emitted user message.updated events for internal sends via internalSendSessions tracking set. - Add Heavy Brain plan confirmation: pass awaitPlanConfirmation to HeavyBrainOrchestrator, pause on first dispatch when requirePlanConfirmation is set. Emit run update in awaitPlanConfirmation so frontend shows the confirmation UI. - Persist user prompt: save the user's orchestration prompt to the parent session conversation file in createRun so it survives refresh. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR wires the unified Light/Heavy Brain “team orchestration” flow end-to-end (gateway ↔ engine manager ↔ orchestrators ↔ UI), improves project/worktree grouping reliability after refresh, and adjusts relay-message rendering so orchestration relays don’t appear as normal user input.
Changes:
- Add orchestration run APIs/events to the gateway protocol + client bindings, and implement orchestration services (DAG/task execution, skills/parsers, prompts, user relay channel, plan confirmation).
- Update UI/stores/types to support orchestration runs, plan confirmation cards, role→engine mappings, internal (hidden) relay messages, and team session grouping.
- Enhance headless dev server scripts with a
restartcommand that preserves the managed Cloudflare tunnel where possible.
Reviewed changes
Copilot reviewed 57 out of 58 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/src/lib/gateway-api.test.ts | Adds unit coverage for orchestration methods/events in GatewayAPI. |
| tests/unit/shared/server-dev-script.test.ts | Adds integration-style tests for scripts/server-dev.sh restart behavior. |
| tests/unit/electron/services/orchestration/task-executor.test.ts | Tests TaskExecutor inactivity timeout, retries, worktreeId propagation, role→engine resolution. |
| tests/unit/electron/services/orchestration/skills.test.ts | Tests JSON extraction/parsing + planning/dispatch skill validators and retry flow. |
| tests/unit/electron/services/orchestration/light-brain.test.ts | Tests Light Brain worktree context, planner worktree propagation, and plan-confirmation gating. |
| tests/unit/electron/services/orchestration/index.test.ts | Tests orchestration service persistence, relay contract, role mappings, and plan confirmation gate behavior. |
| tests/unit/electron/services/orchestration/dag-executor.test.ts | Tests DAG execution ordering, concurrency limits, and team worktree routing logic. |
| tests/unit/electron/gateway/ws-server.test.ts | Adds gateway WS route + broadcast tests for orchestration requests/notifications. |
| src/types/unified.ts | Introduces orchestration types + gateway request/notification constants; adds internal?: boolean on messages. |
| src/stores/session.ts | Adds teamId grouping + teamOrchestrationEnabled feature flag in session store. |
| src/stores/orchestration.ts | New frontend orchestration store for runs/teams/session grouping + role mappings persistence/sync. |
| src/pages/Settings.tsx | Adds team orchestration toggle and role→engine mapping editor UI. |
| src/locales/zh.ts | Adds i18n strings for orchestration UI + settings. |
| src/locales/ru.ts | Adds i18n strings for orchestration UI + settings. |
| src/locales/en.ts | Adds i18n strings for orchestration UI + settings. |
| src/lib/theme.ts | Changes default theme fallback behavior. |
| src/lib/gateway-client.ts | Adds orchestration APIs + event typings to gateway client. |
| src/lib/gateway-api.ts | Adds orchestration methods + binds orchestration notifications to handlers. |
| src/index.css | Adds CSS tooltip workaround for sidebar buttons with title. |
| src/components/orchestration/TeamResultCard.tsx | UI card for completed/failed run summary + per-subtask results. |
| src/components/orchestration/TeamPlanCard.tsx | UI card for plan confirmation/editing before execution. |
| src/components/orchestration/TeamExecutionCard.tsx | UI card for live DAG execution progress + visualization. |
| src/components/orchestration/SubtaskEditor.tsx | Editor for modifying subtasks (role/engine/deps/description). |
| src/components/orchestration/OrchestrationCards.tsx | Switchboard component for orchestration status → appropriate card. |
| src/components/SessionTurn.tsx | Hides user bubble for internal user messages while preserving turn structure. |
| src/components/PromptInput.tsx | Adds Team Run menu (Light/Heavy) and relay-to-orchestrator UX behavior. |
| scripts/server-init.sh | Documents new server:restart command. |
| scripts/server-dev.sh | Implements restart that preserves managed tunnel when possible. |
| package.json | Adds server:restart npm script; bumps @github/copilot-sdk version. |
| electron/main/services/orchestration/user-channel.ts | Adds a buffered human-in-the-loop channel for orchestrator relays. |
| electron/main/services/orchestration/task-executor.ts | Implements per-subtask session execution, retries, inactivity timeout handling. |
| electron/main/services/orchestration/skills.ts | Adds structured-output “skills” for planning/dispatch JSON formats + retry/correction loop. |
| electron/main/services/orchestration/prompts.ts | Adds engine-agnostic prompt templates and task-result formatting. |
| electron/main/services/orchestration/logger.ts | Re-exports scoped logger for orchestration. |
| electron/main/services/orchestration/light-brain.ts | Implements Light Brain DAG planning + optional plan confirmation + execution. |
| electron/main/services/orchestration/guardrails.ts | Adds orchestration guardrail constants. |
| electron/main/services/orchestration/dag-executor.ts | Implements deterministic DAG scheduler + team worktree routing policy. |
| electron/main/services/orchestration/index.ts | OrchestrationService CRUD, persistence, role mappings, plan-confirmation gate, and run execution wiring. |
| electron/main/services/orchestration/heavy-brain.ts | Heavy Brain orchestrator loop support (incl. relays / dispatch protocol). |
| electron/main/services/logger.ts | Adds orchestrationLog scope. |
| electron/main/index.ts | Initializes orchestrationService at app startup. |
| electron/main/gateway/ws-server.ts | Adds gateway routes + broadcasts for orchestration APIs and whitelists team-* worktrees. |
| electron/main/gateway/engine-manager.ts | Adds internal-send suppression + internal message persistence + buffered-part merge into returned message. |
| electron/main/engines/opencode/index.ts | Adds per-session system prompt composition for orchestration instructions. |
| electron/main/engines/copilot/index.ts | Adds per-session system prompt composition for orchestration instructions (create/resume). |
| electron/main/engines/codex/index.ts | Adds per-session system prompt propagation into thread start/resume. |
| electron/main/engines/claude/index.ts | Adds per-session system prompt append support. |
| docs/orchestration.md | Adds orchestration architecture/behavior documentation. |
| bun.lock | Updates lockfile for @github/copilot-sdk bump. |
| README.zh-CN.md | Updates quick tunnel rotation wording. |
| README.ru.md | Updates quick tunnel rotation wording. |
| README.md | Documents server:restart and updates quick tunnel rotation wording. |
| README.ko.md | Updates quick tunnel rotation wording. |
| README.ja.md | Updates quick tunnel rotation wording. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const result = await adapter.sendMessage(engineSessionId, content, { | ||
| ...options, | ||
| directory: conv.directory, | ||
| }); | ||
|
|
||
| // Clear the internal send suppression flag after the send completes | ||
| this.internalSendSessions.delete(engineSessionId); | ||
|
|
There was a problem hiding this comment.
internalSendSessions is only cleared after adapter.sendMessage resolves. If adapter.sendMessage throws/rejects, the session will remain in internalSendSessions, causing future real user message.updated events to be suppressed indefinitely for that engine session. Move the internalSendSessions.delete(engineSessionId) into a finally block that always runs after the send attempt (and only add/delete when options.internal is true).
| const result = await adapter.sendMessage(engineSessionId, content, { | |
| ...options, | |
| directory: conv.directory, | |
| }); | |
| // Clear the internal send suppression flag after the send completes | |
| this.internalSendSessions.delete(engineSessionId); | |
| let result; | |
| try { | |
| result = await adapter.sendMessage(engineSessionId, content, { | |
| ...options, | |
| directory: conv.directory, | |
| }); | |
| } finally { | |
| // Clear the internal send suppression flag after the send attempt completes | |
| if (options?.internal) { | |
| this.internalSendSessions.delete(engineSessionId); | |
| } | |
| } |
Summary
Fix multiple issues with the team orchestration feature:
Heavy Brain mode wiring
PromptInputteam menu throughhandleOrchestrationSendtogateway.createOrchestrationHeavyBrainOrchestrator— pauses on first dispatch whenrequirePlanConfirmationis set, same pattern as Light BrainProject grouping after refresh
worktreeIdandparentDirectoryfrom the team session toOrchestrationCreateRequestso the orchestration run inherits correct project associationcreateSession— the worktree dir is resolved internally fromworktreeId, preventingresolveProjectIdfrom deriving the wrong project nameRelay message display
internalflag toConversationMessageandUnifiedMessagetypesinternal: truesoSessionTurnhides the user bubble while preserving turn structure for the assistant responsemessage.updatedevents for internal sends viainternalSendSessionstracking set — prevents the relay prompt from appearing as user input in real-timeapplyTitleFallbackfor internal messages to prevent the session title from being overwritten by the relay promptUser prompt persistence
OrchestrationService.createRunso it survives page refreshFiles changed
electron/main/gateway/engine-manager.ts—internaloption onsendMessage, suppress user events, persistinternalflagelectron/main/services/orchestration/index.ts— persist user prompt, passawaitPlanConfirmationto Heavy Brain, mark relay as internalelectron/main/services/orchestration/heavy-brain.ts— plan confirmation support, acceptawaitPlanConfirmationelectron/main/services/orchestration/dag-executor.ts— always use parent dir for task executionsrc/pages/Chat.tsx— wireonTeamSend, passworktreeId/parentDirectory, mode parametersrc/components/PromptInput.tsx— hide send button when team menu is activesrc/components/SessionTurn.tsx— hide user bubble for internal messagessrc/types/unified.ts— addinternalfield to message types