@volter/twin-livekit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +106 -0
  3. package/dist/src/cli.d.ts +2 -0
  4. package/dist/src/cli.js +23 -0
  5. package/dist/src/egress-service-cli.d.ts +2 -0
  6. package/dist/src/egress-service-cli.js +101 -0
  7. package/dist/src/index.d.ts +14 -0
  8. package/dist/src/index.js +53 -0
  9. package/dist/src/livekit-budget.d.ts +57 -0
  10. package/dist/src/livekit-budget.js +131 -0
  11. package/dist/src/livekit-capabilities.d.ts +3 -0
  12. package/dist/src/livekit-capabilities.js +728 -0
  13. package/dist/src/livekit-conformance.d.ts +8 -0
  14. package/dist/src/livekit-conformance.js +13 -0
  15. package/dist/src/livekit-connector.d.ts +130 -0
  16. package/dist/src/livekit-connector.js +382 -0
  17. package/dist/src/livekit-data.d.ts +86 -0
  18. package/dist/src/livekit-data.js +246 -0
  19. package/dist/src/livekit-perform-harness.d.ts +5 -0
  20. package/dist/src/livekit-perform-harness.js +17 -0
  21. package/dist/src/livekit-server.d.ts +23 -0
  22. package/dist/src/livekit-server.js +45 -0
  23. package/dist/src/livekit-service-cli.d.ts +2 -0
  24. package/dist/src/livekit-service-cli.js +88 -0
  25. package/dist/src/livekit-token.d.ts +68 -0
  26. package/dist/src/livekit-token.js +76 -0
  27. package/dist/src/livekit-twin.d.ts +4 -0
  28. package/dist/src/livekit-twin.js +1161 -0
  29. package/dist/src/livekit-types.d.ts +203 -0
  30. package/dist/src/livekit-types.js +1 -0
  31. package/dist/src/livekit-webhook.d.ts +26 -0
  32. package/dist/src/livekit-webhook.js +79 -0
  33. package/dist/src/redis-service-cli.d.ts +2 -0
  34. package/dist/src/redis-service-cli.js +35 -0
  35. package/dist/test-fixtures/livekit-openapi-operations.SOURCE.md +88 -0
  36. package/dist/test-fixtures/livekit-openapi-operations.json +442 -0
  37. package/dist/test-fixtures/protobufs/cloud_replay.proto +82 -0
  38. package/dist/test-fixtures/protobufs/livekit_agent.proto +185 -0
  39. package/dist/test-fixtures/protobufs/livekit_agent_dispatch.proto +103 -0
  40. package/dist/test-fixtures/protobufs/livekit_agent_simulation.proto +422 -0
  41. package/dist/test-fixtures/protobufs/livekit_agent_worker.proto +29 -0
  42. package/dist/test-fixtures/protobufs/livekit_agentdb.proto +226 -0
  43. package/dist/test-fixtures/protobufs/livekit_analytics.proto +312 -0
  44. package/dist/test-fixtures/protobufs/livekit_cloud_agent.proto +376 -0
  45. package/dist/test-fixtures/protobufs/livekit_connector.proto +41 -0
  46. package/dist/test-fixtures/protobufs/livekit_connector_twilio.proto +65 -0
  47. package/dist/test-fixtures/protobufs/livekit_connector_whatsapp.proto +171 -0
  48. package/dist/test-fixtures/protobufs/livekit_egress.proto +641 -0
  49. package/dist/test-fixtures/protobufs/livekit_ingress.proto +222 -0
  50. package/dist/test-fixtures/protobufs/livekit_internal.proto +228 -0
  51. package/dist/test-fixtures/protobufs/livekit_metrics.proto +103 -0
  52. package/dist/test-fixtures/protobufs/livekit_models.proto +992 -0
  53. package/dist/test-fixtures/protobufs/livekit_phone_number.proto +151 -0
  54. package/dist/test-fixtures/protobufs/livekit_room.proto +312 -0
  55. package/dist/test-fixtures/protobufs/livekit_rtc.proto +673 -0
  56. package/dist/test-fixtures/protobufs/livekit_sip.proto +1000 -0
  57. package/dist/test-fixtures/protobufs/livekit_token_source.proto +49 -0
  58. package/dist/test-fixtures/protobufs/livekit_webhook.proto +62 -0
  59. package/package.json +58 -0
  60. package/src/cli.ts +22 -0
  61. package/src/egress-service-cli.ts +111 -0
  62. package/src/index.ts +103 -0
  63. package/src/livekit-budget.ts +158 -0
  64. package/src/livekit-capabilities.ts +789 -0
  65. package/src/livekit-conformance.ts +15 -0
  66. package/src/livekit-connector.ts +406 -0
  67. package/src/livekit-data.ts +278 -0
  68. package/src/livekit-perform-harness.ts +17 -0
  69. package/src/livekit-server.ts +67 -0
  70. package/src/livekit-service-cli.ts +93 -0
  71. package/src/livekit-token.ts +133 -0
  72. package/src/livekit-twin.ts +1162 -0
  73. package/src/livekit-types.ts +211 -0
  74. package/src/livekit-webhook.ts +91 -0
  75. package/src/redis-service-cli.ts +39 -0
  76. package/test-fixtures/livekit-openapi-operations.SOURCE.md +88 -0
  77. package/test-fixtures/livekit-openapi-operations.json +442 -0
  78. package/test-fixtures/protobufs/cloud_replay.proto +82 -0
  79. package/test-fixtures/protobufs/livekit_agent.proto +185 -0
  80. package/test-fixtures/protobufs/livekit_agent_dispatch.proto +103 -0
  81. package/test-fixtures/protobufs/livekit_agent_simulation.proto +422 -0
  82. package/test-fixtures/protobufs/livekit_agent_worker.proto +29 -0
  83. package/test-fixtures/protobufs/livekit_agentdb.proto +226 -0
  84. package/test-fixtures/protobufs/livekit_analytics.proto +312 -0
  85. package/test-fixtures/protobufs/livekit_cloud_agent.proto +376 -0
  86. package/test-fixtures/protobufs/livekit_connector.proto +41 -0
  87. package/test-fixtures/protobufs/livekit_connector_twilio.proto +65 -0
  88. package/test-fixtures/protobufs/livekit_connector_whatsapp.proto +171 -0
  89. package/test-fixtures/protobufs/livekit_egress.proto +641 -0
  90. package/test-fixtures/protobufs/livekit_ingress.proto +222 -0
  91. package/test-fixtures/protobufs/livekit_internal.proto +228 -0
  92. package/test-fixtures/protobufs/livekit_metrics.proto +103 -0
  93. package/test-fixtures/protobufs/livekit_models.proto +992 -0
  94. package/test-fixtures/protobufs/livekit_phone_number.proto +151 -0
  95. package/test-fixtures/protobufs/livekit_room.proto +312 -0
  96. package/test-fixtures/protobufs/livekit_rtc.proto +673 -0
  97. package/test-fixtures/protobufs/livekit_sip.proto +1000 -0
  98. package/test-fixtures/protobufs/livekit_token_source.proto +49 -0
  99. package/test-fixtures/protobufs/livekit_webhook.proto +62 -0
@@ -0,0 +1,103 @@
1
+ // Copyright 2023 LiveKit, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ package livekit;
18
+ option go_package = "github.com/livekit/protocol/livekit";
19
+ option csharp_namespace = "LiveKit.Proto";
20
+ option ruby_package = "LiveKit::Proto";
21
+
22
+ import "livekit_agent.proto";
23
+ import "logger/options.proto";
24
+
25
+ enum JobRestartPolicy {
26
+ JRP_ON_FAILURE = 0; // restart when the job fails (default)
27
+ JRP_NEVER = 1; // never restart
28
+ }
29
+
30
+ service AgentDispatchService {
31
+ rpc CreateDispatch(CreateAgentDispatchRequest) returns (AgentDispatch);
32
+ rpc DeleteDispatch(DeleteAgentDispatchRequest) returns (AgentDispatch);
33
+ rpc ListDispatch(ListAgentDispatchRequest) returns (ListAgentDispatchResponse);
34
+ }
35
+
36
+ message CreateAgentDispatchRequest {
37
+ string agent_name = 1;
38
+ string room = 2;
39
+ string metadata = 3 [
40
+ (logger.sensitivity) = SENSITIVITY_PII,
41
+ (logger.redact_format) = "<redacted ({{ .Size }} bytes)>"
42
+ ];
43
+ JobRestartPolicy restart_policy = 4; // cloud only
44
+ string deployment = 5;
45
+ map<string, string> attributes = 6 [
46
+ (logger.sensitivity) = SENSITIVITY_PII,
47
+ (logger.redact_format) = "<redacted ({{ .Size }} bytes)>"
48
+ ];
49
+ }
50
+
51
+ message RoomAgentDispatch {
52
+ string agent_name = 1;
53
+ string metadata = 2 [
54
+ (logger.sensitivity) = SENSITIVITY_PII,
55
+ (logger.redact_format) = "<redacted ({{ .Size }} bytes)>"
56
+ ];
57
+ JobRestartPolicy restart_policy = 3; // cloud only
58
+ string deployment = 4;
59
+ map<string, string> attributes = 5 [
60
+ (logger.sensitivity) = SENSITIVITY_PII,
61
+ (logger.redact_format) = "<redacted ({{ .Size }} bytes)>"
62
+ ];
63
+ }
64
+
65
+ message DeleteAgentDispatchRequest {
66
+ string dispatch_id = 1 [(logger.name) = "dispatchID"];
67
+ string room = 2;
68
+ }
69
+
70
+ message ListAgentDispatchRequest {
71
+ string dispatch_id = 1 [(logger.name) = "dispatchID"]; // if set, only the dispatch whose id is given will be returned
72
+ string room = 2; // name of the room to list agents for. Must be set.
73
+ }
74
+
75
+ message ListAgentDispatchResponse {
76
+ repeated AgentDispatch agent_dispatches = 1;
77
+ }
78
+
79
+ message AgentDispatch {
80
+ string id = 1;
81
+ string agent_name = 2;
82
+ string room = 3;
83
+ string metadata = 4 [
84
+ (logger.sensitivity) = SENSITIVITY_PII,
85
+ (logger.redact_format) = "<redacted ({{ .Size }} bytes)>"
86
+ ];
87
+ AgentDispatchState state = 5;
88
+ JobRestartPolicy restart_policy = 6; // cloud only
89
+ string deployment = 7;
90
+ map<string, string> attributes = 8 [
91
+ (logger.sensitivity) = SENSITIVITY_PII,
92
+ (logger.redact_format) = "<redacted ({{ .Size }} bytes)>"
93
+ ];
94
+ }
95
+
96
+ message AgentDispatchState {
97
+ // For dispatches of tyoe JT_ROOM, there will be at most 1 job.
98
+ // For dispatches of type JT_PUBLISHER, there will be 1 per publisher.
99
+ repeated Job jobs = 1;
100
+ int64 created_at = 2;
101
+ int64 deleted_at = 3;
102
+ }
103
+
@@ -0,0 +1,422 @@
1
+ // Copyright 2024 LiveKit, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ package livekit;
18
+
19
+ import "agent/livekit_agent_session.proto";
20
+ import "google/protobuf/duration.proto";
21
+ import "google/protobuf/timestamp.proto";
22
+ import "livekit_cloud_agent.proto";
23
+ import "livekit_models.proto";
24
+
25
+ option csharp_namespace = "LiveKit.Proto";
26
+ option go_package = "github.com/livekit/protocol/livekit";
27
+ option ruby_package = "LiveKit::Proto";
28
+
29
+ message SimulationRunSummary {
30
+ int32 passed = 1;
31
+ int32 failed = 2;
32
+ string going_well = 3;
33
+ string to_improve = 4;
34
+ repeated Issue issues = 5;
35
+ map<string, livekit.agent.ChatContext> chat_history = 6;
36
+
37
+ message Issue {
38
+ string description = 1;
39
+ string suggestion = 2;
40
+ string label = 3;
41
+ }
42
+ }
43
+
44
+ message SimulationRun {
45
+ enum Status {
46
+ STATUS_PENDING_UPLOAD = 0;
47
+ STATUS_GENERATING = 1;
48
+ STATUS_RUNNING = 2;
49
+ STATUS_SUMMARIZING = 3;
50
+ STATUS_COMPLETED = 4;
51
+ STATUS_FAILED = 5;
52
+ STATUS_CANCELLED = 6;
53
+ }
54
+
55
+ message Job {
56
+ enum Status {
57
+ STATUS_PENDING = 0;
58
+ STATUS_RUNNING = 1;
59
+ STATUS_COMPLETED = 2;
60
+ STATUS_FAILED = 3;
61
+ STATUS_CANCELLED = 4;
62
+ }
63
+ string id = 1;
64
+ Status status = 2;
65
+ string instructions = 3;
66
+ string error = 4;
67
+ string agent_expectations = 5;
68
+ string label = 6;
69
+ repeated string tags = 7;
70
+ string room_name = 8;
71
+ reserved 9; // was scenario_id (scenarios are no longer stored)
72
+ google.protobuf.Timestamp started_at = 10;
73
+ google.protobuf.Timestamp ended_at = 11;
74
+ string room_id = 12;
75
+ Usage usage = 13;
76
+ // Quality metrics for this job's call. Unset when the job produced none.
77
+ JobMetrics metrics = 14;
78
+
79
+ message Usage {
80
+ int32 text_turns_count = 1;
81
+ int32 audio_turns_count = 2;
82
+ }
83
+ }
84
+
85
+ message JobMetrics {
86
+ // Headline scores, 0-1. All absent when the simulator spoiled the call.
87
+ optional float accuracy_score = 1;
88
+ optional float experience_score = 2;
89
+ optional float task_completion = 3; // the scenario verdict as 1/0
90
+
91
+ STT stt = 4;
92
+ LLM llm = 5;
93
+ TTS tts = 6;
94
+ Conversation conversation = 7;
95
+
96
+ // One entry per turn, both speakers.
97
+ repeated Turn turns = 9;
98
+
99
+ string judge_model = 10; // text judge for judged scores; "" if none ran
100
+ bool has_remote_session = 12; // false = waveform-only capture (e.g. SIP)
101
+ google.protobuf.Timestamp t0 = 13; // audio only; call start (first speech edge); turn times relative to it
102
+
103
+ // Judged over the authored dialog (text and audio); needs the text judge.
104
+ optional float conciseness = 14; // judged {0, 0.5, 1} per agent turn; job = mean
105
+ // Whole-call issue flags; true = present, absent = not judged.
106
+ optional bool unnecessary_tool_calls = 15;
107
+ optional bool information_loss = 16;
108
+ optional bool redundant_statements = 17;
109
+ optional bool poor_question_quality = 18;
110
+ optional float conversation_progression = 19; // 0-1, derived from the flags above
111
+
112
+ // The agent's perception of the caller. Audio only.
113
+ message STT {
114
+ optional float wer = 1; // needs the RemoteSession; word_errors / words
115
+ optional uint32 words = 2; // needs the RemoteSession
116
+ optional uint32 word_errors = 3; // needs the RemoteSession
117
+ optional float cer = 4; // needs the RemoteSession; char_errors / chars
118
+ optional uint32 chars = 9; // needs the RemoteSession
119
+ optional uint32 char_errors = 10; // needs the RemoteSession
120
+ optional uint32 stt_delay_ms = 8; // needs the RemoteSession; agent-reported STT/endpointing delay
121
+
122
+ // Key entities (names, IDs, amounts) the caller said. Needs the text judge.
123
+ optional float entity_recognition = 11; // recognized / uttered
124
+ optional uint32 entities_uttered = 12;
125
+ optional uint32 entities_recognized = 13;
126
+ // Retention: an entity is acquired at the first saying heard right, and
127
+ // these count only the sayings after that, so recall separates keeping an
128
+ // entity from ever getting it.
129
+ optional float entity_recall = 14; // acquired_recognized / acquired_uttered
130
+ optional uint32 entities_acquired_uttered = 15;
131
+ optional uint32 entities_acquired_recognized = 16;
132
+ }
133
+
134
+ message LLM {
135
+ optional uint32 ttft_ms = 1; // needs the RemoteSession; time to first token
136
+ optional uint32 ttfs_ms = 2; // needs the RemoteSession; time to first sentence, the smallest speakable unit
137
+ optional float tokens_per_second = 3; // needs the RemoteSession
138
+ }
139
+
140
+ // The agent's voice. Audio only.
141
+ message TTS {
142
+ optional uint32 ttfb_ms = 2; // needs the RemoteSession; provider byte-level TTFB
143
+ optional float wer = 3; // needs the RemoteSession; word_errors / words
144
+ optional uint32 words = 7; // needs the RemoteSession
145
+ optional uint32 word_errors = 8; // needs the RemoteSession
146
+ optional float cer = 9; // needs the RemoteSession; char_errors / chars
147
+ optional uint32 chars = 10; // needs the RemoteSession
148
+ optional uint32 char_errors = 11; // needs the RemoteSession
149
+
150
+ // Key entities the agent said, as the caller heard them. Needs the text judge.
151
+ optional float entity_recognition = 14; // recognized / uttered
152
+ optional uint32 entities_uttered = 15;
153
+ optional uint32 entities_recognized = 16;
154
+ optional float entity_recall = 17; // acquired_recognized / acquired_uttered
155
+ optional uint32 entities_acquired_uttered = 18;
156
+ optional uint32 entities_acquired_recognized = 19;
157
+ }
158
+
159
+ // Audio only.
160
+ message Conversation {
161
+ optional float turn_taking_score = 1; // 0-1
162
+ optional int32 heard_e2e_latency_p50_ms = 2; // floor-transfer offset; a gap is > 0, an overlap < 0
163
+ optional int32 heard_e2e_latency_p95_ms = 3;
164
+ optional int32 heard_e2e_latency_p99_ms = 4;
165
+ optional uint32 time_to_yield_ms = 5; // agent audio continuing past a barge-in
166
+ optional uint32 eot_misprediction_count = 6; // agent started before the caller's turn ended
167
+ optional float overlap_ratio = 7; // overlapping speech / total speech
168
+ optional uint32 overlap_speech_ms = 8; // pooling stats for overlap_ratio
169
+ optional uint32 total_speech_ms = 9;
170
+ optional uint32 awkward_silence_count = 11; // gaps past the natural-pause threshold
171
+ optional uint32 unanswered_turns = 12; // the simulated party spoke, the agent never responded
172
+ optional uint32 false_interruption_count = 13; // needs the RemoteSession; agent paused for a non-interruption
173
+ optional uint32 e2e_latency_ms = 15; // needs the RemoteSession; the agent's own claim
174
+ }
175
+
176
+ // Rows exist for text and audio. The groups above hold the means and pools
177
+ // over these; anything not measured for a turn stays unset.
178
+ message Turn {
179
+ uint32 index = 1; // 1-based, conversation order
180
+ livekit.agent.ChatRole role = 2; // ASSISTANT = the agent under test, USER = simulator persona
181
+ optional uint32 start_ms = 3; // audio only; relative to t0; unset if the turn could not be aligned to the audio
182
+ optional uint32 end_ms = 4; // audio only
183
+
184
+ optional uint32 stt_delay_ms = 5; // needs the RemoteSession
185
+ optional uint32 llm_ttft_ms = 6; // needs the RemoteSession
186
+ optional uint32 llm_ttfs_ms = 7; // needs the RemoteSession
187
+ optional float llm_tps = 8; // needs the RemoteSession
188
+ optional uint32 tts_ttfb_ms = 9; // needs the RemoteSession
189
+ optional uint32 e2e_latency_ms = 10; // needs the RemoteSession
190
+
191
+ optional int32 heard_e2e_latency_ms = 11;
192
+ optional uint32 time_to_yield_ms = 12;
193
+ optional float turn_taking_score = 13;
194
+ optional float conciseness = 14; // needs the text judge
195
+
196
+ optional bool eot_misprediction = 15;
197
+ optional bool awkward_silence = 16;
198
+ optional bool unanswered = 17;
199
+ }
200
+ }
201
+
202
+ // Aggregates over this run's jobs, so a run summary does not have to pull
203
+ // every job and turn. Reuses the JobMetrics group shapes.
204
+ message RunMetrics {
205
+ optional float accuracy_score = 1; // mean over scored jobs
206
+ optional float experience_score = 2;
207
+ optional float scenario_pass_rate = 3; // share of jobs whose scenario verdict passed
208
+
209
+ JobMetrics.STT stt = 4;
210
+ JobMetrics.LLM llm = 5;
211
+ JobMetrics.TTS tts = 6;
212
+ JobMetrics.Conversation conversation = 7;
213
+
214
+ // Means over the jobs that report them.
215
+ optional float conciseness = 8;
216
+ optional float conversation_progression = 9;
217
+ }
218
+
219
+ message Create {
220
+ message Request {
221
+ reserved 3; // was agent_description (input never consumed; description is derived from source)
222
+ reserved "agent_description";
223
+ string project_id = 1;
224
+ string agent_name = 2;
225
+ int32 num_simulations = 4;
226
+ string region = 6;
227
+
228
+ // When set, run these scenarios (loaded from a scenarios.yaml).
229
+ // When unset, generate num_simulations scenarios from the uploaded agent source.
230
+ optional ScenarioGroup scenario_group = 7;
231
+
232
+ // Maximum simulate jobs running in parallel for this run. Clamped to the
233
+ // project's concurrency quota; 0/unset uses the server default.
234
+ optional int32 concurrency = 8;
235
+
236
+ // Conversation mode for every job in this run; unspecified = TEXT.
237
+ SimulationMode mode = 9;
238
+
239
+ // Impairments applied to the simulated user's audio; AUDIO mode only.
240
+ bool background_noise = 10;
241
+ bool low_quality_microphone = 11;
242
+ bool packet_loss = 12;
243
+ }
244
+ message Response {
245
+ string simulation_run_id = 1;
246
+ PresignedPostRequest presigned_post_request = 2;
247
+ }
248
+ }
249
+
250
+ message ConfirmSourceUpload {
251
+ message Request {
252
+ string project_id = 1;
253
+ string simulation_run_id = 2;
254
+ string code_entrypoint = 3;
255
+ }
256
+ message Response {}
257
+ }
258
+
259
+ message Get {
260
+ message Request {
261
+ string project_id = 1;
262
+ string simulation_run_id = 2;
263
+ }
264
+ message Response {
265
+ SimulationRun run = 1;
266
+ }
267
+ }
268
+
269
+ message List {
270
+ message Request {
271
+ string project_id = 1;
272
+ optional Status status = 2;
273
+ optional TokenPagination page_token = 3;
274
+ // Half-open window [start_time, end_time) on created_at, the leading key
275
+ // of this list's keyset. Unset bounds mean no window, so existing callers
276
+ // keep their unbounded scan; the histogram's selected range sets both.
277
+ optional google.protobuf.Timestamp start_time = 4;
278
+ optional google.protobuf.Timestamp end_time = 5;
279
+ // Exact agent name. Unset means every agent — including the runs whose
280
+ // name is empty, which a bare string could not tell from no filter.
281
+ optional string agent_name = 6;
282
+ // Absent applies no mode filter. TEXT matches runs stored as TEXT or
283
+ // UNSPECIFIED, which `SimulationRun.mode` defines as the same mode.
284
+ optional SimulationMode mode = 7;
285
+ }
286
+ message Response {
287
+ repeated SimulationRun runs = 1;
288
+ TokenPagination next_page_token = 2;
289
+ }
290
+ }
291
+
292
+ // Counts of the runs `List` would return over the same window, bucketed by
293
+ // created_at instead of paginated.
294
+ message Counts {
295
+ message Request {
296
+ string project_id = 1;
297
+ // Both bounds required: a bucketed scan of a project's whole history is
298
+ // never what a caller wants.
299
+ google.protobuf.Timestamp start_time = 2;
300
+ google.protobuf.Timestamp end_time = 3;
301
+ // Applied as `List` applies it: a filter the rows honour and the bars
302
+ // above them drop would make the histogram an answer about a wider set.
303
+ optional Status status = 4;
304
+ optional string agent_name = 5;
305
+ optional SimulationMode mode = 6;
306
+ }
307
+ message Response {
308
+ // Buckets holding at least one run, ascending by bucket_start. Empty
309
+ // buckets are omitted; each run lands in exactly one bucket, so the
310
+ // counts sum to the number of runs in the window.
311
+ repeated Bucket buckets = 1;
312
+ // The bucket width the server chose from the window, so the client
313
+ // zero-fills the omitted buckets on the grid the counts were built on.
314
+ google.protobuf.Duration interval = 2;
315
+ }
316
+ message Bucket {
317
+ google.protobuf.Timestamp bucket_start = 1;
318
+ uint64 count = 2;
319
+ }
320
+ }
321
+
322
+ message Cancel {
323
+ message Request {
324
+ string project_id = 1;
325
+ string simulation_run_id = 2;
326
+ }
327
+ message Response {}
328
+ }
329
+
330
+ string id = 1;
331
+ string project_id = 2;
332
+ Status status = 3;
333
+ string agent_description = 4;
334
+ string error = 5;
335
+ google.protobuf.Timestamp created_at = 6;
336
+ repeated Job jobs = 7;
337
+ // was: SimulationRunSummary summary (replaced by summary_zstd)
338
+ reserved 8;
339
+ reserved "summary";
340
+ string agent_name = 9;
341
+ ScenarioGroup scenario_group = 10;
342
+ google.protobuf.Timestamp ended_at = 11;
343
+ int32 job_count = 12;
344
+ int32 passed_count = 13;
345
+ int32 failed_count = 14;
346
+ int32 num_simulations = 15;
347
+ // Aggregate usage across all jobs in this run (sum of Job.usage).
348
+ Usage usage = 16;
349
+ // Maximum simulate jobs running in parallel for this run (0 = server default).
350
+ int32 concurrency = 17;
351
+ // Conversation mode for every job in this run; unspecified = TEXT.
352
+ SimulationMode mode = 18;
353
+ // Run-level aggregates over this run's jobs.
354
+ RunMetrics metrics = 19;
355
+ // zstd-compressed SimulationRunSummary: decompress, then proto.Unmarshal.
356
+ // Compressed by default so the blob ships as-is on every hop.
357
+ bytes summary_zstd = 20;
358
+
359
+ message Usage {
360
+ int32 text_turns_count = 1;
361
+ int32 audio_turns_count = 2;
362
+ }
363
+ }
364
+
365
+ // A single scenario, mirroring one entry in a scenarios.yaml file. Scenarios
366
+ // are no longer stored server-side; the yaml file is the source of truth.
367
+ message Scenario {
368
+ message CreateFromSession {
369
+ message Request {
370
+ string project_id = 1;
371
+ string room_id = 2;
372
+ string region = 3;
373
+ }
374
+ message Response {
375
+ Scenario scenario = 1;
376
+ }
377
+ }
378
+
379
+ string label = 1;
380
+ string instructions = 2;
381
+ string agent_expectations = 3;
382
+ // Set as participant attributes on the simulation participant's access token.
383
+ map<string, string> tags = 4;
384
+ // Arbitrary JSON-encoded object, surfaced to the agent under test as
385
+ // SimulationContext userdata (e.g. inputs and benchmark target state).
386
+ string userdata = 5;
387
+ }
388
+
389
+ // A named group of scenarios, mirroring a whole scenarios.yaml file.
390
+ message ScenarioGroup {
391
+ string name = 1;
392
+ repeated Scenario scenarios = 2;
393
+ }
394
+
395
+ // How the simulated user interacts with the agent under test.
396
+ enum SimulationMode {
397
+ SIMULATION_MODE_UNSPECIFIED = 0;
398
+ // The simulator chats over text streams (no audio).
399
+ SIMULATION_MODE_TEXT = 1;
400
+ // The simulator publishes/subscribes audio in the room.
401
+ SIMULATION_MODE_AUDIO = 2;
402
+ }
403
+
404
+ // Carried (protojson-encoded) in the simulation room's metadata so the agent
405
+ // under test can read the scenario + run identity synchronously at connect.
406
+ message SimulationDispatch {
407
+ string simulation_run_id = 1;
408
+ string job_id = 2;
409
+ Scenario scenario = 3;
410
+ SimulationMode mode = 4;
411
+ }
412
+
413
+ service AgentSimulation {
414
+ rpc CreateSimulationRun(SimulationRun.Create.Request) returns (SimulationRun.Create.Response);
415
+ rpc ConfirmSimulationSourceUpload(SimulationRun.ConfirmSourceUpload.Request) returns (SimulationRun.ConfirmSourceUpload.Response);
416
+ rpc GetSimulationRun(SimulationRun.Get.Request) returns (SimulationRun.Get.Response);
417
+ rpc ListSimulationRuns(SimulationRun.List.Request) returns (SimulationRun.List.Response);
418
+ rpc CountSimulationRuns(SimulationRun.Counts.Request) returns (SimulationRun.Counts.Response);
419
+ rpc CancelSimulationRun(SimulationRun.Cancel.Request) returns (SimulationRun.Cancel.Response);
420
+
421
+ rpc CreateScenarioFromSession(Scenario.CreateFromSession.Request) returns (Scenario.CreateFromSession.Response);
422
+ }
@@ -0,0 +1,29 @@
1
+ // Copyright 2023 LiveKit, Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ package livekit;
18
+ option go_package = "github.com/livekit/protocol/livekit";
19
+ option csharp_namespace = "LiveKit.Proto";
20
+ option ruby_package = "LiveKit::Proto";
21
+
22
+ message WorkerInfo {
23
+ string worker_type = 1;
24
+ string agent_name = 2;
25
+ float active_jobs = 3;
26
+ string sdk_version = 4;
27
+ float worker_load = 5;
28
+ int32 protocol_version = 6;
29
+ }