syntax = "proto3";

package nominal.ai.v1;

// WorkbookAgentService provides AI-powered assistance for workbook operations
service WorkbookAgentService {
  // StreamChat handles bidirectional streaming chat for workbook AI agent
  rpc StreamChat(StreamChatRequest) returns (stream StreamChatResponse);
}

// StreamChatRequest is a request to stream chat messages for workbook AI agent
message StreamChatRequest {
  repeated ModelMessage messages = 1;
  // JSON-serialized representation of INotebook
  optional string notebook_as_json = 2;
  // The current tab visible in the workbook from the user's perspective
  optional int32 selected_tab_index = 3;
  // Optional: image files to provide to the agent
  repeated ImagePart images = 4;
}

// ModelMessage is a discriminated union of system, user, assistant, and tool messages.
// Each message type has its own structure and content.
message ModelMessage {
  oneof kind {
    UserModelMessage user = 1;
    AssistantModelMessage assistant = 2;
  }
}

// A user message containing text
message UserModelMessage {
  repeated UserContentPart text = 1;
}

// An assistant message containing text
message AssistantModelMessage {
  repeated AssistantContentPart content_parts = 1;
}

message UserContentPart {
  oneof part {
    TextPart text = 1;
  }
}

// Content part for assistant messages: can be text, reasoning, or mutation.
message AssistantContentPart {
  oneof part {
    TextPart text = 1;
    ReasoningPart reasoning = 2;
  }
}

// Text part for user or assistant messages.
message TextPart {
  string text = 1;
}

// User-supplied image part.
message ImagePart {
  // The base64-encoded image data
  bytes data = 1;
  // The media type of the image (e.g. "image/png", "image/jpeg")
  optional string media_type = 2;
  // Optional: the filename of the image
  optional string filename = 3;
}

// Reasoning part for assistant messages.
message ReasoningPart {
  string reasoning = 1;
}

// StreamChatResponse is a discriminated union response to a StreamChatRequest
message StreamChatResponse {
  oneof response {
    Finish finish = 1;
    Error error = 2;
    TextStart text_start = 3;
    TextDelta text_delta = 4;
    TextEnd text_end = 5;
    ReasoningStart reasoning_start = 6;
    ReasoningDelta reasoning_delta = 7;
    ReasoningEnd reasoning_end = 8;
    WorkbookMutation workbook_mutation = 9;
    ToolAction tool_action = 10;
  }
}

// Indicates the end of a chat session
message Finish {}

// An error that occurred during the chat session
message Error {
  string message = 1;
}

// Indicates the start of a text message from the agent
message TextStart {
  // uniquely identifies the text message (e.g. uuid) so that the client can
  // merge parallel message streams (if it happens).
  string id = 1;
}

// A delta (continuation) of a text message from the agent
message TextDelta {
  string id = 1;
  // The next chunk of text
  string delta = 2;
}

// Indicates the end of a text message from the agent
message TextEnd {
  string id = 1;
}

// Indicates the start of a reasoning message from the agent
message ReasoningStart {
  string id = 1;
}

// A delta (continuation) of a reasoning message from the agent
message ReasoningDelta {
  string id = 1;
  // The next chunk of reasoning
  string delta = 2;
}

// Indicates the end of a reasoning message from the agent
message ReasoningEnd {
  string id = 1;
}

// Add a new tab to the workbook
message AddTabMutation {
  // if tab_name is not provided, we'll name it "New Tab"
  optional string tab_name = 1;
}

// this is the "result" of the mutation
message AddOrUpdatePanelMutation {
  // JSON-serialized representation of IVizDefinition
  string panel_as_json = 1;
  string panel_id = 2;
  int32 tab_index = 3;
}

message RemovePanelsMutation {
  repeated string panel_ids = 1;
}

// AddOrReplaceVariableMutation is a mutation to add or replace a variable in the workbook
message AddOrReplaceVariableMutation {
  // scout_compute_api_ComputeSpecWithContext (this needs to be resolved)
  // be careful: this uses the scout_compute_api version of ComputeSpecWithContext, which stores the spec as "seriesNode"
  // and is NOT the same as ComputeSpecWithContext that is stored in INotebook.
  string compute_spec_as_json = 1;
  // if variable_name is not provided, we'll assume it's a new variable and auto-generate a unique name
  optional string variable_name = 2;
  optional string display_name = 3;
}

// DeleteVariablesMutation is a mutation to delete variables from the workbook
message DeleteVariablesMutation {
  repeated string variable_names = 1;
}

// WorkbookMutation is a mutation to the workbook
message WorkbookMutation {
  string id = 1;

  oneof mutation {
    AddTabMutation add_tab = 2;
    AddOrUpdatePanelMutation add_or_update_panel = 3;
    RemovePanelsMutation remove_panels = 4;
    AddOrReplaceVariableMutation add_or_replace_variable = 5;
    DeleteVariablesMutation delete_variables = 6;
  }
}

// this is a concise descirption of a tool call that the agent is making internally
// without revealing too much detail about the tool call, it informs the user what the agent is doing
// at a high level. the format is: `{tool_action_verb} {tool_target}` for example:
// "Search channels for My Datasource"
message ToolAction {
  string id = 1;
  string tool_action_verb = 2; // "Thought", "Read", "Find", "Look-up", etc.
  optional string tool_target = 3; // "workbook", "channel", "variable", "panel", etc.
}
