@tstdl/base 0.93.125 → 0.93.126
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.
- package/ai/genkit/tests/multi-region.test.js +6 -6
- package/ai/index.d.ts +2 -6
- package/ai/index.js +2 -6
- package/ai/parser/index.d.ts +1 -0
- package/ai/parser/index.js +1 -0
- package/ai/parser/parser.d.ts +12 -0
- package/ai/parser/parser.js +28 -0
- package/ai/prompts/build.d.ts +21 -0
- package/ai/prompts/build.js +25 -0
- package/ai/prompts/index.d.ts +2 -0
- package/ai/prompts/index.js +2 -0
- package/ai/prompts/instructions-formatter.d.ts +9 -22
- package/ai/prompts/instructions-formatter.js +20 -7
- package/ai/prompts/instructions.js +1 -1
- package/ai/prompts/steering.d.ts +27 -0
- package/ai/prompts/steering.js +54 -0
- package/ai/tests/instructions-formatter.test.js +115 -0
- package/ai/tests/steering.test.js +37 -0
- package/application/application.d.ts +2 -1
- package/application/application.js +3 -0
- package/authentication/client/module.d.ts +1 -1
- package/authentication/client/module.js +4 -5
- package/authentication/tests/authentication-ancillary.service.test.js +1 -1
- package/authentication/tests/authentication.api-controller.test.js +3 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
- package/authentication/tests/authentication.client-service.test.js +1 -1
- package/authentication/tests/authentication.service.test.js +1 -1
- package/authentication/tests/subject.service.test.js +1 -1
- package/circuit-breaker/tests/circuit-breaker.test.js +1 -1
- package/document-management/api/document-management.api.d.ts +16 -16
- package/document-management/api/document-management.api.js +12 -12
- package/document-management/models/ai-configuration.d.ts +59 -0
- package/document-management/models/ai-configuration.js +1 -0
- package/document-management/models/document-assignment-scope.model.js +2 -4
- package/document-management/models/document-assignment-task.model.js +2 -4
- package/document-management/models/document-collection-assignment.model.js +2 -4
- package/document-management/models/document-collection.model.js +2 -3
- package/document-management/models/document-content.model.d.ts +6 -0
- package/document-management/models/document-content.model.js +32 -0
- package/document-management/models/document-property-value.model.js +1 -2
- package/document-management/models/document-request-collection-assignment.model.js +2 -4
- package/document-management/models/document-request.model.js +2 -4
- package/document-management/models/document-tag-assignment.model.js +2 -3
- package/document-management/models/document-validation-execution-related-document.model.js +2 -4
- package/document-management/models/document-validation-execution.model.js +2 -5
- package/document-management/models/document-workflow.model.d.ts +2 -1
- package/document-management/models/document-workflow.model.js +4 -5
- package/document-management/models/document.model.js +2 -3
- package/document-management/models/index.d.ts +2 -0
- package/document-management/models/index.js +2 -0
- package/document-management/server/api/document-management.api.d.ts +7 -7
- package/document-management/server/api/document-management.api.js +9 -9
- package/document-management/server/configure.d.ts +4 -1
- package/document-management/server/configure.js +9 -4
- package/document-management/server/drizzle/{0000_complex_black_bird.sql → 0000_curious_nighthawk.sql} +7 -27
- package/document-management/server/drizzle/meta/0000_snapshot.json +12 -284
- package/document-management/server/drizzle/meta/_journal.json +2 -2
- package/document-management/server/module.d.ts +2 -0
- package/document-management/server/module.js +1 -0
- package/document-management/server/schemas.d.ts +2 -1
- package/document-management/server/services/document-file.service.d.ts +6 -6
- package/document-management/server/services/document-file.service.js +7 -81
- package/document-management/server/services/document-management-ai-provider.service.d.ts +66 -0
- package/document-management/server/services/document-management-ai-provider.service.js +2 -0
- package/document-management/server/services/document-management-ai.service.d.ts +44 -7
- package/document-management/server/services/document-management-ai.service.js +332 -329
- package/document-management/server/services/document-validation.service.d.ts +1 -1
- package/document-management/server/services/document-workflow.service.d.ts +4 -3
- package/document-management/server/services/document-workflow.service.js +26 -9
- package/document-management/server/services/document.service.d.ts +7 -3
- package/document-management/server/services/document.service.js +13 -4
- package/document-management/server/services/index.d.ts +1 -0
- package/document-management/server/services/index.js +1 -0
- package/document-management/server/validators/ai-validation-executor.d.ts +419 -12
- package/document-management/server/validators/ai-validation-executor.js +51 -46
- package/document-management/server/validators/single-document-validation-executor.d.ts +1 -3
- package/document-management/server/validators/single-document-validation-executor.js +2 -4
- package/document-management/service-models/document.service-model.d.ts +3 -3
- package/document-management/service-models/document.service-model.js +1 -1
- package/document-management/tests/ai-config-hierarchy.test.d.ts +1 -0
- package/document-management/tests/ai-config-hierarchy.test.js +64 -0
- package/document-management/tests/ai-config-integration.test.d.ts +1 -0
- package/document-management/tests/ai-config-integration.test.js +125 -0
- package/document-management/tests/ai-config-merge.test.d.ts +1 -0
- package/document-management/tests/ai-config-merge.test.js +38 -0
- package/document-management/tests/document-management-ai-overrides.test.d.ts +1 -0
- package/document-management/tests/document-management-ai-overrides.test.js +64 -0
- package/document-management/tests/document-management-core.test.js +6 -6
- package/document-management/tests/document-management.api.test.js +5 -5
- package/document-management/tests/document-statistics.service.test.js +10 -6
- package/document-management/tests/document-validation-ai-overrides.test.d.ts +1 -0
- package/document-management/tests/document-validation-ai-overrides.test.js +85 -0
- package/document-management/tests/document.service.test.js +15 -11
- package/document-management/tests/enum-helpers.test.js +5 -5
- package/examples/document-management/ai-provider.d.ts +20 -0
- package/examples/document-management/ai-provider.js +74 -0
- package/examples/document-management/main.js +9 -6
- package/examples/injector/graph-example.d.ts +1 -0
- package/examples/injector/graph-example.js +340 -0
- package/injector/decorators.d.ts +4 -4
- package/injector/decorators.js +5 -6
- package/injector/forward-ref.d.ts +15 -0
- package/injector/forward-ref.js +20 -0
- package/injector/graph.d.ts +113 -0
- package/injector/graph.js +631 -0
- package/injector/index.d.ts +2 -0
- package/injector/index.js +2 -0
- package/injector/inject.d.ts +15 -15
- package/injector/injector.d.ts +101 -13
- package/injector/injector.js +103 -59
- package/injector/resolve-chain.d.ts +20 -6
- package/injector/resolve-chain.js +39 -14
- package/injector/tests/advanced.test.d.ts +1 -0
- package/injector/tests/advanced.test.js +116 -0
- package/injector/tests/async-init.test.d.ts +1 -0
- package/injector/tests/async-init.test.js +77 -0
- package/injector/tests/basic.test.d.ts +1 -0
- package/injector/tests/basic.test.js +114 -0
- package/injector/tests/hierarchical.test.d.ts +1 -0
- package/injector/tests/hierarchical.test.js +59 -0
- package/injector/tests/lifecycles.test.d.ts +1 -0
- package/injector/tests/lifecycles.test.js +109 -0
- package/injector/token.d.ts +2 -1
- package/injector/token.js +4 -1
- package/injector/type-info.d.ts +1 -5
- package/injector/types.d.ts +4 -10
- package/logger/tests/pretty-print.test.d.ts +1 -0
- package/logger/{formatters → tests}/pretty-print.test.js +1 -1
- package/logger/transports/console.d.ts +3 -2
- package/logger/transports/console.js +4 -3
- package/notification/tests/notification-api.test.js +8 -5
- package/notification/tests/notification-client.test.d.ts +1 -0
- package/notification/tests/{unit/notification-client.test.js → notification-client.test.js} +5 -5
- package/notification/tests/notification-flow.test.js +6 -5
- package/notification/tests/notification-sse.service.test.js +1 -1
- package/notification/tests/notification-type.service.test.js +1 -1
- package/object-storage/s3/s3.object-storage.js +3 -0
- package/object-storage/s3/tests/s3.object-storage.integration.test.js +1 -1
- package/orm/tests/repository-attributes.test.js +10 -17
- package/orm/tests/repository-cti-mapping.test.js +2 -2
- package/orm/tests/repository-cti-soft-delete.test.js +1 -1
- package/orm/tests/repository-cti.test.js +19 -33
- package/orm/tests/repository-extra-coverage.test.js +1 -1
- package/orm/tests/repository-search.test.js +5 -2
- package/orm/tests/transaction-safety.test.js +1 -1
- package/package.json +7 -9
- package/rate-limit/tests/postgres-rate-limiter.test.js +6 -16
- package/renderer/d2.d.ts +77 -0
- package/renderer/d2.js +68 -0
- package/renderer/graphviz.d.ts +47 -0
- package/renderer/graphviz.js +58 -0
- package/renderer/index.d.ts +4 -0
- package/renderer/index.js +4 -0
- package/renderer/typst.d.ts +57 -0
- package/renderer/typst.js +62 -0
- package/rpc/adapters/readable-stream.adapter.d.ts +3 -0
- package/rpc/adapters/readable-stream.adapter.js +5 -1
- package/rpc/rpc.js +28 -3
- package/rpc/tests/rpc.integration.test.js +3 -1
- package/schema/schemas/nullable.js +1 -1
- package/task-queue/task-queue.d.ts +2 -0
- package/task-queue/task-queue.js +6 -2
- package/task-queue/tests/complex.test.js +1 -1
- package/task-queue/tests/dependencies.test.js +3 -3
- package/task-queue/tests/extensive-dependencies.test.js +1 -1
- package/task-queue/tests/queue.test.js +1 -1
- package/task-queue/tests/worker.test.js +4 -7
- package/test5.js +52 -8
- package/{unit-test → testing}/integration-setup.d.ts +1 -0
- package/{unit-test → testing}/integration-setup.js +13 -0
- package/utils/base64.d.ts +7 -0
- package/utils/base64.js +10 -1
- package/utils/noop.d.ts +7 -1
- package/utils/noop.js +7 -1
- package/ai/ai-file.service.d.ts +0 -57
- package/ai/ai-file.service.js +0 -233
- package/ai/ai-session.d.ts +0 -38
- package/ai/ai-session.js +0 -50
- package/ai/ai.service.d.ts +0 -126
- package/ai/ai.service.js +0 -481
- package/ai/functions.d.ts +0 -9
- package/ai/functions.js +0 -38
- package/ai/module.d.ts +0 -26
- package/ai/module.js +0 -25
- package/ai/types.d.ts +0 -229
- package/ai/types.js +0 -33
- package/latex/index.d.ts +0 -1
- package/latex/index.js +0 -1
- package/typst/index.d.ts +0 -1
- package/typst/index.js +0 -1
- package/typst/render.d.ts +0 -23
- package/typst/render.js +0 -32
- /package/{logger/formatters/pretty-print.test.d.ts → ai/tests/instructions-formatter.test.d.ts} +0 -0
- /package/{notification/tests/unit/notification-client.test.d.ts → ai/tests/steering.test.d.ts} +0 -0
- /package/{latex/render.d.ts → renderer/latex.d.ts} +0 -0
- /package/{latex/render.js → renderer/latex.js} +0 -0
- /package/{unit-test → testing}/index.d.ts +0 -0
- /package/{unit-test → testing}/index.js +0 -0
package/ai/ai-session.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { toArray } from '../utils/array/array.js';
|
|
2
|
-
/**
|
|
3
|
-
* Represents a conversational session with an AI model.
|
|
4
|
-
*
|
|
5
|
-
* This class maintains the history of contents (messages) in a conversation,
|
|
6
|
-
* allowing for stateful, multi-turn interactions with the AI.
|
|
7
|
-
*/
|
|
8
|
-
export class AiSession {
|
|
9
|
-
#aiService;
|
|
10
|
-
/**
|
|
11
|
-
* The history of contents in the session.
|
|
12
|
-
*/
|
|
13
|
-
contents = [];
|
|
14
|
-
/**
|
|
15
|
-
* Creates an instance of `AiSession`.
|
|
16
|
-
* @param aiService The {@link AiService} instance to use for AI interactions.
|
|
17
|
-
*/
|
|
18
|
-
constructor(aiService) {
|
|
19
|
-
this.#aiService = aiService;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Adds new content to the session's history without triggering a generation.
|
|
23
|
-
* @param content The content or contents to add.
|
|
24
|
-
*/
|
|
25
|
-
addContent(content) {
|
|
26
|
-
this.contents.push(...toArray(content));
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Prompts the model to call one or more functions based on the provided context and session history.
|
|
30
|
-
* The new user content and the resulting model response (function calls) are automatically added to the session history.
|
|
31
|
-
* @param options The options for the function call request.
|
|
32
|
-
*/
|
|
33
|
-
async callFunctions(options) {
|
|
34
|
-
this.contents.push(...toArray(options.contents));
|
|
35
|
-
const result = await this.#aiService.callFunctions({ ...options, contents: this.contents });
|
|
36
|
-
this.contents.push(result.raw.content);
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Generates content from the model based on the provided request and the current session history.
|
|
41
|
-
* The new user content and the resulting model response are automatically added to the session history.
|
|
42
|
-
* @param request The generation request.
|
|
43
|
-
*/
|
|
44
|
-
async generate(request) {
|
|
45
|
-
this.contents.push(...toArray(request.contents));
|
|
46
|
-
const result = await this.#aiService.generate({ ...request, contents: this.contents });
|
|
47
|
-
this.contents.push(result.content);
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
|
-
}
|
package/ai/ai.service.d.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
|
|
2
|
-
import { type SchemaTestable } from '../schema/index.js';
|
|
3
|
-
import type { Enumeration as EnumerationType, EnumerationValue } from '../types/index.js';
|
|
4
|
-
import { AiSession } from './ai-session.js';
|
|
5
|
-
import { AiModuleOptions } from './module.js';
|
|
6
|
-
import { type AiModel, type FileContentPart, type FileInput, type GenerationOptions, type GenerationRequest, type GenerationResult, type SchemaFunctionDeclarations, type SchemaFunctionDeclarationsResult } from './types.js';
|
|
7
|
-
/**
|
|
8
|
-
* A generation result that includes a specialized, typed result alongside the raw generation data.
|
|
9
|
-
* @template T The type of the specialized result.
|
|
10
|
-
*/
|
|
11
|
-
export type SpecializedGenerationResult<T> = {
|
|
12
|
-
/** The specialized, typed result. */
|
|
13
|
-
result: T;
|
|
14
|
-
/** The raw, underlying generation result from the AI model. */
|
|
15
|
-
raw: GenerationResult;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* An async generator for specialized generation results, which also provides access to the final raw generation data.
|
|
19
|
-
* @template T The type of the specialized result yielded by the generator.
|
|
20
|
-
*/
|
|
21
|
-
export type SpecializedGenerationResultGenerator<T> = AsyncGenerator<T> & {
|
|
22
|
-
raw: Promise<GenerationResult>;
|
|
23
|
-
};
|
|
24
|
-
export type AiServiceArgument = AiModuleOptions;
|
|
25
|
-
export type ClassificationResult<T extends EnumerationType> = {
|
|
26
|
-
types: {
|
|
27
|
-
type: EnumerationValue<T>;
|
|
28
|
-
confidence: 'high' | 'medium' | 'low';
|
|
29
|
-
}[] | null;
|
|
30
|
-
};
|
|
31
|
-
export type AnalyzeContentResult<T extends EnumerationType> = {
|
|
32
|
-
content: string[];
|
|
33
|
-
documentTypes: ClassificationResult<T>[];
|
|
34
|
-
tags: string[];
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Options for a function-calling request.
|
|
38
|
-
* @template T The schema declarations for the available functions.
|
|
39
|
-
*/
|
|
40
|
-
export type CallFunctionsOptions<T extends SchemaFunctionDeclarations> = Pick<GenerationRequest, 'contents' | 'model' | 'systemInstruction' | 'functionCallingMode'> & GenerationOptions & {
|
|
41
|
-
/** The function declarations available for the model to call. */
|
|
42
|
-
functions: T;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* A service for interacting with Google's Generative AI models (Gemini).
|
|
46
|
-
*
|
|
47
|
-
* This service provides methods for content generation, function calling, and file processing,
|
|
48
|
-
* supporting both standard Google AI and Vertex AI endpoints.
|
|
49
|
-
*/
|
|
50
|
-
export declare class AiService implements Resolvable<AiServiceArgument> {
|
|
51
|
-
#private;
|
|
52
|
-
/**
|
|
53
|
-
* The default AI model to use for requests if not specified otherwise.
|
|
54
|
-
*/
|
|
55
|
-
readonly defaultModel: AiModel;
|
|
56
|
-
readonly [resolveArgumentType]: AiServiceArgument;
|
|
57
|
-
/**
|
|
58
|
-
* Creates a new {@link AiSession} for managing conversational history.
|
|
59
|
-
*/
|
|
60
|
-
createSession(): AiSession;
|
|
61
|
-
/**
|
|
62
|
-
* Processes a single file for use in AI requests by uploading it and making it available to the model.
|
|
63
|
-
* @param fileInput The file to process.
|
|
64
|
-
* @returns A promise that resolves to a {@link FileContentPart} which can be included in a generation request.
|
|
65
|
-
*/
|
|
66
|
-
processFile(fileInput: FileInput): Promise<FileContentPart>;
|
|
67
|
-
/**
|
|
68
|
-
* Processes multiple files in parallel for use in AI requests.
|
|
69
|
-
* @param fileInputs The files to process.
|
|
70
|
-
* @returns A promise that resolves to an array of {@link FileContentPart}s which can be included in generation requests.
|
|
71
|
-
*/
|
|
72
|
-
processFiles(fileInputs: FileInput[]): Promise<FileContentPart[]>;
|
|
73
|
-
/**
|
|
74
|
-
* Creates a file content part from a previously processed file ID.
|
|
75
|
-
* This does not re-upload the file.
|
|
76
|
-
* @param id The ID of the file, obtained from {@link AiFileService.processFile} or {@link AiFileService.processFiles}.
|
|
77
|
-
* @returns A {@link FileContentPart} for use in a generation request.
|
|
78
|
-
*/
|
|
79
|
-
getFileById(id: string): FileContentPart;
|
|
80
|
-
/**
|
|
81
|
-
* A high-level method to prompt the model to call one or more functions.
|
|
82
|
-
* This method sends the request and parses the model's response to identify function calls.
|
|
83
|
-
* If the function declaration includes a handler, it will be executed automatically.
|
|
84
|
-
* @param options The options for the function call request.
|
|
85
|
-
* @returns A promise that resolves to a {@link SpecializedGenerationResult} containing the function call results.
|
|
86
|
-
*/
|
|
87
|
-
callFunctions<const T extends SchemaFunctionDeclarations>(options: CallFunctionsOptions<T>): Promise<SpecializedGenerationResult<SchemaFunctionDeclarationsResult<T>[]>>;
|
|
88
|
-
/**
|
|
89
|
-
* A streaming version of `callFunctions`.
|
|
90
|
-
* Yields function call results as they are received from the model.
|
|
91
|
-
* If function declarations include handlers, they are executed as soon as a complete function call is parsed.
|
|
92
|
-
* @param options The options for the function call request.
|
|
93
|
-
* @returns A {@link SpecializedGenerationResultGenerator} that yields function call results.
|
|
94
|
-
*/
|
|
95
|
-
callFunctionsStream<const T extends SchemaFunctionDeclarations>(options: CallFunctionsOptions<T>): SpecializedGenerationResultGenerator<SchemaFunctionDeclarationsResult<T>>;
|
|
96
|
-
/**
|
|
97
|
-
* Generates content from the model based on a request.
|
|
98
|
-
* This method waits for the full response from the model. For streaming, use {@link generateStream}.
|
|
99
|
-
* @param request The generation request.
|
|
100
|
-
* @returns A promise that resolves to the complete {@link GenerationResult}.
|
|
101
|
-
*/
|
|
102
|
-
generate<S>(request: GenerationRequest<S>): Promise<GenerationResult<S>>;
|
|
103
|
-
/**
|
|
104
|
-
* Generates content as a stream.
|
|
105
|
-
* Yields partial generation results as they are received from the model.
|
|
106
|
-
* @param request The generation request.
|
|
107
|
-
* @returns An `AsyncGenerator` that yields {@link GenerationResult} chunks.
|
|
108
|
-
*/
|
|
109
|
-
generateStream<S>(request: GenerationRequest<S>): AsyncGenerator<GenerationResult<S>>;
|
|
110
|
-
private _callFunctionsStream;
|
|
111
|
-
private getModelOutputTokenLimit;
|
|
112
|
-
private _getModelOutputTokenLimit;
|
|
113
|
-
private convertContents;
|
|
114
|
-
private convertContent;
|
|
115
|
-
private convertFunctions;
|
|
116
|
-
private convertGoogleContent;
|
|
117
|
-
private mapModel;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Merges an array of streaming generation results into a single, consolidated result.
|
|
121
|
-
* This is useful for combining the chunks from a streaming response into a final object.
|
|
122
|
-
* @param items The array of {@link GenerationResult} items from a stream.
|
|
123
|
-
* @param schema An optional schema to parse the merged JSON output.
|
|
124
|
-
* @returns A single, merged {@link GenerationResult}.
|
|
125
|
-
*/
|
|
126
|
-
export declare function mergeGenerationStreamItems<S>(items: GenerationResult<S>[], schema?: SchemaTestable<S>): GenerationResult<S>;
|
package/ai/ai.service.js
DELETED
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var _a;
|
|
8
|
-
var AiService_1;
|
|
9
|
-
import { ApiError, FinishReason, FunctionCallingConfigMode as GoogleFunctionCallingMode, GoogleGenAI } from '@google/genai';
|
|
10
|
-
import { match } from 'ts-pattern';
|
|
11
|
-
import { CancellationSignal } from '../cancellation/index.js';
|
|
12
|
-
import { NotSupportedError } from '../errors/not-supported.error.js';
|
|
13
|
-
import { Singleton } from '../injector/decorators.js';
|
|
14
|
-
import { inject, injectArgument } from '../injector/inject.js';
|
|
15
|
-
import { Logger } from '../logger/logger.js';
|
|
16
|
-
import { DeferredPromise } from '../promise/deferred-promise.js';
|
|
17
|
-
import { LazyPromise } from '../promise/lazy-promise.js';
|
|
18
|
-
import { convertToOpenApiSchema } from '../schema/converters/open-api-converter.js';
|
|
19
|
-
import { Schema } from '../schema/index.js';
|
|
20
|
-
import { toArray } from '../utils/array/array.js';
|
|
21
|
-
import { mapAsync } from '../utils/async-iterable-helpers/map.js';
|
|
22
|
-
import { toArrayAsync } from '../utils/async-iterable-helpers/to-array.js';
|
|
23
|
-
import { backoffGenerator } from '../utils/backoff.js';
|
|
24
|
-
import { lazyObject } from '../utils/object/lazy-property.js';
|
|
25
|
-
import { hasOwnProperty, objectEntries } from '../utils/object/object.js';
|
|
26
|
-
import { assertDefinedPass, isDefined, isError, isInstanceOf, isNotNull, isNull, isUndefined } from '../utils/type-guards.js';
|
|
27
|
-
import { resolveValueOrAsyncProvider } from '../utils/value-or-provider.js';
|
|
28
|
-
import { AiFileService } from './ai-file.service.js';
|
|
29
|
-
import { AiSession } from './ai-session.js';
|
|
30
|
-
import { AiModuleOptions } from './module.js';
|
|
31
|
-
import { isSchemaFunctionDeclarationWithHandler } from './types.js';
|
|
32
|
-
const functionCallingModeMap = {
|
|
33
|
-
auto: GoogleFunctionCallingMode.AUTO,
|
|
34
|
-
force: GoogleFunctionCallingMode.ANY,
|
|
35
|
-
none: GoogleFunctionCallingMode.NONE,
|
|
36
|
-
};
|
|
37
|
-
let generationCounter = 0;
|
|
38
|
-
/**
|
|
39
|
-
* A service for interacting with Google's Generative AI models (Gemini).
|
|
40
|
-
*
|
|
41
|
-
* This service provides methods for content generation, function calling, and file processing,
|
|
42
|
-
* supporting both standard Google AI and Vertex AI endpoints.
|
|
43
|
-
*/
|
|
44
|
-
let AiService = AiService_1 = class AiService {
|
|
45
|
-
#options = injectArgument(this, { optional: true }) ?? inject(AiModuleOptions);
|
|
46
|
-
#fileService = inject(AiFileService, this.#options);
|
|
47
|
-
#logger = inject(Logger, AiService_1.name);
|
|
48
|
-
#cancellationSignal = inject(CancellationSignal);
|
|
49
|
-
#genAI = new GoogleGenAI({
|
|
50
|
-
vertexai: isDefined(this.#options.vertex?.project),
|
|
51
|
-
project: this.#options.vertex?.project,
|
|
52
|
-
location: this.#options.vertex?.location,
|
|
53
|
-
googleAuthOptions: isDefined(this.#options.vertex?.project) ? { apiKey: this.#options.apiKey, keyFile: this.#options.keyFile } : undefined,
|
|
54
|
-
apiKey: isUndefined(this.#options.vertex?.project) ? assertDefinedPass(this.#options.apiKey, 'Api key not defined') : undefined,
|
|
55
|
-
});
|
|
56
|
-
#maxOutputTokensCache = new Map();
|
|
57
|
-
#backoffOptions = {
|
|
58
|
-
cancellationSignal: this.#cancellationSignal,
|
|
59
|
-
strategy: 'exponential',
|
|
60
|
-
initialDelay: 5000,
|
|
61
|
-
increase: 1.5,
|
|
62
|
-
jitter: 0.2,
|
|
63
|
-
maximumDelay: 30000,
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* The default AI model to use for requests if not specified otherwise.
|
|
67
|
-
*/
|
|
68
|
-
defaultModel = this.#options.defaultModel ?? 'gemini-2.5-flash-lite';
|
|
69
|
-
/**
|
|
70
|
-
* Creates a new {@link AiSession} for managing conversational history.
|
|
71
|
-
*/
|
|
72
|
-
createSession() {
|
|
73
|
-
return new AiSession(this);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Processes a single file for use in AI requests by uploading it and making it available to the model.
|
|
77
|
-
* @param fileInput The file to process.
|
|
78
|
-
* @returns A promise that resolves to a {@link FileContentPart} which can be included in a generation request.
|
|
79
|
-
*/
|
|
80
|
-
async processFile(fileInput) {
|
|
81
|
-
return await this.#fileService.processFile(fileInput);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Processes multiple files in parallel for use in AI requests.
|
|
85
|
-
* @param fileInputs The files to process.
|
|
86
|
-
* @returns A promise that resolves to an array of {@link FileContentPart}s which can be included in generation requests.
|
|
87
|
-
*/
|
|
88
|
-
async processFiles(fileInputs) {
|
|
89
|
-
return await this.#fileService.processFiles(fileInputs);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Creates a file content part from a previously processed file ID.
|
|
93
|
-
* This does not re-upload the file.
|
|
94
|
-
* @param id The ID of the file, obtained from {@link AiFileService.processFile} or {@link AiFileService.processFiles}.
|
|
95
|
-
* @returns A {@link FileContentPart} for use in a generation request.
|
|
96
|
-
*/
|
|
97
|
-
getFileById(id) {
|
|
98
|
-
return { file: id };
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* A high-level method to prompt the model to call one or more functions.
|
|
102
|
-
* This method sends the request and parses the model's response to identify function calls.
|
|
103
|
-
* If the function declaration includes a handler, it will be executed automatically.
|
|
104
|
-
* @param options The options for the function call request.
|
|
105
|
-
* @returns A promise that resolves to a {@link SpecializedGenerationResult} containing the function call results.
|
|
106
|
-
*/
|
|
107
|
-
async callFunctions(options) {
|
|
108
|
-
const generation = await this.generate({
|
|
109
|
-
model: options.model,
|
|
110
|
-
generationOptions: {
|
|
111
|
-
temperature: 0.5,
|
|
112
|
-
...options,
|
|
113
|
-
},
|
|
114
|
-
systemInstruction: options.systemInstruction,
|
|
115
|
-
functions: options.functions,
|
|
116
|
-
functionCallingMode: options.functionCallingMode ?? 'force',
|
|
117
|
-
contents: options.contents,
|
|
118
|
-
});
|
|
119
|
-
const result = [];
|
|
120
|
-
for (const call of generation.functionCalls) {
|
|
121
|
-
const fn = assertDefinedPass(options.functions[call.name], 'Function in response not declared.');
|
|
122
|
-
const parametersSchema = await resolveValueOrAsyncProvider(fn.parameters);
|
|
123
|
-
const parameters = isDefined(parametersSchema) ? parametersSchema.parse(call.parameters) : call.parameters;
|
|
124
|
-
const handlerResult = isSchemaFunctionDeclarationWithHandler(fn) ? await fn.handler(parameters) : undefined;
|
|
125
|
-
result.push({
|
|
126
|
-
functionName: call.name,
|
|
127
|
-
parameters: parameters,
|
|
128
|
-
handlerResult: handlerResult,
|
|
129
|
-
getFunctionResultContentPart: () => ({ functionResult: { name: call.name, value: handlerResult } }),
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
result,
|
|
134
|
-
raw: generation,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* A streaming version of `callFunctions`.
|
|
139
|
-
* Yields function call results as they are received from the model.
|
|
140
|
-
* If function declarations include handlers, they are executed as soon as a complete function call is parsed.
|
|
141
|
-
* @param options The options for the function call request.
|
|
142
|
-
* @returns A {@link SpecializedGenerationResultGenerator} that yields function call results.
|
|
143
|
-
*/
|
|
144
|
-
callFunctionsStream(options) {
|
|
145
|
-
const itemsPromise = new DeferredPromise();
|
|
146
|
-
const generator = this._callFunctionsStream(options, itemsPromise);
|
|
147
|
-
generator.raw = new LazyPromise(async () => {
|
|
148
|
-
const items = await itemsPromise;
|
|
149
|
-
return mergeGenerationStreamItems(items);
|
|
150
|
-
});
|
|
151
|
-
return generator;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Generates content from the model based on a request.
|
|
155
|
-
* This method waits for the full response from the model. For streaming, use {@link generateStream}.
|
|
156
|
-
* @param request The generation request.
|
|
157
|
-
* @returns A promise that resolves to the complete {@link GenerationResult}.
|
|
158
|
-
*/
|
|
159
|
-
async generate(request) {
|
|
160
|
-
const items = await toArrayAsync(this.generateStream(request));
|
|
161
|
-
return mergeGenerationStreamItems(items, request.generationSchema);
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Generates content as a stream.
|
|
165
|
-
* Yields partial generation results as they are received from the model.
|
|
166
|
-
* @param request The generation request.
|
|
167
|
-
* @returns An `AsyncGenerator` that yields {@link GenerationResult} chunks.
|
|
168
|
-
*/
|
|
169
|
-
async *generateStream(request) {
|
|
170
|
-
const generationNumber = ++generationCounter;
|
|
171
|
-
const googleFunctionDeclarations = isDefined(request.functions) ? await this.convertFunctions(request.functions) : undefined;
|
|
172
|
-
const config = {
|
|
173
|
-
systemInstruction: request.systemInstruction,
|
|
174
|
-
temperature: request.generationOptions?.temperature,
|
|
175
|
-
topP: request.generationOptions?.topP,
|
|
176
|
-
topK: request.generationOptions?.topK,
|
|
177
|
-
presencePenalty: request.generationOptions?.presencePenalty,
|
|
178
|
-
frequencyPenalty: request.generationOptions?.frequencyPenalty,
|
|
179
|
-
responseMimeType: isDefined(request.generationSchema) ? 'application/json' : undefined,
|
|
180
|
-
responseSchema: isDefined(request.generationSchema) ? convertToOpenApiSchema(request.generationSchema) : undefined,
|
|
181
|
-
safetySettings: [],
|
|
182
|
-
tools: (isDefined(googleFunctionDeclarations) && (googleFunctionDeclarations.length > 0)) ? [{ functionDeclarations: googleFunctionDeclarations }] : undefined,
|
|
183
|
-
toolConfig: isDefined(request.functionCallingMode)
|
|
184
|
-
? { functionCallingConfig: { mode: functionCallingModeMap[request.functionCallingMode] } }
|
|
185
|
-
: undefined,
|
|
186
|
-
thinkingConfig: {
|
|
187
|
-
thinkingBudget: request.generationOptions?.thinkingBudget,
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
const model = this.mapModel(request.model);
|
|
191
|
-
const maxModelTokens = await this.getModelOutputTokenLimit(model);
|
|
192
|
-
const maxTotalOutputTokens = request.generationOptions?.maxOutputTokens ?? maxModelTokens ?? 65535;
|
|
193
|
-
const inputContent = this.convertContents(request.contents);
|
|
194
|
-
let iterations = 0;
|
|
195
|
-
let totalPromptTokens = 0;
|
|
196
|
-
let totalCachedTokens = 0;
|
|
197
|
-
let totalThoughtsTokens = 0;
|
|
198
|
-
let totalOutputTokens = 0;
|
|
199
|
-
let totalToolsTokens = 0;
|
|
200
|
-
while (totalOutputTokens < maxTotalOutputTokens) {
|
|
201
|
-
let generation;
|
|
202
|
-
let triesLeft = 10;
|
|
203
|
-
for await (const backoff of backoffGenerator(this.#backoffOptions)) {
|
|
204
|
-
try {
|
|
205
|
-
this.#logger.verbose(`[C:${generationNumber}] [I:${iterations + 1}] Generating...`);
|
|
206
|
-
generation = await this.#genAI.models.generateContentStream({
|
|
207
|
-
model,
|
|
208
|
-
config: {
|
|
209
|
-
...config,
|
|
210
|
-
maxOutputTokens: Math.min(1000000, maxTotalOutputTokens - totalOutputTokens),
|
|
211
|
-
},
|
|
212
|
-
contents: inputContent,
|
|
213
|
-
});
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
triesLeft -= 1;
|
|
218
|
-
if ((triesLeft > 0) && isInstanceOf(error, ApiError) && ((error.status == 429) || (error.status == 503))) {
|
|
219
|
-
this.#logger.verbose(`Retrying after transient error: ${error.message}`);
|
|
220
|
-
backoff();
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
throw error; // Non-retryable error
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
iterations++;
|
|
227
|
-
let lastUsageMetadata;
|
|
228
|
-
let candidate;
|
|
229
|
-
for await (const generationResponse of generation) {
|
|
230
|
-
candidate = generationResponse.candidates?.at(0);
|
|
231
|
-
const rawContent = candidate?.content;
|
|
232
|
-
if (isUndefined(candidate)) {
|
|
233
|
-
throw new Error('No candidate returned.');
|
|
234
|
-
}
|
|
235
|
-
if (isUndefined(rawContent)) {
|
|
236
|
-
throw new Error('No content returned.');
|
|
237
|
-
}
|
|
238
|
-
inputContent.push(rawContent);
|
|
239
|
-
const { cachedContentTokenCount = 0, candidatesTokenCount = 0, promptTokenCount = 0, thoughtsTokenCount = 0, toolUsePromptTokenCount = 0, totalTokenCount = 0, } = generationResponse.usageMetadata ?? {};
|
|
240
|
-
lastUsageMetadata = generationResponse.usageMetadata;
|
|
241
|
-
const content = this.convertGoogleContent(rawContent);
|
|
242
|
-
let text;
|
|
243
|
-
let functionCallParts;
|
|
244
|
-
const result = {
|
|
245
|
-
content,
|
|
246
|
-
get text() {
|
|
247
|
-
if (isUndefined(text)) {
|
|
248
|
-
const textParts = content.parts.filter((part) => hasOwnProperty(part, 'text')).map((part) => part.text);
|
|
249
|
-
text = (textParts.length > 0) ? textParts.join('') : null;
|
|
250
|
-
}
|
|
251
|
-
return text;
|
|
252
|
-
},
|
|
253
|
-
get json() {
|
|
254
|
-
throw new NotSupportedError('JSON not supported in streamed items. Use mergeGenerationStreamItems to combine all streamed items.');
|
|
255
|
-
},
|
|
256
|
-
get functionCalls() {
|
|
257
|
-
if (isUndefined(functionCallParts)) {
|
|
258
|
-
functionCallParts = content.parts.filter((part) => hasOwnProperty(part, 'functionCall')).map((part) => part.functionCall);
|
|
259
|
-
}
|
|
260
|
-
return functionCallParts;
|
|
261
|
-
},
|
|
262
|
-
finishReason: candidate.finishReason == FinishReason.MAX_TOKENS
|
|
263
|
-
? 'maxTokens'
|
|
264
|
-
: candidate.finishReason == FinishReason.STOP
|
|
265
|
-
? 'stop'
|
|
266
|
-
: 'unknown',
|
|
267
|
-
usage: {
|
|
268
|
-
iterations,
|
|
269
|
-
cached: totalCachedTokens + cachedContentTokenCount,
|
|
270
|
-
prompt: totalPromptTokens + promptTokenCount,
|
|
271
|
-
thoughts: totalThoughtsTokens + thoughtsTokenCount,
|
|
272
|
-
output: totalOutputTokens + candidatesTokenCount,
|
|
273
|
-
tools: totalToolsTokens + toolUsePromptTokenCount,
|
|
274
|
-
total: totalTokenCount,
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
yield result;
|
|
278
|
-
}
|
|
279
|
-
totalCachedTokens += lastUsageMetadata?.cachedContentTokenCount ?? 0;
|
|
280
|
-
totalPromptTokens += lastUsageMetadata?.promptTokenCount ?? 0;
|
|
281
|
-
totalThoughtsTokens += lastUsageMetadata?.thoughtsTokenCount ?? 0;
|
|
282
|
-
totalOutputTokens += lastUsageMetadata?.responseTokenCount ?? 0;
|
|
283
|
-
totalToolsTokens += lastUsageMetadata?.toolUsePromptTokenCount ?? 0;
|
|
284
|
-
if (candidate?.finishReason != FinishReason.MAX_TOKENS) {
|
|
285
|
-
break;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
async *_callFunctionsStream(options, itemsPromise) {
|
|
290
|
-
const generationStream = this.generateStream({
|
|
291
|
-
model: options.model,
|
|
292
|
-
generationOptions: {
|
|
293
|
-
temperature: 0.5,
|
|
294
|
-
...options,
|
|
295
|
-
},
|
|
296
|
-
systemInstruction: options.systemInstruction,
|
|
297
|
-
functions: options.functions,
|
|
298
|
-
functionCallingMode: options.functionCallingMode ?? 'force',
|
|
299
|
-
contents: options.contents,
|
|
300
|
-
});
|
|
301
|
-
const items = [];
|
|
302
|
-
for await (const generation of generationStream) {
|
|
303
|
-
items.push(generation);
|
|
304
|
-
for (const call of generation.functionCalls) {
|
|
305
|
-
const fn = assertDefinedPass(options.functions[call.name], 'Function in response not declared.');
|
|
306
|
-
const parametersSchema = await resolveValueOrAsyncProvider(fn.parameters);
|
|
307
|
-
const parameters = isDefined(parametersSchema) ? parametersSchema.parse(call.parameters, { coerce: true }) : call.parameters;
|
|
308
|
-
const handlerResult = isSchemaFunctionDeclarationWithHandler(fn) ? await fn.handler(parameters) : undefined;
|
|
309
|
-
yield {
|
|
310
|
-
functionName: call.name,
|
|
311
|
-
parameters: parameters,
|
|
312
|
-
handlerResult: handlerResult,
|
|
313
|
-
getFunctionResultContentPart: () => ({ functionResult: { name: call.name, value: handlerResult } }),
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
itemsPromise.resolve(items);
|
|
318
|
-
}
|
|
319
|
-
async getModelOutputTokenLimit(model) {
|
|
320
|
-
const existingValue = this.#maxOutputTokensCache.get(model);
|
|
321
|
-
if (isDefined(existingValue)) {
|
|
322
|
-
return await existingValue;
|
|
323
|
-
}
|
|
324
|
-
const promise = this._getModelOutputTokenLimit(model);
|
|
325
|
-
this.#maxOutputTokensCache.set(model, promise);
|
|
326
|
-
promise
|
|
327
|
-
.then((limit) => this.#maxOutputTokensCache.set(model, limit))
|
|
328
|
-
.catch(() => this.#maxOutputTokensCache.delete(model));
|
|
329
|
-
return await promise;
|
|
330
|
-
}
|
|
331
|
-
async _getModelOutputTokenLimit(model) {
|
|
332
|
-
let modelInfo;
|
|
333
|
-
let triesLeft = 10;
|
|
334
|
-
for await (const backoff of backoffGenerator(this.#backoffOptions)) {
|
|
335
|
-
try {
|
|
336
|
-
modelInfo = await this.#genAI.models.get({ model });
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
catch (error) {
|
|
340
|
-
triesLeft -= 1;
|
|
341
|
-
if ((triesLeft > 0) && isError(error) && (error.message.includes('429 Too Many Requests') || error.message.includes('503 Service Unavailable'))) {
|
|
342
|
-
this.#logger.verbose(`Could not get model info for ${model} due to a transient error (${error.message}). Retrying...`);
|
|
343
|
-
backoff();
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
throw error;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
if (isUndefined(modelInfo.outputTokenLimit)) {
|
|
350
|
-
return null;
|
|
351
|
-
}
|
|
352
|
-
return modelInfo.outputTokenLimit;
|
|
353
|
-
}
|
|
354
|
-
convertContents(contents) {
|
|
355
|
-
return toArray(contents).map((content) => this.convertContent(content));
|
|
356
|
-
}
|
|
357
|
-
convertContent(content) {
|
|
358
|
-
return {
|
|
359
|
-
role: content.role,
|
|
360
|
-
parts: content.parts.map((part) => {
|
|
361
|
-
if (hasOwnProperty(part, 'text')) {
|
|
362
|
-
return { text: part.text };
|
|
363
|
-
}
|
|
364
|
-
if (hasOwnProperty(part, 'file')) {
|
|
365
|
-
const file = assertDefinedPass(this.#fileService.getFileById(part.file), `File ${part.file} not found.`);
|
|
366
|
-
return { fileData: { fileUri: file.uri, mimeType: file.mimeType } };
|
|
367
|
-
}
|
|
368
|
-
if (hasOwnProperty(part, 'functionResult')) {
|
|
369
|
-
return { functionResponse: { name: part.functionResult.name, response: part.functionResult.value } };
|
|
370
|
-
}
|
|
371
|
-
if (hasOwnProperty(part, 'functionCall')) {
|
|
372
|
-
return { functionCall: { name: part.functionCall.name, args: part.functionCall.parameters } };
|
|
373
|
-
}
|
|
374
|
-
throw new NotSupportedError('Unsupported content part.');
|
|
375
|
-
}),
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
async convertFunctions(functions) {
|
|
379
|
-
const mapped = mapAsync(objectEntries(functions), async ([name, declaration]) => {
|
|
380
|
-
const enabled = await resolveValueOrAsyncProvider(declaration.enabled);
|
|
381
|
-
if (enabled == false) {
|
|
382
|
-
return undefined;
|
|
383
|
-
}
|
|
384
|
-
const parametersSchema = await resolveValueOrAsyncProvider(declaration.parameters);
|
|
385
|
-
return {
|
|
386
|
-
name,
|
|
387
|
-
description: declaration.description,
|
|
388
|
-
parameters: isDefined(parametersSchema) ? convertToOpenApiSchema(parametersSchema) : undefined,
|
|
389
|
-
};
|
|
390
|
-
});
|
|
391
|
-
const functionsArray = await toArrayAsync(mapped);
|
|
392
|
-
return functionsArray.filter(isDefined);
|
|
393
|
-
}
|
|
394
|
-
convertGoogleContent(content) {
|
|
395
|
-
return {
|
|
396
|
-
role: content.role,
|
|
397
|
-
parts: isUndefined(content.parts)
|
|
398
|
-
? []
|
|
399
|
-
: content.parts
|
|
400
|
-
.map((part) => {
|
|
401
|
-
if (isDefined(part.text)) {
|
|
402
|
-
if (part.text.length == 0) {
|
|
403
|
-
return null;
|
|
404
|
-
}
|
|
405
|
-
return { text: part.text };
|
|
406
|
-
}
|
|
407
|
-
if (isDefined(part.fileData)) {
|
|
408
|
-
const file = assertDefinedPass(this.#fileService.getFileByUri(assertDefinedPass(part.fileData.fileUri, 'Missing file uri')), 'File not found.');
|
|
409
|
-
return { file: file.id };
|
|
410
|
-
}
|
|
411
|
-
if (isDefined(part.functionResponse)) {
|
|
412
|
-
return { functionResult: { name: assertDefinedPass(part.functionResponse.name, 'Missing function name'), value: part.functionResponse.response } };
|
|
413
|
-
}
|
|
414
|
-
if (isDefined(part.functionCall)) {
|
|
415
|
-
return { functionCall: { name: assertDefinedPass(part.functionCall.name, 'Missing function name'), parameters: part.functionCall.args } };
|
|
416
|
-
}
|
|
417
|
-
throw new NotSupportedError('Unsupported content part.');
|
|
418
|
-
})
|
|
419
|
-
.filter(isNotNull),
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
mapModel(model) {
|
|
423
|
-
return match(model)
|
|
424
|
-
.with('small', () => 'gemini-2.5-flash-lite')
|
|
425
|
-
.with('medium', () => 'gemini-2.5-flash')
|
|
426
|
-
.with('large', () => 'gemini-2.5-pro')
|
|
427
|
-
.otherwise(() => model ?? this.defaultModel);
|
|
428
|
-
}
|
|
429
|
-
};
|
|
430
|
-
AiService = AiService_1 = __decorate([
|
|
431
|
-
Singleton()
|
|
432
|
-
], AiService);
|
|
433
|
-
export { AiService };
|
|
434
|
-
/**
|
|
435
|
-
* Merges an array of streaming generation results into a single, consolidated result.
|
|
436
|
-
* This is useful for combining the chunks from a streaming response into a final object.
|
|
437
|
-
* @param items The array of {@link GenerationResult} items from a stream.
|
|
438
|
-
* @param schema An optional schema to parse the merged JSON output.
|
|
439
|
-
* @returns A single, merged {@link GenerationResult}.
|
|
440
|
-
*/
|
|
441
|
-
export function mergeGenerationStreamItems(items, schema) {
|
|
442
|
-
if (items.length == 0) {
|
|
443
|
-
return {
|
|
444
|
-
content: { role: 'model', parts: [] },
|
|
445
|
-
text: null,
|
|
446
|
-
json: undefined,
|
|
447
|
-
functionCalls: [],
|
|
448
|
-
finishReason: 'unknown',
|
|
449
|
-
usage: { iterations: 0, cached: 0, prompt: 0, thoughts: 0, output: 0, tools: 0, total: 0 },
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
const parts = items.flatMap((item) => item.content.parts);
|
|
453
|
-
return lazyObject({
|
|
454
|
-
content: { value: { role: 'model', parts } },
|
|
455
|
-
text() {
|
|
456
|
-
const textParts = parts.filter((part) => hasOwnProperty(part, 'text')).map((part) => part.text);
|
|
457
|
-
return (textParts.length > 0) ? textParts.join('') : null;
|
|
458
|
-
},
|
|
459
|
-
json() {
|
|
460
|
-
if (isUndefined(schema)) {
|
|
461
|
-
return undefined;
|
|
462
|
-
}
|
|
463
|
-
if (isNull(this.text)) {
|
|
464
|
-
throw new Error('No text to parse available.');
|
|
465
|
-
}
|
|
466
|
-
let parsed;
|
|
467
|
-
try {
|
|
468
|
-
parsed = JSON.parse(this.text);
|
|
469
|
-
}
|
|
470
|
-
catch (error) {
|
|
471
|
-
throw new SyntaxError(`Failed to parse model output as JSON. Raw text: "${this.text}"`, { cause: error });
|
|
472
|
-
}
|
|
473
|
-
return Schema.parse(schema, parsed, { coerce: true });
|
|
474
|
-
},
|
|
475
|
-
functionCalls() {
|
|
476
|
-
return parts.filter((part) => hasOwnProperty(part, 'functionCall')).map((part) => part.functionCall);
|
|
477
|
-
},
|
|
478
|
-
finishReason: { value: items.at(-1).finishReason },
|
|
479
|
-
usage: { value: items.at(-1).usage },
|
|
480
|
-
});
|
|
481
|
-
}
|
package/ai/functions.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { FunctionDeclaration } from '@google/genai';
|
|
2
|
-
import type { AbstractConstructor } from '../types/index.js';
|
|
3
|
-
/**
|
|
4
|
-
* Extracts Google AI function declarations from a class decorated with schema information.
|
|
5
|
-
* It iterates over the properties of the class schema and converts `FunctionSchema` instances
|
|
6
|
-
* into the format required by the Google Generative AI API.
|
|
7
|
-
* @param type The constructor of the class to extract function declarations from.
|
|
8
|
-
*/
|
|
9
|
-
export declare function getFunctionDeclarations(type: AbstractConstructor): FunctionDeclaration[];
|