// Agent → Django Messages
//
// Messages sent from the Agent to Django server via gRPC stream.

syntax = "proto3";

package terminal;

option go_package = "terminal/proto";

import "google/protobuf/timestamp.proto";
import "common_types.proto";
import "file_operations.proto";
import "tunnel.proto";

// ============================================================================
// AGENT → DJANGO MESSAGES (via stream)
// ============================================================================

// Message from Agent to Django
message AgentMessage {
  string session_id = 1;                     // Session UUID
  string message_id = 2;                     // Unique message ID
  google.protobuf.Timestamp timestamp = 3;

  oneof payload {
    // Connection lifecycle
    RegisterRequest register = 10;           // Initial registration
    HeartbeatUpdate heartbeat = 11;          // Keepalive

    // Terminal output
    TerminalOutput output = 20;              // PTY stdout/stderr chunk
    CommandComplete command_complete = 21;   // Command finished

    // Status updates
    StatusUpdate status = 30;                // Session status change
    ErrorReport error = 31;                  // Error notification

    // Acknowledgements
    CommandAck ack = 40;                     // Command acknowledgement

    // File operation result
    FileOperationResult file_operation_result = 60; // File manager result

    // Tunnel responses
    TunnelCreated tunnel_created = 70;              // Tunnel creation result
    TunnelData tunnel_data = 71;                    // Tunnel data packet (response)
    TunnelClosed tunnel_closed = 72;                // Tunnel closed ack
    TunnelError tunnel_error = 73;                  // Tunnel error report

    // Permission status (added in v2.3.0)
    PermissionStatus permission_status = 80;        // Directory permission status

    // AI Agent responses (v2.12.0)
    AgentResult agent_result = 90;                  // Final agent response
    AgentStreamEvent agent_event = 91;              // Streaming event (token, tool)

    // Skills relay results (v2.24.0)
    SkillListResult skill_list_result = 110;         // Skill list result
    SkillShowResult skill_show_result = 111;         // Skill show result
    SkillRunResult skill_run_result = 112;            // Skill run result

    // MFA authentication response (v2.25.0)
    AuthResponse auth_response = 120;                // Response to server AuthChallenge
  }
}

// Registration request from Agent
message RegisterRequest {
  string version = 1;                        // Agent version
  string hostname = 2;                       // Machine hostname
  string platform = 3;                       // OS platform (darwin, win32, linux, ios, android)
  repeated string supported_shells = 4;      // Available shells (empty for mobile)
  TerminalSize initial_size = 5;             // Initial terminal size

  // Mobile device support (added in v2.1.0)
  string architecture = 6;                   // CPU architecture (arm64, x86_64, etc.)
  string device_id = 7;                      // Unique device ID (UDID for iOS, Android ID)
  string device_type = 8;                    // Device type: desktop, ios, android
  bool has_shell = 9;                        // Whether device has shell access (false for mobile)
  string device_model = 10;                  // Device model (iPhone 14 Pro, Pixel 8, etc.)

  // Extended system info (added in v2.2.0)
  string public_ip = 11;                     // Public IP address
  repeated string local_ips = 12;            // Local IP addresses
  string username = 13;                      // Current username
  uint32 uid = 14;                           // User ID (Unix)
  bool is_root = 15;                         // Running as root/admin
  string home_dir = 16;                      // User home directory
  string os_version = 17;                    // OS version (e.g., "Ubuntu 22.04", "macOS 14.2")
  string kernel_version = 18;                // Kernel version
  string cpu_model = 19;                     // CPU model name
  uint32 cpu_count = 20;                     // Number of CPU cores
  uint64 total_ram = 21;                     // Total RAM in bytes
  uint64 uptime_seconds = 22;                // System uptime in seconds

  // MFA / Machine Identity fields (v2.25.0)
  // Fields 30–35 reserved for security extensions.
  // Populated only when the workspace requires MFA or signed sessions.
  bytes  session_signature = 30;             // Ed25519 signature of handshake payload (64 bytes)
  bytes  session_public_key = 31;            // Ed25519 public key for this machine (32 bytes)
  uint32 key_version = 32;                   // Key version (for rotation tracking)
  repeated string agent_capabilities = 33;   // Supported auth methods: ["password", "ed25519"]
  string continuity_token = 34;             // Short-lived token for grace-period reconnects
  string agent_password = 35;               // plaintext agent password — Django hashes on first save (v2.26.0)
}

// Heartbeat with optional system metrics
// Sent every 30 seconds to keep connection alive and report machine status
message HeartbeatUpdate {
  SystemMetrics metrics = 1;                 // System metrics (optional, for monitoring)
}

// Terminal output chunk (stdout/stderr from PTY)
message TerminalOutput {
  bytes data = 1;                            // Raw output bytes
  bool is_stderr = 2;                        // True if from stderr
  int64 sequence = 3;                        // Sequence number for ordering
}

// Command completed notification
message CommandComplete {
  string command_id = 1;                     // Command that completed
  int32 exit_code = 2;                       // Exit code
  int64 duration_ms = 3;                     // Execution time in ms
}

// Status update from Agent
message StatusUpdate {
  SessionStatus old_status = 1;
  SessionStatus new_status = 2;
  string reason = 3;                         // Reason for status change
  string working_directory = 4;              // Current working directory
}

// Error report with user-friendly suggestions
message ErrorReport {
  string error_code = 1;                     // Error code
  string message = 2;                        // Error message
  string stack_trace = 3;                    // Optional stack trace
  bool is_fatal = 4;                         // If true, session will close
  repeated string suggestions = 5;           // User-friendly suggestions for resolution
  bool can_retry = 6;                        // Whether the operation can be retried
}

// Command acknowledgement
message CommandAck {
  string command_id = 1;                     // ID of acknowledged command
  bool success = 2;                          // Successful?
  string message = 3;                        // Optional message
}

// ============================================================================
// PERMISSION STATUS (added in v2.3.0)
// ============================================================================

// Permission status for directories
// Sent after warm-up to inform Django about accessible directories
message PermissionStatus {
  repeated DirectoryPermission directories = 1; // List of checked directories
  string platform = 2;                          // Platform (darwin, windows, linux)
  int64 checked_at = 3;                         // Unix timestamp when checked
}

// Permission status for a single directory
message DirectoryPermission {
  string path = 1;                              // Directory path
  PermissionAccessStatus status = 2;            // Access status
  string error_message = 3;                     // Error message if denied
  bool is_sensitive = 4;                        // True for protected directories (Desktop, Documents, etc.)
}

// Permission access status enum
enum PermissionAccessStatus {
  PERMISSION_GRANTED = 0;   // Access is granted
  PERMISSION_DENIED = 1;    // Access is denied (TCC, UAC, etc.)
  PERMISSION_PENDING = 2;   // OS is showing permission dialog
  PERMISSION_UNKNOWN = 3;   // Status could not be determined
}

// ============================================================================
// AI AGENT RESPONSES (v2.12.0)
// ============================================================================

// Final result from AI agent execution
message AgentResult {
  string request_id = 1;          // Correlates with AgentRunCommand.request_id
  bool success = 2;               // Whether execution succeeded
  string text = 3;                // Response text from agent
  string error = 4;               // Error message if failed
  repeated AgentToolResult tool_results = 5;  // Tool execution results
  AgentUsage usage = 6;           // Token usage stats
  int64 duration_ms = 7;          // Execution duration in milliseconds

  // Structured output JSON (if output_schema was provided)
  string output_json = 8;
}

// Tool execution result
message AgentToolResult {
  string tool_name = 1;           // Name of the tool
  string tool_call_id = 2;        // Tool call ID
  bool success = 3;               // Whether tool succeeded
  string result = 4;              // Tool result (JSON string)
  string error = 5;               // Error if failed
  int64 duration_ms = 6;          // Tool execution time
}

// Token usage statistics
message AgentUsage {
  int32 prompt_tokens = 1;        // Input tokens
  int32 completion_tokens = 2;    // Output tokens
  int32 total_tokens = 3;         // Total tokens
}

// Streaming event from agent (tokens, tool calls)
message AgentStreamEvent {
  string request_id = 1;          // Correlates with AgentRunCommand.request_id
  AgentEventType type = 2;        // Event type
  string payload = 3;             // Event-specific payload (JSON)
  int64 timestamp = 4;            // Unix timestamp in milliseconds
}

// Agent event types
enum AgentEventType {
  AGENT_EVENT_TOKEN = 0;          // Token generated (payload: token string)
  AGENT_EVENT_TOOL_START = 1;     // Tool execution started
  AGENT_EVENT_TOOL_END = 2;       // Tool execution completed
  AGENT_EVENT_THINKING = 3;       // Agent is thinking/processing
  AGENT_EVENT_ERROR = 4;          // Error occurred
  AGENT_EVENT_HANDOFF = 5;        // Handoff to another agent
  AGENT_EVENT_CANCELLED = 6;      // Agent run cancelled (v2.15.0)
}

// ============================================================================
// MFA AUTHENTICATION (v2.25.0)
// ============================================================================

// Response to an AuthChallenge sent by the server to an SDK client.
// SDK clients send this during ConnectTerminal attach when workspace requires MFA.
// NOTE: Go agents (CLI / Wails) never send AuthResponse — they use Ed25519 RegisterRequest signing.
message AuthResponse {
  string challenge_id = 1;          // Echoes AuthChallenge.challenge_id
  string password = 2;              // Plaintext session password for verification (v2.26.0)
  bytes  signature = 3;             // Ed25519 signature, 64 bytes (if method includes "ed25519")
  bytes  public_key = 4;            // Ed25519 public key, 32 bytes (first-time registration)
  uint32 key_version = 5;           // Key version for rotation tracking
}

// ============================================================================
// SKILL RELAY RESULTS (v2.24.0)
// ============================================================================

// Lightweight skill info for streaming messages.
// Avoids circular import with rpc_messages/skills.proto which imports agent_messages.proto.
message SkillInfoItem {
  string name = 1;                    // Skill name (e.g. "code-review")
  string description = 2;             // Human-readable description
  string author = 3;                  // Skill author
  string version = 4;                 // Semantic version
  string model = 5;                   // LLM model override
  string origin = 6;                  // Where loaded from: builtin, global, workspace
  repeated string required_bins = 7;  // Required system binaries
  repeated string required_env = 8;   // Required environment variables
}

// Result of SkillListCommand
message SkillListResult {
  string request_id = 1;                    // Correlates with SkillListCommand.request_id
  repeated SkillInfoItem skills = 2;        // All installed skills
}

// Result of SkillShowCommand
message SkillShowResult {
  string request_id = 1;              // Correlates with SkillShowCommand.request_id
  bool found = 2;                     // Whether the skill was found
  SkillInfoItem info = 3;             // Skill metadata (only set if found=true)
  string content = 4;                 // System prompt body (markdown)
  string source = 5;                  // Source file path on the machine
  string error = 6;                   // Error message if lookup failed
}

// Result of SkillRunCommand
message SkillRunResult {
  string request_id = 1;                          // Correlates with SkillRunCommand.request_id
  bool success = 2;                                // Whether execution succeeded
  string text = 3;                                 // Skill's response text
  string error = 4;                                // Error message if !success
  repeated AgentToolResult tool_results = 5;       // Tool execution results
  AgentUsage usage = 6;                            // Token usage stats
  int64 duration_ms = 7;                           // Execution duration in ms
  string output_json = 8;                          // Structured output JSON (if schema provided)
}
