feat!: replace msgpack with protobuf for all NATS messages
Some checks failed
CI / Lint (push) Failing after 3m2s
CI / Test (push) Successful in 3m44s
CI / Release (push) Has been skipped
CI / Notify Downstream (chat-handler) (push) Has been skipped
CI / Notify Downstream (pipeline-bridge) (push) Has been skipped
CI / Notify Downstream (stt-module) (push) Has been skipped
CI / Notify Downstream (tts-module) (push) Has been skipped
CI / Notify Downstream (voice-assistant) (push) Has been skipped
CI / Notify (push) Successful in 1s
Some checks failed
CI / Lint (push) Failing after 3m2s
CI / Test (push) Successful in 3m44s
CI / Release (push) Has been skipped
CI / Notify Downstream (chat-handler) (push) Has been skipped
CI / Notify Downstream (pipeline-bridge) (push) Has been skipped
CI / Notify Downstream (stt-module) (push) Has been skipped
CI / Notify Downstream (tts-module) (push) Has been skipped
CI / Notify Downstream (voice-assistant) (push) Has been skipped
CI / Notify (push) Successful in 1s
BREAKING CHANGE: All NATS message serialization now uses Protocol Buffers. - Added proto/messages/v1/messages.proto with 22 message types - Generated Go code at gen/messagespb/ - messages/ package now exports type aliases to proto types - natsutil.Publish/Request/Decode use proto.Marshal/Unmarshal - Removed legacy MessageHandler, OnMessage, wrapMapHandler - TypedMessageHandler now returns (proto.Message, error) - EffectiveQuery is now a free function: messages.EffectiveQuery(req) - Removed msgpack dependency entirely
This commit is contained in:
257
proto/messages/v1/messages.proto
Normal file
257
proto/messages/v1/messages.proto
Normal file
@@ -0,0 +1,257 @@
|
||||
// Homelab AI service message contracts.
|
||||
//
|
||||
// This is the single source of truth for all NATS message types.
|
||||
// Generated Go code lives in handler-base/gen/messagespb.
|
||||
//
|
||||
// Naming: field numbers are stable across versions — add new fields,
|
||||
// never reuse or renumber existing ones.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package messages.v1;
|
||||
|
||||
option go_package = "git.daviestechlabs.io/daviestechlabs/handler-base/gen/messagespb";
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Common
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ErrorResponse is the standard error reply from any handler.
|
||||
message ErrorResponse {
|
||||
bool error = 1;
|
||||
string message = 2;
|
||||
string type = 3;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Chat (companions-frontend ↔ chat-handler)
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// LoginEvent is published when a user authenticates.
|
||||
// Subject: ai.chat.user.{user_id}.login
|
||||
message LoginEvent {
|
||||
string user_id = 1;
|
||||
string username = 2;
|
||||
string nickname = 3;
|
||||
bool premium = 4;
|
||||
int64 timestamp = 5; // Unix seconds
|
||||
}
|
||||
|
||||
// GreetingRequest asks the LLM to generate a personalised greeting.
|
||||
// Subject: ai.chat.user.{user_id}.greeting.request
|
||||
message GreetingRequest {
|
||||
string user_id = 1;
|
||||
string username = 2;
|
||||
string nickname = 3;
|
||||
bool premium = 4;
|
||||
}
|
||||
|
||||
// GreetingResponse carries the generated greeting text.
|
||||
// Subject: ai.chat.user.{user_id}.greeting.response
|
||||
message GreetingResponse {
|
||||
string user_id = 1;
|
||||
string greeting = 2;
|
||||
}
|
||||
|
||||
// ChatRequest is an incoming chat message routed via NATS.
|
||||
// Subject: ai.chat.user.{user_id}.message
|
||||
message ChatRequest {
|
||||
string request_id = 1;
|
||||
string user_id = 2;
|
||||
string username = 3;
|
||||
string message = 4;
|
||||
string query = 5; // alternative to message (EffectiveQuery picks first non-empty)
|
||||
bool premium = 6;
|
||||
bool enable_rag = 7;
|
||||
bool enable_reranker = 8;
|
||||
bool enable_streaming = 9;
|
||||
int32 top_k = 10;
|
||||
string collection = 11;
|
||||
bool enable_tts = 12;
|
||||
string system_prompt = 13;
|
||||
string response_subject = 14;
|
||||
}
|
||||
|
||||
// ChatResponse is the full reply to a ChatRequest.
|
||||
// Subject: ai.chat.response.{request_id} (or ChatRequest.response_subject)
|
||||
message ChatResponse {
|
||||
string user_id = 1;
|
||||
string response = 2;
|
||||
string response_text = 3;
|
||||
bool used_rag = 4;
|
||||
repeated string rag_sources = 5;
|
||||
bool success = 6;
|
||||
bytes audio = 7;
|
||||
string error = 8;
|
||||
}
|
||||
|
||||
// ChatStreamChunk is one piece of a streaming LLM response.
|
||||
// Subject: ai.chat.response.stream.{request_id}
|
||||
message ChatStreamChunk {
|
||||
string request_id = 1;
|
||||
string type = 2; // "chunk" | "done"
|
||||
string content = 3;
|
||||
bool done = 4;
|
||||
int64 timestamp = 5;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Voice Assistant
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// VoiceRequest is an incoming voice-to-voice request.
|
||||
// Subject: ai.voice.request
|
||||
message VoiceRequest {
|
||||
string request_id = 1;
|
||||
bytes audio = 2;
|
||||
string language = 3;
|
||||
string collection = 4;
|
||||
}
|
||||
|
||||
// DocumentSource is a single RAG search-result citation.
|
||||
message DocumentSource {
|
||||
string text = 1;
|
||||
double score = 2;
|
||||
}
|
||||
|
||||
// VoiceResponse is the reply to a VoiceRequest.
|
||||
// Subject: ai.voice.response.{request_id}
|
||||
message VoiceResponse {
|
||||
string request_id = 1;
|
||||
string response = 2;
|
||||
bytes audio = 3;
|
||||
string transcription = 4;
|
||||
repeated DocumentSource sources = 5;
|
||||
string error = 6;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// TTS Module
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// TTSRequest is a text-to-speech synthesis request.
|
||||
// Subject: ai.voice.tts.request.{session_id}
|
||||
message TTSRequest {
|
||||
string text = 1;
|
||||
string speaker = 2;
|
||||
string language = 3;
|
||||
string speaker_wav_b64 = 4;
|
||||
bool stream = 5;
|
||||
}
|
||||
|
||||
// TTSAudioChunk is a streamed audio chunk from TTS synthesis.
|
||||
// Subject: ai.voice.tts.audio.{session_id}
|
||||
message TTSAudioChunk {
|
||||
string session_id = 1;
|
||||
int32 chunk_index = 2;
|
||||
int32 total_chunks = 3;
|
||||
bytes audio = 4;
|
||||
bool is_last = 5;
|
||||
int64 timestamp = 6;
|
||||
int32 sample_rate = 7;
|
||||
}
|
||||
|
||||
// TTSFullResponse is a non-streamed TTS response (whole audio blob).
|
||||
// Subject: ai.voice.tts.audio.{session_id}
|
||||
message TTSFullResponse {
|
||||
string session_id = 1;
|
||||
bytes audio = 2;
|
||||
int64 timestamp = 3;
|
||||
int32 sample_rate = 4;
|
||||
}
|
||||
|
||||
// TTSStatus is a TTS processing status update.
|
||||
// Subject: ai.voice.tts.status.{session_id}
|
||||
message TTSStatus {
|
||||
string session_id = 1;
|
||||
string status = 2;
|
||||
string message = 3;
|
||||
int64 timestamp = 4;
|
||||
}
|
||||
|
||||
// TTSVoiceInfo is summary info about a custom voice.
|
||||
message TTSVoiceInfo {
|
||||
string name = 1;
|
||||
string language = 2;
|
||||
string model_type = 3;
|
||||
string created_at = 4;
|
||||
}
|
||||
|
||||
// TTSVoiceListResponse is the reply to a voice list request.
|
||||
// Subject: ai.voice.tts.voices.list (request-reply)
|
||||
message TTSVoiceListResponse {
|
||||
string default_speaker = 1;
|
||||
repeated TTSVoiceInfo custom_voices = 2;
|
||||
int64 last_refresh = 3;
|
||||
int64 timestamp = 4;
|
||||
}
|
||||
|
||||
// TTSVoiceRefreshResponse is the reply to a voice refresh request.
|
||||
// Subject: ai.voice.tts.voices.refresh (request-reply)
|
||||
message TTSVoiceRefreshResponse {
|
||||
int32 count = 1;
|
||||
repeated TTSVoiceInfo custom_voices = 2;
|
||||
int64 timestamp = 3;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// STT Module
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// STTStreamMessage is any message on the ai.voice.stream.{session_id} subject.
|
||||
message STTStreamMessage {
|
||||
string type = 1; // "start" | "chunk" | "state_change" | "end"
|
||||
bytes audio = 2;
|
||||
string state = 3;
|
||||
string speaker_id = 4;
|
||||
}
|
||||
|
||||
// STTTranscription is the transcription result published by the STT module.
|
||||
// Subject: ai.voice.transcription.{session_id}
|
||||
message STTTranscription {
|
||||
string session_id = 1;
|
||||
string transcript = 2;
|
||||
int32 sequence = 3;
|
||||
bool is_partial = 4;
|
||||
bool is_final = 5;
|
||||
int64 timestamp = 6;
|
||||
string speaker_id = 7;
|
||||
bool has_voice_activity = 8;
|
||||
string state = 9;
|
||||
}
|
||||
|
||||
// STTInterrupt is published when the STT module detects a user interrupt.
|
||||
// Subject: ai.voice.transcription.{session_id}
|
||||
message STTInterrupt {
|
||||
string session_id = 1;
|
||||
string type = 2; // "interrupt"
|
||||
int64 timestamp = 3;
|
||||
string speaker_id = 4;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Pipeline Bridge
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// PipelineTrigger is the request to start a pipeline.
|
||||
// Subject: ai.pipeline.trigger
|
||||
message PipelineTrigger {
|
||||
string request_id = 1;
|
||||
string pipeline = 2;
|
||||
// Protobuf Struct could be used here, but a simple string map covers
|
||||
// all current use-cases and avoids a google/protobuf import.
|
||||
map<string, string> parameters = 3;
|
||||
}
|
||||
|
||||
// PipelineStatus is the response / status update for a pipeline run.
|
||||
// Subject: ai.pipeline.status.{request_id}
|
||||
message PipelineStatus {
|
||||
string request_id = 1;
|
||||
string status = 2;
|
||||
string run_id = 3;
|
||||
string engine = 4;
|
||||
string pipeline = 5;
|
||||
string submitted_at = 6;
|
||||
string error = 7;
|
||||
repeated string available_pipelines = 8;
|
||||
}
|
||||
Reference in New Issue
Block a user