/// Codex sandbox mode for controlling file system access. enum CodexSandboxMode { readOnly('read-only'), workspaceWrite('workspace-write'), dangerFullAccess('danger-full-access'); final String value; const CodexSandboxMode(this.value); } /// Codex approval policy for controlling automatic execution. enum CodexApprovalPolicy { suggest('suggest'), autoEdit('auto-edit'), fullAuto('full-auto'); final String value; const CodexApprovalPolicy(this.value); } /// Codex authentication mode. enum CodexAuthMode { apiKey('api-key'), chatgpt('chatgpt'), chatgptAuthTokens('chatgptAuthTokens'); final String value; const CodexAuthMode(this.value); } /// Codex thread information. class CodexThread { final String id; final String? path; final bool ephemeral; final DateTime? createdAt; const CodexThread({ required this.id, this.path, this.ephemeral = false, this.createdAt, }); factory CodexThread.fromJson(Map json) { return CodexThread( id: json['id'] as String, path: json['path'] as String?, ephemeral: json['ephemeral'] as bool? ?? false, createdAt: json['createdAt'] != null ? DateTime.tryParse(json['createdAt'] as String) : null, ); } Map toJson() => { 'id': id, if (path != null) 'path': path, 'ephemeral': ephemeral, if (createdAt != null) 'createdAt': createdAt!.toIso8601String(), }; } /// Codex turn information. class CodexTurn { final String id; final String threadId; final String status; final DateTime? startedAt; final DateTime? completedAt; const CodexTurn({ required this.id, required this.threadId, required this.status, this.startedAt, this.completedAt, }); factory CodexTurn.fromJson(Map json) { return CodexTurn( id: json['id'] as String, threadId: json['threadId'] as String, status: json['status'] as String, startedAt: json['startedAt'] != null ? DateTime.tryParse(json['startedAt'] as String) : null, completedAt: json['completedAt'] != null ? DateTime.tryParse(json['completedAt'] as String) : null, ); } } /// Codex account information. class CodexAccount { final String? email; final String? plan; final bool hasCredits; final double? creditsBalance; final List rateLimits; const CodexAccount({ this.email, this.plan, this.hasCredits = false, this.creditsBalance, this.rateLimits = const [], }); factory CodexAccount.fromJson(Map json) { return CodexAccount( email: json['email'] as String?, plan: json['plan'] as String?, hasCredits: json['hasCredits'] as bool? ?? false, creditsBalance: (json['creditsBalance'] as num?)?.toDouble(), rateLimits: (json['rateLimits'] as List?) ?.map((e) => CodexRateLimit.fromJson(e as Map)) .toList() ?? [], ); } } /// Codex rate limit information. class CodexRateLimit { final String type; final int percentRemaining; final DateTime? resetsAt; const CodexRateLimit({ required this.type, required this.percentRemaining, this.resetsAt, }); factory CodexRateLimit.fromJson(Map json) { return CodexRateLimit( type: json['type'] as String, percentRemaining: json['percentRemaining'] as int? ?? 0, resetsAt: json['resetsAt'] != null ? DateTime.tryParse(json['resetsAt'] as String) : null, ); } } /// Codex user input for turn/start. class CodexUserInput { final String type; final String content; final List? attachments; const CodexUserInput({ this.type = 'message', required this.content, this.attachments, }); Map toJson() => { 'type': type, 'content': content, if (attachments != null && attachments!.isNotEmpty) 'attachments': attachments!.map((a) => a.toJson()).toList(), }; } /// Codex file attachment. class CodexAttachment { final String path; final String? name; const CodexAttachment({required this.path, this.name}); Map toJson() => { 'path': path, if (name != null) 'name': name, }; } /// Base class for Codex events. sealed class CodexEvent { const CodexEvent(); } /// Log event from Codex. class CodexLogEvent extends CodexEvent { final String level; final String message; final DateTime timestamp; const CodexLogEvent({ required this.level, required this.message, required this.timestamp, }); } /// Notification event from Codex App Server. class CodexNotificationEvent extends CodexEvent { final String method; final Map params; const CodexNotificationEvent({required this.method, required this.params}); } /// Turn event (item/started, item/completed, etc.). class CodexTurnEvent extends CodexEvent { final String type; final String? threadId; final String? turnId; final String? itemId; final Map data; const CodexTurnEvent({ required this.type, this.threadId, this.turnId, this.itemId, required this.data, }); factory CodexTurnEvent.fromNotification(CodexNotificationEvent notification) { final params = notification.params; return CodexTurnEvent( type: notification.method, threadId: params['threadId'] as String?, turnId: params['turnId'] as String?, itemId: params['itemId'] as String?, data: params, ); } /// Check if this is a text delta event. bool get isTextDelta => type == 'item/agentMessage/delta'; /// Get text delta content. String? get textDelta => data['delta'] as String?; } /// Error from Codex RPC. class CodexRpcError implements Exception { final int code; final String message; final dynamic data; const CodexRpcError({required this.code, required this.message, this.data}); factory CodexRpcError.fromJson(Map json) { return CodexRpcError( code: json['code'] as int? ?? -1, message: json['message'] as String? ?? 'Unknown error', data: json['data'], ); } @override String toString() => 'CodexRpcError($code): $message'; } /// Connection state for CodexRuntime. enum CodexConnectionState { disconnected, connecting, connected, initializing, ready, error, } /// Codex App Server RPC client. class CodexRuntime {} class CodexLaunchConfiguration { const CodexLaunchConfiguration({ required this.executable, required this.arguments, this.runInShell = false, }); final String executable; final List arguments; final bool runInShell; }