syntax = "proto3";

package grackle.powerline;

// ─── Types ──────────────────────────────────────────────────

message Empty {}

message SessionId {
  string id = 1;
}

message KillRequest {
  string id = 1;
  string reason = 2; // "completed", "killed", or "interrupted"
}

message EnvironmentInfo {
  string hostname = 1;
  string os = 2;
  string node_version = 3;
  repeated string available_runtimes = 4;
  int64 uptime_seconds = 5;
}

message Pong {
  int64 timestamp = 1;
}

message SpawnRequest {
  string session_id = 1; // Server-assigned session ID
  string runtime = 2; // "claude-code" | "copilot" | "codex" | "goose" | "stub" | ...
  string prompt = 3;
  string model = 4;
  int32 max_turns = 5;
  string branch = 6; // Branch for worktree (empty = skip)
  string working_directory = 7; // Repo root, e.g. "/workspace"
  string system_context = 8; // Prepended to prompt (task desc + findings)
  optional string workspace_id = 9; // So MCP server knows which workspace
  string task_id = 10; // So MCP server knows which task
  string mcp_servers_json = 11; // JSON-encoded MCP server configs from persona
  string mcp_url = 14;         // Server's MCP endpoint URL (tunneled for remote envs)
  string mcp_token = 15;       // Pre-created scoped token for this session
  string script_content = 16;  // Script source code (for script personas)
  optional bool use_worktrees = 17; // When set, controls worktree behavior; when unset, defaults to true
  string pipe = 18; // Propagated from server SpawnRequest ("sync", "async", "detach", or "")
}

message ResumeRequest {
  string session_id = 1;
  string runtime_session_id = 2; // Runtime-native session ID
  string runtime = 3;
}

message InputMessage {
  string session_id = 1;
  string text = 2;
}

message AgentEvent {
  string session_id = 1;
  string type = 2;
  string timestamp = 3;
  string content = 4;
  string raw = 5; // JSON, optional
}

message SessionInfo {
  string session_id = 1;
  string runtime = 2;
  string status = 3;
}

message SessionList {
  repeated SessionInfo sessions = 1;
}

// ─── Token Injection ────────────────────────────────────────

message TokenItem {
  string name = 1;
  string type = 2;
  string env_var = 3;
  string file_path = 4;
  string value = 5;
}

message TokenBundle {
  repeated TokenItem tokens = 1;
}

// ─── Worktree ──────────────────────────────────────────────

message WorktreeCleanupRequest {
  string branch = 1;
  string working_directory = 2;
}

// ─── Drain ─────────────────────────────────────────────────

message DrainRequest {
  string session_id = 1;
}

// ─── Service ────────────────────────────────────────────────

service GracklePowerLine {
  rpc GetInfo(Empty) returns (EnvironmentInfo);
  rpc Spawn(SpawnRequest) returns (stream AgentEvent);
  rpc Resume(ResumeRequest) returns (stream AgentEvent);
  rpc SendInput(InputMessage) returns (Empty);
  rpc Kill(KillRequest) returns (Empty);
  rpc ListSessions(Empty) returns (SessionList);
  rpc Ping(Empty) returns (Pong);
  rpc PushTokens(TokenBundle) returns (Empty);
  rpc CleanupWorktree(WorktreeCleanupRequest) returns (Empty);
  rpc DrainBufferedEvents(DrainRequest) returns (stream AgentEvent);
}
