CODEX_ADK/FRONTEND/lib/api/endpoints/agent_endpoint.dart
jean-philippe ff34042975 feat: Complete API integration for Agents, Conversations, and Executions
Implement full CQRS API integration with type-safe endpoints for all core backend operations.

## What's New
- **Agent Management**: 4 endpoints (create, get, update, delete) with 3 enums
- **Conversations**: 2 endpoints (create, get) with message support
- **Executions**: 3 endpoints (start, complete, get) with status tracking
- **OpenAPI Schema**: Updated to backend v1.0.0-mvp (10 endpoints)

## Implementation Details
- All endpoints follow CQRS pattern (commands/queries)
- 100% strict typing (no dynamic, all explicit types)
- Functional error handling with Result<T> pattern
- 3,136+ lines of production code
- 1,500+ lines of comprehensive documentation

## Files Added
- lib/api/endpoints/agent_endpoint.dart (364 lines)
- lib/api/endpoints/conversation_endpoint.dart (319 lines)
- lib/api/endpoints/execution_endpoint.dart (434 lines)
- lib/api/examples/agent_example.dart (212 lines)
- docs/AGENT_API_INTEGRATION.md (431 lines)
- docs/COMPLETE_API_INTEGRATION.md (555 lines)
- docs/INTEGRATION_STATUS.md (339 lines)

## Quality Metrics
- Flutter analyze: 0 errors 
- Type safety: 100% (0 dynamic types) 
- CQRS compliance: 100% 
- Backend compatibility: v1.0.0-mvp 

## Backend Integration
- Updated api-schema.json from backend openapi.json
- Supports all MVP endpoints except list operations (deferred to Phase 3)
- Ready for JWT authentication (infrastructure in place)

## Usage
```dart
import 'package:console/api/api.dart';

final client = CqrsApiClient(config: ApiClientConfig.development);

// Agent CRUD
await client.createAgent(CreateAgentCommand(...));
await client.getAgent('uuid');

// Conversations
await client.createConversation(CreateConversationCommand(...));

// Executions
await client.startAgentExecution(StartAgentExecutionCommand(...));
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 18:53:19 -04:00

365 lines
10 KiB
Dart

/// Agent management endpoints for CQRS API
library;
import '../client.dart';
import '../types.dart';
// =============================================================================
// Enums
// =============================================================================
/// Specifies the type/purpose of the agent
enum AgentType {
codeGenerator('CodeGenerator'),
codeReviewer('CodeReviewer'),
debugger('Debugger'),
documenter('Documenter'),
custom('Custom');
const AgentType(this.value);
final String value;
static AgentType fromString(String value) {
return AgentType.values.firstWhere(
(type) => type.value == value,
orElse: () => AgentType.custom,
);
}
}
/// Represents the current status of an agent
enum AgentStatus {
active('Active'),
inactive('Inactive'),
error('Error');
const AgentStatus(this.value);
final String value;
static AgentStatus fromString(String value) {
return AgentStatus.values.firstWhere(
(status) => status.value == value,
orElse: () => AgentStatus.inactive,
);
}
}
/// Specifies the type of model provider (cloud API or local endpoint)
enum ModelProviderType {
cloudApi('CloudApi'),
localEndpoint('LocalEndpoint'),
custom('Custom');
const ModelProviderType(this.value);
final String value;
static ModelProviderType fromString(String value) {
return ModelProviderType.values.firstWhere(
(type) => type.value == value,
orElse: () => ModelProviderType.custom,
);
}
}
// =============================================================================
// Commands
// =============================================================================
/// Command to create a new AI agent with configuration
class CreateAgentCommand implements Serializable {
final String name;
final String description;
final AgentType type;
final String modelProvider;
final String modelName;
final ModelProviderType providerType;
final String? modelEndpoint;
final String? apiKey;
final double temperature;
final int maxTokens;
final String systemPrompt;
final bool enableMemory;
final int conversationWindowSize;
const CreateAgentCommand({
required this.name,
required this.description,
required this.type,
required this.modelProvider,
required this.modelName,
required this.providerType,
this.modelEndpoint,
this.apiKey,
this.temperature = 0.7,
this.maxTokens = 4000,
required this.systemPrompt,
this.enableMemory = true,
this.conversationWindowSize = 10,
});
@override
Map<String, Object?> toJson() => {
'name': name,
'description': description,
'type': type.value,
'modelProvider': modelProvider,
'modelName': modelName,
'providerType': providerType.value,
'modelEndpoint': modelEndpoint,
'apiKey': apiKey,
'temperature': temperature,
'maxTokens': maxTokens,
'systemPrompt': systemPrompt,
'enableMemory': enableMemory,
'conversationWindowSize': conversationWindowSize,
};
}
/// Command to update an existing agent's configuration
class UpdateAgentCommand implements Serializable {
final String id;
final String? name;
final String? description;
final AgentType? type;
final String? modelProvider;
final String? modelName;
final ModelProviderType? providerType;
final String? modelEndpoint;
final String? apiKey;
final double? temperature;
final int? maxTokens;
final String? systemPrompt;
final bool? enableMemory;
final int? conversationWindowSize;
final AgentStatus? status;
const UpdateAgentCommand({
required this.id,
this.name,
this.description,
this.type,
this.modelProvider,
this.modelName,
this.providerType,
this.modelEndpoint,
this.apiKey,
this.temperature,
this.maxTokens,
this.systemPrompt,
this.enableMemory,
this.conversationWindowSize,
this.status,
});
@override
Map<String, Object?> toJson() => {
'id': id,
if (name != null) 'name': name,
if (description != null) 'description': description,
if (type != null) 'type': type!.value,
if (modelProvider != null) 'modelProvider': modelProvider,
if (modelName != null) 'modelName': modelName,
if (providerType != null) 'providerType': providerType!.value,
if (modelEndpoint != null) 'modelEndpoint': modelEndpoint,
if (apiKey != null) 'apiKey': apiKey,
if (temperature != null) 'temperature': temperature,
if (maxTokens != null) 'maxTokens': maxTokens,
if (systemPrompt != null) 'systemPrompt': systemPrompt,
if (enableMemory != null) 'enableMemory': enableMemory,
if (conversationWindowSize != null)
'conversationWindowSize': conversationWindowSize,
if (status != null) 'status': status!.value,
};
}
/// Command to soft-delete an agent
class DeleteAgentCommand implements Serializable {
final String id;
const DeleteAgentCommand({required this.id});
@override
Map<String, Object?> toJson() => {'id': id};
}
// =============================================================================
// Queries
// =============================================================================
/// Query to get a single agent by ID
class GetAgentQuery implements Serializable {
final String id;
const GetAgentQuery({required this.id});
@override
Map<String, Object?> toJson() => {'id': id};
}
// =============================================================================
// DTOs
// =============================================================================
/// Response containing agent details
class AgentDto {
final String id;
final String name;
final String description;
final AgentType type;
final String modelProvider;
final String modelName;
final ModelProviderType providerType;
final String? modelEndpoint;
final double temperature;
final int maxTokens;
final String systemPrompt;
final bool enableMemory;
final int conversationWindowSize;
final AgentStatus status;
final DateTime createdAt;
final DateTime updatedAt;
const AgentDto({
required this.id,
required this.name,
required this.description,
required this.type,
required this.modelProvider,
required this.modelName,
required this.providerType,
this.modelEndpoint,
required this.temperature,
required this.maxTokens,
required this.systemPrompt,
required this.enableMemory,
required this.conversationWindowSize,
required this.status,
required this.createdAt,
required this.updatedAt,
});
factory AgentDto.fromJson(Map<String, Object?> json) {
return AgentDto(
id: json['id'] as String,
name: json['name'] as String,
description: json['description'] as String,
type: AgentType.fromString(json['type'] as String),
modelProvider: json['modelProvider'] as String,
modelName: json['modelName'] as String,
providerType: ModelProviderType.fromString(json['providerType'] as String),
modelEndpoint: json['modelEndpoint'] as String?,
temperature: (json['temperature'] as num).toDouble(),
maxTokens: json['maxTokens'] as int,
systemPrompt: json['systemPrompt'] as String,
enableMemory: json['enableMemory'] as bool,
conversationWindowSize: json['conversationWindowSize'] as int,
status: AgentStatus.fromString(json['status'] as String),
createdAt: DateTime.parse(json['createdAt'] as String),
updatedAt: DateTime.parse(json['updatedAt'] as String),
);
}
Map<String, Object?> toJson() => {
'id': id,
'name': name,
'description': description,
'type': type.value,
'modelProvider': modelProvider,
'modelName': modelName,
'providerType': providerType.value,
'modelEndpoint': modelEndpoint,
'temperature': temperature,
'maxTokens': maxTokens,
'systemPrompt': systemPrompt,
'enableMemory': enableMemory,
'conversationWindowSize': conversationWindowSize,
'status': status.value,
'createdAt': createdAt.toIso8601String(),
'updatedAt': updatedAt.toIso8601String(),
};
}
// =============================================================================
// Extension Methods
// =============================================================================
/// Agent management endpoints
extension AgentEndpoint on CqrsApiClient {
/// Create a new AI agent
///
/// Example:
/// ```dart
/// final result = await client.createAgent(
/// CreateAgentCommand(
/// name: 'Code Generator',
/// description: 'AI agent for code generation',
/// type: AgentType.codeGenerator,
/// modelProvider: 'ollama',
/// modelName: 'phi',
/// providerType: ModelProviderType.localEndpoint,
/// modelEndpoint: 'http://localhost:11434',
/// systemPrompt: 'You are a code generation assistant',
/// ),
/// );
/// ```
Future<Result<void>> createAgent(CreateAgentCommand command) async {
return executeCommand(
endpoint: 'createAgent',
command: command,
);
}
/// Update an existing agent's configuration
///
/// Example:
/// ```dart
/// final result = await client.updateAgent(
/// UpdateAgentCommand(
/// id: 'agent-uuid',
/// name: 'Updated Name',
/// status: AgentStatus.active,
/// ),
/// );
/// ```
Future<Result<void>> updateAgent(UpdateAgentCommand command) async {
return executeCommand(
endpoint: 'updateAgent',
command: command,
);
}
/// Soft-delete an agent
///
/// Example:
/// ```dart
/// final result = await client.deleteAgent(
/// DeleteAgentCommand(id: 'agent-uuid'),
/// );
/// ```
Future<Result<void>> deleteAgent(DeleteAgentCommand command) async {
return executeCommand(
endpoint: 'deleteAgent',
command: command,
);
}
/// Get a single agent by ID
///
/// Example:
/// ```dart
/// final result = await client.getAgent('agent-uuid');
///
/// result.when(
/// success: (agent) => print('Agent: ${agent.name}'),
/// error: (error) => print('Error: ${error.message}'),
/// );
/// ```
Future<Result<AgentDto>> getAgent(String id) async {
return executeQuery<AgentDto>(
endpoint: 'getAgent',
query: GetAgentQuery(id: id),
fromJson: (json) => AgentDto.fromJson(json as Map<String, Object?>),
);
}
}