From bc77171b96eb6e449ea63b21de8651785fb41992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Mon, 27 Jul 2026 10:40:25 -0700 Subject: [PATCH 01/10] Add agent session store protocols livekit_agent_session_store.proto is the management API (Twirp): create, get, list and delete a session, plus Dump for a consistent download URL. livekit_agent_session_db.proto is the data plane: a request/response frame pair over one WebSocket per session, correlated by client-chosen request_id, with exec, query, atomic batch, interactive transactions, and credit-paced row batches so any result size streams with bounded memory at every hop. SessionValue mirrors SQLite's five storage classes. The other twirp files change only because protoc-gen-twirp numbers file descriptors by position in the invocation, so inserting one service shifts the ones after it. --- livekit/livekit_agent_session_db.pb.go | 1610 +++++++++++++++++ livekit/livekit_agent_session_store.pb.go | 683 +++++++ livekit/livekit_agent_session_store.twirp.go | 1685 ++++++++++++++++++ livekit/livekit_agent_simulation.twirp.go | 4 +- livekit/livekit_cloud_agent.twirp.go | 4 +- livekit/livekit_connector.twirp.go | 4 +- livekit/livekit_egress.twirp.go | 4 +- livekit/livekit_ingress.twirp.go | 4 +- livekit/livekit_phone_number.twirp.go | 4 +- livekit/livekit_room.twirp.go | 4 +- livekit/livekit_sip.twirp.go | 4 +- magefile.go | 2 + protobufs/livekit_agent_session_db.proto | 145 ++ protobufs/livekit_agent_session_store.proto | 95 + 14 files changed, 4236 insertions(+), 16 deletions(-) create mode 100644 livekit/livekit_agent_session_db.pb.go create mode 100644 livekit/livekit_agent_session_store.pb.go create mode 100644 livekit/livekit_agent_session_store.twirp.go create mode 100644 protobufs/livekit_agent_session_db.proto create mode 100644 protobufs/livekit_agent_session_store.proto diff --git a/livekit/livekit_agent_session_db.pb.go b/livekit/livekit_agent_session_db.pb.go new file mode 100644 index 000000000..40ef02f82 --- /dev/null +++ b/livekit/livekit_agent_session_db.pb.go @@ -0,0 +1,1610 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v7.34.1 +// source: livekit_agent_session_db.proto + +package livekit + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// SessionQueryLang selects the query language of a statement; both execute +// against the same session database. +type SessionQueryLang int32 + +const ( + SessionQueryLang_SESSION_QUERY_LANG_SQL SessionQueryLang = 0 + SessionQueryLang_SESSION_QUERY_LANG_CYPHER SessionQueryLang = 1 +) + +// Enum value maps for SessionQueryLang. +var ( + SessionQueryLang_name = map[int32]string{ + 0: "SESSION_QUERY_LANG_SQL", + 1: "SESSION_QUERY_LANG_CYPHER", + } + SessionQueryLang_value = map[string]int32{ + "SESSION_QUERY_LANG_SQL": 0, + "SESSION_QUERY_LANG_CYPHER": 1, + } +) + +func (x SessionQueryLang) Enum() *SessionQueryLang { + p := new(SessionQueryLang) + *p = x + return p +} + +func (x SessionQueryLang) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SessionQueryLang) Descriptor() protoreflect.EnumDescriptor { + return file_livekit_agent_session_db_proto_enumTypes[0].Descriptor() +} + +func (SessionQueryLang) Type() protoreflect.EnumType { + return &file_livekit_agent_session_db_proto_enumTypes[0] +} + +func (x SessionQueryLang) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SessionQueryLang.Descriptor instead. +func (SessionQueryLang) EnumDescriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{0} +} + +type SessionStoreRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId uint32 `protobuf:"varint,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + // Types that are valid to be assigned to Message: + // + // *SessionStoreRequest_Hello + // *SessionStoreRequest_Exec + // *SessionStoreRequest_Query + // *SessionStoreRequest_Batch + // *SessionStoreRequest_Begin + // *SessionStoreRequest_Commit + // *SessionStoreRequest_Rollback + // *SessionStoreRequest_Cancel + // *SessionStoreRequest_Credit + // *SessionStoreRequest_Ping + Message isSessionStoreRequest_Message `protobuf_oneof:"message"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionStoreRequest) Reset() { + *x = SessionStoreRequest{} + mi := &file_livekit_agent_session_db_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionStoreRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionStoreRequest) ProtoMessage() {} + +func (x *SessionStoreRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionStoreRequest.ProtoReflect.Descriptor instead. +func (*SessionStoreRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{0} +} + +func (x *SessionStoreRequest) GetRequestId() uint32 { + if x != nil { + return x.RequestId + } + return 0 +} + +func (x *SessionStoreRequest) GetMessage() isSessionStoreRequest_Message { + if x != nil { + return x.Message + } + return nil +} + +func (x *SessionStoreRequest) GetHello() *SessionHello { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Hello); ok { + return x.Hello + } + } + return nil +} + +func (x *SessionStoreRequest) GetExec() *SessionStatement { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Exec); ok { + return x.Exec + } + } + return nil +} + +func (x *SessionStoreRequest) GetQuery() *SessionStatement { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Query); ok { + return x.Query + } + } + return nil +} + +func (x *SessionStoreRequest) GetBatch() *SessionBatch { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Batch); ok { + return x.Batch + } + } + return nil +} + +func (x *SessionStoreRequest) GetBegin() *SessionBegin { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Begin); ok { + return x.Begin + } + } + return nil +} + +func (x *SessionStoreRequest) GetCommit() *SessionCommit { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Commit); ok { + return x.Commit + } + } + return nil +} + +func (x *SessionStoreRequest) GetRollback() *SessionRollback { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Rollback); ok { + return x.Rollback + } + } + return nil +} + +func (x *SessionStoreRequest) GetCancel() *SessionCancel { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Cancel); ok { + return x.Cancel + } + } + return nil +} + +func (x *SessionStoreRequest) GetCredit() *SessionCredit { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Credit); ok { + return x.Credit + } + } + return nil +} + +func (x *SessionStoreRequest) GetPing() *SessionPing { + if x != nil { + if x, ok := x.Message.(*SessionStoreRequest_Ping); ok { + return x.Ping + } + } + return nil +} + +type isSessionStoreRequest_Message interface { + isSessionStoreRequest_Message() +} + +type SessionStoreRequest_Hello struct { + Hello *SessionHello `protobuf:"bytes,2,opt,name=hello,proto3,oneof"` // must be first on the socket +} + +type SessionStoreRequest_Exec struct { + Exec *SessionStatement `protobuf:"bytes,3,opt,name=exec,proto3,oneof"` // no result rows; answers SessionExecResult +} + +type SessionStoreRequest_Query struct { + Query *SessionStatement `protobuf:"bytes,4,opt,name=query,proto3,oneof"` // answers SessionColumns + SessionRowBatch* + SessionDone +} + +type SessionStoreRequest_Batch struct { + Batch *SessionBatch `protobuf:"bytes,5,opt,name=batch,proto3,oneof"` // atomic multi-statement exec +} + +type SessionStoreRequest_Begin struct { + Begin *SessionBegin `protobuf:"bytes,6,opt,name=begin,proto3,oneof"` // interactive transaction (server enforces idle/duration timeouts) +} + +type SessionStoreRequest_Commit struct { + Commit *SessionCommit `protobuf:"bytes,7,opt,name=commit,proto3,oneof"` +} + +type SessionStoreRequest_Rollback struct { + Rollback *SessionRollback `protobuf:"bytes,8,opt,name=rollback,proto3,oneof"` +} + +type SessionStoreRequest_Cancel struct { + Cancel *SessionCancel `protobuf:"bytes,9,opt,name=cancel,proto3,oneof"` // stop a running query's stream/cursor +} + +type SessionStoreRequest_Credit struct { + Credit *SessionCredit `protobuf:"bytes,10,opt,name=credit,proto3,oneof"` // grant more RowBatch credits for request_id +} + +type SessionStoreRequest_Ping struct { + Ping *SessionPing `protobuf:"bytes,11,opt,name=ping,proto3,oneof"` +} + +func (*SessionStoreRequest_Hello) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Exec) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Query) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Batch) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Begin) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Commit) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Rollback) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Cancel) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Credit) isSessionStoreRequest_Message() {} + +func (*SessionStoreRequest_Ping) isSessionStoreRequest_Message() {} + +type SessionStoreResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId uint32 `protobuf:"varint,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + // Types that are valid to be assigned to Message: + // + // *SessionStoreResponse_HelloOk + // *SessionStoreResponse_Columns + // *SessionStoreResponse_RowBatch + // *SessionStoreResponse_ExecResult + // *SessionStoreResponse_Done + // *SessionStoreResponse_Error + // *SessionStoreResponse_Pong + Message isSessionStoreResponse_Message `protobuf_oneof:"message"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionStoreResponse) Reset() { + *x = SessionStoreResponse{} + mi := &file_livekit_agent_session_db_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionStoreResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionStoreResponse) ProtoMessage() {} + +func (x *SessionStoreResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionStoreResponse.ProtoReflect.Descriptor instead. +func (*SessionStoreResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{1} +} + +func (x *SessionStoreResponse) GetRequestId() uint32 { + if x != nil { + return x.RequestId + } + return 0 +} + +func (x *SessionStoreResponse) GetMessage() isSessionStoreResponse_Message { + if x != nil { + return x.Message + } + return nil +} + +func (x *SessionStoreResponse) GetHelloOk() *SessionHelloOk { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_HelloOk); ok { + return x.HelloOk + } + } + return nil +} + +func (x *SessionStoreResponse) GetColumns() *SessionColumns { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_Columns); ok { + return x.Columns + } + } + return nil +} + +func (x *SessionStoreResponse) GetRowBatch() *SessionRowBatch { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_RowBatch); ok { + return x.RowBatch + } + } + return nil +} + +func (x *SessionStoreResponse) GetExecResult() *SessionExecResult { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_ExecResult); ok { + return x.ExecResult + } + } + return nil +} + +func (x *SessionStoreResponse) GetDone() *SessionDone { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_Done); ok { + return x.Done + } + } + return nil +} + +func (x *SessionStoreResponse) GetError() *SessionStoreError { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_Error); ok { + return x.Error + } + } + return nil +} + +func (x *SessionStoreResponse) GetPong() *SessionPong { + if x != nil { + if x, ok := x.Message.(*SessionStoreResponse_Pong); ok { + return x.Pong + } + } + return nil +} + +type isSessionStoreResponse_Message interface { + isSessionStoreResponse_Message() +} + +type SessionStoreResponse_HelloOk struct { + HelloOk *SessionHelloOk `protobuf:"bytes,2,opt,name=hello_ok,json=helloOk,proto3,oneof"` +} + +type SessionStoreResponse_Columns struct { + Columns *SessionColumns `protobuf:"bytes,3,opt,name=columns,proto3,oneof"` +} + +type SessionStoreResponse_RowBatch struct { + RowBatch *SessionRowBatch `protobuf:"bytes,4,opt,name=row_batch,json=rowBatch,proto3,oneof"` +} + +type SessionStoreResponse_ExecResult struct { + ExecResult *SessionExecResult `protobuf:"bytes,5,opt,name=exec_result,json=execResult,proto3,oneof"` +} + +type SessionStoreResponse_Done struct { + Done *SessionDone `protobuf:"bytes,6,opt,name=done,proto3,oneof"` +} + +type SessionStoreResponse_Error struct { + Error *SessionStoreError `protobuf:"bytes,7,opt,name=error,proto3,oneof"` +} + +type SessionStoreResponse_Pong struct { + Pong *SessionPong `protobuf:"bytes,8,opt,name=pong,proto3,oneof"` +} + +func (*SessionStoreResponse_HelloOk) isSessionStoreResponse_Message() {} + +func (*SessionStoreResponse_Columns) isSessionStoreResponse_Message() {} + +func (*SessionStoreResponse_RowBatch) isSessionStoreResponse_Message() {} + +func (*SessionStoreResponse_ExecResult) isSessionStoreResponse_Message() {} + +func (*SessionStoreResponse_Done) isSessionStoreResponse_Message() {} + +func (*SessionStoreResponse_Error) isSessionStoreResponse_Message() {} + +func (*SessionStoreResponse_Pong) isSessionStoreResponse_Message() {} + +// SessionValue mirrors SQLite's five storage classes exactly. +type SessionValue struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Value: + // + // *SessionValue_NullValue + // *SessionValue_IntValue + // *SessionValue_DoubleValue + // *SessionValue_TextValue + // *SessionValue_BlobValue + Value isSessionValue_Value `protobuf_oneof:"value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionValue) Reset() { + *x = SessionValue{} + mi := &file_livekit_agent_session_db_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionValue) ProtoMessage() {} + +func (x *SessionValue) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionValue.ProtoReflect.Descriptor instead. +func (*SessionValue) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{2} +} + +func (x *SessionValue) GetValue() isSessionValue_Value { + if x != nil { + return x.Value + } + return nil +} + +func (x *SessionValue) GetNullValue() bool { + if x != nil { + if x, ok := x.Value.(*SessionValue_NullValue); ok { + return x.NullValue + } + } + return false +} + +func (x *SessionValue) GetIntValue() int64 { + if x != nil { + if x, ok := x.Value.(*SessionValue_IntValue); ok { + return x.IntValue + } + } + return 0 +} + +func (x *SessionValue) GetDoubleValue() float64 { + if x != nil { + if x, ok := x.Value.(*SessionValue_DoubleValue); ok { + return x.DoubleValue + } + } + return 0 +} + +func (x *SessionValue) GetTextValue() string { + if x != nil { + if x, ok := x.Value.(*SessionValue_TextValue); ok { + return x.TextValue + } + } + return "" +} + +func (x *SessionValue) GetBlobValue() []byte { + if x != nil { + if x, ok := x.Value.(*SessionValue_BlobValue); ok { + return x.BlobValue + } + } + return nil +} + +type isSessionValue_Value interface { + isSessionValue_Value() +} + +type SessionValue_NullValue struct { + NullValue bool `protobuf:"varint,1,opt,name=null_value,json=nullValue,proto3,oneof"` // always true when set +} + +type SessionValue_IntValue struct { + IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +type SessionValue_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,3,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type SessionValue_TextValue struct { + TextValue string `protobuf:"bytes,4,opt,name=text_value,json=textValue,proto3,oneof"` +} + +type SessionValue_BlobValue struct { + BlobValue []byte `protobuf:"bytes,5,opt,name=blob_value,json=blobValue,proto3,oneof"` +} + +func (*SessionValue_NullValue) isSessionValue_Value() {} + +func (*SessionValue_IntValue) isSessionValue_Value() {} + +func (*SessionValue_DoubleValue) isSessionValue_Value() {} + +func (*SessionValue_TextValue) isSessionValue_Value() {} + +func (*SessionValue_BlobValue) isSessionValue_Value() {} + +type SessionStatement struct { + state protoimpl.MessageState `protogen:"open.v1"` + Sql string `protobuf:"bytes,1,opt,name=sql,proto3" json:"sql,omitempty"` // statement text in the selected lang + Params []*SessionValue `protobuf:"bytes,2,rep,name=params,proto3" json:"params,omitempty"` // positional bind parameters + Lang SessionQueryLang `protobuf:"varint,3,opt,name=lang,proto3,enum=livekit.SessionQueryLang" json:"lang,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionStatement) Reset() { + *x = SessionStatement{} + mi := &file_livekit_agent_session_db_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionStatement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionStatement) ProtoMessage() {} + +func (x *SessionStatement) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionStatement.ProtoReflect.Descriptor instead. +func (*SessionStatement) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{3} +} + +func (x *SessionStatement) GetSql() string { + if x != nil { + return x.Sql + } + return "" +} + +func (x *SessionStatement) GetParams() []*SessionValue { + if x != nil { + return x.Params + } + return nil +} + +func (x *SessionStatement) GetLang() SessionQueryLang { + if x != nil { + return x.Lang + } + return SessionQueryLang_SESSION_QUERY_LANG_SQL +} + +type SessionBatch struct { + state protoimpl.MessageState `protogen:"open.v1"` + Statements []*SessionStatement `protobuf:"bytes,1,rep,name=statements,proto3" json:"statements,omitempty"` // applied atomically, in order + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionBatch) Reset() { + *x = SessionBatch{} + mi := &file_livekit_agent_session_db_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionBatch) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionBatch) ProtoMessage() {} + +func (x *SessionBatch) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionBatch.ProtoReflect.Descriptor instead. +func (*SessionBatch) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{4} +} + +func (x *SessionBatch) GetStatements() []*SessionStatement { + if x != nil { + return x.Statements + } + return nil +} + +type SessionBegin struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionBegin) Reset() { + *x = SessionBegin{} + mi := &file_livekit_agent_session_db_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionBegin) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionBegin) ProtoMessage() {} + +func (x *SessionBegin) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionBegin.ProtoReflect.Descriptor instead. +func (*SessionBegin) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{5} +} + +type SessionCommit struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionCommit) Reset() { + *x = SessionCommit{} + mi := &file_livekit_agent_session_db_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionCommit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionCommit) ProtoMessage() {} + +func (x *SessionCommit) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionCommit.ProtoReflect.Descriptor instead. +func (*SessionCommit) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{6} +} + +type SessionRollback struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionRollback) Reset() { + *x = SessionRollback{} + mi := &file_livekit_agent_session_db_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionRollback) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionRollback) ProtoMessage() {} + +func (x *SessionRollback) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionRollback.ProtoReflect.Descriptor instead. +func (*SessionRollback) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{7} +} + +type SessionCancel struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionCancel) Reset() { + *x = SessionCancel{} + mi := &file_livekit_agent_session_db_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionCancel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionCancel) ProtoMessage() {} + +func (x *SessionCancel) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionCancel.ProtoReflect.Descriptor instead. +func (*SessionCancel) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{8} +} + +type SessionCredit struct { + state protoimpl.MessageState `protogen:"open.v1"` + Batches uint32 `protobuf:"varint,1,opt,name=batches,proto3" json:"batches,omitempty"` // additional RowBatch frames the client can absorb + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionCredit) Reset() { + *x = SessionCredit{} + mi := &file_livekit_agent_session_db_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionCredit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionCredit) ProtoMessage() {} + +func (x *SessionCredit) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionCredit.ProtoReflect.Descriptor instead. +func (*SessionCredit) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{9} +} + +func (x *SessionCredit) GetBatches() uint32 { + if x != nil { + return x.Batches + } + return 0 +} + +type SessionPing struct { + state protoimpl.MessageState `protogen:"open.v1"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionPing) Reset() { + *x = SessionPing{} + mi := &file_livekit_agent_session_db_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionPing) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionPing) ProtoMessage() {} + +func (x *SessionPing) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionPing.ProtoReflect.Descriptor instead. +func (*SessionPing) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{10} +} + +func (x *SessionPing) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +type SessionPong struct { + state protoimpl.MessageState `protogen:"open.v1"` + LastPingTimestamp int64 `protobuf:"varint,1,opt,name=last_ping_timestamp,json=lastPingTimestamp,proto3" json:"last_ping_timestamp,omitempty"` + Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionPong) Reset() { + *x = SessionPong{} + mi := &file_livekit_agent_session_db_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionPong) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionPong) ProtoMessage() {} + +func (x *SessionPong) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionPong.ProtoReflect.Descriptor instead. +func (*SessionPong) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{11} +} + +func (x *SessionPong) GetLastPingTimestamp() int64 { + if x != nil { + return x.LastPingTimestamp + } + return 0 +} + +func (x *SessionPong) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +type SessionHello struct { + state protoimpl.MessageState `protogen:"open.v1"` + Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` // access token; authorization is checked here + SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionHello) Reset() { + *x = SessionHello{} + mi := &file_livekit_agent_session_db_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionHello) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionHello) ProtoMessage() {} + +func (x *SessionHello) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionHello.ProtoReflect.Descriptor instead. +func (*SessionHello) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{12} +} + +func (x *SessionHello) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +func (x *SessionHello) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type SessionHelloOk struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tip int64 `protobuf:"varint,1,opt,name=tip,proto3" json:"tip,omitempty"` // latest durable commit sequence + PingIntervalMs uint32 `protobuf:"varint,2,opt,name=ping_interval_ms,json=pingIntervalMs,proto3" json:"ping_interval_ms,omitempty"` // server-advertised keepalive cadence + PingTimeoutMs uint32 `protobuf:"varint,3,opt,name=ping_timeout_ms,json=pingTimeoutMs,proto3" json:"ping_timeout_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionHelloOk) Reset() { + *x = SessionHelloOk{} + mi := &file_livekit_agent_session_db_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionHelloOk) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionHelloOk) ProtoMessage() {} + +func (x *SessionHelloOk) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionHelloOk.ProtoReflect.Descriptor instead. +func (*SessionHelloOk) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{13} +} + +func (x *SessionHelloOk) GetTip() int64 { + if x != nil { + return x.Tip + } + return 0 +} + +func (x *SessionHelloOk) GetPingIntervalMs() uint32 { + if x != nil { + return x.PingIntervalMs + } + return 0 +} + +func (x *SessionHelloOk) GetPingTimeoutMs() uint32 { + if x != nil { + return x.PingTimeoutMs + } + return 0 +} + +type SessionColumns struct { + state protoimpl.MessageState `protogen:"open.v1"` + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionColumns) Reset() { + *x = SessionColumns{} + mi := &file_livekit_agent_session_db_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionColumns) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionColumns) ProtoMessage() {} + +func (x *SessionColumns) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionColumns.ProtoReflect.Descriptor instead. +func (*SessionColumns) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{14} +} + +func (x *SessionColumns) GetNames() []string { + if x != nil { + return x.Names + } + return nil +} + +type SessionRow struct { + state protoimpl.MessageState `protogen:"open.v1"` + Values []*SessionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionRow) Reset() { + *x = SessionRow{} + mi := &file_livekit_agent_session_db_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionRow) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionRow) ProtoMessage() {} + +func (x *SessionRow) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionRow.ProtoReflect.Descriptor instead. +func (*SessionRow) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{15} +} + +func (x *SessionRow) GetValues() []*SessionValue { + if x != nil { + return x.Values + } + return nil +} + +type SessionRowBatch struct { + state protoimpl.MessageState `protogen:"open.v1"` + Rows []*SessionRow `protobuf:"bytes,1,rep,name=rows,proto3" json:"rows,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionRowBatch) Reset() { + *x = SessionRowBatch{} + mi := &file_livekit_agent_session_db_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionRowBatch) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionRowBatch) ProtoMessage() {} + +func (x *SessionRowBatch) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionRowBatch.ProtoReflect.Descriptor instead. +func (*SessionRowBatch) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{16} +} + +func (x *SessionRowBatch) GetRows() []*SessionRow { + if x != nil { + return x.Rows + } + return nil +} + +type SessionExecResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + RowsAffected int64 `protobuf:"varint,1,opt,name=rows_affected,json=rowsAffected,proto3" json:"rows_affected,omitempty"` + LastInsertId int64 `protobuf:"varint,2,opt,name=last_insert_id,json=lastInsertId,proto3" json:"last_insert_id,omitempty"` + Tip int64 `protobuf:"varint,3,opt,name=tip,proto3" json:"tip,omitempty"` // durable commit sequence after this exec + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionExecResult) Reset() { + *x = SessionExecResult{} + mi := &file_livekit_agent_session_db_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionExecResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionExecResult) ProtoMessage() {} + +func (x *SessionExecResult) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionExecResult.ProtoReflect.Descriptor instead. +func (*SessionExecResult) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{17} +} + +func (x *SessionExecResult) GetRowsAffected() int64 { + if x != nil { + return x.RowsAffected + } + return 0 +} + +func (x *SessionExecResult) GetLastInsertId() int64 { + if x != nil { + return x.LastInsertId + } + return 0 +} + +func (x *SessionExecResult) GetTip() int64 { + if x != nil { + return x.Tip + } + return 0 +} + +type SessionDone struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tip int64 `protobuf:"varint,1,opt,name=tip,proto3" json:"tip,omitempty"` // snapshot the query ran at + TotalRows uint64 `protobuf:"varint,2,opt,name=total_rows,json=totalRows,proto3" json:"total_rows,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionDone) Reset() { + *x = SessionDone{} + mi := &file_livekit_agent_session_db_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionDone) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionDone) ProtoMessage() {} + +func (x *SessionDone) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionDone.ProtoReflect.Descriptor instead. +func (*SessionDone) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{18} +} + +func (x *SessionDone) GetTip() int64 { + if x != nil { + return x.Tip + } + return 0 +} + +func (x *SessionDone) GetTotalRows() uint64 { + if x != nil { + return x.TotalRows + } + return 0 +} + +type SessionStoreError struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` // stable machine-readable code + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionStoreError) Reset() { + *x = SessionStoreError{} + mi := &file_livekit_agent_session_db_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionStoreError) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionStoreError) ProtoMessage() {} + +func (x *SessionStoreError) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_db_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionStoreError.ProtoReflect.Descriptor instead. +func (*SessionStoreError) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{19} +} + +func (x *SessionStoreError) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *SessionStoreError) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_livekit_agent_session_db_proto protoreflect.FileDescriptor + +const file_livekit_agent_session_db_proto_rawDesc = "" + + "\n" + + "\x1elivekit_agent_session_db.proto\x12\alivekit\"\xaa\x04\n" + + "\x13SessionStoreRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\rR\trequestId\x12-\n" + + "\x05hello\x18\x02 \x01(\v2\x15.livekit.SessionHelloH\x00R\x05hello\x12/\n" + + "\x04exec\x18\x03 \x01(\v2\x19.livekit.SessionStatementH\x00R\x04exec\x121\n" + + "\x05query\x18\x04 \x01(\v2\x19.livekit.SessionStatementH\x00R\x05query\x12-\n" + + "\x05batch\x18\x05 \x01(\v2\x15.livekit.SessionBatchH\x00R\x05batch\x12-\n" + + "\x05begin\x18\x06 \x01(\v2\x15.livekit.SessionBeginH\x00R\x05begin\x120\n" + + "\x06commit\x18\a \x01(\v2\x16.livekit.SessionCommitH\x00R\x06commit\x126\n" + + "\brollback\x18\b \x01(\v2\x18.livekit.SessionRollbackH\x00R\brollback\x120\n" + + "\x06cancel\x18\t \x01(\v2\x16.livekit.SessionCancelH\x00R\x06cancel\x120\n" + + "\x06credit\x18\n" + + " \x01(\v2\x16.livekit.SessionCreditH\x00R\x06credit\x12*\n" + + "\x04ping\x18\v \x01(\v2\x14.livekit.SessionPingH\x00R\x04pingB\t\n" + + "\amessage\"\xaf\x03\n" + + "\x14SessionStoreResponse\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\rR\trequestId\x124\n" + + "\bhello_ok\x18\x02 \x01(\v2\x17.livekit.SessionHelloOkH\x00R\ahelloOk\x123\n" + + "\acolumns\x18\x03 \x01(\v2\x17.livekit.SessionColumnsH\x00R\acolumns\x127\n" + + "\trow_batch\x18\x04 \x01(\v2\x18.livekit.SessionRowBatchH\x00R\browBatch\x12=\n" + + "\vexec_result\x18\x05 \x01(\v2\x1a.livekit.SessionExecResultH\x00R\n" + + "execResult\x12*\n" + + "\x04done\x18\x06 \x01(\v2\x14.livekit.SessionDoneH\x00R\x04done\x122\n" + + "\x05error\x18\a \x01(\v2\x1a.livekit.SessionStoreErrorH\x00R\x05error\x12*\n" + + "\x04pong\x18\b \x01(\v2\x14.livekit.SessionPongH\x00R\x04pongB\t\n" + + "\amessage\"\xbe\x01\n" + + "\fSessionValue\x12\x1f\n" + + "\n" + + "null_value\x18\x01 \x01(\bH\x00R\tnullValue\x12\x1d\n" + + "\tint_value\x18\x02 \x01(\x03H\x00R\bintValue\x12#\n" + + "\fdouble_value\x18\x03 \x01(\x01H\x00R\vdoubleValue\x12\x1f\n" + + "\n" + + "text_value\x18\x04 \x01(\tH\x00R\ttextValue\x12\x1f\n" + + "\n" + + "blob_value\x18\x05 \x01(\fH\x00R\tblobValueB\a\n" + + "\x05value\"\x82\x01\n" + + "\x10SessionStatement\x12\x10\n" + + "\x03sql\x18\x01 \x01(\tR\x03sql\x12-\n" + + "\x06params\x18\x02 \x03(\v2\x15.livekit.SessionValueR\x06params\x12-\n" + + "\x04lang\x18\x03 \x01(\x0e2\x19.livekit.SessionQueryLangR\x04lang\"I\n" + + "\fSessionBatch\x129\n" + + "\n" + + "statements\x18\x01 \x03(\v2\x19.livekit.SessionStatementR\n" + + "statements\"\x0e\n" + + "\fSessionBegin\"\x0f\n" + + "\rSessionCommit\"\x11\n" + + "\x0fSessionRollback\"\x0f\n" + + "\rSessionCancel\")\n" + + "\rSessionCredit\x12\x18\n" + + "\abatches\x18\x01 \x01(\rR\abatches\"+\n" + + "\vSessionPing\x12\x1c\n" + + "\ttimestamp\x18\x01 \x01(\x03R\ttimestamp\"[\n" + + "\vSessionPong\x12.\n" + + "\x13last_ping_timestamp\x18\x01 \x01(\x03R\x11lastPingTimestamp\x12\x1c\n" + + "\ttimestamp\x18\x02 \x01(\x03R\ttimestamp\"C\n" + + "\fSessionHello\x12\x14\n" + + "\x05token\x18\x01 \x01(\tR\x05token\x12\x1d\n" + + "\n" + + "session_id\x18\x02 \x01(\tR\tsessionId\"t\n" + + "\x0eSessionHelloOk\x12\x10\n" + + "\x03tip\x18\x01 \x01(\x03R\x03tip\x12(\n" + + "\x10ping_interval_ms\x18\x02 \x01(\rR\x0epingIntervalMs\x12&\n" + + "\x0fping_timeout_ms\x18\x03 \x01(\rR\rpingTimeoutMs\"&\n" + + "\x0eSessionColumns\x12\x14\n" + + "\x05names\x18\x01 \x03(\tR\x05names\";\n" + + "\n" + + "SessionRow\x12-\n" + + "\x06values\x18\x01 \x03(\v2\x15.livekit.SessionValueR\x06values\":\n" + + "\x0fSessionRowBatch\x12'\n" + + "\x04rows\x18\x01 \x03(\v2\x13.livekit.SessionRowR\x04rows\"p\n" + + "\x11SessionExecResult\x12#\n" + + "\rrows_affected\x18\x01 \x01(\x03R\frowsAffected\x12$\n" + + "\x0elast_insert_id\x18\x02 \x01(\x03R\flastInsertId\x12\x10\n" + + "\x03tip\x18\x03 \x01(\x03R\x03tip\">\n" + + "\vSessionDone\x12\x10\n" + + "\x03tip\x18\x01 \x01(\x03R\x03tip\x12\x1d\n" + + "\n" + + "total_rows\x18\x02 \x01(\x04R\ttotalRows\"A\n" + + "\x11SessionStoreError\x12\x12\n" + + "\x04code\x18\x01 \x01(\tR\x04code\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage*M\n" + + "\x10SessionQueryLang\x12\x1a\n" + + "\x16SESSION_QUERY_LANG_SQL\x10\x00\x12\x1d\n" + + "\x19SESSION_QUERY_LANG_CYPHER\x10\x01BFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" + +var ( + file_livekit_agent_session_db_proto_rawDescOnce sync.Once + file_livekit_agent_session_db_proto_rawDescData []byte +) + +func file_livekit_agent_session_db_proto_rawDescGZIP() []byte { + file_livekit_agent_session_db_proto_rawDescOnce.Do(func() { + file_livekit_agent_session_db_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_livekit_agent_session_db_proto_rawDesc), len(file_livekit_agent_session_db_proto_rawDesc))) + }) + return file_livekit_agent_session_db_proto_rawDescData +} + +var file_livekit_agent_session_db_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_livekit_agent_session_db_proto_msgTypes = make([]protoimpl.MessageInfo, 20) +var file_livekit_agent_session_db_proto_goTypes = []any{ + (SessionQueryLang)(0), // 0: livekit.SessionQueryLang + (*SessionStoreRequest)(nil), // 1: livekit.SessionStoreRequest + (*SessionStoreResponse)(nil), // 2: livekit.SessionStoreResponse + (*SessionValue)(nil), // 3: livekit.SessionValue + (*SessionStatement)(nil), // 4: livekit.SessionStatement + (*SessionBatch)(nil), // 5: livekit.SessionBatch + (*SessionBegin)(nil), // 6: livekit.SessionBegin + (*SessionCommit)(nil), // 7: livekit.SessionCommit + (*SessionRollback)(nil), // 8: livekit.SessionRollback + (*SessionCancel)(nil), // 9: livekit.SessionCancel + (*SessionCredit)(nil), // 10: livekit.SessionCredit + (*SessionPing)(nil), // 11: livekit.SessionPing + (*SessionPong)(nil), // 12: livekit.SessionPong + (*SessionHello)(nil), // 13: livekit.SessionHello + (*SessionHelloOk)(nil), // 14: livekit.SessionHelloOk + (*SessionColumns)(nil), // 15: livekit.SessionColumns + (*SessionRow)(nil), // 16: livekit.SessionRow + (*SessionRowBatch)(nil), // 17: livekit.SessionRowBatch + (*SessionExecResult)(nil), // 18: livekit.SessionExecResult + (*SessionDone)(nil), // 19: livekit.SessionDone + (*SessionStoreError)(nil), // 20: livekit.SessionStoreError +} +var file_livekit_agent_session_db_proto_depIdxs = []int32{ + 13, // 0: livekit.SessionStoreRequest.hello:type_name -> livekit.SessionHello + 4, // 1: livekit.SessionStoreRequest.exec:type_name -> livekit.SessionStatement + 4, // 2: livekit.SessionStoreRequest.query:type_name -> livekit.SessionStatement + 5, // 3: livekit.SessionStoreRequest.batch:type_name -> livekit.SessionBatch + 6, // 4: livekit.SessionStoreRequest.begin:type_name -> livekit.SessionBegin + 7, // 5: livekit.SessionStoreRequest.commit:type_name -> livekit.SessionCommit + 8, // 6: livekit.SessionStoreRequest.rollback:type_name -> livekit.SessionRollback + 9, // 7: livekit.SessionStoreRequest.cancel:type_name -> livekit.SessionCancel + 10, // 8: livekit.SessionStoreRequest.credit:type_name -> livekit.SessionCredit + 11, // 9: livekit.SessionStoreRequest.ping:type_name -> livekit.SessionPing + 14, // 10: livekit.SessionStoreResponse.hello_ok:type_name -> livekit.SessionHelloOk + 15, // 11: livekit.SessionStoreResponse.columns:type_name -> livekit.SessionColumns + 17, // 12: livekit.SessionStoreResponse.row_batch:type_name -> livekit.SessionRowBatch + 18, // 13: livekit.SessionStoreResponse.exec_result:type_name -> livekit.SessionExecResult + 19, // 14: livekit.SessionStoreResponse.done:type_name -> livekit.SessionDone + 20, // 15: livekit.SessionStoreResponse.error:type_name -> livekit.SessionStoreError + 12, // 16: livekit.SessionStoreResponse.pong:type_name -> livekit.SessionPong + 3, // 17: livekit.SessionStatement.params:type_name -> livekit.SessionValue + 0, // 18: livekit.SessionStatement.lang:type_name -> livekit.SessionQueryLang + 4, // 19: livekit.SessionBatch.statements:type_name -> livekit.SessionStatement + 3, // 20: livekit.SessionRow.values:type_name -> livekit.SessionValue + 16, // 21: livekit.SessionRowBatch.rows:type_name -> livekit.SessionRow + 22, // [22:22] is the sub-list for method output_type + 22, // [22:22] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name +} + +func init() { file_livekit_agent_session_db_proto_init() } +func file_livekit_agent_session_db_proto_init() { + if File_livekit_agent_session_db_proto != nil { + return + } + file_livekit_agent_session_db_proto_msgTypes[0].OneofWrappers = []any{ + (*SessionStoreRequest_Hello)(nil), + (*SessionStoreRequest_Exec)(nil), + (*SessionStoreRequest_Query)(nil), + (*SessionStoreRequest_Batch)(nil), + (*SessionStoreRequest_Begin)(nil), + (*SessionStoreRequest_Commit)(nil), + (*SessionStoreRequest_Rollback)(nil), + (*SessionStoreRequest_Cancel)(nil), + (*SessionStoreRequest_Credit)(nil), + (*SessionStoreRequest_Ping)(nil), + } + file_livekit_agent_session_db_proto_msgTypes[1].OneofWrappers = []any{ + (*SessionStoreResponse_HelloOk)(nil), + (*SessionStoreResponse_Columns)(nil), + (*SessionStoreResponse_RowBatch)(nil), + (*SessionStoreResponse_ExecResult)(nil), + (*SessionStoreResponse_Done)(nil), + (*SessionStoreResponse_Error)(nil), + (*SessionStoreResponse_Pong)(nil), + } + file_livekit_agent_session_db_proto_msgTypes[2].OneofWrappers = []any{ + (*SessionValue_NullValue)(nil), + (*SessionValue_IntValue)(nil), + (*SessionValue_DoubleValue)(nil), + (*SessionValue_TextValue)(nil), + (*SessionValue_BlobValue)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_livekit_agent_session_db_proto_rawDesc), len(file_livekit_agent_session_db_proto_rawDesc)), + NumEnums: 1, + NumMessages: 20, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_livekit_agent_session_db_proto_goTypes, + DependencyIndexes: file_livekit_agent_session_db_proto_depIdxs, + EnumInfos: file_livekit_agent_session_db_proto_enumTypes, + MessageInfos: file_livekit_agent_session_db_proto_msgTypes, + }.Build() + File_livekit_agent_session_db_proto = out.File + file_livekit_agent_session_db_proto_goTypes = nil + file_livekit_agent_session_db_proto_depIdxs = nil +} diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go new file mode 100644 index 000000000..f32465f69 --- /dev/null +++ b/livekit/livekit_agent_session_store.pb.go @@ -0,0 +1,683 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v7.34.1 +// source: livekit_agent_session_store.proto + +package livekit + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CreateSessionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` // data region the session is stored in + UserAttributes string `protobuf:"bytes,2,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` // opaque JSON metadata for the caller + TtlSeconds int64 `protobuf:"varint,3,opt,name=ttl_seconds,json=ttlSeconds,proto3" json:"ttl_seconds,omitempty"` // per-session TTL, clamped to a hard max; never extended + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateSessionRequest) Reset() { + *x = CreateSessionRequest{} + mi := &file_livekit_agent_session_store_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSessionRequest) ProtoMessage() {} + +func (x *CreateSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateSessionRequest.ProtoReflect.Descriptor instead. +func (*CreateSessionRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateSessionRequest) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *CreateSessionRequest) GetUserAttributes() string { + if x != nil { + return x.UserAttributes + } + return "" +} + +func (x *CreateSessionRequest) GetTtlSeconds() int64 { + if x != nil { + return x.TtlSeconds + } + return 0 +} + +type CreateSessionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // "SESS_..." + ExpiresAtUnix int64 `protobuf:"varint,2,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateSessionResponse) Reset() { + *x = CreateSessionResponse{} + mi := &file_livekit_agent_session_store_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSessionResponse) ProtoMessage() {} + +func (x *CreateSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateSessionResponse.ProtoReflect.Descriptor instead. +func (*CreateSessionResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateSessionResponse) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *CreateSessionResponse) GetExpiresAtUnix() int64 { + if x != nil { + return x.ExpiresAtUnix + } + return 0 +} + +type GetSessionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSessionRequest) Reset() { + *x = GetSessionRequest{} + mi := &file_livekit_agent_session_store_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSessionRequest) ProtoMessage() {} + +func (x *GetSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSessionRequest.ProtoReflect.Descriptor instead. +func (*GetSessionRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{2} +} + +func (x *GetSessionRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type GetSessionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Region string `protobuf:"bytes,2,opt,name=region,proto3" json:"region,omitempty"` + UserAttributes string `protobuf:"bytes,3,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` + CreatedAtUnix int64 `protobuf:"varint,4,opt,name=created_at_unix,json=createdAtUnix,proto3" json:"created_at_unix,omitempty"` + ExpiresAtUnix int64 `protobuf:"varint,5,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` + Tip int64 `protobuf:"varint,6,opt,name=tip,proto3" json:"tip,omitempty"` // latest durable commit sequence + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSessionResponse) Reset() { + *x = GetSessionResponse{} + mi := &file_livekit_agent_session_store_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSessionResponse) ProtoMessage() {} + +func (x *GetSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSessionResponse.ProtoReflect.Descriptor instead. +func (*GetSessionResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{3} +} + +func (x *GetSessionResponse) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *GetSessionResponse) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *GetSessionResponse) GetUserAttributes() string { + if x != nil { + return x.UserAttributes + } + return "" +} + +func (x *GetSessionResponse) GetCreatedAtUnix() int64 { + if x != nil { + return x.CreatedAtUnix + } + return 0 +} + +func (x *GetSessionResponse) GetExpiresAtUnix() int64 { + if x != nil { + return x.ExpiresAtUnix + } + return 0 +} + +func (x *GetSessionResponse) GetTip() int64 { + if x != nil { + return x.Tip + } + return 0 +} + +type ListSessionsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // server-clamped + PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` // opaque cursor from a previous response + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSessionsRequest) Reset() { + *x = ListSessionsRequest{} + mi := &file_livekit_agent_session_store_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSessionsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSessionsRequest) ProtoMessage() {} + +func (x *ListSessionsRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListSessionsRequest.ProtoReflect.Descriptor instead. +func (*ListSessionsRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{4} +} + +func (x *ListSessionsRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListSessionsRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +type ListSessionsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Sessions []*GetSessionResponse `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` // empty when exhausted + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSessionsResponse) Reset() { + *x = ListSessionsResponse{} + mi := &file_livekit_agent_session_store_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSessionsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSessionsResponse) ProtoMessage() {} + +func (x *ListSessionsResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListSessionsResponse.ProtoReflect.Descriptor instead. +func (*ListSessionsResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{5} +} + +func (x *ListSessionsResponse) GetSessions() []*GetSessionResponse { + if x != nil { + return x.Sessions + } + return nil +} + +func (x *ListSessionsResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +type DeleteSessionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteSessionRequest) Reset() { + *x = DeleteSessionRequest{} + mi := &file_livekit_agent_session_store_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSessionRequest) ProtoMessage() {} + +func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSessionRequest.ProtoReflect.Descriptor instead. +func (*DeleteSessionRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{6} +} + +func (x *DeleteSessionRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type DeleteSessionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteSessionResponse) Reset() { + *x = DeleteSessionResponse{} + mi := &file_livekit_agent_session_store_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSessionResponse) ProtoMessage() {} + +func (x *DeleteSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSessionResponse.ProtoReflect.Descriptor instead. +func (*DeleteSessionResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{7} +} + +type DumpSessionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DumpSessionRequest) Reset() { + *x = DumpSessionRequest{} + mi := &file_livekit_agent_session_store_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DumpSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DumpSessionRequest) ProtoMessage() {} + +func (x *DumpSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DumpSessionRequest.ProtoReflect.Descriptor instead. +func (*DumpSessionRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{8} +} + +func (x *DumpSessionRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type DumpSessionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + DownloadUrl string `protobuf:"bytes,1,opt,name=download_url,json=downloadUrl,proto3" json:"download_url,omitempty"` // pre-authenticated object-storage URL + ExpiresAtUnix int64 `protobuf:"varint,2,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` // URL expiry + Tip int64 `protobuf:"varint,3,opt,name=tip,proto3" json:"tip,omitempty"` // commit sequence the dump is consistent at + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DumpSessionResponse) Reset() { + *x = DumpSessionResponse{} + mi := &file_livekit_agent_session_store_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DumpSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DumpSessionResponse) ProtoMessage() {} + +func (x *DumpSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DumpSessionResponse.ProtoReflect.Descriptor instead. +func (*DumpSessionResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{9} +} + +func (x *DumpSessionResponse) GetDownloadUrl() string { + if x != nil { + return x.DownloadUrl + } + return "" +} + +func (x *DumpSessionResponse) GetExpiresAtUnix() int64 { + if x != nil { + return x.ExpiresAtUnix + } + return 0 +} + +func (x *DumpSessionResponse) GetTip() int64 { + if x != nil { + return x.Tip + } + return 0 +} + +var File_livekit_agent_session_store_proto protoreflect.FileDescriptor + +const file_livekit_agent_session_store_proto_rawDesc = "" + + "\n" + + "!livekit_agent_session_store.proto\x12\alivekit\"x\n" + + "\x14CreateSessionRequest\x12\x16\n" + + "\x06region\x18\x01 \x01(\tR\x06region\x12'\n" + + "\x0fuser_attributes\x18\x02 \x01(\tR\x0euserAttributes\x12\x1f\n" + + "\vttl_seconds\x18\x03 \x01(\x03R\n" + + "ttlSeconds\"^\n" + + "\x15CreateSessionResponse\x12\x1d\n" + + "\n" + + "session_id\x18\x01 \x01(\tR\tsessionId\x12&\n" + + "\x0fexpires_at_unix\x18\x02 \x01(\x03R\rexpiresAtUnix\"2\n" + + "\x11GetSessionRequest\x12\x1d\n" + + "\n" + + "session_id\x18\x01 \x01(\tR\tsessionId\"\xd6\x01\n" + + "\x12GetSessionResponse\x12\x1d\n" + + "\n" + + "session_id\x18\x01 \x01(\tR\tsessionId\x12\x16\n" + + "\x06region\x18\x02 \x01(\tR\x06region\x12'\n" + + "\x0fuser_attributes\x18\x03 \x01(\tR\x0euserAttributes\x12&\n" + + "\x0fcreated_at_unix\x18\x04 \x01(\x03R\rcreatedAtUnix\x12&\n" + + "\x0fexpires_at_unix\x18\x05 \x01(\x03R\rexpiresAtUnix\x12\x10\n" + + "\x03tip\x18\x06 \x01(\x03R\x03tip\"Q\n" + + "\x13ListSessionsRequest\x12\x1b\n" + + "\tpage_size\x18\x01 \x01(\x05R\bpageSize\x12\x1d\n" + + "\n" + + "page_token\x18\x02 \x01(\tR\tpageToken\"w\n" + + "\x14ListSessionsResponse\x127\n" + + "\bsessions\x18\x01 \x03(\v2\x1b.livekit.GetSessionResponseR\bsessions\x12&\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"5\n" + + "\x14DeleteSessionRequest\x12\x1d\n" + + "\n" + + "session_id\x18\x01 \x01(\tR\tsessionId\"\x17\n" + + "\x15DeleteSessionResponse\"3\n" + + "\x12DumpSessionRequest\x12\x1d\n" + + "\n" + + "session_id\x18\x01 \x01(\tR\tsessionId\"r\n" + + "\x13DumpSessionResponse\x12!\n" + + "\fdownload_url\x18\x01 \x01(\tR\vdownloadUrl\x12&\n" + + "\x0fexpires_at_unix\x18\x02 \x01(\x03R\rexpiresAtUnix\x12\x10\n" + + "\x03tip\x18\x03 \x01(\x03R\x03tip2\x8a\x03\n" + + "\x11AgentSessionStore\x12N\n" + + "\rCreateSession\x12\x1d.livekit.CreateSessionRequest\x1a\x1e.livekit.CreateSessionResponse\x12E\n" + + "\n" + + "GetSession\x12\x1a.livekit.GetSessionRequest\x1a\x1b.livekit.GetSessionResponse\x12K\n" + + "\fListSessions\x12\x1c.livekit.ListSessionsRequest\x1a\x1d.livekit.ListSessionsResponse\x12N\n" + + "\rDeleteSession\x12\x1d.livekit.DeleteSessionRequest\x1a\x1e.livekit.DeleteSessionResponse\x12A\n" + + "\x04Dump\x12\x1b.livekit.DumpSessionRequest\x1a\x1c.livekit.DumpSessionResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" + +var ( + file_livekit_agent_session_store_proto_rawDescOnce sync.Once + file_livekit_agent_session_store_proto_rawDescData []byte +) + +func file_livekit_agent_session_store_proto_rawDescGZIP() []byte { + file_livekit_agent_session_store_proto_rawDescOnce.Do(func() { + file_livekit_agent_session_store_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_livekit_agent_session_store_proto_rawDesc), len(file_livekit_agent_session_store_proto_rawDesc))) + }) + return file_livekit_agent_session_store_proto_rawDescData +} + +var file_livekit_agent_session_store_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_livekit_agent_session_store_proto_goTypes = []any{ + (*CreateSessionRequest)(nil), // 0: livekit.CreateSessionRequest + (*CreateSessionResponse)(nil), // 1: livekit.CreateSessionResponse + (*GetSessionRequest)(nil), // 2: livekit.GetSessionRequest + (*GetSessionResponse)(nil), // 3: livekit.GetSessionResponse + (*ListSessionsRequest)(nil), // 4: livekit.ListSessionsRequest + (*ListSessionsResponse)(nil), // 5: livekit.ListSessionsResponse + (*DeleteSessionRequest)(nil), // 6: livekit.DeleteSessionRequest + (*DeleteSessionResponse)(nil), // 7: livekit.DeleteSessionResponse + (*DumpSessionRequest)(nil), // 8: livekit.DumpSessionRequest + (*DumpSessionResponse)(nil), // 9: livekit.DumpSessionResponse +} +var file_livekit_agent_session_store_proto_depIdxs = []int32{ + 3, // 0: livekit.ListSessionsResponse.sessions:type_name -> livekit.GetSessionResponse + 0, // 1: livekit.AgentSessionStore.CreateSession:input_type -> livekit.CreateSessionRequest + 2, // 2: livekit.AgentSessionStore.GetSession:input_type -> livekit.GetSessionRequest + 4, // 3: livekit.AgentSessionStore.ListSessions:input_type -> livekit.ListSessionsRequest + 6, // 4: livekit.AgentSessionStore.DeleteSession:input_type -> livekit.DeleteSessionRequest + 8, // 5: livekit.AgentSessionStore.Dump:input_type -> livekit.DumpSessionRequest + 1, // 6: livekit.AgentSessionStore.CreateSession:output_type -> livekit.CreateSessionResponse + 3, // 7: livekit.AgentSessionStore.GetSession:output_type -> livekit.GetSessionResponse + 5, // 8: livekit.AgentSessionStore.ListSessions:output_type -> livekit.ListSessionsResponse + 7, // 9: livekit.AgentSessionStore.DeleteSession:output_type -> livekit.DeleteSessionResponse + 9, // 10: livekit.AgentSessionStore.Dump:output_type -> livekit.DumpSessionResponse + 6, // [6:11] is the sub-list for method output_type + 1, // [1:6] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_livekit_agent_session_store_proto_init() } +func file_livekit_agent_session_store_proto_init() { + if File_livekit_agent_session_store_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_livekit_agent_session_store_proto_rawDesc), len(file_livekit_agent_session_store_proto_rawDesc)), + NumEnums: 0, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_livekit_agent_session_store_proto_goTypes, + DependencyIndexes: file_livekit_agent_session_store_proto_depIdxs, + MessageInfos: file_livekit_agent_session_store_proto_msgTypes, + }.Build() + File_livekit_agent_session_store_proto = out.File + file_livekit_agent_session_store_proto_goTypes = nil + file_livekit_agent_session_store_proto_depIdxs = nil +} diff --git a/livekit/livekit_agent_session_store.twirp.go b/livekit/livekit_agent_session_store.twirp.go new file mode 100644 index 000000000..4577e11cb --- /dev/null +++ b/livekit/livekit_agent_session_store.twirp.go @@ -0,0 +1,1685 @@ +// Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. +// source: livekit_agent_session_store.proto + +package livekit + +import context "context" +import fmt "fmt" +import http "net/http" +import io "io" +import json "encoding/json" +import strconv "strconv" +import strings "strings" + +import protojson "google.golang.org/protobuf/encoding/protojson" +import proto "google.golang.org/protobuf/proto" +import twirp "github.com/twitchtv/twirp" +import ctxsetters "github.com/twitchtv/twirp/ctxsetters" + +// Version compatibility assertion. +// If the constant is not defined in the package, that likely means +// the package needs to be updated to work with this generated code. +// See https://twitchtv.github.io/twirp/docs/version_matrix.html +const _ = twirp.TwirpPackageMinVersion_8_1_0 + +// =========================== +// AgentSessionStore Interface +// =========================== + +// AgentSessionStore is the MANAGEMENT plane for per-session SQLite databases: +// lifecycle and export only. All querying goes through the data plane (a +// WebSocket speaking SessionStoreRequest/SessionStoreResponse, defined in +// livekit_agent_session_db.proto). project_id is taken from the authenticated +// principal (access key) on every call, never a request field. +type AgentSessionStore interface { + // CreateSession allocates a new session database. + CreateSession(context.Context, *CreateSessionRequest) (*CreateSessionResponse, error) + + // GetSession returns session metadata. + GetSession(context.Context, *GetSessionRequest) (*GetSessionResponse, error) + + // ListSessions pages through the caller's sessions. + ListSessions(context.Context, *ListSessionsRequest) (*ListSessionsResponse, error) + + // DeleteSession removes a session and all its stored data. + DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) + + // Dump exports a consistent full SQLite database file for the session and + // returns a time-limited download URL (object-storage pre-authenticated + // request). Runs off the serving path; never blocks the session's writes. + Dump(context.Context, *DumpSessionRequest) (*DumpSessionResponse, error) +} + +// ================================= +// AgentSessionStore Protobuf Client +// ================================= + +type agentSessionStoreProtobufClient struct { + client HTTPClient + urls [5]string + interceptor twirp.Interceptor + opts twirp.ClientOptions +} + +// NewAgentSessionStoreProtobufClient creates a Protobuf client that implements the AgentSessionStore interface. +// It communicates using Protobuf and can be configured with a custom HTTPClient. +func NewAgentSessionStoreProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) AgentSessionStore { + if c, ok := client.(*http.Client); ok { + client = withoutRedirects(c) + } + + clientOpts := twirp.ClientOptions{} + for _, o := range opts { + o(&clientOpts) + } + + // Using ReadOpt allows backwards and forwards compatibility with new options in the future + literalURLs := false + _ = clientOpts.ReadOpt("literalURLs", &literalURLs) + var pathPrefix string + if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { + pathPrefix = "/twirp" // default prefix + } + + // Build method URLs: []/./ + serviceURL := sanitizeBaseURL(baseURL) + serviceURL += baseServicePath(pathPrefix, "livekit", "AgentSessionStore") + urls := [5]string{ + serviceURL + "CreateSession", + serviceURL + "GetSession", + serviceURL + "ListSessions", + serviceURL + "DeleteSession", + serviceURL + "Dump", + } + + return &agentSessionStoreProtobufClient{ + client: client, + urls: urls, + interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), + opts: clientOpts, + } +} + +func (c *agentSessionStoreProtobufClient) CreateSession(ctx context.Context, in *CreateSessionRequest) (*CreateSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "CreateSession") + caller := c.callCreateSession + if c.interceptor != nil { + caller = func(ctx context.Context, req *CreateSessionRequest) (*CreateSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CreateSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CreateSessionRequest) when calling interceptor") + } + return c.callCreateSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CreateSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CreateSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreProtobufClient) callCreateSession(ctx context.Context, in *CreateSessionRequest) (*CreateSessionResponse, error) { + out := new(CreateSessionResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreProtobufClient) GetSession(ctx context.Context, in *GetSessionRequest) (*GetSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "GetSession") + caller := c.callGetSession + if c.interceptor != nil { + caller = func(ctx context.Context, req *GetSessionRequest) (*GetSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetSessionRequest) when calling interceptor") + } + return c.callGetSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreProtobufClient) callGetSession(ctx context.Context, in *GetSessionRequest) (*GetSessionResponse, error) { + out := new(GetSessionResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreProtobufClient) ListSessions(ctx context.Context, in *ListSessionsRequest) (*ListSessionsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "ListSessions") + caller := c.callListSessions + if c.interceptor != nil { + caller = func(ctx context.Context, req *ListSessionsRequest) (*ListSessionsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListSessionsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListSessionsRequest) when calling interceptor") + } + return c.callListSessions(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListSessionsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListSessionsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreProtobufClient) callListSessions(ctx context.Context, in *ListSessionsRequest) (*ListSessionsResponse, error) { + out := new(ListSessionsResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreProtobufClient) DeleteSession(ctx context.Context, in *DeleteSessionRequest) (*DeleteSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "DeleteSession") + caller := c.callDeleteSession + if c.interceptor != nil { + caller = func(ctx context.Context, req *DeleteSessionRequest) (*DeleteSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteSessionRequest) when calling interceptor") + } + return c.callDeleteSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreProtobufClient) callDeleteSession(ctx context.Context, in *DeleteSessionRequest) (*DeleteSessionResponse, error) { + out := new(DeleteSessionResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreProtobufClient) Dump(ctx context.Context, in *DumpSessionRequest) (*DumpSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "Dump") + caller := c.callDump + if c.interceptor != nil { + caller = func(ctx context.Context, req *DumpSessionRequest) (*DumpSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DumpSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DumpSessionRequest) when calling interceptor") + } + return c.callDump(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DumpSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DumpSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreProtobufClient) callDump(ctx context.Context, in *DumpSessionRequest) (*DumpSessionResponse, error) { + out := new(DumpSessionResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[4], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +// ============================= +// AgentSessionStore JSON Client +// ============================= + +type agentSessionStoreJSONClient struct { + client HTTPClient + urls [5]string + interceptor twirp.Interceptor + opts twirp.ClientOptions +} + +// NewAgentSessionStoreJSONClient creates a JSON client that implements the AgentSessionStore interface. +// It communicates using JSON and can be configured with a custom HTTPClient. +func NewAgentSessionStoreJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) AgentSessionStore { + if c, ok := client.(*http.Client); ok { + client = withoutRedirects(c) + } + + clientOpts := twirp.ClientOptions{} + for _, o := range opts { + o(&clientOpts) + } + + // Using ReadOpt allows backwards and forwards compatibility with new options in the future + literalURLs := false + _ = clientOpts.ReadOpt("literalURLs", &literalURLs) + var pathPrefix string + if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { + pathPrefix = "/twirp" // default prefix + } + + // Build method URLs: []/./ + serviceURL := sanitizeBaseURL(baseURL) + serviceURL += baseServicePath(pathPrefix, "livekit", "AgentSessionStore") + urls := [5]string{ + serviceURL + "CreateSession", + serviceURL + "GetSession", + serviceURL + "ListSessions", + serviceURL + "DeleteSession", + serviceURL + "Dump", + } + + return &agentSessionStoreJSONClient{ + client: client, + urls: urls, + interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), + opts: clientOpts, + } +} + +func (c *agentSessionStoreJSONClient) CreateSession(ctx context.Context, in *CreateSessionRequest) (*CreateSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "CreateSession") + caller := c.callCreateSession + if c.interceptor != nil { + caller = func(ctx context.Context, req *CreateSessionRequest) (*CreateSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CreateSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CreateSessionRequest) when calling interceptor") + } + return c.callCreateSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CreateSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CreateSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreJSONClient) callCreateSession(ctx context.Context, in *CreateSessionRequest) (*CreateSessionResponse, error) { + out := new(CreateSessionResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreJSONClient) GetSession(ctx context.Context, in *GetSessionRequest) (*GetSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "GetSession") + caller := c.callGetSession + if c.interceptor != nil { + caller = func(ctx context.Context, req *GetSessionRequest) (*GetSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetSessionRequest) when calling interceptor") + } + return c.callGetSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreJSONClient) callGetSession(ctx context.Context, in *GetSessionRequest) (*GetSessionResponse, error) { + out := new(GetSessionResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreJSONClient) ListSessions(ctx context.Context, in *ListSessionsRequest) (*ListSessionsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "ListSessions") + caller := c.callListSessions + if c.interceptor != nil { + caller = func(ctx context.Context, req *ListSessionsRequest) (*ListSessionsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListSessionsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListSessionsRequest) when calling interceptor") + } + return c.callListSessions(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListSessionsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListSessionsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreJSONClient) callListSessions(ctx context.Context, in *ListSessionsRequest) (*ListSessionsResponse, error) { + out := new(ListSessionsResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreJSONClient) DeleteSession(ctx context.Context, in *DeleteSessionRequest) (*DeleteSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "DeleteSession") + caller := c.callDeleteSession + if c.interceptor != nil { + caller = func(ctx context.Context, req *DeleteSessionRequest) (*DeleteSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteSessionRequest) when calling interceptor") + } + return c.callDeleteSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreJSONClient) callDeleteSession(ctx context.Context, in *DeleteSessionRequest) (*DeleteSessionResponse, error) { + out := new(DeleteSessionResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentSessionStoreJSONClient) Dump(ctx context.Context, in *DumpSessionRequest) (*DumpSessionResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithMethodName(ctx, "Dump") + caller := c.callDump + if c.interceptor != nil { + caller = func(ctx context.Context, req *DumpSessionRequest) (*DumpSessionResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DumpSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DumpSessionRequest) when calling interceptor") + } + return c.callDump(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DumpSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DumpSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentSessionStoreJSONClient) callDump(ctx context.Context, in *DumpSessionRequest) (*DumpSessionResponse, error) { + out := new(DumpSessionResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[4], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +// ================================ +// AgentSessionStore Server Handler +// ================================ + +type agentSessionStoreServer struct { + AgentSessionStore + interceptor twirp.Interceptor + hooks *twirp.ServerHooks + pathPrefix string // prefix for routing + jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response + jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names +} + +// NewAgentSessionStoreServer builds a TwirpServer that can be used as an http.Handler to handle +// HTTP requests that are routed to the right method in the provided svc implementation. +// The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). +func NewAgentSessionStoreServer(svc AgentSessionStore, opts ...interface{}) TwirpServer { + serverOpts := newServerOpts(opts) + + // Using ReadOpt allows backwards and forwards compatibility with new options in the future + jsonSkipDefaults := false + _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) + jsonCamelCase := false + _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) + var pathPrefix string + if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { + pathPrefix = "/twirp" // default prefix + } + + return &agentSessionStoreServer{ + AgentSessionStore: svc, + hooks: serverOpts.Hooks, + interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), + pathPrefix: pathPrefix, + jsonSkipDefaults: jsonSkipDefaults, + jsonCamelCase: jsonCamelCase, + } +} + +// writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. +// If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) +func (s *agentSessionStoreServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { + writeError(ctx, resp, err, s.hooks) +} + +// handleRequestBodyError is used to handle error when the twirp server cannot read request +func (s *agentSessionStoreServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { + if context.Canceled == ctx.Err() { + s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) + return + } + if context.DeadlineExceeded == ctx.Err() { + s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) + return + } + s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) +} + +// AgentSessionStorePathPrefix is a convenience constant that may identify URL paths. +// Should be used with caution, it only matches routes generated by Twirp Go clients, +// with the default "/twirp" prefix and default CamelCase service and method names. +// More info: https://twitchtv.github.io/twirp/docs/routing.html +const AgentSessionStorePathPrefix = "/twirp/livekit.AgentSessionStore/" + +func (s *agentSessionStoreServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { + ctx := req.Context() + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentSessionStore") + ctx = ctxsetters.WithResponseWriter(ctx, resp) + + var err error + ctx, err = callRequestReceived(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + if req.Method != "POST" { + msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } + + // Verify path format: []/./ + prefix, pkgService, method := parseTwirpPath(req.URL.Path) + if pkgService != "livekit.AgentSessionStore" { + msg := fmt.Sprintf("no handler for path %q", req.URL.Path) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } + if prefix != s.pathPrefix { + msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } + + switch method { + case "CreateSession": + s.serveCreateSession(ctx, resp, req) + return + case "GetSession": + s.serveGetSession(ctx, resp, req) + return + case "ListSessions": + s.serveListSessions(ctx, resp, req) + return + case "DeleteSession": + s.serveDeleteSession(ctx, resp, req) + return + case "Dump": + s.serveDump(ctx, resp, req) + return + default: + msg := fmt.Sprintf("no handler for path %q", req.URL.Path) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } +} + +func (s *agentSessionStoreServer) serveCreateSession(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveCreateSessionJSON(ctx, resp, req) + case "application/protobuf": + s.serveCreateSessionProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentSessionStoreServer) serveCreateSessionJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "CreateSession") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(CreateSessionRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentSessionStore.CreateSession + if s.interceptor != nil { + handler = func(ctx context.Context, req *CreateSessionRequest) (*CreateSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CreateSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CreateSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.CreateSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CreateSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CreateSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *CreateSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *CreateSessionResponse and nil error while calling CreateSession. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveCreateSessionProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "CreateSession") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(CreateSessionRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentSessionStore.CreateSession + if s.interceptor != nil { + handler = func(ctx context.Context, req *CreateSessionRequest) (*CreateSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CreateSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CreateSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.CreateSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CreateSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CreateSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *CreateSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *CreateSessionResponse and nil error while calling CreateSession. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveGetSession(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveGetSessionJSON(ctx, resp, req) + case "application/protobuf": + s.serveGetSessionProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentSessionStoreServer) serveGetSessionJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "GetSession") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(GetSessionRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentSessionStore.GetSession + if s.interceptor != nil { + handler = func(ctx context.Context, req *GetSessionRequest) (*GetSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.GetSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *GetSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *GetSessionResponse and nil error while calling GetSession. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveGetSessionProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "GetSession") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(GetSessionRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentSessionStore.GetSession + if s.interceptor != nil { + handler = func(ctx context.Context, req *GetSessionRequest) (*GetSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.GetSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *GetSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *GetSessionResponse and nil error while calling GetSession. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveListSessions(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveListSessionsJSON(ctx, resp, req) + case "application/protobuf": + s.serveListSessionsProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentSessionStoreServer) serveListSessionsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ListSessions") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(ListSessionsRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentSessionStore.ListSessions + if s.interceptor != nil { + handler = func(ctx context.Context, req *ListSessionsRequest) (*ListSessionsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListSessionsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListSessionsRequest) when calling interceptor") + } + return s.AgentSessionStore.ListSessions(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListSessionsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListSessionsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ListSessionsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ListSessionsResponse and nil error while calling ListSessions. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveListSessionsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ListSessions") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(ListSessionsRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentSessionStore.ListSessions + if s.interceptor != nil { + handler = func(ctx context.Context, req *ListSessionsRequest) (*ListSessionsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListSessionsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListSessionsRequest) when calling interceptor") + } + return s.AgentSessionStore.ListSessions(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListSessionsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListSessionsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ListSessionsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ListSessionsResponse and nil error while calling ListSessions. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveDeleteSession(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveDeleteSessionJSON(ctx, resp, req) + case "application/protobuf": + s.serveDeleteSessionProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentSessionStoreServer) serveDeleteSessionJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "DeleteSession") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(DeleteSessionRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentSessionStore.DeleteSession + if s.interceptor != nil { + handler = func(ctx context.Context, req *DeleteSessionRequest) (*DeleteSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.DeleteSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *DeleteSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *DeleteSessionResponse and nil error while calling DeleteSession. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveDeleteSessionProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "DeleteSession") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(DeleteSessionRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentSessionStore.DeleteSession + if s.interceptor != nil { + handler = func(ctx context.Context, req *DeleteSessionRequest) (*DeleteSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.DeleteSession(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *DeleteSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *DeleteSessionResponse and nil error while calling DeleteSession. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveDump(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveDumpJSON(ctx, resp, req) + case "application/protobuf": + s.serveDumpProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentSessionStoreServer) serveDumpJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "Dump") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(DumpSessionRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentSessionStore.Dump + if s.interceptor != nil { + handler = func(ctx context.Context, req *DumpSessionRequest) (*DumpSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DumpSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DumpSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.Dump(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DumpSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DumpSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *DumpSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *DumpSessionResponse and nil error while calling Dump. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) serveDumpProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "Dump") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(DumpSessionRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentSessionStore.Dump + if s.interceptor != nil { + handler = func(ctx context.Context, req *DumpSessionRequest) (*DumpSessionResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DumpSessionRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DumpSessionRequest) when calling interceptor") + } + return s.AgentSessionStore.Dump(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DumpSessionResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DumpSessionResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *DumpSessionResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *DumpSessionResponse and nil error while calling Dump. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentSessionStoreServer) ServiceDescriptor() ([]byte, int) { + return twirpFileDescriptor2, 0 +} + +func (s *agentSessionStoreServer) ProtocGenTwirpVersion() string { + return "v8.1.3" +} + +// PathPrefix returns the base service path, in the form: "//./" +// that is everything in a Twirp route except for the . This can be used for routing, +// for example to identify the requests that are targeted to this service in a mux. +func (s *agentSessionStoreServer) PathPrefix() string { + return baseServicePath(s.pathPrefix, "livekit", "AgentSessionStore") +} + +var twirpFileDescriptor2 = []byte{ + // 567 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdb, 0x6e, 0xd3, 0x40, + 0x10, 0x55, 0xe2, 0x36, 0x34, 0x93, 0xa6, 0xa1, 0xdb, 0x14, 0xa2, 0xb4, 0x81, 0xd4, 0x48, 0x25, + 0x4f, 0xa9, 0x94, 0x0a, 0x21, 0xf5, 0x2d, 0x50, 0x40, 0xa8, 0x55, 0x55, 0x1c, 0xfa, 0xc2, 0x03, + 0x96, 0x13, 0x8f, 0xc2, 0xaa, 0xae, 0xd7, 0x78, 0xc7, 0x6d, 0xd4, 0x4f, 0xe0, 0x53, 0xf8, 0x20, + 0x3e, 0x82, 0xaf, 0x40, 0x5e, 0xaf, 0x9d, 0x9b, 0x7b, 0xe1, 0x2d, 0x3e, 0x73, 0xdb, 0x73, 0xce, + 0x4c, 0x60, 0xcf, 0xe3, 0xd7, 0x78, 0xc9, 0xc9, 0x76, 0xc6, 0xe8, 0x93, 0x2d, 0x51, 0x4a, 0x2e, + 0x7c, 0x5b, 0x92, 0x08, 0xb1, 0x1b, 0x84, 0x82, 0x04, 0x7b, 0xa2, 0x53, 0xcc, 0x09, 0xd4, 0xdf, + 0x87, 0xe8, 0x10, 0x0e, 0x92, 0x2c, 0x0b, 0x7f, 0x46, 0x28, 0x89, 0x3d, 0x83, 0x52, 0x88, 0x63, + 0x2e, 0xfc, 0x46, 0xa1, 0x5d, 0xe8, 0x94, 0x2d, 0xfd, 0xc5, 0x5e, 0x43, 0x2d, 0x92, 0x18, 0xda, + 0x0e, 0x51, 0xc8, 0x87, 0x11, 0xa1, 0x6c, 0x14, 0x55, 0xc2, 0x46, 0x0c, 0xf7, 0x33, 0x94, 0xbd, + 0x84, 0x0a, 0x91, 0x67, 0x4b, 0x1c, 0x09, 0xdf, 0x95, 0x0d, 0xa3, 0x5d, 0xe8, 0x18, 0x16, 0x10, + 0x79, 0x83, 0x04, 0x31, 0xbf, 0xc3, 0xf6, 0xc2, 0x64, 0x19, 0x08, 0x5f, 0x22, 0x6b, 0x01, 0xa4, + 0x4f, 0xe6, 0xae, 0x1e, 0x5f, 0xd6, 0xc8, 0x67, 0x97, 0xed, 0x43, 0x0d, 0x27, 0x01, 0x0f, 0x51, + 0xda, 0x0e, 0xd9, 0x91, 0xcf, 0x27, 0xea, 0x05, 0x86, 0x55, 0xd5, 0x70, 0x9f, 0x2e, 0x7c, 0x3e, + 0x31, 0x7b, 0xb0, 0xf9, 0x09, 0x69, 0x81, 0xd6, 0xfd, 0xbd, 0xcd, 0x3f, 0x05, 0x60, 0xb3, 0x45, + 0x8f, 0x7b, 0xd1, 0x54, 0xab, 0xe2, 0x43, 0x5a, 0x19, 0xb9, 0x5a, 0xed, 0x43, 0x6d, 0xa4, 0xa4, + 0x70, 0x33, 0x4a, 0x2b, 0x09, 0x25, 0x0d, 0x27, 0x94, 0xf2, 0xa8, 0xaf, 0xe6, 0x50, 0x67, 0x4f, + 0xc1, 0x20, 0x1e, 0x34, 0x4a, 0x2a, 0x16, 0xff, 0x34, 0xbf, 0xc0, 0xd6, 0x29, 0x97, 0x29, 0x31, + 0x99, 0xca, 0xb1, 0x03, 0xe5, 0xc0, 0x19, 0xa3, 0x2d, 0xf9, 0x2d, 0x2a, 0x5e, 0xab, 0xd6, 0x5a, + 0x0c, 0x0c, 0xf8, 0xad, 0x62, 0xad, 0x82, 0x24, 0x2e, 0x31, 0xa5, 0xa6, 0xd2, 0xbf, 0xc6, 0x80, + 0x79, 0x03, 0xf5, 0xf9, 0x96, 0x5a, 0xac, 0xb7, 0xb0, 0xa6, 0xa5, 0x91, 0x8d, 0x42, 0xdb, 0xe8, + 0x54, 0x7a, 0x3b, 0x5d, 0xbd, 0x6d, 0xdd, 0x65, 0x6d, 0xad, 0x2c, 0x39, 0x66, 0xe7, 0xe3, 0x84, + 0xec, 0xa5, 0xa1, 0xd5, 0x18, 0x3e, 0xcf, 0x06, 0xbf, 0x81, 0xfa, 0x31, 0x7a, 0xb8, 0xb4, 0xb2, + 0x0f, 0x78, 0xfb, 0x1c, 0xb6, 0x17, 0xca, 0x92, 0x17, 0x98, 0x87, 0xc0, 0x8e, 0xa3, 0xab, 0xe0, + 0xff, 0xba, 0x85, 0xb0, 0x35, 0x57, 0xa4, 0xc9, 0xef, 0xc1, 0xba, 0x2b, 0x6e, 0x7c, 0x4f, 0x38, + 0xae, 0x1d, 0x85, 0x9e, 0xae, 0xab, 0xa4, 0xd8, 0x45, 0xe8, 0x3d, 0x76, 0x7f, 0x53, 0x13, 0x8d, + 0xcc, 0xc4, 0xde, 0x2f, 0x03, 0x36, 0xfb, 0xf1, 0x49, 0xeb, 0xa9, 0x83, 0xf8, 0xa0, 0xd9, 0x19, + 0x54, 0xe7, 0xee, 0x88, 0xb5, 0x32, 0xb9, 0xf3, 0x2e, 0xbb, 0xf9, 0xe2, 0xae, 0xb0, 0xa6, 0xf0, + 0x01, 0x60, 0x6a, 0x13, 0x6b, 0xe6, 0x7a, 0x97, 0x74, 0xba, 0xcf, 0x57, 0x76, 0x02, 0xeb, 0xb3, + 0xeb, 0xc1, 0x76, 0xb3, 0xe4, 0x9c, 0x45, 0x6c, 0xb6, 0xee, 0x88, 0xea, 0x66, 0x67, 0x50, 0x9d, + 0xf3, 0x6e, 0x86, 0x63, 0xde, 0x2a, 0xcc, 0x70, 0xcc, 0xb5, 0x9c, 0xf5, 0x61, 0x25, 0x76, 0x8f, + 0x4d, 0x19, 0x2c, 0x6f, 0x40, 0x73, 0x37, 0x3f, 0x98, 0xb4, 0x78, 0xf7, 0xf1, 0xdb, 0xab, 0x31, + 0xa7, 0x1f, 0xd1, 0xb0, 0x3b, 0x12, 0x57, 0x07, 0x3a, 0xf3, 0x40, 0xfd, 0xbb, 0x8e, 0x84, 0x97, + 0x02, 0xbf, 0x8b, 0xd5, 0x53, 0x7e, 0x8d, 0x27, 0x9c, 0xba, 0xe7, 0x71, 0xe8, 0x6f, 0x71, 0x43, + 0x7f, 0x1f, 0x1d, 0x29, 0x60, 0x58, 0x52, 0x25, 0x87, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x3f, + 0x0b, 0xdd, 0x24, 0xb5, 0x05, 0x00, 0x00, +} diff --git a/livekit/livekit_agent_simulation.twirp.go b/livekit/livekit_agent_simulation.twirp.go index b2d752787..79ee02cf0 100644 --- a/livekit/livekit_agent_simulation.twirp.go +++ b/livekit/livekit_agent_simulation.twirp.go @@ -1897,7 +1897,7 @@ func (s *agentSimulationServer) serveCreateScenarioFromSessionProtobuf(ctx conte } func (s *agentSimulationServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor9, 0 + return twirpFileDescriptor10, 0 } func (s *agentSimulationServer) ProtocGenTwirpVersion() string { @@ -1911,7 +1911,7 @@ func (s *agentSimulationServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "AgentSimulation") } -var twirpFileDescriptor9 = []byte{ +var twirpFileDescriptor10 = []byte{ // 3365 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x6f, 0x1b, 0x49, 0x76, 0x37, 0x3f, 0x45, 0x3e, 0x8a, 0x1f, 0x2a, 0xc9, 0x32, 0xdd, 0xb3, 0x9e, 0x91, 0x3d, 0x33, diff --git a/livekit/livekit_cloud_agent.twirp.go b/livekit/livekit_cloud_agent.twirp.go index 27ce9a912..689ae25bc 100644 --- a/livekit/livekit_cloud_agent.twirp.go +++ b/livekit/livekit_cloud_agent.twirp.go @@ -5245,7 +5245,7 @@ func (s *cloudAgentServer) serveGetPrivateLinkStatusProtobuf(ctx context.Context } func (s *cloudAgentServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor6, 0 + return twirpFileDescriptor7, 0 } func (s *cloudAgentServer) ProtocGenTwirpVersion() string { @@ -5259,7 +5259,7 @@ func (s *cloudAgentServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "CloudAgent") } -var twirpFileDescriptor6 = []byte{ +var twirpFileDescriptor7 = []byte{ // 2600 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5a, 0x5d, 0x6f, 0x1b, 0x4b, 0xf9, 0xcf, 0xfa, 0x2d, 0xf6, 0xe3, 0xb8, 0x71, 0x26, 0x69, 0xea, 0x38, 0x49, 0x9b, 0x6c, 0xdb, diff --git a/livekit/livekit_connector.twirp.go b/livekit/livekit_connector.twirp.go index d88f01c00..472bc090a 100644 --- a/livekit/livekit_connector.twirp.go +++ b/livekit/livekit_connector.twirp.go @@ -1618,7 +1618,7 @@ func (s *connectorServer) serveConnectTwilioCallProtobuf(ctx context.Context, re } func (s *connectorServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor8, 0 + return twirpFileDescriptor9, 0 } func (s *connectorServer) ProtocGenTwirpVersion() string { @@ -1632,7 +1632,7 @@ func (s *connectorServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "Connector") } -var twirpFileDescriptor8 = []byte{ +var twirpFileDescriptor9 = []byte{ // 313 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x41, 0x4b, 0xf3, 0x30, 0x1c, 0xc6, 0xdf, 0xb7, 0xc2, 0xd4, 0xbf, 0x4e, 0x6b, 0x04, 0x85, 0x1e, 0x64, 0x5b, 0x45, 0xc1, diff --git a/livekit/livekit_egress.twirp.go b/livekit/livekit_egress.twirp.go index df5542a5a..86cf46b7c 100644 --- a/livekit/livekit_egress.twirp.go +++ b/livekit/livekit_egress.twirp.go @@ -3019,7 +3019,7 @@ func (s *egressServer) serveStartTrackEgressProtobuf(ctx context.Context, resp h } func (s *egressServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor2, 0 + return twirpFileDescriptor3, 0 } func (s *egressServer) ProtocGenTwirpVersion() string { @@ -3033,7 +3033,7 @@ func (s *egressServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "Egress") } -var twirpFileDescriptor2 = []byte{ +var twirpFileDescriptor3 = []byte{ // 4257 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3b, 0x4b, 0x70, 0x1c, 0x59, 0x52, 0xaa, 0xea, 0x7f, 0xf6, 0xaf, 0xf4, 0x24, 0x6b, 0xda, 0xf2, 0x7a, 0xec, 0x6d, 0xef, 0x8c, diff --git a/livekit/livekit_ingress.twirp.go b/livekit/livekit_ingress.twirp.go index fa7244522..acb4d95a2 100644 --- a/livekit/livekit_ingress.twirp.go +++ b/livekit/livekit_ingress.twirp.go @@ -1341,7 +1341,7 @@ func (s *ingressServer) serveDeleteIngressProtobuf(ctx context.Context, resp htt } func (s *ingressServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor3, 0 + return twirpFileDescriptor4, 0 } func (s *ingressServer) ProtocGenTwirpVersion() string { @@ -1355,7 +1355,7 @@ func (s *ingressServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "Ingress") } -var twirpFileDescriptor3 = []byte{ +var twirpFileDescriptor4 = []byte{ // 1620 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4d, 0x6f, 0xdb, 0xcc, 0x11, 0x36, 0xf5, 0xad, 0x91, 0x25, 0x2b, 0x6b, 0xf9, 0x7d, 0x15, 0x7f, 0xb4, 0x82, 0x92, 0x22, diff --git a/livekit/livekit_phone_number.twirp.go b/livekit/livekit_phone_number.twirp.go index 21c6c897f..9b78d0f35 100644 --- a/livekit/livekit_phone_number.twirp.go +++ b/livekit/livekit_phone_number.twirp.go @@ -1904,7 +1904,7 @@ func (s *phoneNumberServiceServer) serveReleasePhoneNumbersProtobuf(ctx context. } func (s *phoneNumberServiceServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor7, 0 + return twirpFileDescriptor8, 0 } func (s *phoneNumberServiceServer) ProtocGenTwirpVersion() string { @@ -1918,7 +1918,7 @@ func (s *phoneNumberServiceServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "PhoneNumberService") } -var twirpFileDescriptor7 = []byte{ +var twirpFileDescriptor8 = []byte{ // 1241 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0x51, 0x6e, 0xdb, 0x46, 0x13, 0xd6, 0x52, 0xb6, 0x63, 0x8d, 0x64, 0x5b, 0xd9, 0x38, 0x09, 0x4d, 0x27, 0xb1, 0x42, 0xff, diff --git a/livekit/livekit_room.twirp.go b/livekit/livekit_room.twirp.go index eae205ebf..122269f8a 100644 --- a/livekit/livekit_room.twirp.go +++ b/livekit/livekit_room.twirp.go @@ -4152,7 +4152,7 @@ func (s *roomServiceServer) servePerformRpcProtobuf(ctx context.Context, resp ht } func (s *roomServiceServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor4, 0 + return twirpFileDescriptor5, 0 } func (s *roomServiceServer) ProtocGenTwirpVersion() string { @@ -4166,7 +4166,7 @@ func (s *roomServiceServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "RoomService") } -var twirpFileDescriptor4 = []byte{ +var twirpFileDescriptor5 = []byte{ // 1612 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x5b, 0x6f, 0x13, 0xd7, 0x16, 0x3e, 0x4e, 0x6c, 0xc7, 0x5e, 0xce, 0xcd, 0x3b, 0x01, 0x26, 0x13, 0x2e, 0x66, 0xc2, 0x39, diff --git a/livekit/livekit_sip.twirp.go b/livekit/livekit_sip.twirp.go index 3677e1398..3150829ac 100644 --- a/livekit/livekit_sip.twirp.go +++ b/livekit/livekit_sip.twirp.go @@ -4689,7 +4689,7 @@ func (s *sIPServer) serveTransferSIPParticipantProtobuf(ctx context.Context, res } func (s *sIPServer) ServiceDescriptor() ([]byte, int) { - return twirpFileDescriptor5, 0 + return twirpFileDescriptor6, 0 } func (s *sIPServer) ProtocGenTwirpVersion() string { @@ -4703,7 +4703,7 @@ func (s *sIPServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "livekit", "SIP") } -var twirpFileDescriptor5 = []byte{ +var twirpFileDescriptor6 = []byte{ // 5797 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x7c, 0x69, 0x8c, 0x1b, 0xc9, 0x75, 0xb0, 0xc8, 0xe6, 0xcc, 0x70, 0x1e, 0xe7, 0xe8, 0xa9, 0x19, 0x8d, 0xa8, 0xd1, 0x35, 0x4b, diff --git a/magefile.go b/magefile.go index 087bbf623..7f2980770 100644 --- a/magefile.go +++ b/magefile.go @@ -45,6 +45,7 @@ func Proto() error { twirpProtoFiles := []string{ "cloud_replay.proto", "livekit_agent_dispatch.proto", + "livekit_agent_session_store.proto", "livekit_egress.proto", "livekit_ingress.proto", "livekit_room.proto", @@ -66,6 +67,7 @@ func Proto() error { protoFiles := []string{ "livekit_agent.proto", + "livekit_agent_session_db.proto", "livekit_analytics.proto", "livekit_internal.proto", "livekit_models.proto", diff --git a/protobufs/livekit_agent_session_db.proto b/protobufs/livekit_agent_session_db.proto new file mode 100644 index 000000000..2898aaaca --- /dev/null +++ b/protobufs/livekit_agent_session_db.proto @@ -0,0 +1,145 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package livekit; + +option go_package = "github.com/livekit/protocol/livekit"; +option csharp_namespace = "LiveKit.Proto"; +option ruby_package = "LiveKit::Proto"; + +// Data plane for AgentSessionStore session databases: a SQL(+openCypher) +// protocol carried over a WebSocket. One binary-protobuf message per WS +// frame; requests and responses correlate by request_id (monotonic per +// connection, chosen by the client). One WebSocket = one session connection. +// +// Flow control: query results stream as SessionRowBatch frames paced by +// per-request credits (SessionCredit) the client advertises; the server +// never sends more un-consumed batches than granted, so any result size +// streams with bounded memory at every hop. + +message SessionStoreRequest { + uint32 request_id = 1; + oneof message { + SessionHello hello = 2; // must be first on the socket + SessionStatement exec = 3; // no result rows; answers SessionExecResult + SessionStatement query = 4; // answers SessionColumns + SessionRowBatch* + SessionDone + SessionBatch batch = 5; // atomic multi-statement exec + SessionBegin begin = 6; // interactive transaction (server enforces idle/duration timeouts) + SessionCommit commit = 7; + SessionRollback rollback = 8; + SessionCancel cancel = 9; // stop a running query's stream/cursor + SessionCredit credit = 10; // grant more RowBatch credits for request_id + SessionPing ping = 11; + } +} + +message SessionStoreResponse { + uint32 request_id = 1; + oneof message { + SessionHelloOk hello_ok = 2; + SessionColumns columns = 3; + SessionRowBatch row_batch = 4; + SessionExecResult exec_result = 5; + SessionDone done = 6; + SessionStoreError error = 7; + SessionPong pong = 8; + } +} + +// SessionQueryLang selects the query language of a statement; both execute +// against the same session database. +enum SessionQueryLang { + SESSION_QUERY_LANG_SQL = 0; + SESSION_QUERY_LANG_CYPHER = 1; +} + +// SessionValue mirrors SQLite's five storage classes exactly. +message SessionValue { + oneof value { + bool null_value = 1; // always true when set + int64 int_value = 2; + double double_value = 3; + string text_value = 4; + bytes blob_value = 5; + } +} + +message SessionStatement { + string sql = 1; // statement text in the selected lang + repeated SessionValue params = 2; // positional bind parameters + SessionQueryLang lang = 3; +} + +message SessionBatch { + repeated SessionStatement statements = 1; // applied atomically, in order +} + +message SessionBegin {} +message SessionCommit {} +message SessionRollback {} +message SessionCancel {} + +message SessionCredit { + uint32 batches = 1; // additional RowBatch frames the client can absorb +} + +message SessionPing { + int64 timestamp = 1; +} + +message SessionPong { + int64 last_ping_timestamp = 1; + int64 timestamp = 2; +} + +message SessionHello { + string token = 1; // access token; authorization is checked here + string session_id = 2; +} + +message SessionHelloOk { + int64 tip = 1; // latest durable commit sequence + uint32 ping_interval_ms = 2; // server-advertised keepalive cadence + uint32 ping_timeout_ms = 3; +} + +message SessionColumns { + repeated string names = 1; +} + +message SessionRow { + repeated SessionValue values = 1; +} + +message SessionRowBatch { + repeated SessionRow rows = 1; +} + +message SessionExecResult { + int64 rows_affected = 1; + int64 last_insert_id = 2; + int64 tip = 3; // durable commit sequence after this exec +} + +message SessionDone { + int64 tip = 1; // snapshot the query ran at + uint64 total_rows = 2; +} + +message SessionStoreError { + string code = 1; // stable machine-readable code + string message = 2; +} diff --git a/protobufs/livekit_agent_session_store.proto b/protobufs/livekit_agent_session_store.proto new file mode 100644 index 000000000..5c0f046b9 --- /dev/null +++ b/protobufs/livekit_agent_session_store.proto @@ -0,0 +1,95 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package livekit; + +option go_package = "github.com/livekit/protocol/livekit"; +option csharp_namespace = "LiveKit.Proto"; +option ruby_package = "LiveKit::Proto"; + +// AgentSessionStore is the MANAGEMENT plane for per-session SQLite databases: +// lifecycle and export only. All querying goes through the data plane (a +// WebSocket speaking SessionStoreRequest/SessionStoreResponse, defined in +// livekit_agent_session_db.proto). project_id is taken from the authenticated +// principal (access key) on every call, never a request field. +service AgentSessionStore { + // CreateSession allocates a new session database. + rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse); + + // GetSession returns session metadata. + rpc GetSession(GetSessionRequest) returns (GetSessionResponse); + + // ListSessions pages through the caller's sessions. + rpc ListSessions(ListSessionsRequest) returns (ListSessionsResponse); + + // DeleteSession removes a session and all its stored data. + rpc DeleteSession(DeleteSessionRequest) returns (DeleteSessionResponse); + + // Dump exports a consistent full SQLite database file for the session and + // returns a time-limited download URL (object-storage pre-authenticated + // request). Runs off the serving path; never blocks the session's writes. + rpc Dump(DumpSessionRequest) returns (DumpSessionResponse); +} + +message CreateSessionRequest { + string region = 1; // data region the session is stored in + string user_attributes = 2; // opaque JSON metadata for the caller + int64 ttl_seconds = 3; // per-session TTL, clamped to a hard max; never extended +} + +message CreateSessionResponse { + string session_id = 1; // "SESS_..." + int64 expires_at_unix = 2; +} + +message GetSessionRequest { + string session_id = 1; +} + +message GetSessionResponse { + string session_id = 1; + string region = 2; + string user_attributes = 3; + int64 created_at_unix = 4; + int64 expires_at_unix = 5; + int64 tip = 6; // latest durable commit sequence +} + +message ListSessionsRequest { + int32 page_size = 1; // server-clamped + string page_token = 2; // opaque cursor from a previous response +} + +message ListSessionsResponse { + repeated GetSessionResponse sessions = 1; + string next_page_token = 2; // empty when exhausted +} + +message DeleteSessionRequest { + string session_id = 1; +} + +message DeleteSessionResponse {} + +message DumpSessionRequest { + string session_id = 1; +} + +message DumpSessionResponse { + string download_url = 1; // pre-authenticated object-storage URL + int64 expires_at_unix = 2; // URL expiry + int64 tip = 3; // commit sequence the dump is consistent at +} From c4cdd6ac5b84a45ffcda8598faee51781ec00475 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 17:41:37 +0000 Subject: [PATCH 02/10] generated protobuf --- livekit/livekit_agent_session_db.pb.go | 2 +- livekit/livekit_agent_session_store.pb.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/livekit/livekit_agent_session_db.pb.go b/livekit/livekit_agent_session_db.pb.go index 40ef02f82..6e02ead27 100644 --- a/livekit/livekit_agent_session_db.pb.go +++ b/livekit/livekit_agent_session_db.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc v7.35.1 // source: livekit_agent_session_db.proto package livekit diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index f32465f69..729fd663d 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc v7.35.1 // source: livekit_agent_session_store.proto package livekit From 1aeca8889e1c61d8ce359b27590274d841fcbdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Mon, 27 Jul 2026 10:48:45 -0700 Subject: [PATCH 03/10] Drop rpc comments that only restate the method name Regenerated, so the same lines leave the Go doc comments. --- livekit/livekit_agent_session_store.pb.go | 2 +- livekit/livekit_agent_session_store.twirp.go | 11 ++++------- protobufs/livekit_agent_session_store.proto | 15 +++++---------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index 729fd663d..4a69f285d 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -37,7 +37,7 @@ const ( type CreateSessionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` // data region the session is stored in + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` UserAttributes string `protobuf:"bytes,2,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` // opaque JSON metadata for the caller TtlSeconds int64 `protobuf:"varint,3,opt,name=ttl_seconds,json=ttlSeconds,proto3" json:"ttl_seconds,omitempty"` // per-session TTL, clamped to a hard max; never extended unknownFields protoimpl.UnknownFields diff --git a/livekit/livekit_agent_session_store.twirp.go b/livekit/livekit_agent_session_store.twirp.go index 4577e11cb..1f70ffb7f 100644 --- a/livekit/livekit_agent_session_store.twirp.go +++ b/livekit/livekit_agent_session_store.twirp.go @@ -32,21 +32,18 @@ const _ = twirp.TwirpPackageMinVersion_8_1_0 // livekit_agent_session_db.proto). project_id is taken from the authenticated // principal (access key) on every call, never a request field. type AgentSessionStore interface { - // CreateSession allocates a new session database. CreateSession(context.Context, *CreateSessionRequest) (*CreateSessionResponse, error) - // GetSession returns session metadata. GetSession(context.Context, *GetSessionRequest) (*GetSessionResponse, error) - // ListSessions pages through the caller's sessions. ListSessions(context.Context, *ListSessionsRequest) (*ListSessionsResponse, error) - // DeleteSession removes a session and all its stored data. + // Deletes the stored data too, not just the metadata row. DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) - // Dump exports a consistent full SQLite database file for the session and - // returns a time-limited download URL (object-storage pre-authenticated - // request). Runs off the serving path; never blocks the session's writes. + // Exports a consistent full SQLite database file and returns a time-limited + // download URL (object-storage pre-authenticated request). Runs off the + // serving path; never blocks the session's writes. Dump(context.Context, *DumpSessionRequest) (*DumpSessionResponse, error) } diff --git a/protobufs/livekit_agent_session_store.proto b/protobufs/livekit_agent_session_store.proto index 5c0f046b9..e996fd14c 100644 --- a/protobufs/livekit_agent_session_store.proto +++ b/protobufs/livekit_agent_session_store.proto @@ -26,26 +26,21 @@ option ruby_package = "LiveKit::Proto"; // livekit_agent_session_db.proto). project_id is taken from the authenticated // principal (access key) on every call, never a request field. service AgentSessionStore { - // CreateSession allocates a new session database. rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse); - - // GetSession returns session metadata. rpc GetSession(GetSessionRequest) returns (GetSessionResponse); - - // ListSessions pages through the caller's sessions. rpc ListSessions(ListSessionsRequest) returns (ListSessionsResponse); - // DeleteSession removes a session and all its stored data. + // Deletes the stored data too, not just the metadata row. rpc DeleteSession(DeleteSessionRequest) returns (DeleteSessionResponse); - // Dump exports a consistent full SQLite database file for the session and - // returns a time-limited download URL (object-storage pre-authenticated - // request). Runs off the serving path; never blocks the session's writes. + // Exports a consistent full SQLite database file and returns a time-limited + // download URL (object-storage pre-authenticated request). Runs off the + // serving path; never blocks the session's writes. rpc Dump(DumpSessionRequest) returns (DumpSessionResponse); } message CreateSessionRequest { - string region = 1; // data region the session is stored in + string region = 1; string user_attributes = 2; // opaque JSON metadata for the caller int64 ttl_seconds = 3; // per-session TTL, clamped to a hard max; never extended } From bd60d2bf08bd2880ef92d24e25547b52cb4bba14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Tue, 28 Jul 2026 13:19:37 -0700 Subject: [PATCH 04/10] Add AgentGrant.SessionAdmin Gates the agent session store: creating, reading, querying, exporting and deleting a project's session databases, on both the management API and the data-plane connection. Without it that service could only verify that a token was signed by a key belonging to the project, not what it was allowed to do. --- auth/grants.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/auth/grants.go b/auth/grants.go index e50e703ec..646bb0689 100644 --- a/auth/grants.go +++ b/auth/grants.go @@ -581,6 +581,10 @@ type AgentGrant struct { Admin bool `json:"admin,omitempty"` // SimulationAdmin grants access to manage simulations and scenarios for evaluating agents. SimulationAdmin bool `json:"simulationAdmin,omitempty"` + // SessionAdmin grants access to the agent session store: creating, reading, + // querying, exporting and deleting a project's session databases. It gates + // both the management API and the data-plane connection. + SessionAdmin bool `json:"sessionAdmin,omitempty"` } func (s *AgentGrant) Clone() *AgentGrant { @@ -600,6 +604,7 @@ func (s *AgentGrant) MarshalLogObject(e zapcore.ObjectEncoder) error { e.AddBool("Admin", s.Admin) e.AddBool("SimulationAdmin", s.SimulationAdmin) + e.AddBool("SessionAdmin", s.SessionAdmin) return nil } From 376b8e6bdb0e07f2197e6c244dfbf9e4c34132fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Tue, 28 Jul 2026 15:19:07 -0700 Subject: [PATCH 05/10] Column-oriented session results, and drop tip from ListSessions Query results were row-oriented: a SessionValue message per cell plus its oneof wrapper, which cost two allocations per cell on the server, the same again as the client unmarshalled, and left the garbage collector walking pointer-dense batches. A SessionColumnBatch carries a type tag per value (SQLite types values individually, not by column) plus one packed array per storage class, with text and blob bytes concatenated and addressed by exclusive end offsets rather than repeated string, which is what lets a decoder hand out subslices of one buffer. Measured end to end in the service, an 8000-row scan went from 47,819 allocations to 63, and a scalar-heavy batch is 43% smaller on the wire so more rows fit per credit. ListSessions now returns SessionSummary rather than GetSessionResponse, which drops tip from listings. tip advances on every commit, so a listing index cannot carry it without putting a write on the commit path, which means listing has to read every session's metadata row to fill it in. It is also stale on arrival, since anything acting on it must re-read. Everything else listing returns is immutable, so a summary can be served straight from an index. GetSession still returns tip for a single session. A separate message rather than leaving the field unset: 0 is a valid tip, for a session with no commits, so an unset field would be genuinely ambiguous. --- livekit/livekit_agent_session_db.pb.go | 322 +++++++++++++------ livekit/livekit_agent_session_store.pb.go | 173 +++++++--- livekit/livekit_agent_session_store.twirp.go | 75 ++--- protobufs/livekit_agent_session_db.proto | 46 ++- protobufs/livekit_agent_session_store.proto | 17 +- 5 files changed, 452 insertions(+), 181 deletions(-) diff --git a/livekit/livekit_agent_session_db.pb.go b/livekit/livekit_agent_session_db.pb.go index 6e02ead27..6256b6f53 100644 --- a/livekit/livekit_agent_session_db.pb.go +++ b/livekit/livekit_agent_session_db.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.35.1 +// protoc v7.34.1 // source: livekit_agent_session_db.proto package livekit @@ -83,6 +83,62 @@ func (SessionQueryLang) EnumDescriptor() ([]byte, []int) { return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{0} } +// SessionValueType tags one value's storage class within a SessionColumn. +type SessionValueType int32 + +const ( + SessionValueType_SESSION_VALUE_TYPE_NULL SessionValueType = 0 + SessionValueType_SESSION_VALUE_TYPE_INT SessionValueType = 1 + SessionValueType_SESSION_VALUE_TYPE_DOUBLE SessionValueType = 2 + SessionValueType_SESSION_VALUE_TYPE_TEXT SessionValueType = 3 + SessionValueType_SESSION_VALUE_TYPE_BLOB SessionValueType = 4 +) + +// Enum value maps for SessionValueType. +var ( + SessionValueType_name = map[int32]string{ + 0: "SESSION_VALUE_TYPE_NULL", + 1: "SESSION_VALUE_TYPE_INT", + 2: "SESSION_VALUE_TYPE_DOUBLE", + 3: "SESSION_VALUE_TYPE_TEXT", + 4: "SESSION_VALUE_TYPE_BLOB", + } + SessionValueType_value = map[string]int32{ + "SESSION_VALUE_TYPE_NULL": 0, + "SESSION_VALUE_TYPE_INT": 1, + "SESSION_VALUE_TYPE_DOUBLE": 2, + "SESSION_VALUE_TYPE_TEXT": 3, + "SESSION_VALUE_TYPE_BLOB": 4, + } +) + +func (x SessionValueType) Enum() *SessionValueType { + p := new(SessionValueType) + *p = x + return p +} + +func (x SessionValueType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SessionValueType) Descriptor() protoreflect.EnumDescriptor { + return file_livekit_agent_session_db_proto_enumTypes[1].Descriptor() +} + +func (SessionValueType) Type() protoreflect.EnumType { + return &file_livekit_agent_session_db_proto_enumTypes[1] +} + +func (x SessionValueType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SessionValueType.Descriptor instead. +func (SessionValueType) EnumDescriptor() ([]byte, []int) { + return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{1} +} + type SessionStoreRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId uint32 `protobuf:"varint,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` @@ -250,7 +306,7 @@ type SessionStoreRequest_Exec struct { } type SessionStoreRequest_Query struct { - Query *SessionStatement `protobuf:"bytes,4,opt,name=query,proto3,oneof"` // answers SessionColumns + SessionRowBatch* + SessionDone + Query *SessionStatement `protobuf:"bytes,4,opt,name=query,proto3,oneof"` // answers SessionColumns + SessionColumnBatch* + SessionDone } type SessionStoreRequest_Batch struct { @@ -274,7 +330,7 @@ type SessionStoreRequest_Cancel struct { } type SessionStoreRequest_Credit struct { - Credit *SessionCredit `protobuf:"bytes,10,opt,name=credit,proto3,oneof"` // grant more RowBatch credits for request_id + Credit *SessionCredit `protobuf:"bytes,10,opt,name=credit,proto3,oneof"` // grant more batch credits for request_id } type SessionStoreRequest_Ping struct { @@ -308,7 +364,7 @@ type SessionStoreResponse struct { // // *SessionStoreResponse_HelloOk // *SessionStoreResponse_Columns - // *SessionStoreResponse_RowBatch + // *SessionStoreResponse_ColumnBatch // *SessionStoreResponse_ExecResult // *SessionStoreResponse_Done // *SessionStoreResponse_Error @@ -380,10 +436,10 @@ func (x *SessionStoreResponse) GetColumns() *SessionColumns { return nil } -func (x *SessionStoreResponse) GetRowBatch() *SessionRowBatch { +func (x *SessionStoreResponse) GetColumnBatch() *SessionColumnBatch { if x != nil { - if x, ok := x.Message.(*SessionStoreResponse_RowBatch); ok { - return x.RowBatch + if x, ok := x.Message.(*SessionStoreResponse_ColumnBatch); ok { + return x.ColumnBatch } } return nil @@ -437,8 +493,8 @@ type SessionStoreResponse_Columns struct { Columns *SessionColumns `protobuf:"bytes,3,opt,name=columns,proto3,oneof"` } -type SessionStoreResponse_RowBatch struct { - RowBatch *SessionRowBatch `protobuf:"bytes,4,opt,name=row_batch,json=rowBatch,proto3,oneof"` +type SessionStoreResponse_ColumnBatch struct { + ColumnBatch *SessionColumnBatch `protobuf:"bytes,4,opt,name=column_batch,json=columnBatch,proto3,oneof"` } type SessionStoreResponse_ExecResult struct { @@ -461,7 +517,7 @@ func (*SessionStoreResponse_HelloOk) isSessionStoreResponse_Message() {} func (*SessionStoreResponse_Columns) isSessionStoreResponse_Message() {} -func (*SessionStoreResponse_RowBatch) isSessionStoreResponse_Message() {} +func (*SessionStoreResponse_ColumnBatch) isSessionStoreResponse_Message() {} func (*SessionStoreResponse_ExecResult) isSessionStoreResponse_Message() {} @@ -852,7 +908,7 @@ func (*SessionCancel) Descriptor() ([]byte, []int) { type SessionCredit struct { state protoimpl.MessageState `protogen:"open.v1"` - Batches uint32 `protobuf:"varint,1,opt,name=batches,proto3" json:"batches,omitempty"` // additional RowBatch frames the client can absorb + Batches uint32 `protobuf:"varint,1,opt,name=batches,proto3" json:"batches,omitempty"` // additional batch frames the client can absorb unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1146,27 +1202,45 @@ func (x *SessionColumns) GetNames() []string { return nil } -type SessionRow struct { - state protoimpl.MessageState `protogen:"open.v1"` - Values []*SessionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +// SessionColumn carries one column of a batch, column-oriented so a result set +// costs a handful of allocations per batch rather than two per cell (a message +// plus a oneof wrapper), and so scalar runs land in pointer-free arrays the +// garbage collector never scans. +// +// SQLite types values individually rather than by column, so `types` tags every +// value and each typed array holds only the values of its own class, in row +// order. Reading a column means walking `types` and taking the next entry from +// the matching array; NULLs occupy a tag and nothing else. +type SessionColumn struct { + state protoimpl.MessageState `protogen:"open.v1"` + Types []byte `protobuf:"bytes,1,opt,name=types,proto3" json:"types,omitempty"` // one SessionValueType per row, one byte each + Ints []int64 `protobuf:"zigzag64,2,rep,packed,name=ints,proto3" json:"ints,omitempty"` // zigzag, so negative values stay small + Doubles []float64 `protobuf:"fixed64,3,rep,packed,name=doubles,proto3" json:"doubles,omitempty"` + // Text and blob values are concatenated with an exclusive end offset each, + // rather than `repeated string`, so a decoder can hand out subslices of one + // buffer instead of copying every value. + TextData []byte `protobuf:"bytes,4,opt,name=text_data,json=textData,proto3" json:"text_data,omitempty"` + TextEnds []uint32 `protobuf:"varint,5,rep,packed,name=text_ends,json=textEnds,proto3" json:"text_ends,omitempty"` + BlobData []byte `protobuf:"bytes,6,opt,name=blob_data,json=blobData,proto3" json:"blob_data,omitempty"` + BlobEnds []uint32 `protobuf:"varint,7,rep,packed,name=blob_ends,json=blobEnds,proto3" json:"blob_ends,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *SessionRow) Reset() { - *x = SessionRow{} +func (x *SessionColumn) Reset() { + *x = SessionColumn{} mi := &file_livekit_agent_session_db_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *SessionRow) String() string { +func (x *SessionColumn) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SessionRow) ProtoMessage() {} +func (*SessionColumn) ProtoMessage() {} -func (x *SessionRow) ProtoReflect() protoreflect.Message { +func (x *SessionColumn) ProtoReflect() protoreflect.Message { mi := &file_livekit_agent_session_db_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1178,39 +1252,82 @@ func (x *SessionRow) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SessionRow.ProtoReflect.Descriptor instead. -func (*SessionRow) Descriptor() ([]byte, []int) { +// Deprecated: Use SessionColumn.ProtoReflect.Descriptor instead. +func (*SessionColumn) Descriptor() ([]byte, []int) { return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{15} } -func (x *SessionRow) GetValues() []*SessionValue { +func (x *SessionColumn) GetTypes() []byte { + if x != nil { + return x.Types + } + return nil +} + +func (x *SessionColumn) GetInts() []int64 { if x != nil { - return x.Values + return x.Ints } return nil } -type SessionRowBatch struct { +func (x *SessionColumn) GetDoubles() []float64 { + if x != nil { + return x.Doubles + } + return nil +} + +func (x *SessionColumn) GetTextData() []byte { + if x != nil { + return x.TextData + } + return nil +} + +func (x *SessionColumn) GetTextEnds() []uint32 { + if x != nil { + return x.TextEnds + } + return nil +} + +func (x *SessionColumn) GetBlobData() []byte { + if x != nil { + return x.BlobData + } + return nil +} + +func (x *SessionColumn) GetBlobEnds() []uint32 { + if x != nil { + return x.BlobEnds + } + return nil +} + +type SessionColumnBatch struct { state protoimpl.MessageState `protogen:"open.v1"` - Rows []*SessionRow `protobuf:"bytes,1,rep,name=rows,proto3" json:"rows,omitempty"` + Columns []*SessionColumn `protobuf:"bytes,1,rep,name=columns,proto3" json:"columns,omitempty"` // one per column of SessionColumns + Rows uint32 `protobuf:"varint,2,opt,name=rows,proto3" json:"rows,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *SessionRowBatch) Reset() { - *x = SessionRowBatch{} +func (x *SessionColumnBatch) Reset() { + *x = SessionColumnBatch{} mi := &file_livekit_agent_session_db_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *SessionRowBatch) String() string { +func (x *SessionColumnBatch) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SessionRowBatch) ProtoMessage() {} +func (*SessionColumnBatch) ProtoMessage() {} -func (x *SessionRowBatch) ProtoReflect() protoreflect.Message { +func (x *SessionColumnBatch) ProtoReflect() protoreflect.Message { mi := &file_livekit_agent_session_db_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1222,18 +1339,25 @@ func (x *SessionRowBatch) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SessionRowBatch.ProtoReflect.Descriptor instead. -func (*SessionRowBatch) Descriptor() ([]byte, []int) { +// Deprecated: Use SessionColumnBatch.ProtoReflect.Descriptor instead. +func (*SessionColumnBatch) Descriptor() ([]byte, []int) { return file_livekit_agent_session_db_proto_rawDescGZIP(), []int{16} } -func (x *SessionRowBatch) GetRows() []*SessionRow { +func (x *SessionColumnBatch) GetColumns() []*SessionColumn { if x != nil { - return x.Rows + return x.Columns } return nil } +func (x *SessionColumnBatch) GetRows() uint32 { + if x != nil { + return x.Rows + } + return 0 +} + type SessionExecResult struct { state protoimpl.MessageState `protogen:"open.v1"` RowsAffected int64 `protobuf:"varint,1,opt,name=rows_affected,json=rowsAffected,proto3" json:"rows_affected,omitempty"` @@ -1417,13 +1541,13 @@ const file_livekit_agent_session_db_proto_rawDesc = "" + "\x06credit\x18\n" + " \x01(\v2\x16.livekit.SessionCreditH\x00R\x06credit\x12*\n" + "\x04ping\x18\v \x01(\v2\x14.livekit.SessionPingH\x00R\x04pingB\t\n" + - "\amessage\"\xaf\x03\n" + + "\amessage\"\xb8\x03\n" + "\x14SessionStoreResponse\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\rR\trequestId\x124\n" + "\bhello_ok\x18\x02 \x01(\v2\x17.livekit.SessionHelloOkH\x00R\ahelloOk\x123\n" + - "\acolumns\x18\x03 \x01(\v2\x17.livekit.SessionColumnsH\x00R\acolumns\x127\n" + - "\trow_batch\x18\x04 \x01(\v2\x18.livekit.SessionRowBatchH\x00R\browBatch\x12=\n" + + "\acolumns\x18\x03 \x01(\v2\x17.livekit.SessionColumnsH\x00R\acolumns\x12@\n" + + "\fcolumn_batch\x18\x04 \x01(\v2\x1b.livekit.SessionColumnBatchH\x00R\vcolumnBatch\x12=\n" + "\vexec_result\x18\x05 \x01(\v2\x1a.livekit.SessionExecResultH\x00R\n" + "execResult\x12*\n" + "\x04done\x18\x06 \x01(\v2\x14.livekit.SessionDoneH\x00R\x04done\x122\n" + @@ -1468,12 +1592,18 @@ const file_livekit_agent_session_db_proto_rawDesc = "" + "\x10ping_interval_ms\x18\x02 \x01(\rR\x0epingIntervalMs\x12&\n" + "\x0fping_timeout_ms\x18\x03 \x01(\rR\rpingTimeoutMs\"&\n" + "\x0eSessionColumns\x12\x14\n" + - "\x05names\x18\x01 \x03(\tR\x05names\";\n" + - "\n" + - "SessionRow\x12-\n" + - "\x06values\x18\x01 \x03(\v2\x15.livekit.SessionValueR\x06values\":\n" + - "\x0fSessionRowBatch\x12'\n" + - "\x04rows\x18\x01 \x03(\v2\x13.livekit.SessionRowR\x04rows\"p\n" + + "\x05names\x18\x01 \x03(\tR\x05names\"\xc7\x01\n" + + "\rSessionColumn\x12\x14\n" + + "\x05types\x18\x01 \x01(\fR\x05types\x12\x12\n" + + "\x04ints\x18\x02 \x03(\x12R\x04ints\x12\x18\n" + + "\adoubles\x18\x03 \x03(\x01R\adoubles\x12\x1b\n" + + "\ttext_data\x18\x04 \x01(\fR\btextData\x12\x1b\n" + + "\ttext_ends\x18\x05 \x03(\rR\btextEnds\x12\x1b\n" + + "\tblob_data\x18\x06 \x01(\fR\bblobData\x12\x1b\n" + + "\tblob_ends\x18\a \x03(\rR\bblobEnds\"Z\n" + + "\x12SessionColumnBatch\x120\n" + + "\acolumns\x18\x01 \x03(\v2\x16.livekit.SessionColumnR\acolumns\x12\x12\n" + + "\x04rows\x18\x02 \x01(\rR\x04rows\"p\n" + "\x11SessionExecResult\x12#\n" + "\rrows_affected\x18\x01 \x01(\x03R\frowsAffected\x12$\n" + "\x0elast_insert_id\x18\x02 \x01(\x03R\flastInsertId\x12\x10\n" + @@ -1487,7 +1617,13 @@ const file_livekit_agent_session_db_proto_rawDesc = "" + "\amessage\x18\x02 \x01(\tR\amessage*M\n" + "\x10SessionQueryLang\x12\x1a\n" + "\x16SESSION_QUERY_LANG_SQL\x10\x00\x12\x1d\n" + - "\x19SESSION_QUERY_LANG_CYPHER\x10\x01BFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" + "\x19SESSION_QUERY_LANG_CYPHER\x10\x01*\xa4\x01\n" + + "\x10SessionValueType\x12\x1b\n" + + "\x17SESSION_VALUE_TYPE_NULL\x10\x00\x12\x1a\n" + + "\x16SESSION_VALUE_TYPE_INT\x10\x01\x12\x1d\n" + + "\x19SESSION_VALUE_TYPE_DOUBLE\x10\x02\x12\x1b\n" + + "\x17SESSION_VALUE_TYPE_TEXT\x10\x03\x12\x1b\n" + + "\x17SESSION_VALUE_TYPE_BLOB\x10\x04BFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" var ( file_livekit_agent_session_db_proto_rawDescOnce sync.Once @@ -1501,59 +1637,59 @@ func file_livekit_agent_session_db_proto_rawDescGZIP() []byte { return file_livekit_agent_session_db_proto_rawDescData } -var file_livekit_agent_session_db_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_livekit_agent_session_db_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_livekit_agent_session_db_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_livekit_agent_session_db_proto_goTypes = []any{ (SessionQueryLang)(0), // 0: livekit.SessionQueryLang - (*SessionStoreRequest)(nil), // 1: livekit.SessionStoreRequest - (*SessionStoreResponse)(nil), // 2: livekit.SessionStoreResponse - (*SessionValue)(nil), // 3: livekit.SessionValue - (*SessionStatement)(nil), // 4: livekit.SessionStatement - (*SessionBatch)(nil), // 5: livekit.SessionBatch - (*SessionBegin)(nil), // 6: livekit.SessionBegin - (*SessionCommit)(nil), // 7: livekit.SessionCommit - (*SessionRollback)(nil), // 8: livekit.SessionRollback - (*SessionCancel)(nil), // 9: livekit.SessionCancel - (*SessionCredit)(nil), // 10: livekit.SessionCredit - (*SessionPing)(nil), // 11: livekit.SessionPing - (*SessionPong)(nil), // 12: livekit.SessionPong - (*SessionHello)(nil), // 13: livekit.SessionHello - (*SessionHelloOk)(nil), // 14: livekit.SessionHelloOk - (*SessionColumns)(nil), // 15: livekit.SessionColumns - (*SessionRow)(nil), // 16: livekit.SessionRow - (*SessionRowBatch)(nil), // 17: livekit.SessionRowBatch - (*SessionExecResult)(nil), // 18: livekit.SessionExecResult - (*SessionDone)(nil), // 19: livekit.SessionDone - (*SessionStoreError)(nil), // 20: livekit.SessionStoreError + (SessionValueType)(0), // 1: livekit.SessionValueType + (*SessionStoreRequest)(nil), // 2: livekit.SessionStoreRequest + (*SessionStoreResponse)(nil), // 3: livekit.SessionStoreResponse + (*SessionValue)(nil), // 4: livekit.SessionValue + (*SessionStatement)(nil), // 5: livekit.SessionStatement + (*SessionBatch)(nil), // 6: livekit.SessionBatch + (*SessionBegin)(nil), // 7: livekit.SessionBegin + (*SessionCommit)(nil), // 8: livekit.SessionCommit + (*SessionRollback)(nil), // 9: livekit.SessionRollback + (*SessionCancel)(nil), // 10: livekit.SessionCancel + (*SessionCredit)(nil), // 11: livekit.SessionCredit + (*SessionPing)(nil), // 12: livekit.SessionPing + (*SessionPong)(nil), // 13: livekit.SessionPong + (*SessionHello)(nil), // 14: livekit.SessionHello + (*SessionHelloOk)(nil), // 15: livekit.SessionHelloOk + (*SessionColumns)(nil), // 16: livekit.SessionColumns + (*SessionColumn)(nil), // 17: livekit.SessionColumn + (*SessionColumnBatch)(nil), // 18: livekit.SessionColumnBatch + (*SessionExecResult)(nil), // 19: livekit.SessionExecResult + (*SessionDone)(nil), // 20: livekit.SessionDone + (*SessionStoreError)(nil), // 21: livekit.SessionStoreError } var file_livekit_agent_session_db_proto_depIdxs = []int32{ - 13, // 0: livekit.SessionStoreRequest.hello:type_name -> livekit.SessionHello - 4, // 1: livekit.SessionStoreRequest.exec:type_name -> livekit.SessionStatement - 4, // 2: livekit.SessionStoreRequest.query:type_name -> livekit.SessionStatement - 5, // 3: livekit.SessionStoreRequest.batch:type_name -> livekit.SessionBatch - 6, // 4: livekit.SessionStoreRequest.begin:type_name -> livekit.SessionBegin - 7, // 5: livekit.SessionStoreRequest.commit:type_name -> livekit.SessionCommit - 8, // 6: livekit.SessionStoreRequest.rollback:type_name -> livekit.SessionRollback - 9, // 7: livekit.SessionStoreRequest.cancel:type_name -> livekit.SessionCancel - 10, // 8: livekit.SessionStoreRequest.credit:type_name -> livekit.SessionCredit - 11, // 9: livekit.SessionStoreRequest.ping:type_name -> livekit.SessionPing - 14, // 10: livekit.SessionStoreResponse.hello_ok:type_name -> livekit.SessionHelloOk - 15, // 11: livekit.SessionStoreResponse.columns:type_name -> livekit.SessionColumns - 17, // 12: livekit.SessionStoreResponse.row_batch:type_name -> livekit.SessionRowBatch - 18, // 13: livekit.SessionStoreResponse.exec_result:type_name -> livekit.SessionExecResult - 19, // 14: livekit.SessionStoreResponse.done:type_name -> livekit.SessionDone - 20, // 15: livekit.SessionStoreResponse.error:type_name -> livekit.SessionStoreError - 12, // 16: livekit.SessionStoreResponse.pong:type_name -> livekit.SessionPong - 3, // 17: livekit.SessionStatement.params:type_name -> livekit.SessionValue + 14, // 0: livekit.SessionStoreRequest.hello:type_name -> livekit.SessionHello + 5, // 1: livekit.SessionStoreRequest.exec:type_name -> livekit.SessionStatement + 5, // 2: livekit.SessionStoreRequest.query:type_name -> livekit.SessionStatement + 6, // 3: livekit.SessionStoreRequest.batch:type_name -> livekit.SessionBatch + 7, // 4: livekit.SessionStoreRequest.begin:type_name -> livekit.SessionBegin + 8, // 5: livekit.SessionStoreRequest.commit:type_name -> livekit.SessionCommit + 9, // 6: livekit.SessionStoreRequest.rollback:type_name -> livekit.SessionRollback + 10, // 7: livekit.SessionStoreRequest.cancel:type_name -> livekit.SessionCancel + 11, // 8: livekit.SessionStoreRequest.credit:type_name -> livekit.SessionCredit + 12, // 9: livekit.SessionStoreRequest.ping:type_name -> livekit.SessionPing + 15, // 10: livekit.SessionStoreResponse.hello_ok:type_name -> livekit.SessionHelloOk + 16, // 11: livekit.SessionStoreResponse.columns:type_name -> livekit.SessionColumns + 18, // 12: livekit.SessionStoreResponse.column_batch:type_name -> livekit.SessionColumnBatch + 19, // 13: livekit.SessionStoreResponse.exec_result:type_name -> livekit.SessionExecResult + 20, // 14: livekit.SessionStoreResponse.done:type_name -> livekit.SessionDone + 21, // 15: livekit.SessionStoreResponse.error:type_name -> livekit.SessionStoreError + 13, // 16: livekit.SessionStoreResponse.pong:type_name -> livekit.SessionPong + 4, // 17: livekit.SessionStatement.params:type_name -> livekit.SessionValue 0, // 18: livekit.SessionStatement.lang:type_name -> livekit.SessionQueryLang - 4, // 19: livekit.SessionBatch.statements:type_name -> livekit.SessionStatement - 3, // 20: livekit.SessionRow.values:type_name -> livekit.SessionValue - 16, // 21: livekit.SessionRowBatch.rows:type_name -> livekit.SessionRow - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 5, // 19: livekit.SessionBatch.statements:type_name -> livekit.SessionStatement + 17, // 20: livekit.SessionColumnBatch.columns:type_name -> livekit.SessionColumn + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_livekit_agent_session_db_proto_init() } @@ -1576,7 +1712,7 @@ func file_livekit_agent_session_db_proto_init() { file_livekit_agent_session_db_proto_msgTypes[1].OneofWrappers = []any{ (*SessionStoreResponse_HelloOk)(nil), (*SessionStoreResponse_Columns)(nil), - (*SessionStoreResponse_RowBatch)(nil), + (*SessionStoreResponse_ColumnBatch)(nil), (*SessionStoreResponse_ExecResult)(nil), (*SessionStoreResponse_Done)(nil), (*SessionStoreResponse_Error)(nil), @@ -1594,7 +1730,7 @@ func file_livekit_agent_session_db_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_livekit_agent_session_db_proto_rawDesc), len(file_livekit_agent_session_db_proto_rawDesc)), - NumEnums: 1, + NumEnums: 2, NumMessages: 20, NumExtensions: 0, NumServices: 0, diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index 4a69f285d..db735c864 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.35.1 +// protoc v7.34.1 // source: livekit_agent_session_store.proto package livekit @@ -329,7 +329,7 @@ func (x *ListSessionsRequest) GetPageToken() string { type ListSessionsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Sessions []*GetSessionResponse `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` + Sessions []*SessionSummary `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` // empty when exhausted unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -365,7 +365,7 @@ func (*ListSessionsResponse) Descriptor() ([]byte, []int) { return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{5} } -func (x *ListSessionsResponse) GetSessions() []*GetSessionResponse { +func (x *ListSessionsResponse) GetSessions() []*SessionSummary { if x != nil { return x.Sessions } @@ -379,6 +379,89 @@ func (x *ListSessionsResponse) GetNextPageToken() string { return "" } +// SessionSummary is what listing returns: a session's immutable facts. +// +// tip is deliberately absent. It advances on every commit, so it cannot be +// carried in the listing index without putting a write on the commit path, which +// would mean listing reads every session's metadata row forever. It would also +// be stale the moment it was returned, since anything acting on it has to +// re-read. GetSession returns it for a single session. +type SessionSummary struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Region string `protobuf:"bytes,2,opt,name=region,proto3" json:"region,omitempty"` + UserAttributes string `protobuf:"bytes,3,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` + CreatedAtUnix int64 `protobuf:"varint,4,opt,name=created_at_unix,json=createdAtUnix,proto3" json:"created_at_unix,omitempty"` + ExpiresAtUnix int64 `protobuf:"varint,5,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionSummary) Reset() { + *x = SessionSummary{} + mi := &file_livekit_agent_session_store_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionSummary) ProtoMessage() {} + +func (x *SessionSummary) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_session_store_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionSummary.ProtoReflect.Descriptor instead. +func (*SessionSummary) Descriptor() ([]byte, []int) { + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{6} +} + +func (x *SessionSummary) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *SessionSummary) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *SessionSummary) GetUserAttributes() string { + if x != nil { + return x.UserAttributes + } + return "" +} + +func (x *SessionSummary) GetCreatedAtUnix() int64 { + if x != nil { + return x.CreatedAtUnix + } + return 0 +} + +func (x *SessionSummary) GetExpiresAtUnix() int64 { + if x != nil { + return x.ExpiresAtUnix + } + return 0 +} + type DeleteSessionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` @@ -388,7 +471,7 @@ type DeleteSessionRequest struct { func (x *DeleteSessionRequest) Reset() { *x = DeleteSessionRequest{} - mi := &file_livekit_agent_session_store_proto_msgTypes[6] + mi := &file_livekit_agent_session_store_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -400,7 +483,7 @@ func (x *DeleteSessionRequest) String() string { func (*DeleteSessionRequest) ProtoMessage() {} func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_livekit_agent_session_store_proto_msgTypes[6] + mi := &file_livekit_agent_session_store_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -413,7 +496,7 @@ func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteSessionRequest.ProtoReflect.Descriptor instead. func (*DeleteSessionRequest) Descriptor() ([]byte, []int) { - return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{6} + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{7} } func (x *DeleteSessionRequest) GetSessionId() string { @@ -431,7 +514,7 @@ type DeleteSessionResponse struct { func (x *DeleteSessionResponse) Reset() { *x = DeleteSessionResponse{} - mi := &file_livekit_agent_session_store_proto_msgTypes[7] + mi := &file_livekit_agent_session_store_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -443,7 +526,7 @@ func (x *DeleteSessionResponse) String() string { func (*DeleteSessionResponse) ProtoMessage() {} func (x *DeleteSessionResponse) ProtoReflect() protoreflect.Message { - mi := &file_livekit_agent_session_store_proto_msgTypes[7] + mi := &file_livekit_agent_session_store_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -456,7 +539,7 @@ func (x *DeleteSessionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteSessionResponse.ProtoReflect.Descriptor instead. func (*DeleteSessionResponse) Descriptor() ([]byte, []int) { - return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{7} + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{8} } type DumpSessionRequest struct { @@ -468,7 +551,7 @@ type DumpSessionRequest struct { func (x *DumpSessionRequest) Reset() { *x = DumpSessionRequest{} - mi := &file_livekit_agent_session_store_proto_msgTypes[8] + mi := &file_livekit_agent_session_store_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -480,7 +563,7 @@ func (x *DumpSessionRequest) String() string { func (*DumpSessionRequest) ProtoMessage() {} func (x *DumpSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_livekit_agent_session_store_proto_msgTypes[8] + mi := &file_livekit_agent_session_store_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -493,7 +576,7 @@ func (x *DumpSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DumpSessionRequest.ProtoReflect.Descriptor instead. func (*DumpSessionRequest) Descriptor() ([]byte, []int) { - return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{8} + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{9} } func (x *DumpSessionRequest) GetSessionId() string { @@ -514,7 +597,7 @@ type DumpSessionResponse struct { func (x *DumpSessionResponse) Reset() { *x = DumpSessionResponse{} - mi := &file_livekit_agent_session_store_proto_msgTypes[9] + mi := &file_livekit_agent_session_store_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +609,7 @@ func (x *DumpSessionResponse) String() string { func (*DumpSessionResponse) ProtoMessage() {} func (x *DumpSessionResponse) ProtoReflect() protoreflect.Message { - mi := &file_livekit_agent_session_store_proto_msgTypes[9] + mi := &file_livekit_agent_session_store_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +622,7 @@ func (x *DumpSessionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DumpSessionResponse.ProtoReflect.Descriptor instead. func (*DumpSessionResponse) Descriptor() ([]byte, []int) { - return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{9} + return file_livekit_agent_session_store_proto_rawDescGZIP(), []int{10} } func (x *DumpSessionResponse) GetDownloadUrl() string { @@ -591,10 +674,17 @@ const file_livekit_agent_session_store_proto_rawDesc = "" + "\x13ListSessionsRequest\x12\x1b\n" + "\tpage_size\x18\x01 \x01(\x05R\bpageSize\x12\x1d\n" + "\n" + - "page_token\x18\x02 \x01(\tR\tpageToken\"w\n" + - "\x14ListSessionsResponse\x127\n" + - "\bsessions\x18\x01 \x03(\v2\x1b.livekit.GetSessionResponseR\bsessions\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"5\n" + + "page_token\x18\x02 \x01(\tR\tpageToken\"s\n" + + "\x14ListSessionsResponse\x123\n" + + "\bsessions\x18\x01 \x03(\v2\x17.livekit.SessionSummaryR\bsessions\x12&\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\xc0\x01\n" + + "\x0eSessionSummary\x12\x1d\n" + + "\n" + + "session_id\x18\x01 \x01(\tR\tsessionId\x12\x16\n" + + "\x06region\x18\x02 \x01(\tR\x06region\x12'\n" + + "\x0fuser_attributes\x18\x03 \x01(\tR\x0euserAttributes\x12&\n" + + "\x0fcreated_at_unix\x18\x04 \x01(\x03R\rcreatedAtUnix\x12&\n" + + "\x0fexpires_at_unix\x18\x05 \x01(\x03R\rexpiresAtUnix\"5\n" + "\x14DeleteSessionRequest\x12\x1d\n" + "\n" + "session_id\x18\x01 \x01(\tR\tsessionId\"\x17\n" + @@ -626,7 +716,7 @@ func file_livekit_agent_session_store_proto_rawDescGZIP() []byte { return file_livekit_agent_session_store_proto_rawDescData } -var file_livekit_agent_session_store_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_livekit_agent_session_store_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_livekit_agent_session_store_proto_goTypes = []any{ (*CreateSessionRequest)(nil), // 0: livekit.CreateSessionRequest (*CreateSessionResponse)(nil), // 1: livekit.CreateSessionResponse @@ -634,28 +724,29 @@ var file_livekit_agent_session_store_proto_goTypes = []any{ (*GetSessionResponse)(nil), // 3: livekit.GetSessionResponse (*ListSessionsRequest)(nil), // 4: livekit.ListSessionsRequest (*ListSessionsResponse)(nil), // 5: livekit.ListSessionsResponse - (*DeleteSessionRequest)(nil), // 6: livekit.DeleteSessionRequest - (*DeleteSessionResponse)(nil), // 7: livekit.DeleteSessionResponse - (*DumpSessionRequest)(nil), // 8: livekit.DumpSessionRequest - (*DumpSessionResponse)(nil), // 9: livekit.DumpSessionResponse + (*SessionSummary)(nil), // 6: livekit.SessionSummary + (*DeleteSessionRequest)(nil), // 7: livekit.DeleteSessionRequest + (*DeleteSessionResponse)(nil), // 8: livekit.DeleteSessionResponse + (*DumpSessionRequest)(nil), // 9: livekit.DumpSessionRequest + (*DumpSessionResponse)(nil), // 10: livekit.DumpSessionResponse } var file_livekit_agent_session_store_proto_depIdxs = []int32{ - 3, // 0: livekit.ListSessionsResponse.sessions:type_name -> livekit.GetSessionResponse - 0, // 1: livekit.AgentSessionStore.CreateSession:input_type -> livekit.CreateSessionRequest - 2, // 2: livekit.AgentSessionStore.GetSession:input_type -> livekit.GetSessionRequest - 4, // 3: livekit.AgentSessionStore.ListSessions:input_type -> livekit.ListSessionsRequest - 6, // 4: livekit.AgentSessionStore.DeleteSession:input_type -> livekit.DeleteSessionRequest - 8, // 5: livekit.AgentSessionStore.Dump:input_type -> livekit.DumpSessionRequest - 1, // 6: livekit.AgentSessionStore.CreateSession:output_type -> livekit.CreateSessionResponse - 3, // 7: livekit.AgentSessionStore.GetSession:output_type -> livekit.GetSessionResponse - 5, // 8: livekit.AgentSessionStore.ListSessions:output_type -> livekit.ListSessionsResponse - 7, // 9: livekit.AgentSessionStore.DeleteSession:output_type -> livekit.DeleteSessionResponse - 9, // 10: livekit.AgentSessionStore.Dump:output_type -> livekit.DumpSessionResponse - 6, // [6:11] is the sub-list for method output_type - 1, // [1:6] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 6, // 0: livekit.ListSessionsResponse.sessions:type_name -> livekit.SessionSummary + 0, // 1: livekit.AgentSessionStore.CreateSession:input_type -> livekit.CreateSessionRequest + 2, // 2: livekit.AgentSessionStore.GetSession:input_type -> livekit.GetSessionRequest + 4, // 3: livekit.AgentSessionStore.ListSessions:input_type -> livekit.ListSessionsRequest + 7, // 4: livekit.AgentSessionStore.DeleteSession:input_type -> livekit.DeleteSessionRequest + 9, // 5: livekit.AgentSessionStore.Dump:input_type -> livekit.DumpSessionRequest + 1, // 6: livekit.AgentSessionStore.CreateSession:output_type -> livekit.CreateSessionResponse + 3, // 7: livekit.AgentSessionStore.GetSession:output_type -> livekit.GetSessionResponse + 5, // 8: livekit.AgentSessionStore.ListSessions:output_type -> livekit.ListSessionsResponse + 8, // 9: livekit.AgentSessionStore.DeleteSession:output_type -> livekit.DeleteSessionResponse + 10, // 10: livekit.AgentSessionStore.Dump:output_type -> livekit.DumpSessionResponse + 6, // [6:11] is the sub-list for method output_type + 1, // [1:6] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_livekit_agent_session_store_proto_init() } @@ -669,7 +760,7 @@ func file_livekit_agent_session_store_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_livekit_agent_session_store_proto_rawDesc), len(file_livekit_agent_session_store_proto_rawDesc)), NumEnums: 0, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/livekit/livekit_agent_session_store.twirp.go b/livekit/livekit_agent_session_store.twirp.go index 1f70ffb7f..6e602c5ce 100644 --- a/livekit/livekit_agent_session_store.twirp.go +++ b/livekit/livekit_agent_session_store.twirp.go @@ -1642,41 +1642,42 @@ func (s *agentSessionStoreServer) PathPrefix() string { } var twirpFileDescriptor2 = []byte{ - // 567 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdb, 0x6e, 0xd3, 0x40, - 0x10, 0x55, 0xe2, 0x36, 0x34, 0x93, 0xa6, 0xa1, 0xdb, 0x14, 0xa2, 0xb4, 0x81, 0xd4, 0x48, 0x25, - 0x4f, 0xa9, 0x94, 0x0a, 0x21, 0xf5, 0x2d, 0x50, 0x40, 0xa8, 0x55, 0x55, 0x1c, 0xfa, 0xc2, 0x03, - 0x96, 0x13, 0x8f, 0xc2, 0xaa, 0xae, 0xd7, 0x78, 0xc7, 0x6d, 0xd4, 0x4f, 0xe0, 0x53, 0xf8, 0x20, - 0x3e, 0x82, 0xaf, 0x40, 0x5e, 0xaf, 0x9d, 0x9b, 0x7b, 0xe1, 0x2d, 0x3e, 0x73, 0xdb, 0x73, 0xce, - 0x4c, 0x60, 0xcf, 0xe3, 0xd7, 0x78, 0xc9, 0xc9, 0x76, 0xc6, 0xe8, 0x93, 0x2d, 0x51, 0x4a, 0x2e, - 0x7c, 0x5b, 0x92, 0x08, 0xb1, 0x1b, 0x84, 0x82, 0x04, 0x7b, 0xa2, 0x53, 0xcc, 0x09, 0xd4, 0xdf, - 0x87, 0xe8, 0x10, 0x0e, 0x92, 0x2c, 0x0b, 0x7f, 0x46, 0x28, 0x89, 0x3d, 0x83, 0x52, 0x88, 0x63, - 0x2e, 0xfc, 0x46, 0xa1, 0x5d, 0xe8, 0x94, 0x2d, 0xfd, 0xc5, 0x5e, 0x43, 0x2d, 0x92, 0x18, 0xda, - 0x0e, 0x51, 0xc8, 0x87, 0x11, 0xa1, 0x6c, 0x14, 0x55, 0xc2, 0x46, 0x0c, 0xf7, 0x33, 0x94, 0xbd, - 0x84, 0x0a, 0x91, 0x67, 0x4b, 0x1c, 0x09, 0xdf, 0x95, 0x0d, 0xa3, 0x5d, 0xe8, 0x18, 0x16, 0x10, - 0x79, 0x83, 0x04, 0x31, 0xbf, 0xc3, 0xf6, 0xc2, 0x64, 0x19, 0x08, 0x5f, 0x22, 0x6b, 0x01, 0xa4, - 0x4f, 0xe6, 0xae, 0x1e, 0x5f, 0xd6, 0xc8, 0x67, 0x97, 0xed, 0x43, 0x0d, 0x27, 0x01, 0x0f, 0x51, - 0xda, 0x0e, 0xd9, 0x91, 0xcf, 0x27, 0xea, 0x05, 0x86, 0x55, 0xd5, 0x70, 0x9f, 0x2e, 0x7c, 0x3e, - 0x31, 0x7b, 0xb0, 0xf9, 0x09, 0x69, 0x81, 0xd6, 0xfd, 0xbd, 0xcd, 0x3f, 0x05, 0x60, 0xb3, 0x45, - 0x8f, 0x7b, 0xd1, 0x54, 0xab, 0xe2, 0x43, 0x5a, 0x19, 0xb9, 0x5a, 0xed, 0x43, 0x6d, 0xa4, 0xa4, - 0x70, 0x33, 0x4a, 0x2b, 0x09, 0x25, 0x0d, 0x27, 0x94, 0xf2, 0xa8, 0xaf, 0xe6, 0x50, 0x67, 0x4f, - 0xc1, 0x20, 0x1e, 0x34, 0x4a, 0x2a, 0x16, 0xff, 0x34, 0xbf, 0xc0, 0xd6, 0x29, 0x97, 0x29, 0x31, - 0x99, 0xca, 0xb1, 0x03, 0xe5, 0xc0, 0x19, 0xa3, 0x2d, 0xf9, 0x2d, 0x2a, 0x5e, 0xab, 0xd6, 0x5a, - 0x0c, 0x0c, 0xf8, 0xad, 0x62, 0xad, 0x82, 0x24, 0x2e, 0x31, 0xa5, 0xa6, 0xd2, 0xbf, 0xc6, 0x80, - 0x79, 0x03, 0xf5, 0xf9, 0x96, 0x5a, 0xac, 0xb7, 0xb0, 0xa6, 0xa5, 0x91, 0x8d, 0x42, 0xdb, 0xe8, - 0x54, 0x7a, 0x3b, 0x5d, 0xbd, 0x6d, 0xdd, 0x65, 0x6d, 0xad, 0x2c, 0x39, 0x66, 0xe7, 0xe3, 0x84, - 0xec, 0xa5, 0xa1, 0xd5, 0x18, 0x3e, 0xcf, 0x06, 0xbf, 0x81, 0xfa, 0x31, 0x7a, 0xb8, 0xb4, 0xb2, - 0x0f, 0x78, 0xfb, 0x1c, 0xb6, 0x17, 0xca, 0x92, 0x17, 0x98, 0x87, 0xc0, 0x8e, 0xa3, 0xab, 0xe0, - 0xff, 0xba, 0x85, 0xb0, 0x35, 0x57, 0xa4, 0xc9, 0xef, 0xc1, 0xba, 0x2b, 0x6e, 0x7c, 0x4f, 0x38, - 0xae, 0x1d, 0x85, 0x9e, 0xae, 0xab, 0xa4, 0xd8, 0x45, 0xe8, 0x3d, 0x76, 0x7f, 0x53, 0x13, 0x8d, - 0xcc, 0xc4, 0xde, 0x2f, 0x03, 0x36, 0xfb, 0xf1, 0x49, 0xeb, 0xa9, 0x83, 0xf8, 0xa0, 0xd9, 0x19, - 0x54, 0xe7, 0xee, 0x88, 0xb5, 0x32, 0xb9, 0xf3, 0x2e, 0xbb, 0xf9, 0xe2, 0xae, 0xb0, 0xa6, 0xf0, - 0x01, 0x60, 0x6a, 0x13, 0x6b, 0xe6, 0x7a, 0x97, 0x74, 0xba, 0xcf, 0x57, 0x76, 0x02, 0xeb, 0xb3, - 0xeb, 0xc1, 0x76, 0xb3, 0xe4, 0x9c, 0x45, 0x6c, 0xb6, 0xee, 0x88, 0xea, 0x66, 0x67, 0x50, 0x9d, - 0xf3, 0x6e, 0x86, 0x63, 0xde, 0x2a, 0xcc, 0x70, 0xcc, 0xb5, 0x9c, 0xf5, 0x61, 0x25, 0x76, 0x8f, - 0x4d, 0x19, 0x2c, 0x6f, 0x40, 0x73, 0x37, 0x3f, 0x98, 0xb4, 0x78, 0xf7, 0xf1, 0xdb, 0xab, 0x31, - 0xa7, 0x1f, 0xd1, 0xb0, 0x3b, 0x12, 0x57, 0x07, 0x3a, 0xf3, 0x40, 0xfd, 0xbb, 0x8e, 0x84, 0x97, - 0x02, 0xbf, 0x8b, 0xd5, 0x53, 0x7e, 0x8d, 0x27, 0x9c, 0xba, 0xe7, 0x71, 0xe8, 0x6f, 0x71, 0x43, - 0x7f, 0x1f, 0x1d, 0x29, 0x60, 0x58, 0x52, 0x25, 0x87, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x3f, - 0x0b, 0xdd, 0x24, 0xb5, 0x05, 0x00, 0x00, + // 591 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcf, 0x6e, 0xd3, 0x4e, + 0x10, 0x96, 0xe3, 0xb6, 0xbf, 0x66, 0xd2, 0x24, 0xbf, 0x6e, 0x53, 0x1a, 0xa5, 0x0d, 0xa4, 0x46, + 0x2a, 0x39, 0xa5, 0x52, 0x22, 0x2e, 0xbd, 0x05, 0x0a, 0x08, 0xb5, 0xaa, 0x8a, 0x43, 0x2f, 0x1c, + 0xb0, 0x9c, 0x78, 0x14, 0x56, 0x75, 0xbc, 0x66, 0x77, 0x5d, 0x42, 0x1f, 0x81, 0x47, 0xe1, 0x29, + 0x78, 0x0a, 0x1e, 0x82, 0xa7, 0x40, 0x5e, 0xaf, 0x9d, 0x7f, 0x2e, 0x2d, 0x47, 0x6e, 0xf1, 0x37, + 0xdf, 0xcc, 0xee, 0x37, 0xf3, 0xed, 0x04, 0x0e, 0x7d, 0x7a, 0x83, 0xd7, 0x54, 0x3a, 0xee, 0x18, + 0x03, 0xe9, 0x08, 0x14, 0x82, 0xb2, 0xc0, 0x11, 0x92, 0x71, 0xec, 0x84, 0x9c, 0x49, 0x46, 0xfe, + 0xd3, 0x14, 0x6b, 0x0a, 0xb5, 0x97, 0x1c, 0x5d, 0x89, 0x83, 0x84, 0x65, 0xe3, 0xe7, 0x08, 0x85, + 0x24, 0x8f, 0x60, 0x83, 0xe3, 0x98, 0xb2, 0xa0, 0x6e, 0xb4, 0x8c, 0x76, 0xd1, 0xd6, 0x5f, 0xe4, + 0x19, 0x54, 0x23, 0x81, 0xdc, 0x71, 0xa5, 0xe4, 0x74, 0x18, 0x49, 0x14, 0xf5, 0x82, 0x22, 0x54, + 0x62, 0xb8, 0x9f, 0xa1, 0xe4, 0x09, 0x94, 0xa4, 0xf4, 0x1d, 0x81, 0x23, 0x16, 0x78, 0xa2, 0x6e, + 0xb6, 0x8c, 0xb6, 0x69, 0x83, 0x94, 0xfe, 0x20, 0x41, 0xac, 0x8f, 0xb0, 0xbb, 0x74, 0xb2, 0x08, + 0x59, 0x20, 0x90, 0x34, 0x01, 0xd2, 0x2b, 0x53, 0x4f, 0x1f, 0x5f, 0xd4, 0xc8, 0x5b, 0x8f, 0x1c, + 0x41, 0x15, 0xa7, 0x21, 0xe5, 0x28, 0x1c, 0x57, 0x3a, 0x51, 0x40, 0xa7, 0xea, 0x06, 0xa6, 0x5d, + 0xd6, 0x70, 0x5f, 0x5e, 0x05, 0x74, 0x6a, 0x75, 0x61, 0xfb, 0x0d, 0xca, 0x25, 0x59, 0x7f, 0xae, + 0x6d, 0xfd, 0x34, 0x80, 0xcc, 0x27, 0x3d, 0xec, 0x46, 0xb3, 0x5e, 0x15, 0xee, 0xeb, 0x95, 0x99, + 0xdb, 0xab, 0x23, 0xa8, 0x8e, 0x54, 0x2b, 0xbc, 0x4c, 0xd2, 0x5a, 0x22, 0x49, 0xc3, 0x89, 0xa4, + 0x3c, 0xe9, 0xeb, 0x39, 0xd2, 0xc9, 0xff, 0x60, 0x4a, 0x1a, 0xd6, 0x37, 0x54, 0x2c, 0xfe, 0x69, + 0xbd, 0x83, 0x9d, 0x73, 0x2a, 0x52, 0x61, 0x22, 0x6d, 0xc7, 0x3e, 0x14, 0x43, 0x77, 0x8c, 0x8e, + 0xa0, 0xb7, 0xa8, 0x74, 0xad, 0xdb, 0x9b, 0x31, 0x30, 0xa0, 0xb7, 0x4a, 0xb5, 0x0a, 0x4a, 0x76, + 0x8d, 0xa9, 0x34, 0x45, 0x7f, 0x1f, 0x03, 0x96, 0x80, 0xda, 0x62, 0x49, 0xdd, 0xac, 0x1e, 0x6c, + 0xea, 0xd6, 0x88, 0xba, 0xd1, 0x32, 0xdb, 0xa5, 0xee, 0x5e, 0x47, 0xbb, 0xad, 0xa3, 0xc9, 0x83, + 0x68, 0x32, 0x71, 0xf9, 0x57, 0x3b, 0x23, 0xc6, 0xca, 0x02, 0x9c, 0x4a, 0x67, 0xe5, 0xc0, 0x72, + 0x0c, 0x5f, 0x66, 0x87, 0xfe, 0x30, 0xa0, 0xb2, 0x58, 0xe4, 0x5f, 0x1b, 0x8e, 0xf5, 0x1c, 0x6a, + 0xa7, 0xe8, 0xe3, 0xca, 0x8b, 0xbb, 0xc7, 0x9a, 0x7b, 0xb0, 0xbb, 0x94, 0x96, 0xf4, 0xdb, 0xea, + 0x01, 0x39, 0x8d, 0x26, 0xe1, 0xdf, 0x55, 0xe3, 0xb0, 0xb3, 0x90, 0xa4, 0x67, 0x77, 0x08, 0x5b, + 0x1e, 0xfb, 0x12, 0xf8, 0xcc, 0xf5, 0x9c, 0x88, 0xfb, 0x3a, 0xaf, 0x94, 0x62, 0x57, 0xdc, 0x7f, + 0xe8, 0xf3, 0x4b, 0x3d, 0x68, 0x66, 0x1e, 0xec, 0x7e, 0x33, 0x61, 0xbb, 0x1f, 0x6f, 0xa4, 0x74, + 0x80, 0xf1, 0x3e, 0x22, 0x17, 0x50, 0x5e, 0x58, 0x03, 0xa4, 0x99, 0xb9, 0x25, 0x6f, 0x31, 0x35, + 0x1e, 0xdf, 0x15, 0xd6, 0x12, 0x5e, 0x01, 0xcc, 0x5e, 0x30, 0x69, 0x64, 0xec, 0x95, 0x5d, 0xd0, + 0xd8, 0xcf, 0x8d, 0xe9, 0x32, 0x67, 0xb0, 0x35, 0xef, 0x6e, 0x72, 0x90, 0x91, 0x73, 0xde, 0x51, + 0xa3, 0x79, 0x47, 0x54, 0x17, 0xbb, 0x80, 0xf2, 0xc2, 0xec, 0xe6, 0x34, 0xe6, 0x59, 0x61, 0x4e, + 0x63, 0xee, 0xc8, 0x49, 0x1f, 0xd6, 0xe2, 0xe9, 0x91, 0x99, 0x82, 0x55, 0x07, 0x34, 0x0e, 0xf2, + 0x83, 0x49, 0x89, 0x17, 0xaf, 0x3f, 0x3c, 0x1d, 0x53, 0xf9, 0x29, 0x1a, 0x76, 0x46, 0x6c, 0x72, + 0xac, 0x99, 0xc7, 0xea, 0xcf, 0x61, 0xc4, 0xfc, 0x14, 0xf8, 0x5e, 0x28, 0x9f, 0xd3, 0x1b, 0x3c, + 0xa3, 0xb2, 0x73, 0x19, 0x87, 0x7e, 0x15, 0x2a, 0xfa, 0xfb, 0xe4, 0x44, 0x01, 0xc3, 0x0d, 0x95, + 0xd2, 0xfb, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x56, 0xcf, 0x7b, 0x99, 0x74, 0x06, 0x00, 0x00, } diff --git a/protobufs/livekit_agent_session_db.proto b/protobufs/livekit_agent_session_db.proto index 2898aaaca..1648d59ba 100644 --- a/protobufs/livekit_agent_session_db.proto +++ b/protobufs/livekit_agent_session_db.proto @@ -25,7 +25,7 @@ option ruby_package = "LiveKit::Proto"; // frame; requests and responses correlate by request_id (monotonic per // connection, chosen by the client). One WebSocket = one session connection. // -// Flow control: query results stream as SessionRowBatch frames paced by +// Flow control: query results stream as SessionColumnBatch frames paced by // per-request credits (SessionCredit) the client advertises; the server // never sends more un-consumed batches than granted, so any result size // streams with bounded memory at every hop. @@ -35,13 +35,13 @@ message SessionStoreRequest { oneof message { SessionHello hello = 2; // must be first on the socket SessionStatement exec = 3; // no result rows; answers SessionExecResult - SessionStatement query = 4; // answers SessionColumns + SessionRowBatch* + SessionDone + SessionStatement query = 4; // answers SessionColumns + SessionColumnBatch* + SessionDone SessionBatch batch = 5; // atomic multi-statement exec SessionBegin begin = 6; // interactive transaction (server enforces idle/duration timeouts) SessionCommit commit = 7; SessionRollback rollback = 8; SessionCancel cancel = 9; // stop a running query's stream/cursor - SessionCredit credit = 10; // grant more RowBatch credits for request_id + SessionCredit credit = 10; // grant more batch credits for request_id SessionPing ping = 11; } } @@ -51,7 +51,7 @@ message SessionStoreResponse { oneof message { SessionHelloOk hello_ok = 2; SessionColumns columns = 3; - SessionRowBatch row_batch = 4; + SessionColumnBatch column_batch = 4; SessionExecResult exec_result = 5; SessionDone done = 6; SessionStoreError error = 7; @@ -93,7 +93,7 @@ message SessionRollback {} message SessionCancel {} message SessionCredit { - uint32 batches = 1; // additional RowBatch frames the client can absorb + uint32 batches = 1; // additional batch frames the client can absorb } message SessionPing { @@ -120,12 +120,40 @@ message SessionColumns { repeated string names = 1; } -message SessionRow { - repeated SessionValue values = 1; +// SessionValueType tags one value's storage class within a SessionColumn. +enum SessionValueType { + SESSION_VALUE_TYPE_NULL = 0; + SESSION_VALUE_TYPE_INT = 1; + SESSION_VALUE_TYPE_DOUBLE = 2; + SESSION_VALUE_TYPE_TEXT = 3; + SESSION_VALUE_TYPE_BLOB = 4; } -message SessionRowBatch { - repeated SessionRow rows = 1; +// SessionColumn carries one column of a batch, column-oriented so a result set +// costs a handful of allocations per batch rather than two per cell (a message +// plus a oneof wrapper), and so scalar runs land in pointer-free arrays the +// garbage collector never scans. +// +// SQLite types values individually rather than by column, so `types` tags every +// value and each typed array holds only the values of its own class, in row +// order. Reading a column means walking `types` and taking the next entry from +// the matching array; NULLs occupy a tag and nothing else. +message SessionColumn { + bytes types = 1; // one SessionValueType per row, one byte each + repeated sint64 ints = 2; // zigzag, so negative values stay small + repeated double doubles = 3; + // Text and blob values are concatenated with an exclusive end offset each, + // rather than `repeated string`, so a decoder can hand out subslices of one + // buffer instead of copying every value. + bytes text_data = 4; + repeated uint32 text_ends = 5; + bytes blob_data = 6; + repeated uint32 blob_ends = 7; +} + +message SessionColumnBatch { + repeated SessionColumn columns = 1; // one per column of SessionColumns + uint32 rows = 2; } message SessionExecResult { diff --git a/protobufs/livekit_agent_session_store.proto b/protobufs/livekit_agent_session_store.proto index e996fd14c..b3f53dc09 100644 --- a/protobufs/livekit_agent_session_store.proto +++ b/protobufs/livekit_agent_session_store.proto @@ -69,10 +69,25 @@ message ListSessionsRequest { } message ListSessionsResponse { - repeated GetSessionResponse sessions = 1; + repeated SessionSummary sessions = 1; string next_page_token = 2; // empty when exhausted } +// SessionSummary is what listing returns: a session's immutable facts. +// +// tip is deliberately absent. It advances on every commit, so it cannot be +// carried in the listing index without putting a write on the commit path, which +// would mean listing reads every session's metadata row forever. It would also +// be stale the moment it was returned, since anything acting on it has to +// re-read. GetSession returns it for a single session. +message SessionSummary { + string session_id = 1; + string region = 2; + string user_attributes = 3; + int64 created_at_unix = 4; + int64 expires_at_unix = 5; +} + message DeleteSessionRequest { string session_id = 1; } From 6010a1e4d46791e20c5aa974d9a4068e4545bad4 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 22:20:06 +0000 Subject: [PATCH 06/10] generated protobuf --- livekit/livekit_agent_session_db.pb.go | 2 +- livekit/livekit_agent_session_store.pb.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/livekit/livekit_agent_session_db.pb.go b/livekit/livekit_agent_session_db.pb.go index 6256b6f53..a4c92b7c2 100644 --- a/livekit/livekit_agent_session_db.pb.go +++ b/livekit/livekit_agent_session_db.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc v7.35.1 // source: livekit_agent_session_db.proto package livekit diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index db735c864..44df73997 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc v7.35.1 // source: livekit_agent_session_store.proto package livekit From 2b4b7a60070d79d33b5d85483951bcb31ec5166b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Tue, 28 Jul 2026 15:29:07 -0700 Subject: [PATCH 07/10] Rename AgentGrant.SessionAdmin to SessionStoreAdmin An agent session is already a running conversation in this package's vocabulary (agent/livekit_agent_session.proto carries chat messages, function calls and handoffs), so agent.sessionAdmin read as authority over those rather than over the session store's databases, which is what it gates. The store's service is AgentSessionStore, so the grant now matches it. --- auth/grants.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/auth/grants.go b/auth/grants.go index 646bb0689..5d634abdb 100644 --- a/auth/grants.go +++ b/auth/grants.go @@ -581,10 +581,14 @@ type AgentGrant struct { Admin bool `json:"admin,omitempty"` // SimulationAdmin grants access to manage simulations and scenarios for evaluating agents. SimulationAdmin bool `json:"simulationAdmin,omitempty"` - // SessionAdmin grants access to the agent session store: creating, reading, - // querying, exporting and deleting a project's session databases. It gates - // both the management API and the data-plane connection. - SessionAdmin bool `json:"sessionAdmin,omitempty"` + // SessionStoreAdmin grants access to the agent session store: creating, + // reading, querying, exporting and deleting a project's session databases. It + // gates both the management API and the data-plane connection. + // + // Named for the store rather than "session" because an agent session is + // already a running conversation elsewhere in this package's vocabulary (see + // agent/livekit_agent_session.proto), which this has nothing to do with. + SessionStoreAdmin bool `json:"sessionStoreAdmin,omitempty"` } func (s *AgentGrant) Clone() *AgentGrant { @@ -604,7 +608,7 @@ func (s *AgentGrant) MarshalLogObject(e zapcore.ObjectEncoder) error { e.AddBool("Admin", s.Admin) e.AddBool("SimulationAdmin", s.SimulationAdmin) - e.AddBool("SessionAdmin", s.SessionAdmin) + e.AddBool("SessionStoreAdmin", s.SessionStoreAdmin) return nil } From bb404b76daa1d58fc21f3e652ef169ffab52e6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Tue, 28 Jul 2026 15:49:12 -0700 Subject: [PATCH 08/10] Trim comments on the session store protos They carried rationale from the implementation that motivated them, including Go allocation counts, which does not belong in a protocol every SDK reads. What is left states the contract: that values are typed per value rather than per column, how the text and blob offsets address a value, and that a summary has no tip. --- auth/grants.go | 8 +---- livekit/livekit_agent_session_db.pb.go | 23 +++++-------- livekit/livekit_agent_session_store.pb.go | 11 ++---- livekit/livekit_agent_session_store.twirp.go | 12 +++---- protobufs/livekit_agent_session_db.proto | 35 ++++++++------------ protobufs/livekit_agent_session_store.proto | 21 ++++-------- 6 files changed, 35 insertions(+), 75 deletions(-) diff --git a/auth/grants.go b/auth/grants.go index 5d634abdb..ad51d416f 100644 --- a/auth/grants.go +++ b/auth/grants.go @@ -581,13 +581,7 @@ type AgentGrant struct { Admin bool `json:"admin,omitempty"` // SimulationAdmin grants access to manage simulations and scenarios for evaluating agents. SimulationAdmin bool `json:"simulationAdmin,omitempty"` - // SessionStoreAdmin grants access to the agent session store: creating, - // reading, querying, exporting and deleting a project's session databases. It - // gates both the management API and the data-plane connection. - // - // Named for the store rather than "session" because an agent session is - // already a running conversation elsewhere in this package's vocabulary (see - // agent/livekit_agent_session.proto), which this has nothing to do with. + // SessionStoreAdmin grants access to a project's agent session store databases. SessionStoreAdmin bool `json:"sessionStoreAdmin,omitempty"` } diff --git a/livekit/livekit_agent_session_db.pb.go b/livekit/livekit_agent_session_db.pb.go index a4c92b7c2..6383240a0 100644 --- a/livekit/livekit_agent_session_db.pb.go +++ b/livekit/livekit_agent_session_db.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.35.1 +// protoc v7.34.1 // source: livekit_agent_session_db.proto package livekit @@ -1202,23 +1202,16 @@ func (x *SessionColumns) GetNames() []string { return nil } -// SessionColumn carries one column of a batch, column-oriented so a result set -// costs a handful of allocations per batch rather than two per cell (a message -// plus a oneof wrapper), and so scalar runs land in pointer-free arrays the -// garbage collector never scans. -// -// SQLite types values individually rather than by column, so `types` tags every -// value and each typed array holds only the values of its own class, in row -// order. Reading a column means walking `types` and taking the next entry from -// the matching array; NULLs occupy a tag and nothing else. +// SessionColumn is one column of a batch. Values are typed individually, as +// SQLite types them, so a column may mix classes: walk `types` and take the next +// entry from the matching array. A NULL occupies a tag only. type SessionColumn struct { state protoimpl.MessageState `protogen:"open.v1"` - Types []byte `protobuf:"bytes,1,opt,name=types,proto3" json:"types,omitempty"` // one SessionValueType per row, one byte each - Ints []int64 `protobuf:"zigzag64,2,rep,packed,name=ints,proto3" json:"ints,omitempty"` // zigzag, so negative values stay small + Types []byte `protobuf:"bytes,1,opt,name=types,proto3" json:"types,omitempty"` // one SessionValueType per row + Ints []int64 `protobuf:"zigzag64,2,rep,packed,name=ints,proto3" json:"ints,omitempty"` Doubles []float64 `protobuf:"fixed64,3,rep,packed,name=doubles,proto3" json:"doubles,omitempty"` - // Text and blob values are concatenated with an exclusive end offset each, - // rather than `repeated string`, so a decoder can hand out subslices of one - // buffer instead of copying every value. + // Values concatenated, one exclusive end offset each: value i is + // data[ends[i-1]:ends[i]], with 0 implied before the first. TextData []byte `protobuf:"bytes,4,opt,name=text_data,json=textData,proto3" json:"text_data,omitempty"` TextEnds []uint32 `protobuf:"varint,5,rep,packed,name=text_ends,json=textEnds,proto3" json:"text_ends,omitempty"` BlobData []byte `protobuf:"bytes,6,opt,name=blob_data,json=blobData,proto3" json:"blob_data,omitempty"` diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index 44df73997..102edd81c 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.35.1 +// protoc v7.34.1 // source: livekit_agent_session_store.proto package livekit @@ -379,13 +379,8 @@ func (x *ListSessionsResponse) GetNextPageToken() string { return "" } -// SessionSummary is what listing returns: a session's immutable facts. -// -// tip is deliberately absent. It advances on every commit, so it cannot be -// carried in the listing index without putting a write on the commit path, which -// would mean listing reads every session's metadata row forever. It would also -// be stale the moment it was returned, since anything acting on it has to -// re-read. GetSession returns it for a single session. +// SessionSummary is a session's immutable fields. No tip: it changes on every +// commit, so call GetSession for it. type SessionSummary struct { state protoimpl.MessageState `protogen:"open.v1"` SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` diff --git a/livekit/livekit_agent_session_store.twirp.go b/livekit/livekit_agent_session_store.twirp.go index 6e602c5ce..76795a979 100644 --- a/livekit/livekit_agent_session_store.twirp.go +++ b/livekit/livekit_agent_session_store.twirp.go @@ -26,11 +26,9 @@ const _ = twirp.TwirpPackageMinVersion_8_1_0 // AgentSessionStore Interface // =========================== -// AgentSessionStore is the MANAGEMENT plane for per-session SQLite databases: -// lifecycle and export only. All querying goes through the data plane (a -// WebSocket speaking SessionStoreRequest/SessionStoreResponse, defined in -// livekit_agent_session_db.proto). project_id is taken from the authenticated -// principal (access key) on every call, never a request field. +// AgentSessionStore manages per-session SQLite databases: lifecycle and export. +// Querying goes through the data plane in livekit_agent_session_db.proto. The +// project comes from the access token, never from a request field. type AgentSessionStore interface { CreateSession(context.Context, *CreateSessionRequest) (*CreateSessionResponse, error) @@ -41,9 +39,7 @@ type AgentSessionStore interface { // Deletes the stored data too, not just the metadata row. DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) - // Exports a consistent full SQLite database file and returns a time-limited - // download URL (object-storage pre-authenticated request). Runs off the - // serving path; never blocks the session's writes. + // Exports a consistent SQLite file, returning a time-limited download URL. Dump(context.Context, *DumpSessionRequest) (*DumpSessionResponse, error) } diff --git a/protobufs/livekit_agent_session_db.proto b/protobufs/livekit_agent_session_db.proto index 1648d59ba..5ee9a8035 100644 --- a/protobufs/livekit_agent_session_db.proto +++ b/protobufs/livekit_agent_session_db.proto @@ -20,15 +20,13 @@ option go_package = "github.com/livekit/protocol/livekit"; option csharp_namespace = "LiveKit.Proto"; option ruby_package = "LiveKit::Proto"; -// Data plane for AgentSessionStore session databases: a SQL(+openCypher) -// protocol carried over a WebSocket. One binary-protobuf message per WS -// frame; requests and responses correlate by request_id (monotonic per -// connection, chosen by the client). One WebSocket = one session connection. +// Data plane for AgentSessionStore databases: one WebSocket per session, one +// protobuf message per frame, requests and responses correlated by a +// client-chosen request_id. // -// Flow control: query results stream as SessionColumnBatch frames paced by -// per-request credits (SessionCredit) the client advertises; the server -// never sends more un-consumed batches than granted, so any result size -// streams with bounded memory at every hop. +// Query results stream as SessionColumnBatch frames paced by the credits the +// client advertises (SessionCredit): the server never sends more un-consumed +// batches than granted. message SessionStoreRequest { uint32 request_id = 1; @@ -129,22 +127,15 @@ enum SessionValueType { SESSION_VALUE_TYPE_BLOB = 4; } -// SessionColumn carries one column of a batch, column-oriented so a result set -// costs a handful of allocations per batch rather than two per cell (a message -// plus a oneof wrapper), and so scalar runs land in pointer-free arrays the -// garbage collector never scans. -// -// SQLite types values individually rather than by column, so `types` tags every -// value and each typed array holds only the values of its own class, in row -// order. Reading a column means walking `types` and taking the next entry from -// the matching array; NULLs occupy a tag and nothing else. +// SessionColumn is one column of a batch. Values are typed individually, as +// SQLite types them, so a column may mix classes: walk `types` and take the next +// entry from the matching array. A NULL occupies a tag only. message SessionColumn { - bytes types = 1; // one SessionValueType per row, one byte each - repeated sint64 ints = 2; // zigzag, so negative values stay small + bytes types = 1; // one SessionValueType per row + repeated sint64 ints = 2; repeated double doubles = 3; - // Text and blob values are concatenated with an exclusive end offset each, - // rather than `repeated string`, so a decoder can hand out subslices of one - // buffer instead of copying every value. + // Values concatenated, one exclusive end offset each: value i is + // data[ends[i-1]:ends[i]], with 0 implied before the first. bytes text_data = 4; repeated uint32 text_ends = 5; bytes blob_data = 6; diff --git a/protobufs/livekit_agent_session_store.proto b/protobufs/livekit_agent_session_store.proto index b3f53dc09..f346c143e 100644 --- a/protobufs/livekit_agent_session_store.proto +++ b/protobufs/livekit_agent_session_store.proto @@ -20,11 +20,9 @@ option go_package = "github.com/livekit/protocol/livekit"; option csharp_namespace = "LiveKit.Proto"; option ruby_package = "LiveKit::Proto"; -// AgentSessionStore is the MANAGEMENT plane for per-session SQLite databases: -// lifecycle and export only. All querying goes through the data plane (a -// WebSocket speaking SessionStoreRequest/SessionStoreResponse, defined in -// livekit_agent_session_db.proto). project_id is taken from the authenticated -// principal (access key) on every call, never a request field. +// AgentSessionStore manages per-session SQLite databases: lifecycle and export. +// Querying goes through the data plane in livekit_agent_session_db.proto. The +// project comes from the access token, never from a request field. service AgentSessionStore { rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse); rpc GetSession(GetSessionRequest) returns (GetSessionResponse); @@ -33,9 +31,7 @@ service AgentSessionStore { // Deletes the stored data too, not just the metadata row. rpc DeleteSession(DeleteSessionRequest) returns (DeleteSessionResponse); - // Exports a consistent full SQLite database file and returns a time-limited - // download URL (object-storage pre-authenticated request). Runs off the - // serving path; never blocks the session's writes. + // Exports a consistent SQLite file, returning a time-limited download URL. rpc Dump(DumpSessionRequest) returns (DumpSessionResponse); } @@ -73,13 +69,8 @@ message ListSessionsResponse { string next_page_token = 2; // empty when exhausted } -// SessionSummary is what listing returns: a session's immutable facts. -// -// tip is deliberately absent. It advances on every commit, so it cannot be -// carried in the listing index without putting a write on the commit path, which -// would mean listing reads every session's metadata row forever. It would also -// be stale the moment it was returned, since anything acting on it has to -// re-read. GetSession returns it for a single session. +// SessionSummary is a session's immutable fields. No tip: it changes on every +// commit, so call GetSession for it. message SessionSummary { string session_id = 1; string region = 2; From e2795aee776af6a63dabc5399e57062ae26c0303 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 22:50:06 +0000 Subject: [PATCH 09/10] generated protobuf --- livekit/livekit_agent_session_db.pb.go | 2 +- livekit/livekit_agent_session_store.pb.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/livekit/livekit_agent_session_db.pb.go b/livekit/livekit_agent_session_db.pb.go index 6383240a0..8cf5f4ded 100644 --- a/livekit/livekit_agent_session_db.pb.go +++ b/livekit/livekit_agent_session_db.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc v7.35.1 // source: livekit_agent_session_db.proto package livekit diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index 102edd81c..6e9aeb6b1 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc v7.35.1 // source: livekit_agent_session_store.proto package livekit From 17bed51d6b5201566c70f04249421ce6e22b6105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Tue, 28 Jul 2026 17:10:25 -0700 Subject: [PATCH 10/10] agent session store: document unset ttl_seconds as no expiry --- livekit/livekit_agent_session_store.pb.go | 12 ++++++------ protobufs/livekit_agent_session_store.proto | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/livekit/livekit_agent_session_store.pb.go b/livekit/livekit_agent_session_store.pb.go index 6e9aeb6b1..419899987 100644 --- a/livekit/livekit_agent_session_store.pb.go +++ b/livekit/livekit_agent_session_store.pb.go @@ -39,7 +39,7 @@ type CreateSessionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` UserAttributes string `protobuf:"bytes,2,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` // opaque JSON metadata for the caller - TtlSeconds int64 `protobuf:"varint,3,opt,name=ttl_seconds,json=ttlSeconds,proto3" json:"ttl_seconds,omitempty"` // per-session TTL, clamped to a hard max; never extended + TtlSeconds int64 `protobuf:"varint,3,opt,name=ttl_seconds,json=ttlSeconds,proto3" json:"ttl_seconds,omitempty"` // unset: never expires. Otherwise clamped to the server cap, and never extended unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -97,8 +97,8 @@ func (x *CreateSessionRequest) GetTtlSeconds() int64 { type CreateSessionResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // "SESS_..." - ExpiresAtUnix int64 `protobuf:"varint,2,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // "SESS_..." + ExpiresAtUnix int64 `protobuf:"varint,2,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` // 0: never expires unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -197,8 +197,8 @@ type GetSessionResponse struct { Region string `protobuf:"bytes,2,opt,name=region,proto3" json:"region,omitempty"` UserAttributes string `protobuf:"bytes,3,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` CreatedAtUnix int64 `protobuf:"varint,4,opt,name=created_at_unix,json=createdAtUnix,proto3" json:"created_at_unix,omitempty"` - ExpiresAtUnix int64 `protobuf:"varint,5,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` - Tip int64 `protobuf:"varint,6,opt,name=tip,proto3" json:"tip,omitempty"` // latest durable commit sequence + ExpiresAtUnix int64 `protobuf:"varint,5,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` // 0: never expires + Tip int64 `protobuf:"varint,6,opt,name=tip,proto3" json:"tip,omitempty"` // latest durable commit sequence unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -387,7 +387,7 @@ type SessionSummary struct { Region string `protobuf:"bytes,2,opt,name=region,proto3" json:"region,omitempty"` UserAttributes string `protobuf:"bytes,3,opt,name=user_attributes,json=userAttributes,proto3" json:"user_attributes,omitempty"` CreatedAtUnix int64 `protobuf:"varint,4,opt,name=created_at_unix,json=createdAtUnix,proto3" json:"created_at_unix,omitempty"` - ExpiresAtUnix int64 `protobuf:"varint,5,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` + ExpiresAtUnix int64 `protobuf:"varint,5,opt,name=expires_at_unix,json=expiresAtUnix,proto3" json:"expires_at_unix,omitempty"` // 0: never expires unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } diff --git a/protobufs/livekit_agent_session_store.proto b/protobufs/livekit_agent_session_store.proto index f346c143e..69aa3ea3a 100644 --- a/protobufs/livekit_agent_session_store.proto +++ b/protobufs/livekit_agent_session_store.proto @@ -38,12 +38,12 @@ service AgentSessionStore { message CreateSessionRequest { string region = 1; string user_attributes = 2; // opaque JSON metadata for the caller - int64 ttl_seconds = 3; // per-session TTL, clamped to a hard max; never extended + int64 ttl_seconds = 3; // unset: never expires. Otherwise clamped to the server cap, and never extended } message CreateSessionResponse { string session_id = 1; // "SESS_..." - int64 expires_at_unix = 2; + int64 expires_at_unix = 2; // 0: never expires } message GetSessionRequest { @@ -55,7 +55,7 @@ message GetSessionResponse { string region = 2; string user_attributes = 3; int64 created_at_unix = 4; - int64 expires_at_unix = 5; + int64 expires_at_unix = 5; // 0: never expires int64 tip = 6; // latest durable commit sequence } @@ -76,7 +76,7 @@ message SessionSummary { string region = 2; string user_attributes = 3; int64 created_at_unix = 4; - int64 expires_at_unix = 5; + int64 expires_at_unix = 5; // 0: never expires } message DeleteSessionRequest {