Skip to content
Merged
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
13 changes: 13 additions & 0 deletions packages/agent_sdk/lib/agent_sdk.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
library agent_sdk;

// Client interface
export 'src/client/agent_client.dart';
export 'src/client/agent_client_capabilities.dart';

// Models
export 'src/models/agent_conversation.dart';
export 'src/models/agent_init_data.dart';
export 'src/models/agent_message.dart';
export 'src/models/agent_response.dart';
export 'src/models/agent_status.dart';
export 'src/models/token_usage.dart';
87 changes: 87 additions & 0 deletions packages/agent_sdk/lib/src/client/agent_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'dart:async';

import '../models/agent_conversation.dart';
import '../models/agent_init_data.dart';
import '../models/agent_message.dart';
import '../models/agent_response.dart';
import '../models/agent_status.dart';

/// Generic interface for interacting with an AI coding agent.
///
/// This is the common contract that consumers (like vide_core) depend on.
/// Each agent SDK (claude_sdk, codex_sdk) provides a bridge implementation
/// that wraps their SDK-specific client and maps types into this interface.
///
/// Extended capabilities (model switching, permission modes, etc.) are
/// expressed as separate interfaces that the bridge may also implement.
/// Use `if (client is ModelConfigurable)` to check for support.
abstract class AgentClient {
// ── Streams ──────────────────────────────────────────────

/// Stream of conversation state changes.
/// Emits whenever messages are added or updated (including streaming deltas).
Stream<AgentConversation> get conversation;

/// Emits when an agent turn completes (assistant finishes responding).
Stream<void> get onTurnComplete;

/// Stream of processing status updates (thinking, responding, etc.)
Stream<AgentProcessingStatus> get statusStream;

/// Stream of initialization data (model name, tools, etc.)
/// Emits when the agent CLI sends its init message.
Stream<AgentInitData> get initDataStream;

/// Stream of queued message text changes.
/// Emits the queued text, or null when queue is cleared.
Stream<String?> get queuedMessage;

// ── Current state ────────────────────────────────────────

/// The current conversation snapshot.
AgentConversation get currentConversation;

/// The most recent processing status.
AgentProcessingStatus get currentStatus;

/// The most recent initialization data, or null if not yet received.
AgentInitData? get initData;

/// The current queued message text, or null if no message is queued.
String? get currentQueuedMessage;

/// The session ID for this client instance.
String get sessionId;

/// The working directory for this agent.
String get workingDirectory;

/// Future that completes when the client has finished initializing.
Future<void> get initialized;

// ── Actions ──────────────────────────────────────────────

/// Send a message to the agent.
void sendMessage(AgentMessage message);

/// Abort the current operation.
Future<void> abort();

/// Close the client and release all resources.
Future<void> close();

/// Clear the conversation history, starting fresh.
Future<void> clearConversation();

/// Clear any queued message without sending it.
void clearQueuedMessage();

/// Inject a synthetic tool result into the conversation.
/// Used to mark a pending tool invocation as failed (e.g., when
/// permission is denied).
void injectToolResult(AgentToolResultResponse toolResult);

/// Get a registered MCP server by name and type.
/// Returns null if not found.
T? getMcpServer<T>(String name);
}
80 changes: 80 additions & 0 deletions packages/agent_sdk/lib/src/client/agent_client_capabilities.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/// Extended capability interfaces for agent-specific features.
///
/// Not all agents support the same operations. These interfaces allow
/// consumers to check for specific capabilities using `is` checks:
///
/// ```dart
/// if (client is ModelConfigurable) {
/// await client.setModel('opus');
/// }
/// ```

/// Agent supports changing the model at runtime.
abstract class ModelConfigurable {
Future<void> setModel(String model);
}

/// Agent supports setting a maximum thinking token budget.
abstract class ThinkingConfigurable {
Future<void> setMaxThinkingTokens(int maxTokens);
}

/// Agent supports changing permission mode at runtime.
abstract class PermissionModeConfigurable {
Future<void> setPermissionMode(String mode);
}

/// Agent supports interrupting the current execution
/// (more graceful than abort — marks current message as complete).
abstract class Interruptible {
Future<void> interrupt();
}

/// Agent supports rewinding files to a previous state.
abstract class FileRewindable {
Future<void> rewindFiles(String userMessageId);
}

/// Agent supports dynamic MCP server configuration.
abstract class McpConfigurable {
Future<void> setMcpServers(
List<AgentMcpServerConfig> servers, {
bool replace,
});
Future<AgentMcpStatusInfo> getMcpStatus();
}

/// Configuration for a dynamically-added MCP server.
class AgentMcpServerConfig {
final String name;
final String command;
final List<String> args;
final Map<String, String>? env;

const AgentMcpServerConfig({
required this.name,
required this.command,
this.args = const [],
this.env,
});
}

/// Status information for connected MCP servers.
class AgentMcpStatusInfo {
final List<AgentMcpServerStatus> servers;

const AgentMcpStatusInfo({required this.servers});
}

/// Status of a single MCP server.
class AgentMcpServerStatus {
final String name;
final String status;
final List<String> tools;

const AgentMcpServerStatus({
required this.name,
required this.status,
this.tools = const [],
});
}
Loading