Skip to content

Commit cce59ab

Browse files
hoonjicopybara-github
authored andcommitted
ADK changes
PiperOrigin-RevId: 812567196
1 parent 4557781 commit cce59ab

File tree

8 files changed

+112
-69
lines changed

8 files changed

+112
-69
lines changed

karma.conf.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
118
module.exports = function (config) {
219
config.set({
320
basePath: '',

package-lock.json

Lines changed: 11 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/components/chat/chat.component.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import {URLUtil} from '../../../utils/url-util';
4444
import {AgentRunRequest} from '../../core/models/AgentRunRequest';
4545
import {EvalCase} from '../../core/models/Eval';
4646
import {Session, SessionState} from '../../core/models/Session';
47-
import {LlmResponse} from '../../core/models/types';
47+
import {Event as AdkEvent} from '../../core/models/types';
4848
import {AGENT_SERVICE, AgentService} from '../../core/services/agent.service';
4949
import {ARTIFACT_SERVICE, ArtifactService} from '../../core/services/artifact.service';
5050
import {AUDIO_SERVICE, AudioService} from '../../core/services/audio.service';
@@ -66,7 +66,6 @@ import {AudioPlayerComponent} from '../audio-player/audio-player.component';
6666
import {ChatPanelComponent} from '../chat-panel/chat-panel.component';
6767
import {EditJsonDialogComponent} from '../edit-json-dialog/edit-json-dialog.component';
6868
import {EvalTabComponent} from '../eval-tab/eval-tab.component';
69-
import {EventTabComponent} from '../event-tab/event-tab.component';
7069
import {PendingEventDialogComponent} from '../pending-event-dialog/pending-event-dialog.component';
7170
import {DeleteSessionDialogComponent, DeleteSessionDialogData,} from '../session-tab/delete-session-dialog/delete-session-dialog.component';
7271
import {SessionTabComponent} from '../session-tab/session-tab.component';
@@ -147,7 +146,6 @@ const BIDI_STREAMING_RESTART_WARNING =
147146
export class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
148147
chatPanel = viewChild.required(ChatPanelComponent);
149148
sideDrawer = viewChild.required<MatDrawer>('sideDrawer');
150-
eventTabComponent = viewChild.required(EventTabComponent);
151149
sessionTab = viewChild(SessionTabComponent);
152150
evalTab = viewChild(EvalTabComponent);
153151
private scrollContainer = viewChild.required<ElementRef>('autoScroll');
@@ -459,7 +457,7 @@ export class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
459457
let index = this.eventMessageIndexArray.length - 1;
460458
this.streamingTextMessage = null;
461459
this.agentService.runSse(req).subscribe({
462-
next: async (chunkJson: LlmResponse) => {
460+
next: async (chunkJson: AdkEvent) => {
463461
if (chunkJson.error) {
464462
this.openSnackBar(chunkJson.error, 'OK');
465463
return;
@@ -1155,6 +1153,7 @@ export class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
11551153
});
11561154

11571155
this.bottomPanelVisible = false;
1156+
this.changeDetectorRef.detectChanges();
11581157
}
11591158

11601159
protected updateWithSelectedEvalCase(evalCase: EvalCase) {

src/app/components/event-tab/event-tab.component.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
-->
1616

1717
<div class="events-wrapper">
18-
@if (eventsMap.size>0) {
18+
@if (eventsMap().size>0) {
1919
<div class="events-container">
2020
<div class="event-header">
2121
@if (!isTraceView()) {
@@ -24,7 +24,7 @@
2424
@if (isTraceView()) {
2525
<p>Trace</p>
2626
}
27-
@if (traceData) {
27+
@if (traceData()) {
2828
<mat-button-toggle-group name="fontStyle" aria-label="Font Style" style="scale: 0.8" [(ngModel)]="view">
2929
<mat-button-toggle value="events">Events</mat-button-toggle>
3030
<mat-button-toggle value="trace">Trace</mat-button-toggle>
@@ -33,7 +33,7 @@
3333
</div>
3434
@if (!isTraceView()) {
3535
<mat-list class="event-list">
36-
@for (jsonData of eventsMap | keyvalue: mapOrderPreservingSort; track jsonData; let i = $index) {
36+
@for (jsonData of eventsMap() | keyvalue: mapOrderPreservingSort; track jsonData; let i = $index) {
3737
<mat-list-item (click)="selectEvent(jsonData.key)">
3838
<span class="event-index">{{i}}</span>
3939
<span class="event-title">{{jsonData.value.title}}</span>
@@ -43,17 +43,17 @@
4343
}
4444
@if (isTraceView()) {
4545
<mat-list class="event-list">
46-
@for (invoc of invocTraces | keyvalue: mapOrderPreservingSort; track invoc; let i = $index) {
46+
@for (invoc of spansByTraceId() | keyvalue: mapOrderPreservingSort; track invoc; let i = $index) {
4747
<mat-list-item (click)="openDialog(invoc.key)">
4848
<span class="event-index">{{i}}</span>
49-
<span>Invocation {{findInvocIdFromTraceId(invoc.key)}}</span>
49+
<span>Invocation {{invoc.value | invocId}}</span>
5050
</mat-list-item>
5151
}
5252
</mat-list>
5353
}
5454
</div>
5555
}
56-
@if (eventsMap.size==0) {
56+
@if (eventsMap().size==0) {
5757
<div>
5858
<p>No conversations</p>
5959
</div>

src/app/components/event-tab/event-tab.component.ts

Lines changed: 35 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
* limitations under the License.
1616
*/
1717

18-
import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core';
18+
import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, computed, inject, input, signal} from '@angular/core';
1919
import {MatDialog} from '@angular/material/dialog';
2020

21+
import {Span} from '../../core/models/Trace';
2122
import {TraceChartComponent} from './trace-chart/trace-chart.component';
2223
import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
2324
import { FormsModule } from '@angular/forms';
2425
import { MatList, MatListItem } from '@angular/material/list';
2526
import { KeyValuePipe } from '@angular/common';
27+
import {InvocIdPipe} from './invoc-id.pipe';
2628

2729
@Component({
2830
selector: 'app-event-tab',
@@ -35,29 +37,36 @@ import { KeyValuePipe } from '@angular/common';
3537
MatList,
3638
MatListItem,
3739
KeyValuePipe,
40+
InvocIdPipe,
3841
],
3942
})
40-
export class EventTabComponent implements OnChanges {
41-
@Input() eventsMap = new Map<string, any>();
43+
export class EventTabComponent {
44+
readonly eventsMap = input<Map<string, any>>(new Map<string, any>());
45+
readonly traceData = input<Span[]>([]);
4246
@Output() selectedEvent = new EventEmitter<string>();
43-
@Input() traceData: any[] = [];
44-
llmRequest: any = undefined;
45-
llmResponse: any = undefined;
46-
llmRequestKey = 'gcp.vertex.agent.llm_request';
47-
llmResponseKey = 'gcp.vertex.agent.llm_response';
48-
isDetailsPanelOpen = false;
49-
view = 'events';
50-
invocTraces = new Map<string, any[]>();
47+
private readonly dialog = inject(MatDialog);
5148

52-
constructor(private dialog: MatDialog) {}
53-
54-
ngOnChanges(changes: SimpleChanges): void {
55-
if ('traceData' in changes) {
56-
this.prcessTraceDataToInvocTrace();
49+
readonly view = signal<string>('events');
50+
readonly isTraceView = computed(() => this.view() === 'trace');
51+
readonly spansByTraceId = computed(() => {
52+
if (!this.traceData || this.traceData.length == 0) {
53+
return new Map<string, Span[]>();
5754
}
58-
}
55+
return this.traceData().reduce((map, span) => {
56+
const key = span.trace_id;
57+
const group = map.get(key);
58+
if (group) {
59+
span.invoc_id = span.attributes?.['gcp.vertex.agent.invocation_id'];
60+
group.push(span);
61+
group.sort((a: Span, b: Span) => a.start_time - b.start_time);
62+
} else {
63+
map.set(key, [span]);
64+
}
65+
return map;
66+
}, new Map<string, Span[]>());
67+
});
5968

60-
showJson: boolean[] = Array(this.eventsMap.size).fill(false);
69+
showJson: boolean[] = Array(this.eventsMap().size).fill(false);
6170

6271
toggleJson(index: number) {
6372
this.showJson[index] = !this.showJson[index];
@@ -67,46 +76,24 @@ export class EventTabComponent implements OnChanges {
6776
this.selectedEvent.emit(key);
6877
}
6978

70-
isTraceView() {
71-
return this.view == 'trace';
72-
}
73-
7479
mapOrderPreservingSort = (a: any, b: any): number => 0;
7580

76-
prcessTraceDataToInvocTrace() {
77-
if (!this.traceData || this.traceData.length == 0) {
78-
return;
79-
}
80-
this.invocTraces = this.traceData.reduce((map, item) => {
81-
const key = item.trace_id;
82-
const group = map.get(key);
83-
if (group) {
84-
group.push(item);
85-
group.sort((a: any, b: any) => a.start_time - b.start_time);
86-
} else {
87-
map.set(key, [item]);
88-
}
89-
return map;
90-
}, new Map<string, any[]>());
91-
}
92-
93-
findInvocIdFromTraceId(traceId: string) {
94-
const group = this.invocTraces.get(traceId);
95-
return group
96-
?.find(
81+
findInvocId(spans: Span[]) {
82+
return spans
83+
.find(
9784
item => item.attributes !== undefined &&
9885
'gcp.vertex.agent.invocation_id' in item.attributes)
99-
.attributes['gcp.vertex.agent.invocation_id']
86+
?.attributes['gcp.vertex.agent.invocation_id']
10087
}
10188

10289
openDialog(traceId: string): void {
90+
const spans = this.spansByTraceId().get(traceId);
91+
if (!spans) return;
92+
10393
const dialogRef = this.dialog.open(TraceChartComponent, {
10494
width: 'auto',
10595
maxWidth: '90vw',
106-
data: {
107-
spans: this.invocTraces.get(traceId),
108-
invocId: this.findInvocIdFromTraceId(traceId)
109-
},
96+
data: {spans, invocId: this.findInvocId(spans)},
11097
});
11198
}
11299
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import {Pipe, PipeTransform} from '@angular/core';
19+
import {Span} from '../../core/models/Trace';
20+
21+
@Pipe({
22+
name: 'invocId',
23+
standalone: true,
24+
})
25+
export class InvocIdPipe implements PipeTransform {
26+
transform(spans: Span[] | undefined | null): string | undefined {
27+
if (!spans) {
28+
return undefined;
29+
}
30+
return spans.find(
31+
(item) =>
32+
item.attributes !== undefined &&
33+
'gcp.vertex.agent.invocation_id' in item.attributes,
34+
)?.attributes['gcp.vertex.agent.invocation_id'];
35+
}
36+
}

src/app/core/models/Trace.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface Span {
2323
trace_id: string;
2424
attributes?: any;
2525
children?: Span[];
26+
invoc_id?: string;
2627
// For backward compatibility.
2728
'gcp.vertex.agent.llm_request'?: string;
2829
'gcp.vertex.agent.llm_response'?: string;
@@ -38,4 +39,4 @@ export interface SpanNode extends Span {
3839
export interface TimeTick {
3940
position: number;
4041
label: string;
41-
}
42+
}

src/app/core/models/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ export interface LlmRequest {
5555
}
5656

5757
export interface LlmResponse {
58-
id?: number;
5958
content: GenAiContent;
6059
error?: string;
6160
errorMessage?: string;
@@ -66,9 +65,11 @@ export interface EventActions {
6665
message?: string;
6766
functionCall?: FunctionCall;
6867
functionResponse?: FunctionResponse;
68+
finishReason?: string;
6969
}
7070

7171
export interface Event extends LlmResponse {
72+
id?: string;
7273
author?: string
7374
invocationId?: string;
7475
actions?: EventActions;

0 commit comments

Comments
 (0)