Skip to content

Commit cfb85c3

Browse files
google-genai-botcopybara-github
authored andcommitted
ADK changes
PiperOrigin-RevId: 814088343
1 parent ebd78c6 commit cfb85c3

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 {InjectionToken} from '@angular/core';
19+
20+
export const LOCAL_FILE_SERVICE = new InjectionToken<LocalFileService>(
21+
'LocalFileService',
22+
);
23+
24+
/**
25+
* Service to provide methods to handle local files.
26+
*/
27+
export abstract class LocalFileService {
28+
abstract createMessagePartFromFile(file: File): Promise<any>;
29+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
import {TestBed} from '@angular/core/testing';
18+
19+
import {LocalFileServiceImpl} from './local-file.service';
20+
21+
describe('LocalFileServiceImpl', () => {
22+
let service: LocalFileServiceImpl;
23+
24+
beforeEach(() => {
25+
TestBed.configureTestingModule({
26+
providers: [LocalFileServiceImpl],
27+
});
28+
service = TestBed.inject(LocalFileServiceImpl);
29+
});
30+
31+
it('createMessagePartFromFile successfully reads a file and returns a message part',
32+
async () => {
33+
const fileContent = 'Hello World';
34+
const fileContentBase64 = btoa(fileContent); // Base64 for "Hello World"
35+
const dataUrl = `data:text/plain;base64,${fileContentBase64}`;
36+
const mockFile = new File([fileContent], 'test.txt', {
37+
type: 'text/plain',
38+
});
39+
const mockFileReader = jasmine.createSpyObj('FileReader', [
40+
'readAsDataURL',
41+
'onload',
42+
]);
43+
spyOn(window, 'FileReader').and.returnValue(mockFileReader);
44+
mockFileReader.result = dataUrl;
45+
mockFileReader.readAsDataURL.and.callFake(() => {
46+
mockFileReader.onload({target: mockFileReader});
47+
});
48+
49+
const result = await service.createMessagePartFromFile(mockFile);
50+
51+
expect(mockFileReader.readAsDataURL).toHaveBeenCalledWith(mockFile);
52+
expect(result).toEqual({
53+
inlineData: {
54+
displayName: 'test.txt',
55+
data: fileContentBase64,
56+
mimeType: 'text/plain',
57+
},
58+
});
59+
});
60+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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 {Injectable} from '@angular/core';
19+
20+
import {LocalFileService} from './interfaces/localfile';
21+
22+
/**
23+
* Service to provide methods to handle local files.
24+
*/
25+
@Injectable({
26+
providedIn: 'root',
27+
})
28+
export class LocalFileServiceImpl extends LocalFileService {
29+
async createMessagePartFromFile(file: File): Promise<any> {
30+
return {
31+
inlineData: {
32+
displayName: file.name,
33+
data: await this.readFileAsBytes(file),
34+
mimeType: file.type,
35+
},
36+
};
37+
}
38+
39+
private readFileAsBytes(file: File): Promise<ArrayBuffer> {
40+
return new Promise((resolve, reject) => {
41+
const reader = new FileReader();
42+
reader.onload = (e: any) => {
43+
const base64Data = e.target.result.split(',')[1];
44+
resolve(base64Data);
45+
};
46+
reader.onerror = reject;
47+
reader.readAsDataURL(file); // Read as raw bytes
48+
});
49+
}
50+
}

src/main.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ import {EVAL_SERVICE, EvalService} from './app/core/services/eval.service';
3838
import {EVENT_SERVICE, EventService} from './app/core/services/event.service';
3939
import {FEATURE_FLAG_SERVICE, FeatureFlagService} from './app/core/services/feature-flag.service';
4040
import {GRAPH_SERVICE, GraphService} from './app/core/services/graph.service';
41+
import {LOCAL_FILE_SERVICE} from './app/core/services/interfaces/localfile';
4142
import {SAFE_VALUES_SERVICE} from './app/core/services/interfaces/safevalues';
4243
import {STRING_TO_COLOR_SERVICE, StringToColorService} from './app/core/services/interfaces/string-to-color';
44+
import {LocalFileServiceImpl} from './app/core/services/local-file.service';
4345
import {SafeValuesServiceImpl} from './app/core/services/safevalues.service';
4446
import {SESSION_SERVICE, SessionService} from './app/core/services/session.service';
4547
import {STREAM_CHAT_SERVICE, StreamChatService} from './app/core/services/stream-chat.service';
@@ -78,6 +80,7 @@ fetch('./assets/config/runtime-config.json')
7880
{provide: GRAPH_SERVICE, useClass: GraphService},
7981
{provide: STRING_TO_COLOR_SERVICE, useClass: StringToColorServiceImpl},
8082
{provide: SAFE_VALUES_SERVICE, useClass: SafeValuesServiceImpl},
83+
{provide: LOCAL_FILE_SERVICE, useClass: LocalFileServiceImpl},
8184
{provide: MARKDOWN_COMPONENT, useValue: MarkdownComponent},
8285
...(config.logo ?
8386
[{provide: LOGO_COMPONENT, useValue: CustomLogoComponent}] :

0 commit comments

Comments
 (0)