Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions agentic/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export enum KaiWorkflowMessageType {
export interface KaiModifiedFile {
path: string;
content: string;
originalContent?: string;
userInteraction?: KaiUserInteraction;
}

Expand All @@ -37,6 +38,7 @@ export interface KaiToolCall {
name?: string;
args?: string;
status: "generating" | "running" | "succeeded" | "failed";
result?: string;
}

export interface KaiUserInteraction {
Expand Down
10 changes: 10 additions & 0 deletions changes/unreleased/1351-pluggable-agent-backend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
kind: feature

description: >
Add pluggable agent backend infrastructure supporting Goose, OpenCode, Claude,
and Codex as interchangeable AI backends. Includes MCP server with analysis
tools, structured chat panel with streaming and permission review UI, and
granular tool permission policy.

extensions:
- core
3,862 changes: 303 additions & 3,559 deletions package-lock.json

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions shared/src/types/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ export const DELETE_PROFILE = "DELETE_PROFILE";
export const UPDATE_PROFILE = "UPDATE_PROFILE";
export const QUICK_RESPONSE = "QUICK_RESPONSE";
export const OPEN_FILE_IN_EDITOR = "OPEN_FILE_IN_EDITOR";
export const TOGGLE_AGENT_MODE = "TOGGLE_AGENT_MODE";
export const OPEN_RESOLUTION_PANEL = "OPEN_RESOLUTION_PANEL";
export const OPEN_HUB_SETTINGS = "OPEN_HUB_SETTINGS";
export const UPDATE_HUB_CONFIG = "UPDATE_HUB_CONFIG";
export const SYNC_HUB_PROFILES = "SYNC_HUB_PROFILES";
export const RETRY_PROFILE_SYNC = "RETRY_PROFILE_SYNC";
export const STOP_WORKFLOW = "STOP_WORKFLOW";
export const OPEN_NATIVE_CONFIG = "OPEN_NATIVE_CONFIG";
export const FILE_RESPONSE = "FILE_RESPONSE";
export const BATCH_APPLY_ALL = "BATCH_APPLY_ALL";
export const BATCH_REJECT_ALL = "BATCH_REJECT_ALL";
export const CONTINUE_WITH_FILE_STATE = "CONTINUE_WITH_FILE_STATE";
export const SHOW_DIFF_WITH_DECORATORS = "SHOW_DIFF_WITH_DECORATORS";
Comment thread
coderabbitai[bot] marked this conversation as resolved.

export type WebviewActionType =
| typeof SET_STATE
Expand Down Expand Up @@ -56,13 +61,19 @@ export type WebviewActionType =
| typeof OPEN_PROFILE_MANAGER
| typeof QUICK_RESPONSE
| typeof OPEN_FILE_IN_EDITOR
| typeof TOGGLE_AGENT_MODE
| typeof OPEN_RESOLUTION_PANEL
| typeof OPEN_HUB_SETTINGS
| typeof UPDATE_HUB_CONFIG
| typeof SYNC_HUB_PROFILES
| typeof RETRY_PROFILE_SYNC
| typeof STOP_WORKFLOW;
| typeof STOP_WORKFLOW
| typeof OPEN_NATIVE_CONFIG
| typeof FILE_RESPONSE
| typeof BATCH_APPLY_ALL
| typeof BATCH_REJECT_ALL
| typeof CONTINUE_WITH_FILE_STATE
| typeof SHOW_DIFF_WITH_DECORATORS;

export interface WebviewAction<S, T> {
type: S;
payload: T;
Expand Down
79 changes: 79 additions & 0 deletions shared/src/types/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// ─── Agent backend types ────────────────────────────────────────────

/** Supported agent backends */
export type AgentBackend = "goose" | "opencode" | "claude" | "codex";

/** Agent lifecycle state */
export type AgentState = "stopped" | "starting" | "running" | "error";

// ─── Agent capabilities ─────────────────────────────────────────────

/** Backend-agnostic capability (Goose extension, OpenCode plugin, etc.) */
export interface AgentCapability {
id: string;
name: string;
description: string;
enabled: boolean;
/** Backend-specific type hint — the UI doesn't interpret this */
kind?: string;
}

// ─── Agent configuration ─────────────────────────────────────────────

/**
* Backend-agnostic configuration for the Configuration panel.
*
* The UI renders provider/model/credentials, tool permissions, and
* backend-specific capabilities regardless of which agent backend is active.
*/
export interface AgentConfig {
/** Which backend is active */
backend: AgentBackend;
/**
* When true, the agent has full autonomy to explore, iterate, and fix broadly.
* When false, the agent does a focused fix on specific incidents only.
*/
agentMode: boolean;
provider: string;
model: string;
hasStoredCredentials: boolean;
/** Backend-specific capabilities (Goose extensions, OpenCode plugins, etc.) */
capabilities: AgentCapability[];
/** Path to the backend's native config file (for "Advanced" link) */
nativeConfigPath?: string;
}

// ─── Agent chat types ────────────────────────────────────────────────

export type AgentContentBlockType = "text" | "resource_link" | "resource" | "thinking";

export type AgentContentBlock =
| { type: "text"; text: string }
| { type: "resource_link"; uri: string; name?: string; mimeType?: string }
| {
type: "resource";
uri: string;
name?: string;
mimeType?: string;
text?: string;
blob?: string;
}
| { type: "thinking"; text: string };

export interface AgentChatMessage {
id: string;
role: "user" | "assistant" | "system" | "tool";
content: string;
timestamp: string;
toolCall?: {
name: string;
arguments?: Record<string, unknown>;
status: "pending" | "running" | "succeeded" | "failed";
result?: string;
};
isStreaming?: boolean;
contentBlocks?: AgentContentBlock[];
isThinking?: boolean;
isCancelled?: boolean;
stopReason?: string;
}
23 changes: 23 additions & 0 deletions shared/src/types/agentActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Agent chat actions
export const AGENT_SEND_MESSAGE = "AGENT_SEND_MESSAGE";
export const AGENT_START = "AGENT_START";
export const AGENT_STOP = "AGENT_STOP";
export const AGENT_UPDATE_CONFIG = "AGENT_UPDATE_CONFIG";
export const AGENT_TOGGLE_VIEW = "AGENT_TOGGLE_VIEW";
export const AGENT_INSTALL_CLI = "AGENT_INSTALL_CLI";
export const AGENT_OPEN_SETTINGS = "AGENT_OPEN_SETTINGS";
export const AGENT_PERMISSION_RESPONSE = "AGENT_PERMISSION_RESPONSE";
export const AGENT_CANCEL_GENERATION = "AGENT_CANCEL_GENERATION";
export const SET_EXPERIMENTAL_CHAT = "SET_EXPERIMENTAL_CHAT";

export type AgentActionType =
| typeof AGENT_SEND_MESSAGE
| typeof AGENT_START
| typeof AGENT_STOP
| typeof AGENT_UPDATE_CONFIG
| typeof AGENT_TOGGLE_VIEW
| typeof AGENT_INSTALL_CLI
| typeof AGENT_OPEN_SETTINGS
| typeof AGENT_PERMISSION_RESPONSE
| typeof AGENT_CANCEL_GENERATION
| typeof SET_EXPERIMENTAL_CHAT;
82 changes: 82 additions & 0 deletions shared/src/types/agentMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { AgentState, AgentChatMessage, AgentContentBlockType, AgentConfig } from "./agent";

export const AgentMessageTypes = {
AGENT_STATE_CHANGE: "AGENT_STATE_CHANGE",
AGENT_CHAT_STATE_CHANGE: "AGENT_CHAT_STATE_CHANGE",
AGENT_CHAT_STREAMING_UPDATE: "AGENT_CHAT_STREAMING_UPDATE",
AGENT_TOOL_CALL: "AGENT_TOOL_CALL",
AGENT_CONFIG_UPDATE: "AGENT_CONFIG_UPDATE",
} as const;

export type AgentMessageType = (typeof AgentMessageTypes)[keyof typeof AgentMessageTypes];

export interface AgentStateChangeMessage {
type: "AGENT_STATE_CHANGE";
agentState: AgentState;
agentError?: string;
timestamp: string;
}

export interface AgentChatStateChangeMessage {
type: "AGENT_CHAT_STATE_CHANGE";
messages: AgentChatMessage[];
timestamp: string;
}

export interface AgentChatStreamingUpdateMessage {
type: "AGENT_CHAT_STREAMING_UPDATE";
messageId: string;
content: string;
done: boolean;
timestamp: string;
contentType?: AgentContentBlockType;
stopReason?: string;
resourceUri?: string;
resourceName?: string;
resourceMimeType?: string;
resourceContent?: string;
}

export interface AgentToolCallMessage {
type: "AGENT_TOOL_CALL";
messageId: string;
toolName: string;
callId?: string;
status: "running" | "succeeded" | "failed";
result?: string;
arguments?: Record<string, unknown>;
timestamp: string;
}

export interface AgentConfigUpdateMessage {
type: "AGENT_CONFIG_UPDATE";
config: AgentConfig;
timestamp: string;
}

export type AgentWebviewMessage =
| AgentStateChangeMessage
| AgentChatStateChangeMessage
| AgentChatStreamingUpdateMessage
| AgentToolCallMessage
| AgentConfigUpdateMessage;

export function isAgentStateChange(msg: any): msg is AgentStateChangeMessage {
return msg?.type === AgentMessageTypes.AGENT_STATE_CHANGE;
}

export function isAgentChatStateChange(msg: any): msg is AgentChatStateChangeMessage {
return msg?.type === AgentMessageTypes.AGENT_CHAT_STATE_CHANGE;
}

export function isAgentChatStreamingUpdate(msg: any): msg is AgentChatStreamingUpdateMessage {
return msg?.type === AgentMessageTypes.AGENT_CHAT_STREAMING_UPDATE;
}

export function isAgentToolCall(msg: any): msg is AgentToolCallMessage {
return msg?.type === AgentMessageTypes.AGENT_TOOL_CALL;
}

export function isAgentConfigUpdate(msg: any): msg is AgentConfigUpdateMessage {
return msg?.type === AgentMessageTypes.AGENT_CONFIG_UPDATE;
}
3 changes: 3 additions & 0 deletions shared/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ export * from "./actions";
export * from "./types";
export * from "./auth";
export * from "./messages";
export * from "./agent";
export * from "./agentActions";
export * from "./agentMessages";
Loading
Loading