diff --git a/apps/backend/internal/agent/runtime/agentctl/control.go b/apps/backend/internal/agent/runtime/agentctl/control.go index 73b7e7088b..e988d6575e 100644 --- a/apps/backend/internal/agent/runtime/agentctl/control.go +++ b/apps/backend/internal/agent/runtime/agentctl/control.go @@ -45,7 +45,7 @@ type CreateInstanceRequest struct { ID string `json:"id,omitempty"` WorkspacePath string `json:"workspace_path"` AgentCommand string `json:"agent_command,omitempty"` - Protocol string `json:"protocol,omitempty"` // Protocol adapter to use (acp, rest, mcp, codex) + Protocol string `json:"protocol,omitempty"` // Protocol adapter to use (currently "acp") AgentType string `json:"agent_type,omitempty"` // Agent type ID for debug file naming (e.g., "codex", "auggie") WorkspaceFlag string `json:"workspace_flag,omitempty"` // CLI flag for workspace path (e.g., "--workspace-root") Env map[string]string `json:"env,omitempty"` diff --git a/apps/backend/internal/agentctl/server/config/config.go b/apps/backend/internal/agentctl/server/config/config.go index c3a7144cd4..9dfbf9b8b1 100644 --- a/apps/backend/internal/agentctl/server/config/config.go +++ b/apps/backend/internal/agentctl/server/config/config.go @@ -112,7 +112,7 @@ type PortConfig struct { // InstanceDefaults provides default values for new instances. // These can be overridden when creating an instance. type InstanceDefaults struct { - // Protocol for agent communication (acp, codex, mcp) + // Protocol for agent communication (acp) Protocol agent.Protocol // AgentCommand is the command to run the agent (e.g., "auggie --acp") @@ -453,10 +453,10 @@ func (c *Config) NewInstanceConfig(port int, overrides *InstanceOverrides) *Inst applyOverrides(cfg, overrides) - // Inject local kandev MCP server for MCP tunneling through the agent stream - // This ensures the kandev MCP server is available for protocols that read MCP config - // at startup time (e.g., Codex via -c flags). The MCP server uses the agent stream - // WebSocket connection (bidirectional) to forward tool calls to the backend. + // Inject local kandev MCP server for MCP tunneling through the agent stream. + // This adds the kandev MCP server as an entry in InstanceConfig.McpServers. + // The MCP server uses the agent stream WebSocket connection (bidirectional) + // to forward tool calls to the backend. if port > 0 { cfg.McpServers = injectKandevMcpServer(cfg.McpServers, port) } diff --git a/apps/backend/internal/agentctl/server/instance/instance.go b/apps/backend/internal/agentctl/server/instance/instance.go index 128c155c40..c9a65c4c6a 100644 --- a/apps/backend/internal/agentctl/server/instance/instance.go +++ b/apps/backend/internal/agentctl/server/instance/instance.go @@ -123,7 +123,7 @@ type CreateRequest struct { // AgentCommand is an optional command to start the agent. If empty, a default is used. AgentCommand string `json:"agent_command,omitempty"` - // Protocol is the protocol adapter to use (acp, codex, auggie). If empty, default is used. + // Protocol is the protocol adapter to use (acp). If empty, default is used. Protocol string `json:"protocol,omitempty"` // AgentType identifies the agent (e.g., "auggie", "codex", "claude-code"). diff --git a/apps/backend/internal/agentctl/server/process/manager.go b/apps/backend/internal/agentctl/server/process/manager.go index b7a4649492..8ee8c8570d 100644 --- a/apps/backend/internal/agentctl/server/process/manager.go +++ b/apps/backend/internal/agentctl/server/process/manager.go @@ -1422,7 +1422,7 @@ func (m *Manager) buildFinalCommand() error { m.cmd.Dir = m.cfg.WorkDir m.cmd.Env = m.cfg.AgentEnv // Create a new process group so we can kill all child processes together. - // This is important for adapters like OpenCode that spawn child processes + // This is important for agents like OpenCode that spawn child processes // (npx -> sh -> node -> opencode binary). setAgentProcGroup(m.cmd) @@ -1672,7 +1672,7 @@ func (m *Manager) Configure(command string, agentArgs []string, agentArgsPresent m.cfg.AgentCommand = command m.cfg.AgentArgs = args - // Set approval policy if provided (for Codex) + // Set approval policy if provided if approvalPolicy != "" { m.cfg.ApprovalPolicy = approvalPolicy } @@ -1718,7 +1718,7 @@ func (m *Manager) createAdapter() error { } m.adapter = adpt - // Set stderr provider for adapters that support it (Codex, StreamJSON) + // Set stderr provider if the adapter implements the optional StderrProviderSetter interface if setter, ok := m.adapter.(adapter.StderrProviderSetter); ok { setter.SetStderrProvider(m) } @@ -2055,7 +2055,7 @@ func (m *Manager) drainAfterLateTeardown(ctx context.Context) { } // killProcessGroupIfRequired immediately kills the entire process group for -// adapters (such as OpenCode) that are known not to exit when stdin is closed. +// agents (such as OpenCode) that are known not to exit when stdin is closed. // Other adapters still get process-group cleanup in waitForProcessExit after // their graceful stdin-close path has had a chance to finish. func (m *Manager) killProcessGroupIfRequired() { diff --git a/apps/backend/internal/agentctl/types/streams/agent.go b/apps/backend/internal/agentctl/types/streams/agent.go index 5c98886f95..5358e63bce 100644 --- a/apps/backend/internal/agentctl/types/streams/agent.go +++ b/apps/backend/internal/agentctl/types/streams/agent.go @@ -101,21 +101,22 @@ const ( ) // AgentEvent is the message type streamed from the agent process. -// This represents protocol-agnostic events from the agent, normalized from -// various underlying protocols (ACP, Codex, Claude Code, etc.). +// This represents agent-agnostic events. ACP session updates are normalized +// into this shape; agentctl also synthesizes lifecycle and diagnostic events +// (process exit, MCP attachment, permission cancellation) that never came from +// the agent. // // Stream endpoint: ws://.../api/v1/agent/events type AgentEvent struct { - // Type identifies the event type. Use EventType* constants: - // "message_chunk", "reasoning", "tool_call", "tool_update", "plan", "complete", "error" + // Type identifies the event type. Use the EventType* constants for supported + // values. Type string `json:"type"` // SessionID is the current session identifier. SessionID string `json:"session_id,omitempty"` - // OperationID identifies the current in-flight operation (turn, prompt, etc.). - // Used to target specific operations for cancellation or status updates. - // For Codex this is the turn ID, for other protocols it may be empty. + // OperationID identifies an operation when the agent exposes an operation ID. + // It may be empty when no operation ID is available. OperationID string `json:"operation_id,omitempty"` // PromptGeneration is the lifecycle-owned identity assigned when this diff --git a/apps/backend/internal/agentctl/types/streams/doc.go b/apps/backend/internal/agentctl/types/streams/doc.go index 489e08a793..739d578a9c 100644 --- a/apps/backend/internal/agentctl/types/streams/doc.go +++ b/apps/backend/internal/agentctl/types/streams/doc.go @@ -6,19 +6,13 @@ // // Streams real-time events from the agent process including message chunks, // reasoning/thinking content, tool invocations, plan updates, and completion -// or error notifications. This stream is protocol-agnostic and works with -// any agent backend (ACP, Codex, Claude Code, etc.). +// or error notifications. This stream carries normalized ACP session updates +// plus agentctl-synthesized lifecycle and diagnostic events, and works with +// any agent that speaks ACP. // // Message type: AgentEvent // -// Event types (use EventType* constants): -// - message_chunk: Streaming text content from the agent -// - reasoning: Chain-of-thought or thinking content -// - tool_call: A tool invocation has started -// - tool_update: Tool status update (running, completed, error) -// - plan: Agent plan/task list updates -// - complete: The turn or operation has completed -// - error: An error occurred +// Event types are defined by the EventType* constants in AgentEvent. // // # Permission Stream (/api/v1/acp/permissions/stream) // diff --git a/apps/web/e2e/tests/chat/message-pagination-helpers.ts b/apps/web/e2e/tests/chat/message-pagination-helpers.ts index b025b53f36..8dba015b9b 100644 --- a/apps/web/e2e/tests/chat/message-pagination-helpers.ts +++ b/apps/web/e2e/tests/chat/message-pagination-helpers.ts @@ -75,9 +75,9 @@ export async function seedLongMessageHistory( type: "message", content: LONG_HISTORY_TAIL_MARKER, }); - // Keep the initial bounded window scrollable while the collapsed tool group - // above the anchor remains height-stable across older-page commits. - await apiClient.seedAgentMessages(sessionId, 20, "LONG-HISTORY-VISIBLE-TAIL"); + // Keep the initial bounded window taller than the sentinel preload margin + // so opening the task does not start pagination before the test scrolls up. + await apiClient.seedAgentMessages(sessionId, 40, "LONG-HISTORY-VISIBLE-TAIL"); return { taskId: task.id, sessionId }; }