// Django → Agent Control Messages
//
// Messages sent from Django server to Agent 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";

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

// Message from Django to Agent (control commands)
message ControlMessage {
  string command_id = 1;                     // Unique command ID
  google.protobuf.Timestamp timestamp = 2;

  oneof payload {
    // Terminal input
    TerminalInput input = 10;                // Keyboard input from browser
    ResizeCommand resize = 11;               // Terminal resize

    // Session control
    StartSessionCommand start_session = 20;  // Start terminal session
    CloseSessionCommand close_session = 21;  // Close terminal session

    // Process control
    SignalCommand signal = 30;               // Send signal (SIGINT, SIGTERM, etc.)
    CancelCommand cancel = 31;               // Cancel running command

    // Connection management
    PingCommand ping = 40;                   // Ping for latency check
    ConfigUpdateCommand config_update = 41;  // Update session config

    // File operations (routed through streaming)
    FileOperationRequest file_operation = 60; // File manager operations

    // Push notifications (desktop notifications to user)
    PushNotification push_notification = 70;  // Desktop notification

    // Streaming relay (file transfer chunks)
    StreamingRelayChunk streaming_relay_chunk = 80;  // File chunk for relay transfer

    // Tunnel (HTTP/TCP tunnel to local service)
    TunnelCreate tunnel_create = 90;                 // Create tunnel to local port
    TunnelData tunnel_data = 91;                     // Tunnel data packet (request)
    TunnelClose tunnel_close = 92;                   // Close tunnel

    // Permission management (v2.3.0)
    RefreshPermissionsCommand refresh_permissions = 100;  // Re-check all permissions

    // AI Agent execution (v2.12.0)
    AgentRunCommand agent_run = 110;                      // Run AI agent with prompt
    AgentCancelCommand agent_cancel = 111;                // Cancel running agent (v2.15.0)

    // Skills relay (v2.24.0)
    // SDK → Django → Agent skill management and execution
    SkillListCommand skill_list = 130;                    // List installed skills
    SkillShowCommand skill_show = 131;                    // Get skill details
    SkillRunCommand skill_run = 132;                      // Execute a skill

    // MFA authentication challenge (v2.25.0)
    AuthChallenge auth_challenge = 120;                   // Server requests MFA verification

    // Continuity token for grace-period reconnect without MFA (v2.25.0 Week 5)
    ContinuityToken continuity_token = 121;               // Short-lived token for fast reconnect

    // Auth success — delivers session token after password verification (v2.26.0)
    AuthSuccess auth_success = 122;                       // Server confirms auth + session token
  }
}

// Notification delivery method
enum NotificationMethod {
  NOTIFICATION_METHOD_AUTO = 0;              // System decides (visual if available, else audio)
  NOTIFICATION_METHOD_VISUAL = 1;            // Desktop notification only
  NOTIFICATION_METHOD_AUDIO = 2;             // Voice/sound only (TTS)
  NOTIFICATION_METHOD_BOTH = 3;              // Visual + audio
}

// Push notification to show on agent's desktop
message PushNotification {
  string id = 1;                             // Notification ID
  string type = 2;                           // Type: info, success, warning, error, session, system, custom
  string title = 3;                          // Notification title
  string message = 4;                        // Notification message
  map<string, string> data = 5;              // Additional data
  int32 priority = 6;                        // Priority: 0=normal, 1=high, 2=urgent
  bool silent = 7;                           // If true, process without showing notification
  NotificationMethod method = 8;             // Delivery method (visual, audio, both)
}

// Terminal input from browser (keyboard, paste)
message TerminalInput {
  bytes data = 1;                            // Raw input bytes
  int64 sequence = 2;                        // Sequence number
}

// Terminal resize
message ResizeCommand {
  TerminalSize size = 1;                     // New terminal size
}

// Start terminal session (after registration)
message StartSessionCommand {
  SessionConfig config = 1;                  // Session configuration
  string web_terminal_url = 2;               // Browser terminal URL (e.g., https://cmdop.com/terminal?s=abc123)
  google.protobuf.Timestamp expires_at = 3;  // Optional: URL expiration time
}

// Close terminal session
message CloseSessionCommand {
  string reason = 1;                         // Reason for closing
  bool force = 2;                            // Force close (kill processes)
}

// Send signal to PTY process
message SignalCommand {
  int32 signal = 1;                          // Signal number (2=SIGINT, 15=SIGTERM, 9=SIGKILL)
}

// Cancel running command
message CancelCommand {
  string command_id = 1;                     // Command to cancel (if tracking)
}

// Ping for latency measurement
message PingCommand {
  int64 sequence = 1;                        // Ping sequence number
}

// Configuration update
message ConfigUpdateCommand {
  SessionConfig config = 1;                  // New configuration
}

// Refresh permissions command (v2.3.0)
// Triggers agent to re-check all protected directories
// On macOS, this will show TCC dialogs for any denied directories
message RefreshPermissionsCommand {
  // Empty - just triggers re-check of all protected directories
  // Agent will send PermissionStatus when complete
}

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

// Agent type enum
enum AgentType {
  AGENT_TYPE_CHAT = 0;        // Simple chat agent (no PTY)
  AGENT_TYPE_TERMINAL = 1;    // Terminal agent with PTY access
  AGENT_TYPE_COMMAND = 2;     // Command execution agent
  AGENT_TYPE_ROUTER = 3;      // Router agent (delegates to specialists)
  AGENT_TYPE_PLANNER = 4;     // Planner agent (complex tasks)
}

// Run AI agent command
// Sent from Django to Agent to execute AI prompt
message AgentRunCommand {
  string request_id = 1;      // Unique request ID for correlation
  string prompt = 2;          // User prompt/question
  AgentType agent_type = 3;   // Type of agent to run
  map<string, string> options = 4;  // Additional options (model, max_turns, etc.)
  bool stream_events = 5;     // If true, stream events back (tokens, tool calls)

  // Optional: JSON Schema for structured output
  // If provided, agent returns output_json matching this schema
  string output_schema = 6;
}

// ============================================================================
// AI AGENT CANCELLATION (v2.15.0)
// ============================================================================

// Cancel running AI agent
// Sent from Django to Agent to stop ongoing agent execution
message AgentCancelCommand {
  string request_id = 1;      // Request ID to cancel (from AgentRunCommand)
  string reason = 2;          // Cancellation reason: "user", "timeout", "error"
}

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

// List all installed skills on the agent machine
message SkillListCommand {
  string request_id = 1;      // Unique request ID for correlation
}

// Get details of a specific skill
message SkillShowCommand {
  string request_id = 1;      // Unique request ID for correlation
  string skill_name = 2;      // Skill name to look up
}

// Execute a skill with a prompt
message SkillRunCommand {
  string request_id = 1;                // Unique request ID for correlation
  string skill_name = 2;                // Skill name to execute
  string prompt = 3;                    // User prompt for the skill
  map<string, string> options = 4;      // Additional options (e.g. model override)
  int32 timeout_seconds = 5;            // Max execution time in seconds
  string output_schema = 6;             // Optional JSON Schema for structured output
}

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

// Server sends this to SDK clients during ConnectTerminal attach when workspace requires MFA.
// SDK client must respond with AuthResponse (in AgentMessage) within 60 seconds.
// NOTE: Agents (Go CLI / Wails) do NOT receive AuthChallenge — they authenticate via Ed25519 only.
message AuthChallenge {
  string challenge_id = 1;              // Unique challenge ID (echoed back in AuthResponse)
  repeated string methods = 2;          // Required auth methods: ["password"], ["ed25519"], or both
  // Note: nonce for Ed25519 signing is obtained via GetChallenge() unary RPC before stream open.
  // The challenge_id here is for password flow correlation only.
}

// Server confirms auth and delivers session token to SDK client (v2.26.0).
// Sent after successful password verification in ConnectTerminal attach flow.
// SDK must include session_token as x-session-token metadata on unary RPCs.
message AuthSuccess {
  string challenge_id = 1;              // Echoes AuthChallenge.challenge_id
  string session_token = 2;            // Token for x-session-token metadata on unary RPCs
  int32  ttl_seconds = 3;             // Token TTL in seconds (informational)
}

// Sent at stream close to allow seamless reconnect within the grace period (30s).
// Agent includes this in RegisterRequest.continuity_token on reconnect.
// Single-use: consumed immediately on first successful reconnect.
message ContinuityToken {
  string token = 1;                     // 64-char hex token (32 random bytes)
  int64  expires_at = 2;                // Unix timestamp (stream_close_time + 30s)
}
