@ancplua/qyl-api-schema 11.6.0 → 12.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.
@@ -0,0 +1,1108 @@
1
+ import "./mcp-tools.tsp";
2
+ import "../common/telemetry-query.tsp";
3
+ using TypeSpec.OpenAPI;
4
+ using Qyl.Api.Contracts.Common;
5
+ using Qyl.Api.Contracts.Annotations;
6
+ using Qyl.Api.Contracts.OTel.Traces;
7
+ using Qyl.Api.Contracts.OTel.Metrics;
8
+ using Qyl.Api.Contracts.Domains.Observe.Session;
9
+ using Qyl.Api.Contracts.OTel.Logs;
10
+ namespace Qyl.Api.Contracts.Mcp.Tools;
11
+
12
+ @doc("Persisted failure triage status.")
13
+ enum FailureStatus { open, resolved, ignored }
14
+
15
+ @doc("Filter for failure status.")
16
+ union FailureStatusFilter { status: FailureStatus, all: "all" }
17
+
18
+ @doc("Failure trend in the selected comparison window.")
19
+ enum FailureChange { new, worsening, ongoing, recovering, regressed }
20
+
21
+ @doc("Explicit baseline window or an offset from the selected window.")
22
+ union AnalysisBaseline { previous: "previous_window", window: ToolWindow, offset: BaselineOffset }
23
+
24
+ @doc("MCP comparison window or deployed server version.")
25
+ union McpStatsComparison { previous: "previous_window", offset: McpComparisonOffset, version: McpComparisonVersion, versionText: string }
26
+
27
+ @doc("Metric comparison preceding the selected window.")
28
+ union MetricComparison { previous: "previous_window", offset: MetricComparisonOffset }
29
+
30
+ @doc("AnalysisInput contract.")
31
+ model AnalysisInput {
32
+ ...ToolTimeRange;
33
+ @maxItems(32)
34
+ matchers?: TelemetryMatcher[];
35
+ @minValue(1) @maxValue(200)
36
+ limit?: int32;
37
+ cursor?: Cursor;
38
+ }
39
+
40
+ @doc("ServiceAnalysisInput contract.")
41
+ model ServiceAnalysisInput {
42
+ ...AnalysisInput;
43
+ @encodedName("application/json", "service_name")
44
+ serviceName?: string;
45
+ environment?: string;
46
+ }
47
+
48
+ @doc("BaselineOffset contract.")
49
+ model BaselineOffset {
50
+ @encodedName("application/json", "offset_minutes")
51
+ offsetMinutes: int32;
52
+ }
53
+
54
+ @doc("FailureRelease contract.")
55
+ model FailureRelease {
56
+ service: string;
57
+ version: string;
58
+ @encodedName("application/json", "first_seen")
59
+ firstSeen: utcDateTime;
60
+ revision?: string;
61
+ }
62
+
63
+ @doc("FailureOccurrence contract.")
64
+ model FailureOccurrence {
65
+ @encodedName("application/json", "trace_id")
66
+ traceId: TraceId;
67
+ @encodedName("application/json", "span_id")
68
+ spanId: SpanId;
69
+ @encodedName("application/json", "session_id")
70
+ sessionId?: SessionId;
71
+ timestamp: utcDateTime;
72
+ message?: string;
73
+ release?: string;
74
+ }
75
+
76
+ @doc("FailureReleaseCount contract.")
77
+ model FailureReleaseCount {
78
+ release: string;
79
+ count: int64;
80
+ }
81
+
82
+ @doc("AttributeAssociation contract.")
83
+ model AttributeAssociation {
84
+ key: string;
85
+ value: MatcherValue;
86
+ @encodedName("application/json", "share_a")
87
+ shareA: float64;
88
+ @encodedName("application/json", "share_b")
89
+ shareB: float64;
90
+ @encodedName("application/json", "count_a")
91
+ countA: int64;
92
+ @encodedName("application/json", "count_b")
93
+ countB: int64;
94
+ lift: float64 | null;
95
+ }
96
+
97
+ @doc("FailureSummary contract.")
98
+ model FailureSummary {
99
+ @encodedName("application/json", "failure_id")
100
+ failureId: FailureId;
101
+ etag: ETag;
102
+ signature: string;
103
+ @encodedName("application/json", "exception_type")
104
+ exceptionType?: string;
105
+ @encodedName("application/json", "normalized_message")
106
+ normalizedMessage: string;
107
+ operation: string;
108
+ service: string;
109
+ @encodedName("application/json", "first_seen")
110
+ firstSeen: utcDateTime;
111
+ @encodedName("application/json", "last_seen")
112
+ lastSeen: utcDateTime;
113
+ count: int64;
114
+ @encodedName("application/json", "affected_traces")
115
+ affectedTraces: int64;
116
+ @encodedName("application/json", "affected_sessions")
117
+ affectedSessions: int64;
118
+ @encodedName("application/json", "releases_seen")
119
+ releasesSeen: string[];
120
+ status: FailureStatus;
121
+ @encodedName("application/json", "ignore_until")
122
+ ignoreUntil?: utcDateTime;
123
+ assignee?: string;
124
+ @encodedName("application/json", "annotation_count")
125
+ annotationCount: int64;
126
+ @maxItems(3)
127
+ @encodedName("application/json", "example_trace_ids")
128
+ exampleTraceIds: TraceId[];
129
+ }
130
+
131
+ @doc("FailureDetail contract.")
132
+ model FailureDetail {
133
+ ...FailureSummary;
134
+ @encodedName("application/json", "counts_per_release")
135
+ countsPerRelease?: FailureReleaseCount[];
136
+ discriminators?: AttributeAssociation[];
137
+ @encodedName("application/json", "recent_occurrences")
138
+ recentOccurrences?: FailureOccurrence[];
139
+ @encodedName("application/json", "raw_messages")
140
+ rawMessages?: string[];
141
+ }
142
+
143
+ @doc("TriageInput contract.")
144
+ model TriageInput {
145
+ ...ServiceAnalysisInput;
146
+ baseline?: AnalysisBaseline;
147
+ }
148
+
149
+ @doc("TriageFailure contract.")
150
+ model TriageFailure {
151
+ @encodedName("application/json", "failure_id")
152
+ failureId: FailureId;
153
+ signature: string;
154
+ change: FailureChange;
155
+ count: int64;
156
+ @encodedName("application/json", "baseline_count")
157
+ baselineCount: int64;
158
+ @encodedName("application/json", "affected_traces")
159
+ affectedTraces: int64;
160
+ services: string[];
161
+ @encodedName("application/json", "first_seen")
162
+ firstSeen: utcDateTime;
163
+ @encodedName("application/json", "example_trace_id")
164
+ exampleTraceId?: TraceId;
165
+ @encodedName("application/json", "coinciding_release")
166
+ coincidingRelease?: FailureRelease;
167
+ }
168
+
169
+ @doc("TriageRegression contract.")
170
+ model TriageRegression {
171
+ service: string;
172
+ operation: string;
173
+ measure: "error_rate" | "p95_ms" | "throughput";
174
+ value: float64;
175
+ @encodedName("application/json", "baseline_value")
176
+ baselineValue: float64;
177
+ denominator: int64;
178
+ unit: string;
179
+ }
180
+
181
+ @doc("SilentService contract.")
182
+ model SilentService {
183
+ service: string;
184
+ @encodedName("application/json", "last_seen")
185
+ lastSeen: utcDateTime;
186
+ @encodedName("application/json", "usual_rate")
187
+ usualRate: float64 | null;
188
+ unit: string;
189
+ }
190
+
191
+ @doc("TriageOutput contract.")
192
+ model TriageOutput {
193
+ ...ToolReadContext;
194
+ failures: TriageFailure[];
195
+ regressions: TriageRegression[];
196
+ releases: FailureRelease[];
197
+ @encodedName("application/json", "silent_services")
198
+ silentServices: SilentService[];
199
+ error?: ToolError;
200
+ }
201
+
202
+ @doc("ListFailuresInput contract.")
203
+ model ListFailuresInput {
204
+ ...ServiceAnalysisInput;
205
+ release?: string;
206
+ status?: FailureStatusFilter;
207
+ @encodedName("application/json", "sort_by")
208
+ sortBy?: "count" | "last_seen" | "first_seen" | "affected_traces";
209
+ @encodedName("application/json", "failure_id")
210
+ failureId?: FailureId;
211
+ }
212
+
213
+ @doc("ListFailuresOutput contract.")
214
+ model ListFailuresOutput {
215
+ ...ToolReadContext;
216
+ ...ToolPage;
217
+ failures: FailureDetail[];
218
+ error?: ToolError;
219
+ }
220
+
221
+ @doc("GetFailureContextInput contract.")
222
+ model GetFailureContextInput {
223
+ ...AnalysisInput;
224
+ @encodedName("application/json", "trace_id")
225
+ traceId?: TraceId;
226
+ @encodedName("application/json", "session_id")
227
+ sessionId?: SessionId;
228
+ @encodedName("application/json", "failure_id")
229
+ failureId?: FailureId;
230
+ @encodedName("application/json", "ci_run_id")
231
+ ciRunId?: SessionId;
232
+ @minValue(1) @maxValue(1000)
233
+ @encodedName("application/json", "max_spans")
234
+ maxSpans?: int32;
235
+ @minValue(1) @maxValue(200)
236
+ @encodedName("application/json", "max_logs")
237
+ maxLogs?: int32;
238
+ }
239
+
240
+ @doc("EvidenceSpan contract.")
241
+ model EvidenceSpan {
242
+ @encodedName("application/json", "start_time")
243
+ startTime?: utcDateTime;
244
+ @encodedName("application/json", "end_time")
245
+ endTime?: utcDateTime;
246
+
247
+ @encodedName("application/json", "trace_id")
248
+ traceId: TraceId;
249
+ @encodedName("application/json", "span_id")
250
+ spanId: SpanId;
251
+ @encodedName("application/json", "parent_span_id")
252
+ parentSpanId?: SpanId;
253
+ @encodedName("application/json", "session_id")
254
+ sessionId?: SessionId;
255
+ service: string;
256
+ name: string;
257
+ status: string;
258
+ @encodedName("application/json", "status_message")
259
+ statusMessage?: string;
260
+ exception?: RecordedException;
261
+ @encodedName("application/json", "key_attributes")
262
+ keyAttributes: Attribute[];
263
+ @encodedName("application/json", "duration_ms")
264
+ durationMs: DurationMs;
265
+ role: "matched" | "context";
266
+ }
267
+
268
+ @doc("RecordedException contract.")
269
+ model RecordedException {
270
+ type?: string;
271
+ message?: string;
272
+ stacktrace?: string;
273
+ }
274
+
275
+ @doc("FailurePropagation contract.")
276
+ model FailurePropagation {
277
+ from: EvidenceSpan;
278
+ to: EvidenceSpan;
279
+ }
280
+
281
+ @doc("RetryEvidence contract.")
282
+ model RetryEvidence {
283
+ name: string;
284
+ attempts: int32;
285
+ spans: EvidenceSpan[];
286
+ }
287
+
288
+ @doc("FanoutEvidence contract.")
289
+ model FanoutEvidence {
290
+ name: string;
291
+ count: int32;
292
+ @encodedName("application/json", "parent_span_id")
293
+ parentSpanId?: SpanId;
294
+ @encodedName("application/json", "trace_id")
295
+ traceId: TraceId;
296
+ }
297
+
298
+ @doc("FailureObserved contract.")
299
+ model FailureObserved {
300
+ @encodedName("application/json", "root_cause_span")
301
+ rootCauseSpan: EvidenceSpan | null;
302
+ @encodedName("application/json", "error_spans")
303
+ errorSpans: EvidenceSpan[];
304
+ propagation: FailurePropagation[];
305
+ logs: LogRecord[];
306
+ retries: RetryEvidence[];
307
+ fanout: FanoutEvidence[];
308
+ }
309
+
310
+ @doc("TraceDivergence contract.")
311
+ model TraceDivergence {
312
+ @encodedName("application/json", "a_span")
313
+ aSpan: EvidenceSpan | null;
314
+ @encodedName("application/json", "b_span")
315
+ bSpan: EvidenceSpan | null;
316
+ kind: "missing" | "extra" | "status" | "attribute" | "duration";
317
+ attribute?: string;
318
+ }
319
+
320
+ @doc("FailureComparison contract.")
321
+ model FailureComparison {
322
+ @encodedName("application/json", "nearest_success_trace_id")
323
+ nearestSuccessTraceId?: TraceId;
324
+ @encodedName("application/json", "first_divergence")
325
+ firstDivergence: TraceDivergence | null;
326
+ }
327
+
328
+ @doc("SimilarFailure contract.")
329
+ model SimilarFailure {
330
+ @encodedName("application/json", "failure_id")
331
+ failureId: FailureId;
332
+ count: int64;
333
+ @encodedName("application/json", "first_seen")
334
+ firstSeen: utcDateTime;
335
+ releases: string[];
336
+ }
337
+
338
+ @doc("FailureContext contract.")
339
+ model FailureContext {
340
+ @encodedName("application/json", "similar_failures")
341
+ similarFailures: SimilarFailure[];
342
+ changes: TriageRegression[];
343
+ annotations: Annotation[];
344
+ }
345
+
346
+ @doc("GetFailureContextOutput contract.")
347
+ model GetFailureContextOutput {
348
+ ...ToolReadContext;
349
+ observed: FailureObserved;
350
+ comparison: FailureComparison;
351
+ context: FailureContext;
352
+ settled: boolean;
353
+ unknowns: string[];
354
+ error?: ToolError;
355
+ }
356
+
357
+ @doc("CompareGroup contract.")
358
+ model CompareGroup {
359
+ matchers?: TelemetryMatcher[];
360
+ window?: ToolWindow;
361
+ @encodedName("application/json", "failure_id")
362
+ failureId?: FailureId;
363
+ }
364
+
365
+ @doc("CompareGroupsInput contract.")
366
+ model CompareGroupsInput {
367
+ ...AnalysisInput;
368
+ signal: "spans" | "logs";
369
+ @encodedName("application/json", "group_a")
370
+ groupA: CompareGroup;
371
+ @encodedName("application/json", "group_b")
372
+ groupB: CompareGroup | "rest" | "before";
373
+ @encodedName("application/json", "attribute_scope")
374
+ attributeScope?: "span" | "resource" | "both";
375
+ }
376
+
377
+ @doc("GroupStructure contract.")
378
+ model GroupStructure {
379
+ name: string;
380
+ @encodedName("application/json", "share_a")
381
+ shareA: float64;
382
+ @encodedName("application/json", "share_b")
383
+ shareB: float64;
384
+ }
385
+
386
+ @doc("DurationPercentiles contract.")
387
+ model DurationPercentiles {
388
+ @encodedName("application/json", "p50_ms")
389
+ p50Ms: float64 | null;
390
+ @encodedName("application/json", "p95_ms")
391
+ p95Ms: float64 | null;
392
+ @encodedName("application/json", "p99_ms")
393
+ p99Ms: float64 | null;
394
+ }
395
+
396
+ @doc("GroupDurations contract.")
397
+ model GroupDurations {
398
+ a: DurationPercentiles;
399
+ b: DurationPercentiles;
400
+ }
401
+
402
+ @doc("GroupComposition contract.")
403
+ model GroupComposition {
404
+ changed: boolean;
405
+ @encodedName("application/json", "traffic_mix_changed")
406
+ trafficMixChanged: boolean;
407
+ @encodedName("application/json", "same_traffic_changed")
408
+ sameTrafficChanged: boolean;
409
+ summary: string;
410
+ }
411
+
412
+ @doc("CompareGroupsOutput contract.")
413
+ model CompareGroupsOutput {
414
+ ...ToolReadContext;
415
+ discriminators: AttributeAssociation[];
416
+ structural: GroupStructure[];
417
+ durations: GroupDurations;
418
+ composition: GroupComposition;
419
+ @encodedName("application/json", "size_a")
420
+ sizeA: int64;
421
+ @encodedName("application/json", "size_b")
422
+ sizeB: int64;
423
+ @encodedName("application/json", "excluded_keys")
424
+ excludedKeys: string[];
425
+ error?: ToolError;
426
+ }
427
+
428
+ @doc("ExecutionReference contract.")
429
+ model ExecutionReference {
430
+ @encodedName("application/json", "trace_id")
431
+ traceId?: TraceId;
432
+ @encodedName("application/json", "session_id")
433
+ sessionId?: SessionId;
434
+ }
435
+
436
+ @doc("CompareTracesInput contract.")
437
+ model CompareTracesInput {
438
+ ...AnalysisInput;
439
+ a: ExecutionReference;
440
+ b: ExecutionReference;
441
+ }
442
+
443
+ @doc("AlignedSpans contract.")
444
+ model AlignedSpans {
445
+ @encodedName("application/json", "a_span")
446
+ aSpan: EvidenceSpan;
447
+ @encodedName("application/json", "b_span")
448
+ bSpan: EvidenceSpan;
449
+ differences: TraceDivergence[];
450
+ }
451
+
452
+ @doc("CompareTracesOutput contract.")
453
+ model CompareTracesOutput {
454
+ ...ToolReadContext;
455
+ @encodedName("application/json", "first_divergence")
456
+ firstDivergence: TraceDivergence | null;
457
+ aligned: AlignedSpans[];
458
+ @encodedName("application/json", "after_divergence")
459
+ afterDivergence: TraceDivergence[];
460
+ unmatched: EvidenceSpan[];
461
+ comparable: boolean;
462
+ reason?: string;
463
+ error?: ToolError;
464
+ }
465
+
466
+ @doc("VerifyFixInput contract.")
467
+ model VerifyFixInput {
468
+ ...AnalysisInput;
469
+ @encodedName("application/json", "failure_id")
470
+ failureId?: FailureId;
471
+ since?: utcDateTime;
472
+ release?: string;
473
+ @encodedName("application/json", "min_requests")
474
+ minRequests?: int32;
475
+ @encodedName("application/json", "min_minutes")
476
+ minMinutes?: int32;
477
+ @encodedName("application/json", "verify_id")
478
+ verifyId?: VerifyId;
479
+ }
480
+
481
+ @doc("VerificationPeriod contract.")
482
+ model VerificationPeriod {
483
+ window: ToolWindow;
484
+ occurrences: int64;
485
+ requests: int64;
486
+ rate: float64 | null;
487
+ unit: "requests";
488
+ }
489
+
490
+ @doc("VerificationNeeds contract.")
491
+ model VerificationNeeds {
492
+ requests: int64;
493
+ minutes: float64;
494
+ }
495
+
496
+ @doc("VerifyFixOutput contract.")
497
+ model VerifyFixOutput {
498
+ ...ToolReadContext;
499
+ verdict: "passed" | "failed" | "pending" | "inconclusive";
500
+ before: VerificationPeriod;
501
+ after: VerificationPeriod;
502
+ needs?: VerificationNeeds;
503
+ @maxItems(3)
504
+ recurrences: TraceId[];
505
+ guardrails: TriageFailure[];
506
+ @encodedName("application/json", "verify_id")
507
+ verifyId: VerifyId;
508
+ error?: ToolError;
509
+ }
510
+
511
+ @doc("AggregateTelemetryInput contract.")
512
+ model AggregateTelemetryInput {
513
+ ...AnalysisInput;
514
+ signal: "spans" | "logs";
515
+ @maxItems(4)
516
+ @encodedName("application/json", "group_by")
517
+ groupBy?: string[];
518
+ measures: string[];
519
+ @encodedName("application/json", "step_ms")
520
+ stepMs?: int64;
521
+ @encodedName("application/json", "order_by")
522
+ orderBy?: string;
523
+ }
524
+
525
+ @doc("AggregateBucket contract.")
526
+ model AggregateBucket {
527
+ @encodedName("application/json", "start_time")
528
+ startTime: utcDateTime;
529
+ measures: Record<float64 | null>;
530
+ }
531
+
532
+ @doc("AggregateGroup contract.")
533
+ model AggregateGroup {
534
+ key: Record<MatcherValue>;
535
+ measures: Record<float64 | null>;
536
+ buckets?: AggregateBucket[];
537
+ }
538
+
539
+ @doc("AggregateOther contract.")
540
+ model AggregateOther {
541
+ groups: int64;
542
+ count: int64;
543
+ }
544
+
545
+ @doc("AggregateTelemetryOutput contract.")
546
+ model AggregateTelemetryOutput {
547
+ ...ToolReadContext;
548
+ groups: AggregateGroup[];
549
+ other: AggregateOther;
550
+ units: Record<string>;
551
+ error?: ToolError;
552
+ }
553
+
554
+ @doc("DiscoverAttributesInput contract.")
555
+ model DiscoverAttributesInput {
556
+ ...AnalysisInput;
557
+ signal: "spans" | "logs" | "resources";
558
+ @encodedName("application/json", "key_prefix")
559
+ keyPrefix?: string;
560
+ key?: string;
561
+ }
562
+
563
+ @doc("AttributeValueCount contract.")
564
+ model AttributeValueCount {
565
+ value: MatcherValue;
566
+ count: int64;
567
+ share: float64;
568
+ }
569
+
570
+ @doc("AttributeSemconv contract.")
571
+ model AttributeSemconv {
572
+ brief: string;
573
+ stability: string;
574
+ @encodedName("application/json", "requirement_level")
575
+ requirementLevel: string;
576
+ }
577
+
578
+ @doc("DiscoveredAttribute contract.")
579
+ model DiscoveredAttribute {
580
+ key: string;
581
+ scope: MatcherScope;
582
+ type: string;
583
+ @encodedName("application/json", "coverage_share")
584
+ coverageShare: float64;
585
+ cardinality: int64;
586
+ @encodedName("application/json", "cardinality_exact")
587
+ cardinalityExact: boolean;
588
+ @maxItems(10)
589
+ @encodedName("application/json", "top_values")
590
+ topValues: AttributeValueCount[];
591
+ semconv: AttributeSemconv | null;
592
+ }
593
+
594
+ @doc("DiscoverAttributesOutput contract.")
595
+ model DiscoverAttributesOutput {
596
+ ...ToolReadContext;
597
+ attributes: DiscoveredAttribute[];
598
+ error?: ToolError;
599
+ }
600
+
601
+ @doc("GetAgentRunInput contract.")
602
+ model GetAgentRunInput {
603
+ ...AnalysisInput;
604
+ @encodedName("application/json", "session_id")
605
+ sessionId?: SessionId;
606
+ @encodedName("application/json", "trace_id")
607
+ traceId?: TraceId;
608
+ @minValue(1) @maxValue(1000)
609
+ @encodedName("application/json", "max_steps")
610
+ maxSteps?: int32;
611
+ }
612
+
613
+ @doc("AgentTokens contract.")
614
+ model AgentTokens {
615
+ input: int64 | null;
616
+ output: int64 | null;
617
+ @encodedName("application/json", "cache_read")
618
+ cacheRead: int64 | null;
619
+ @encodedName("application/json", "cache_write")
620
+ cacheWrite: int64 | null;
621
+ reasoning: int64 | null;
622
+ }
623
+
624
+ @doc("AgentRun contract.")
625
+ model AgentRun {
626
+ @encodedName("application/json", "agent_name")
627
+ agentName?: string;
628
+ models: string[];
629
+ started: utcDateTime;
630
+ @encodedName("application/json", "duration_ms")
631
+ durationMs: DurationMs;
632
+ tokens: AgentTokens;
633
+ errors: int64;
634
+ @encodedName("application/json", "session_id")
635
+ sessionId?: SessionId;
636
+ @encodedName("application/json", "trace_id")
637
+ traceId?: TraceId;
638
+ }
639
+
640
+ @doc("AgentStep contract.")
641
+ model AgentStep {
642
+ index: int32;
643
+ kind: "llm_call" | "tool_call" | "agent" | "retrieval";
644
+ name: string;
645
+ @encodedName("application/json", "mcp_method")
646
+ mcpMethod?: string;
647
+ @encodedName("application/json", "mcp_server")
648
+ mcpServer?: string;
649
+ @encodedName("application/json", "duration_ms")
650
+ durationMs: DurationMs;
651
+ tokens: AgentTokens;
652
+ status: string;
653
+ error?: string;
654
+ @encodedName("application/json", "trace_id")
655
+ traceId: TraceId;
656
+ @encodedName("application/json", "span_id")
657
+ spanId: SpanId;
658
+ }
659
+
660
+ @doc("RepeatedCall contract.")
661
+ model RepeatedCall {
662
+ tool: string;
663
+ @encodedName("application/json", "argument_hash")
664
+ argumentHash: string;
665
+ count: int64;
666
+ }
667
+
668
+ @doc("AgentTokenShare contract.")
669
+ model AgentTokenShare {
670
+ name: string;
671
+ tokens: int64;
672
+ share: float64;
673
+ }
674
+
675
+ @doc("AgentFindings contract.")
676
+ model AgentFindings {
677
+ @encodedName("application/json", "repeated_calls")
678
+ repeatedCalls: RepeatedCall[];
679
+ @encodedName("application/json", "failed_tool_calls")
680
+ failedToolCalls: AgentStep[];
681
+ @encodedName("application/json", "slowest_steps")
682
+ slowestSteps: AgentStep[];
683
+ @encodedName("application/json", "token_share")
684
+ tokenShare: AgentTokenShare[];
685
+ }
686
+
687
+ @doc("GetAgentRunOutput contract.")
688
+ model GetAgentRunOutput {
689
+ ...ToolReadContext;
690
+ run: AgentRun;
691
+ steps: AgentStep[];
692
+ findings: AgentFindings;
693
+ unknowns: string[];
694
+ error?: ToolError;
695
+ }
696
+
697
+ @doc("ListReleasesInput contract.")
698
+ model ListReleasesInput {
699
+ ...ServiceAnalysisInput;
700
+ }
701
+
702
+ @doc("ReleasePerformance contract.")
703
+ model ReleasePerformance {
704
+ @encodedName("application/json", "error_rate")
705
+ errorRate: float64 | null;
706
+ @encodedName("application/json", "p95_ms")
707
+ p95Ms: float64 | null;
708
+ }
709
+
710
+ @doc("ReleaseSummary contract.")
711
+ model ReleaseSummary {
712
+ service: string;
713
+ environment?: string;
714
+ version: string;
715
+ revision?: string;
716
+ @encodedName("application/json", "first_seen")
717
+ firstSeen: utcDateTime;
718
+ @encodedName("application/json", "last_seen")
719
+ lastSeen: utcDateTime;
720
+ current: boolean;
721
+ concurrent: boolean;
722
+ @encodedName("application/json", "traffic_share")
723
+ trafficShare: float64;
724
+ before: ReleasePerformance;
725
+ after: ReleasePerformance;
726
+ @encodedName("application/json", "new_failure_ids")
727
+ newFailureIds: FailureId[];
728
+ }
729
+
730
+ @doc("ListReleasesOutput contract.")
731
+ model ListReleasesOutput {
732
+ ...ToolReadContext;
733
+ ...ToolPage;
734
+ releases: ReleaseSummary[];
735
+ error?: ToolError;
736
+ }
737
+
738
+ @doc("GetServiceMapInput contract.")
739
+ model GetServiceMapInput {
740
+ ...ServiceAnalysisInput;
741
+ @minValue(1) @maxValue(3)
742
+ depth?: int32;
743
+ @encodedName("application/json", "include_external")
744
+ includeExternal?: boolean;
745
+ }
746
+
747
+ @doc("ServiceMapNode contract.")
748
+ model ServiceMapNode {
749
+ name: string;
750
+ kind: "service" | "database" | "external" | "messaging";
751
+ calls: int64;
752
+ @encodedName("application/json", "error_rate")
753
+ errorRate: float64;
754
+ @encodedName("application/json", "p95_ms")
755
+ p95Ms: float64 | null;
756
+ unit: "spans";
757
+ }
758
+
759
+ @doc("ServiceMapEdge contract.")
760
+ model ServiceMapEdge {
761
+ from: string;
762
+ to: string;
763
+ calls: int64;
764
+ @encodedName("application/json", "error_rate")
765
+ errorRate: float64;
766
+ @encodedName("application/json", "p95_ms")
767
+ p95Ms: float64 | null;
768
+ @encodedName("application/json", "example_operations")
769
+ exampleOperations: string[];
770
+ unit: "spans";
771
+ }
772
+
773
+ @doc("GetServiceMapOutput contract.")
774
+ model GetServiceMapOutput {
775
+ ...ToolReadContext;
776
+ nodes: ServiceMapNode[];
777
+ edges: ServiceMapEdge[];
778
+ @encodedName("application/json", "unknown_callers")
779
+ unknownCallers: float64;
780
+ error?: ToolError;
781
+ }
782
+
783
+ @doc("CheckTelemetryHealthInput contract.")
784
+ model CheckTelemetryHealthInput {
785
+ ...ServiceAnalysisInput;
786
+ }
787
+
788
+ @doc("OrphanSpans contract.")
789
+ model OrphanSpans {
790
+ count: int64;
791
+ share: float64;
792
+ services: string[];
793
+ unit: "spans";
794
+ }
795
+
796
+ @doc("SemconvGap contract.")
797
+ model SemconvGap {
798
+ service: string;
799
+ operation: string;
800
+ attribute: string;
801
+ @encodedName("application/json", "requirement_level")
802
+ requirementLevel: string;
803
+ @encodedName("application/json", "missing_share")
804
+ missingShare: float64;
805
+ }
806
+
807
+ @doc("TelemetryRetention contract.")
808
+ model TelemetryRetention {
809
+ oldest: utcDateTime | null;
810
+ days: float64 | null;
811
+ }
812
+
813
+ @doc("CheckTelemetryHealthOutput contract.")
814
+ model CheckTelemetryHealthOutput {
815
+ ...ToolReadContext;
816
+ @encodedName("application/json", "silent_services")
817
+ silentServices: SilentService[];
818
+ @encodedName("application/json", "orphan_spans")
819
+ orphanSpans: OrphanSpans;
820
+ @encodedName("application/json", "semconv_gaps")
821
+ semconvGaps: SemconvGap[];
822
+ @encodedName("application/json", "unknown_service_share")
823
+ unknownServiceShare: float64;
824
+ @encodedName("application/json", "schema_urls")
825
+ schemaUrls: string[];
826
+ retention: TelemetryRetention;
827
+ @encodedName("application/json", "ingestion_lag_ms")
828
+ ingestionLagMs?: float64;
829
+ error?: ToolError;
830
+ }
831
+
832
+ @doc("McpComparisonOffset contract.")
833
+ model McpComparisonOffset {
834
+ @encodedName("application/json", "offset_minutes")
835
+ offsetMinutes: int32;
836
+ }
837
+
838
+ @doc("McpComparisonVersion contract.")
839
+ model McpComparisonVersion {
840
+ @encodedName("application/json", "server_version")
841
+ serverVersion: string;
842
+ }
843
+
844
+ @doc("GetMcpStatsInput contract.")
845
+ model GetMcpStatsInput {
846
+ ...AnalysisInput;
847
+ @encodedName("application/json", "server_name")
848
+ serverName?: string;
849
+ @encodedName("application/json", "server_version")
850
+ serverVersion?: string;
851
+ @encodedName("application/json", "tool_name")
852
+ toolName?: string;
853
+ transport?: string;
854
+ @encodedName("application/json", "compare_to")
855
+ compareTo?: McpStatsComparison;
856
+ @encodedName("application/json", "group_by")
857
+ groupBy?: "server" | "tool" | "method" | "transport" | "failure_class";
858
+ }
859
+
860
+ @doc("McpTrafficTotals contract.")
861
+ model McpTrafficTotals {
862
+ requests: int64;
863
+ errors: int64;
864
+ @encodedName("application/json", "error_rate")
865
+ errorRate: float64;
866
+ @encodedName("application/json", "p50_ms")
867
+ p50Ms: float64 | null;
868
+ @encodedName("application/json", "p95_ms")
869
+ p95Ms: float64 | null;
870
+ unit: "requests";
871
+ }
872
+
873
+ @doc("McpTrafficGroup contract.")
874
+ model McpTrafficGroup {
875
+ ...McpTrafficTotals;
876
+ name: string;
877
+ @maxItems(3)
878
+ @encodedName("application/json", "example_trace_ids")
879
+ exampleTraceIds: TraceId[];
880
+ }
881
+
882
+ @doc("McpFailureClasses contract.")
883
+ model McpFailureClasses {
884
+ transport: int64;
885
+ protocol: int64;
886
+ @encodedName("application/json", "tool_result")
887
+ toolResult: int64;
888
+ authentication: int64;
889
+ cancellation: int64;
890
+ timeout: int64;
891
+ }
892
+
893
+ @doc("McpStatsComparisonResult contract.")
894
+ model McpStatsComparisonResult {
895
+ window: ToolWindow;
896
+ totals: McpTrafficTotals;
897
+ groups: McpTrafficGroup[];
898
+ @encodedName("application/json", "failure_classes")
899
+ failureClasses: McpFailureClasses;
900
+ }
901
+
902
+ @doc("GetMcpStatsOutput contract.")
903
+ model GetMcpStatsOutput {
904
+ ...ToolReadContext;
905
+ totals: McpTrafficTotals;
906
+ groups: McpTrafficGroup[];
907
+ @encodedName("application/json", "failure_classes")
908
+ failureClasses: McpFailureClasses;
909
+ comparison?: McpStatsComparisonResult;
910
+ error?: ToolError;
911
+ }
912
+
913
+ @doc("UpdateFailureStatusInput contract.")
914
+ model UpdateFailureStatusInput {
915
+ @encodedName("application/json", "failure_id")
916
+ failureId: FailureId;
917
+ etag: ETag;
918
+ status: FailureStatus;
919
+ @encodedName("application/json", "ignore_until")
920
+ ignoreUntil?: utcDateTime;
921
+ @maxLength(256)
922
+ assignee?: string;
923
+ }
924
+
925
+ @doc("UpdateFailureStatusOutput contract.")
926
+ model UpdateFailureStatusOutput {
927
+ failure: FailureSummary;
928
+ error?: ToolError;
929
+ }
930
+
931
+ @doc("ToolFieldError contract.")
932
+ model ToolFieldError {
933
+ field: string;
934
+ code: string;
935
+ message: string;
936
+ change: string;
937
+ }
938
+
939
+ @doc("TraceGroup contract.")
940
+ model TraceGroup {
941
+ key: string;
942
+ count: int64;
943
+ @maxItems(3)
944
+ @encodedName("application/json", "example_trace_ids")
945
+ exampleTraceIds: TraceId[];
946
+ }
947
+
948
+ @doc("TraceOmitted contract.")
949
+ model TraceOmitted {
950
+ matched: int64;
951
+ context: int64;
952
+ }
953
+
954
+ @doc("TraceLinkAvailability contract.")
955
+ model TraceLinkAvailability {
956
+ @encodedName("application/json", "trace_id")
957
+ traceId: TraceId;
958
+ @encodedName("application/json", "span_id")
959
+ spanId: SpanId;
960
+ available: boolean;
961
+ }
962
+
963
+ @doc("SpanEvidenceRole contract.")
964
+ model SpanEvidenceRole {
965
+ @encodedName("application/json", "span_id")
966
+ spanId: SpanId;
967
+ role: "matched" | "context";
968
+ @encodedName("application/json", "self_time_ms")
969
+ selfTimeMs?: DurationMs;
970
+ @encodedName("application/json", "self_time_share")
971
+ selfTimeShare?: float64;
972
+ }
973
+
974
+ @doc("ToolTraceSummary contract.")
975
+ model ToolTraceSummary {
976
+ ...TraceSummary;
977
+ @encodedName("application/json", "root_error")
978
+ rootError: boolean;
979
+ @encodedName("application/json", "contained_error")
980
+ containedError: boolean;
981
+ @encodedName("application/json", "failure_ids")
982
+ failureIds: FailureId[];
983
+ @encodedName("application/json", "annotation_labels")
984
+ annotationLabels: string[];
985
+ }
986
+
987
+ @doc("ToolSession contract.")
988
+ model ToolSession {
989
+ ...SessionEntity;
990
+ @maxItems(5)
991
+ @encodedName("application/json", "failure_ids")
992
+ failureIds?: FailureId[];
993
+ @encodedName("application/json", "agent_name")
994
+ agentName?: string;
995
+ models?: string[];
996
+ @encodedName("application/json", "tokens_by_model")
997
+ tokensByModel?: Record<AgentTokens>;
998
+ annotations?: Annotation[];
999
+ }
1000
+
1001
+ @doc("LogPattern contract.")
1002
+ model LogPattern {
1003
+ template: string;
1004
+ count: int64;
1005
+ severity: int32;
1006
+ @encodedName("application/json", "first_seen")
1007
+ firstSeen: utcDateTime;
1008
+ @encodedName("application/json", "last_seen")
1009
+ lastSeen: utcDateTime;
1010
+ @maxItems(3)
1011
+ @encodedName("application/json", "example_ids")
1012
+ exampleIds: string[];
1013
+ }
1014
+
1015
+ @doc("MetricKeySummary contract.")
1016
+ model MetricKeySummary {
1017
+ key: string;
1018
+ cardinality: int64;
1019
+ @encodedName("application/json", "cardinality_exact")
1020
+ cardinalityExact: boolean;
1021
+ @encodedName("application/json", "top_values")
1022
+ topValues: AttributeValueCount[];
1023
+ @encodedName("application/json", "coverage_share")
1024
+ coverageShare: float64;
1025
+ }
1026
+
1027
+ @doc("MetricComparisonOffset contract.")
1028
+ model MetricComparisonOffset {
1029
+ @encodedName("application/json", "offset_ms")
1030
+ offsetMs: int64;
1031
+ }
1032
+
1033
+ @doc("MetricRatio contract.")
1034
+ model MetricRatio {
1035
+ @encodedName("application/json", "metric_name")
1036
+ metricName: string;
1037
+ aggregation?: MetricAggregation;
1038
+ matchers?: TelemetryMatcher[];
1039
+ }
1040
+
1041
+ @doc("MetricComparisonResult contract.")
1042
+ model MetricComparisonResult {
1043
+ window: ToolWindow;
1044
+ series: MetricSeriesResult[];
1045
+ }
1046
+
1047
+ @doc("CiAttempt contract.")
1048
+ model CiAttempt {
1049
+ @encodedName("application/json", "run_id")
1050
+ runId: SessionId;
1051
+ attempt: int32;
1052
+ @encodedName("application/json", "provider_run_id")
1053
+ providerRunId?: string;
1054
+ @encodedName("application/json", "provider_run_url")
1055
+ providerRunUrl?: UrlString;
1056
+ }
1057
+
1058
+ @doc("CiPhaseChange contract.")
1059
+ model CiPhaseChange {
1060
+ leg: string;
1061
+ phase: string;
1062
+ @encodedName("application/json", "current_duration_ms")
1063
+ currentDurationMs?: DurationMs;
1064
+ @encodedName("application/json", "baseline_duration_ms")
1065
+ baselineDurationMs?: DurationMs;
1066
+ ratio?: float64;
1067
+ @encodedName("application/json", "trace_ids")
1068
+ traceIds?: TraceId[];
1069
+ }
1070
+
1071
+ @doc("CiComparison contract.")
1072
+ model CiComparison {
1073
+ @encodedName("application/json", "baseline_run_id")
1074
+ baselineRunId?: SessionId;
1075
+ @encodedName("application/json", "new_failures")
1076
+ newFailures: CiPhaseChange[];
1077
+ fixed: CiPhaseChange[];
1078
+ @encodedName("application/json", "duration_regressions")
1079
+ durationRegressions: CiPhaseChange[];
1080
+ }
1081
+
1082
+ @doc("CiErrorExcerpt contract.")
1083
+ model CiErrorExcerpt {
1084
+ id: string;
1085
+ body: string;
1086
+ @encodedName("application/json", "trace_id")
1087
+ traceId?: TraceId;
1088
+ @encodedName("application/json", "span_id")
1089
+ spanId?: SpanId;
1090
+ }
1091
+
1092
+
1093
+ @doc("A span returned as evidence, with selection role and optional critical-path self time.")
1094
+ model ToolSpan extends Span {
1095
+ role: "matched" | "context";
1096
+ @encodedName("application/json", "self_time_ms")
1097
+ selfTimeMs?: DurationMs;
1098
+ @encodedName("application/json", "self_time_share")
1099
+ selfTimeShare?: float64;
1100
+ }
1101
+
1102
+ @doc("Full trace evidence with the selection role on every returned span.")
1103
+ model ToolTrace extends TraceSummary {
1104
+ spans: ToolSpan[];
1105
+ }
1106
+
1107
+ @doc("Canonical classification shared by MCP aggregates and their trace drilldowns.")
1108
+ enum McpFailureClass { transport, protocol, tool_result, authentication, cancellation, timeout }