syntax = "proto3";

package home_native.v1;

option go_package = "server/proto";

import "google/protobuf/empty.proto";

// ---- Unified error codes (concise) ----
enum ErrorCode {
  ERROR_CODE_UNSPECIFIED = 0;
  ERROR_CODE_INVALID_ARGUMENT = 1;
  ERROR_CODE_UNAVAILABLE = 2;      // Downstream/hardware/resource unavailable
  ERROR_CODE_DEADLINE_EXCEEDED = 3;
  ERROR_CODE_INTERNAL = 4;
}

// ---- Standard error payload (used with gRPC status; fatal errors may terminate the stream) ----
message Error {
  ErrorCode code = 1;
  string    message = 2;
  string    detail = 3;             // For logging/troubleshooting (stack, node ID, etc.)
}

// ---- Structured task I/O description (for central routing and client negotiation) ----
message IOTask {
  string name = 1;                           // "embed","detect","ocr","asr","generate","tts",...
  repeated string input_mimes = 2;           // Allow multiple input types: "image/jpeg","audio/pcm;rate=16000","application/json"
  repeated string output_mimes = 3;          // Typical outputs: "application/json;schema=bbox_v1","audio/wav"
  map<string, string> limits = 4;            // e.g., max_hw=1024, max_batch=8, max_length=4096
}

// ---- Capability declaration (retrieve at startup or on demand) ----
message Capability {
  string service_name = 1;                   // "clip-embedder","ocr","llm","tts",...
  repeated string model_ids = 2;             // Supported model IDs/versions
  string runtime = 3;                        // "onnxrt-cuda","tensorrt","coreml","rknn","qnn","cpu"
  uint32 max_concurrency = 4;                // Suggested max concurrency
  repeated string precisions = 5;            // ["fp32","fp16","int8"]
  map<string, string> extra = 6;             // Resolution limits, ANE/NPU features, etc.
  repeated IOTask tasks = 7;                 // Structured task capabilities (recommended)
  string protocol_version = 8;               // Version of current porotocal, should be semantic versioning. e.g., 1.0.0
}

// ---- Inference request (inbound message of bidi stream) ----
message InferRequest {
  string correlation_id = 1;                 // Trace/correlation
  string task = 2;                           // "embed","classify","detect","ocr","asr","generate","tts",...
  bytes  payload = 3;                        // Raw payload (binary or UTF-8 text)
  map<string, string> meta = 4;              // Task-specific parameters: model_id, conf_thres, stop, etc.

  // --- Added: input content type and chunking control ---
  string payload_mime = 5;                   // e.g. "image/jpeg","audio/pcm;rate=16000","application/json"
  uint64 seq = 6;                            // Chunk index (starting at 0)
  uint64 total = 7;                          // Optional: total number of chunks (omit if unknown)
  uint64 offset = 8;                         // Optional: byte offset of payload in the overall stream
}

// ---- Inference response (outbound message of bidi stream) ----
message InferResponse {
  string correlation_id = 1;
  bool   is_final = 2;                       // Streaming partials or final result
  bytes  result = 3;                         // Result bytes; if JSON, specify via result_mime
  map<string, string> meta = 4;              // e.g., lat_ms, tokens, bboxes_count
  Error  error = 5;                          // Populated only on failure (fatal errors may also terminate the stream)

  // --- Added: output content type and chunking control ---
  uint64 seq = 6;                            // Chunk index (starting at 0), used for incremental/audio/video chunks
  uint64 total = 7;                          // Optional: total number of chunks
  uint64 offset = 8;                         // Optional: byte offset of result in the overall output
  string result_mime = 9;                    // e.g. "application/json;schema=embedding_v1","audio/wav","image/png"
  string result_schema = 10;                 // Optional: explicit schema name (e.g., "bbox_v1","mask_rle_v1")
}

// ---- Service contract ----
service Inference {
  // Bidirectional stream: client sends chunks; server returns incremental/final results; ordered but non-blocking
  rpc Infer(stream InferRequest) returns (stream InferResponse);

  // Capability declaration (backward compatibility: single capability; use StreamCapabilities for multiple)
  rpc GetCapabilities(google.protobuf.Empty) returns (Capability);

  // Recommended: server stream returns all capabilities (call at startup or after hot-reload)
  rpc StreamCapabilities(google.protobuf.Empty) returns (stream Capability);

  // Health probe
  rpc Health(google.protobuf.Empty) returns (google.protobuf.Empty);
}
