@tstdl/base 0.92.123 → 0.92.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/ai/ai-file.service.js +23 -18
  2. package/ai/ai.service.d.ts +4 -12
  3. package/ai/ai.service.js +79 -147
  4. package/ai/functions.d.ts +1 -1
  5. package/ai/types.d.ts +3 -1
  6. package/api/server/gateway.js +6 -6
  7. package/authentication/authentication.api.js +24 -24
  8. package/authentication/server/authentication.service.js +20 -20
  9. package/browser/page-controller.js +1 -1
  10. package/context/context.js +5 -5
  11. package/document-management/api/document-management.api.d.ts +60 -215
  12. package/document-management/api/document-management.api.js +32 -68
  13. package/document-management/models/document-assignment-scope.model.d.ts +11 -0
  14. package/document-management/models/{document-request-assignment-task-collection.model.js → document-assignment-scope.model.js} +14 -10
  15. package/document-management/models/document-assignment-task.model.d.ts +13 -0
  16. package/document-management/models/document-assignment-task.model.js +38 -0
  17. package/document-management/models/document-category.model.d.ts +2 -0
  18. package/document-management/models/document-category.model.js +7 -1
  19. package/document-management/models/{document-collection-document.model.d.ts → document-collection-assignment.model.d.ts} +1 -1
  20. package/document-management/models/{document-collection-document.model.js → document-collection-assignment.model.js} +7 -7
  21. package/document-management/models/document-collection.model.d.ts +2 -0
  22. package/document-management/models/document-collection.model.js +10 -0
  23. package/document-management/models/document-property-value.model.d.ts +3 -11
  24. package/document-management/models/document-property-value.model.js +15 -46
  25. package/document-management/models/document-property.model.d.ts +2 -1
  26. package/document-management/models/document-property.model.js +2 -2
  27. package/document-management/models/document-request-submission.model.d.ts +7 -0
  28. package/document-management/models/document-request-submission.model.js +34 -0
  29. package/document-management/models/document-request-template.d.ts +2 -4
  30. package/document-management/models/document-request-template.js +3 -8
  31. package/document-management/models/document-request.model.d.ts +14 -6
  32. package/document-management/models/document-request.model.js +22 -12
  33. package/document-management/models/document-type-validation.model.d.ts +6 -0
  34. package/document-management/models/document-type-validation.model.js +34 -0
  35. package/document-management/models/document-type.model.d.ts +0 -1
  36. package/document-management/models/document-type.model.js +0 -5
  37. package/document-management/models/document-validation-definition.model.d.ts +10 -0
  38. package/document-management/models/document-validation-definition.model.js +39 -0
  39. package/document-management/models/document-validation-execution-related-document.model.d.ts +7 -0
  40. package/document-management/models/document-validation-execution-related-document.model.js +34 -0
  41. package/document-management/models/document-validation-execution.model.d.ts +26 -0
  42. package/document-management/models/document-validation-execution.model.js +72 -0
  43. package/document-management/models/document-workflow.model.d.ts +35 -0
  44. package/document-management/models/document-workflow.model.js +70 -0
  45. package/document-management/models/document.model.d.ts +12 -1
  46. package/document-management/models/document.model.js +21 -5
  47. package/document-management/models/index.d.ts +10 -5
  48. package/document-management/models/index.js +10 -5
  49. package/document-management/models/service-models/categories-and-types.view-model.d.ts +3 -3
  50. package/document-management/models/service-models/categories-and-types.view-model.js +2 -21
  51. package/document-management/models/service-models/document-folders.view-model.d.ts +7 -14
  52. package/document-management/models/service-models/document-folders.view-model.js +20 -44
  53. package/document-management/models/service-models/document-management.view-model.d.ts +41 -0
  54. package/document-management/models/service-models/{document.view-model.js → document-management.view-model.js} +43 -26
  55. package/document-management/models/service-models/document.service-model.d.ts +51 -81
  56. package/document-management/models/service-models/document.service-model.js +30 -28
  57. package/document-management/models/service-models/enriched/enriched-document-assignment.view.d.ts +11 -0
  58. package/document-management/models/service-models/enriched/enriched-document-assignment.view.js +12 -0
  59. package/document-management/models/service-models/enriched/enriched-document-category.view.d.ts +13 -0
  60. package/document-management/models/service-models/enriched/enriched-document-category.view.js +47 -0
  61. package/document-management/models/service-models/enriched/enriched-document-collection.view.d.ts +22 -0
  62. package/document-management/models/service-models/enriched/enriched-document-collection.view.js +89 -0
  63. package/document-management/models/service-models/enriched/enriched-document-file.view.d.ts +12 -0
  64. package/document-management/models/service-models/enriched/enriched-document-file.view.js +16 -0
  65. package/document-management/models/service-models/enriched/enriched-document-management-data.view.d.ts +41 -0
  66. package/document-management/models/service-models/enriched/enriched-document-management-data.view.js +130 -0
  67. package/document-management/models/service-models/enriched/enriched-document-request.view.d.ts +17 -0
  68. package/document-management/models/service-models/enriched/enriched-document-request.view.js +52 -0
  69. package/document-management/models/service-models/enriched/enriched-document-type.view.d.ts +9 -0
  70. package/document-management/models/service-models/enriched/enriched-document-type.view.js +10 -0
  71. package/document-management/models/service-models/enriched/enriched-document.view.d.ts +28 -0
  72. package/document-management/models/service-models/enriched/enriched-document.view.js +77 -0
  73. package/document-management/models/service-models/enriched/enriched.d.ts +18 -0
  74. package/document-management/models/service-models/enriched/enriched.js +39 -0
  75. package/document-management/models/service-models/enriched/index.d.ts +9 -0
  76. package/document-management/models/service-models/enriched/index.js +9 -0
  77. package/document-management/models/service-models/index.d.ts +2 -2
  78. package/document-management/models/service-models/index.js +2 -2
  79. package/document-management/models/service-models/normalized-requests-template-data.model.d.ts +12 -10
  80. package/document-management/models/service-models/normalized-requests-template-data.model.js +5 -4
  81. package/document-management/models/service-models/stats.view-model.d.ts +7 -5
  82. package/document-management/models/service-models/stats.view-model.js +19 -9
  83. package/document-management/server/module.d.ts +2 -2
  84. package/document-management/server/module.js +3 -7
  85. package/document-management/server/schemas.d.ts +18 -23
  86. package/document-management/server/schemas.js +18 -23
  87. package/document-management/server/services/document-category-type.service.d.ts +25 -0
  88. package/document-management/server/services/document-category-type.service.js +66 -0
  89. package/document-management/server/services/document-collection.service.d.ts +13 -0
  90. package/document-management/server/services/document-collection.service.js +41 -0
  91. package/document-management/server/services/document-file.service.d.ts +17 -0
  92. package/document-management/server/services/document-file.service.js +204 -0
  93. package/document-management/server/services/document-management-ai.service.d.ts +22 -0
  94. package/document-management/server/services/document-management-ai.service.js +340 -0
  95. package/document-management/server/services/document-management-ancillary.service.d.ts +127 -3
  96. package/document-management/server/services/document-management-ancillary.service.js +24 -0
  97. package/document-management/server/services/document-management.service.d.ts +10 -122
  98. package/document-management/server/services/document-management.service.js +106 -888
  99. package/document-management/server/services/document-property.service.d.ts +84 -0
  100. package/document-management/server/services/document-property.service.js +87 -0
  101. package/document-management/server/services/document-request.service.d.ts +30 -0
  102. package/document-management/server/services/document-request.service.js +138 -0
  103. package/document-management/server/services/document-validation.service.d.ts +20 -0
  104. package/document-management/server/services/document-validation.service.js +145 -0
  105. package/document-management/server/services/document-workflow.service.d.ts +20 -0
  106. package/document-management/server/services/document-workflow.service.js +132 -0
  107. package/document-management/server/services/document.service.d.ts +16 -0
  108. package/document-management/server/services/document.service.js +81 -0
  109. package/document-management/server/services/index.d.ts +9 -0
  110. package/document-management/server/services/index.js +9 -0
  111. package/document-management/server/validators/ai-validation-executor.d.ts +19 -0
  112. package/document-management/server/validators/ai-validation-executor.js +51 -0
  113. package/document-management/server/validators/index.d.ts +2 -0
  114. package/document-management/server/validators/index.js +2 -0
  115. package/document-management/server/validators/single-document-validation-executor.d.ts +16 -0
  116. package/document-management/server/validators/single-document-validation-executor.js +20 -0
  117. package/document-management/server/validators/validator.d.ts +21 -0
  118. package/document-management/server/validators/validator.js +2 -0
  119. package/eslint.config.js +31 -17
  120. package/examples/document-management/main.d.ts +18 -3
  121. package/examples/document-management/main.js +28 -12
  122. package/file/mime-type.js +2 -9
  123. package/formats.d.ts +5 -2
  124. package/formats.js +32 -23
  125. package/http/client/http-client.js +1 -1
  126. package/injector/injector.js +2 -2
  127. package/object-storage/s3/s3.object-storage.js +1 -1
  128. package/orm/data-types/bytea.d.ts +8 -0
  129. package/orm/data-types/bytea.js +8 -0
  130. package/orm/data-types/index.d.ts +4 -0
  131. package/orm/data-types/index.js +4 -0
  132. package/orm/data-types/numeric-date.d.ts +9 -0
  133. package/orm/data-types/numeric-date.js +9 -0
  134. package/orm/data-types/timestamp.d.ts +9 -0
  135. package/orm/data-types/timestamp.js +9 -0
  136. package/orm/decorators.d.ts +139 -5
  137. package/orm/decorators.js +50 -0
  138. package/orm/entity.d.ts +19 -0
  139. package/orm/entity.js +19 -0
  140. package/orm/index.d.ts +5 -0
  141. package/orm/index.js +5 -0
  142. package/orm/query.d.ts +51 -0
  143. package/orm/query.js +6 -0
  144. package/orm/repository.types.d.ts +54 -2
  145. package/orm/server/database-schema.d.ts +34 -0
  146. package/orm/server/database-schema.js +29 -0
  147. package/orm/server/database.d.ts +19 -1
  148. package/orm/server/database.js +17 -3
  149. package/orm/server/drizzle/schema-converter.d.ts +2 -1
  150. package/orm/server/drizzle/schema-converter.js +12 -1
  151. package/orm/server/encryption.d.ts +16 -0
  152. package/orm/server/encryption.js +29 -4
  153. package/orm/server/index.d.ts +7 -0
  154. package/orm/server/index.js +7 -0
  155. package/orm/server/module.d.ts +20 -0
  156. package/orm/server/module.js +9 -0
  157. package/orm/server/query-converter.d.ts +17 -0
  158. package/orm/server/query-converter.js +66 -11
  159. package/orm/server/repository.d.ts +324 -18
  160. package/orm/server/repository.js +344 -73
  161. package/orm/server/transaction.d.ts +5 -5
  162. package/orm/server/transaction.js +5 -5
  163. package/orm/server/transactional.d.ts +75 -0
  164. package/orm/server/transactional.js +134 -0
  165. package/orm/server/types.d.ts +1 -0
  166. package/orm/sqls.d.ts +55 -0
  167. package/orm/sqls.js +60 -0
  168. package/orm/types.d.ts +67 -4
  169. package/orm/utils.d.ts +19 -3
  170. package/orm/utils.js +12 -0
  171. package/package.json +32 -31
  172. package/password/password-check-result.model.d.ts +9 -7
  173. package/password/password-check-result.model.js +8 -8
  174. package/password/password-check.js +5 -7
  175. package/password/password-check.localization.js +12 -12
  176. package/pdf/pdf.service.js +1 -1
  177. package/pdf/utils.d.ts +9 -0
  178. package/pdf/utils.js +19 -2
  179. package/process/spawn.d.ts +11 -4
  180. package/process/spawn.js +42 -5
  181. package/queue/postgres/queue.js +5 -5
  182. package/queue/queue.d.ts +6 -4
  183. package/queue/queue.js +6 -6
  184. package/schema/schemas/one-or-many.d.ts +2 -1
  185. package/schema/schemas/one-or-many.js +1 -1
  186. package/search-index/elastic/model/index-mapping.d.ts +1 -1
  187. package/search-index/elastic/model/index-mapping.js +0 -1
  188. package/search-index/elastic/search-index.d.ts +1 -2
  189. package/search-index/elastic/search-index.js +3 -3
  190. package/types.d.ts +1 -0
  191. package/utils/async-hook/async-hook.d.ts +9 -0
  192. package/utils/async-hook/async-hook.js +21 -0
  193. package/utils/async-hook/index.d.ts +1 -0
  194. package/utils/async-hook/index.js +1 -0
  195. package/utils/compression.js +1 -1
  196. package/utils/function/class.d.ts +6 -0
  197. package/utils/function/class.js +9 -0
  198. package/utils/function/index.d.ts +1 -0
  199. package/utils/function/index.js +1 -0
  200. package/utils/function/memoize.d.ts +18 -0
  201. package/utils/function/memoize.js +41 -2
  202. package/utils/jwt.d.ts +1 -1
  203. package/utils/jwt.js +5 -5
  204. package/utils/object/forward-ref.d.ts +3 -2
  205. package/utils/object/forward-ref.js +12 -12
  206. package/utils/object/lazy-property.js +2 -2
  207. package/utils/proxy.js +1 -1
  208. package/utils/stream/{readable-stream-from-promise.d.ts → from-promise.d.ts} +1 -0
  209. package/utils/stream/from-promise.js +27 -0
  210. package/utils/stream/index.d.ts +1 -1
  211. package/utils/stream/index.js +1 -1
  212. package/utils/stream/stream-reader.js +71 -31
  213. package/document-management/models/document-request-assignment-task-collection.model.d.ts +0 -7
  214. package/document-management/models/document-request-assignment-task.model.d.ts +0 -14
  215. package/document-management/models/document-request-assignment-task.model.js +0 -77
  216. package/document-management/models/document-request-file.model.d.ts +0 -16
  217. package/document-management/models/document-request-file.model.js +0 -86
  218. package/document-management/models/service-models/document.view-model.d.ts +0 -41
  219. package/document-management/models/service-models/normalized-document-collection-view.model.d.ts +0 -73
  220. package/document-management/models/service-models/normalized-document-collection-view.model.js +0 -110
  221. package/utils/stream/readable-stream-from-promise.js +0 -8
@@ -5,9 +5,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import '../polyfills.js';
8
- import { readFile } from 'node:fs/promises';
8
+ import { openAsBlob } from 'node:fs';
9
9
  import { Storage } from '@google-cloud/storage';
10
- import { FileState, GoogleAIFileManager } from '@google/generative-ai/server';
10
+ import { FileState, GoogleGenAI } from '@google/genai';
11
11
  import { AsyncEnumerable } from '../enumerable/async-enumerable.js';
12
12
  import { DetailsError } from '../errors/details.error.js';
13
13
  import { NotImplementedError } from '../errors/not-implemented.error.js';
@@ -21,7 +21,13 @@ import { assertDefinedPass, isBlob, isDefined, isUndefined } from '../utils/type
21
21
  import { millisecondsPerSecond } from '../utils/units.js';
22
22
  let AiFileService = class AiFileService {
23
23
  #options = injectArgument(this);
24
- #fileManager = isUndefined(this.#options.vertex) ? new GoogleAIFileManager(assertDefinedPass(this.#options.apiKey, 'Api key not defined')) : undefined;
24
+ #genAI = new GoogleGenAI({
25
+ vertexai: isDefined(this.#options.vertex?.project),
26
+ project: this.#options.vertex?.project,
27
+ location: this.#options.vertex?.location,
28
+ googleAuthOptions: isDefined(this.#options.vertex?.project) ? { apiKey: this.#options.apiKey, keyFile: this.#options.keyFile } : undefined,
29
+ apiKey: isUndefined(this.#options.vertex?.project) ? assertDefinedPass(this.#options.apiKey, 'Api key not defined') : undefined,
30
+ });
25
31
  #storage = isDefined(this.#options.vertex) ? new Storage({ keyFile: assertDefinedPass(this.#options.keyFile, 'Key file not defined'), projectId: this.#options.vertex.project }) : undefined;
26
32
  #fileMap = new Map();
27
33
  #fileUriMap = new Map();
@@ -63,11 +69,10 @@ let AiFileService = class AiFileService {
63
69
  }
64
70
  async uploadFile(fileInput, id) {
65
71
  const inputIsBlob = isBlob(fileInput);
66
- const buffer = inputIsBlob
67
- ? Buffer.from(await fileInput.arrayBuffer())
68
- : await readFile(fileInput.path);
69
- const mimeType = inputIsBlob ? fileInput.type : fileInput.mimeType;
70
- this.#logger.verbose(`Uploading file "${id}" (${formatBytes(buffer.length)})...`);
72
+ const blob = inputIsBlob
73
+ ? fileInput
74
+ : await openAsBlob(fileInput.path, { type: fileInput.mimeType });
75
+ this.#logger.verbose(`Uploading file "${id}" (${formatBytes(blob.size)})...`);
71
76
  if (isDefined(this.#storage)) {
72
77
  throw new NotImplementedError();
73
78
  /*
@@ -82,12 +87,12 @@ let AiFileService = class AiFileService {
82
87
  };
83
88
  */
84
89
  }
85
- const response = await this.#fileManager.uploadFile(buffer, { mimeType });
90
+ const response = await this.#genAI.files.upload({ file: blob, config: { mimeType: blob.type } });
86
91
  return {
87
92
  id,
88
- name: response.file.name,
89
- uri: response.file.uri,
90
- mimeType: response.file.mimeType
93
+ name: assertDefinedPass(response.name, 'Missing file name'),
94
+ uri: assertDefinedPass(response.uri, 'Missing file uri'),
95
+ mimeType: assertDefinedPass(response.mimeType, 'Missing file mime type'),
91
96
  };
92
97
  }
93
98
  async getBucket() {
@@ -105,22 +110,22 @@ let AiFileService = class AiFileService {
105
110
  lifecycle: {
106
111
  rule: [{
107
112
  action: { type: 'Delete' },
108
- condition: { age: 1 }
109
- }]
110
- }
113
+ condition: { age: 1 },
114
+ }],
115
+ },
111
116
  });
112
117
  this.#bucket = bucket;
113
118
  }
114
119
  return this.#bucket;
115
120
  }
116
121
  async waitForFileActive(file) {
117
- if (isUndefined(this.#fileManager)) {
122
+ if (isUndefined(this.#genAI)) {
118
123
  return;
119
124
  }
120
- let state = await this.#fileManager.getFile(file.name);
125
+ let state = await this.#genAI.files.get({ name: file.name });
121
126
  while (state.state == FileState.PROCESSING) {
122
127
  await timeout(millisecondsPerSecond);
123
- state = await this.#fileManager.getFile(file.name);
128
+ state = await this.#genAI.files.get({ name: file.name });
124
129
  }
125
130
  if (state.state == FileState.FAILED) {
126
131
  throw new DetailsError(state.error?.message ?? `Failed to process file ${state.name}`, state.error?.details);
@@ -1,8 +1,8 @@
1
1
  import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
2
- import { type OneOrMany, type SchemaTestable } from '../schema/index.js';
2
+ import { type SchemaTestable } from '../schema/index.js';
3
3
  import type { Enumeration as EnumerationType, EnumerationValue } from '../types.js';
4
4
  import { AiSession } from './ai-session.js';
5
- import { type AiModel, type Content, type ContentPart, type FileContentPart, type FileInput, type FunctionResultContentPart, type GenerationOptions, type GenerationRequest, type GenerationResult, type SchemaFunctionDeclarations, type SchemaFunctionDeclarationsResult } from './types.js';
5
+ import { type AiModel, type FileContentPart, type FileInput, type FunctionResultContentPart, type GenerationOptions, type GenerationRequest, type GenerationResult, type SchemaFunctionDeclarations, type SchemaFunctionDeclarationsResult } from './types.js';
6
6
  export type SpecializedGenerationResult<T> = {
7
7
  result: T;
8
8
  raw: GenerationResult;
@@ -43,15 +43,6 @@ export declare class AiService implements Resolvable<AiServiceArgument> {
43
43
  processFile(fileInput: FileInput): Promise<FileContentPart>;
44
44
  processFiles(fileInputs: FileInput[]): Promise<FileContentPart[]>;
45
45
  getFileById(id: string): FileContentPart;
46
- classify<T extends EnumerationType>(parts: OneOrMany<ContentPart>, types: T, options?: GenerationOptions & Pick<GenerationRequest, 'model'>): Promise<SpecializedGenerationResult<ClassificationResult<T>>>;
47
- getClassifyContents(parts: OneOrMany<ContentPart>): Content[];
48
- extractData<T>(parts: OneOrMany<ContentPart>, schema: SchemaTestable<T>, options?: GenerationOptions & Pick<GenerationRequest, 'model'>): Promise<SpecializedGenerationResult<T>>;
49
- getExtractDataConents(parts: OneOrMany<ContentPart>): Content[];
50
- analyzeContent<T extends EnumerationType>(parts: OneOrMany<ContentPart>, types: T, options?: GenerationOptions & {
51
- targetLanguage?: string;
52
- maximumNumberOfTags?: number;
53
- }): Promise<SpecializedGenerationResult<AnalyzeContentResult<T>>>;
54
- getAnalyzeContentConents(parts: OneOrMany<ContentPart>): Content[];
55
46
  callFunctions<const T extends SchemaFunctionDeclarations>(options: CallFunctionsOptions<T>): Promise<SpecializedGenerationResult<SchemaFunctionDeclarationsResult<T>[]> & {
56
47
  getFunctionResultContentParts: () => FunctionResultContentPart[];
57
48
  }>;
@@ -59,10 +50,11 @@ export declare class AiService implements Resolvable<AiServiceArgument> {
59
50
  generate<S>(request: GenerationRequest<S>): Promise<GenerationResult<S>>;
60
51
  generateStream<S>(request: GenerationRequest<S>): AsyncGenerator<GenerationResult<S>>;
61
52
  private _callFunctionsStream;
53
+ private getModelOutputTokenLimit;
54
+ private _getModelOutputTokenLimit;
62
55
  private convertContents;
63
56
  private convertContent;
64
57
  private convertFunctions;
65
58
  private convertGoogleContent;
66
- private getModel;
67
59
  }
68
60
  export declare function mergeGenerationStreamItems<S>(items: GenerationResult<S>[], schema?: SchemaTestable<S>): GenerationResult<S>;
package/ai/ai.service.js CHANGED
@@ -6,8 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  var _a;
8
8
  var AiService_1;
9
- import { FinishReason, FunctionCallingMode as GoogleFunctionCallingMode, VertexAI } from '@google-cloud/vertexai';
10
- import { GoogleGenerativeAI } from '@google/generative-ai';
9
+ import { FinishReason, FunctionCallingConfigMode as GoogleFunctionCallingMode, GoogleGenAI } from '@google/genai';
11
10
  import { NotSupportedError } from '../errors/not-supported.error.js';
12
11
  import { Singleton } from '../injector/decorators.js';
13
12
  import { inject, injectArgument } from '../injector/inject.js';
@@ -16,14 +15,14 @@ import { getShutdownSignal } from '../process-shutdown.js';
16
15
  import { DeferredPromise } from '../promise/deferred-promise.js';
17
16
  import { LazyPromise } from '../promise/lazy-promise.js';
18
17
  import { convertToOpenApiSchema } from '../schema/converters/openapi-converter.js';
19
- import { array, enumeration, nullable, object, Schema, string } from '../schema/index.js';
18
+ import { Schema } from '../schema/index.js';
20
19
  import { toArray } from '../utils/array/array.js';
21
20
  import { mapAsync } from '../utils/async-iterable-helpers/map.js';
22
21
  import { toArrayAsync } from '../utils/async-iterable-helpers/to-array.js';
23
22
  import { lazyObject } from '../utils/object/lazy-property.js';
24
23
  import { hasOwnProperty, objectEntries } from '../utils/object/object.js';
25
24
  import { cancelableTimeout } from '../utils/timing.js';
26
- import { assertDefinedPass, assertNotNullPass, isDefined, isError, isNotNull, isNull, isUndefined } from '../utils/type-guards.js';
25
+ import { assertDefinedPass, isDefined, isError, isNotNull, isNull, isUndefined } from '../utils/type-guards.js';
27
26
  import { millisecondsPerSecond } from '../utils/units.js';
28
27
  import { resolveValueOrAsyncProvider } from '../utils/value-or-provider.js';
29
28
  import { AiFileService } from './ai-file.service.js';
@@ -39,16 +38,21 @@ export class AiServiceOptions {
39
38
  const functionCallingModeMap = {
40
39
  auto: GoogleFunctionCallingMode.AUTO,
41
40
  force: GoogleFunctionCallingMode.ANY,
42
- none: GoogleFunctionCallingMode.NONE
41
+ none: GoogleFunctionCallingMode.NONE,
43
42
  };
44
43
  let generationCounter = 0;
45
44
  let AiService = AiService_1 = class AiService {
46
45
  #options = injectArgument(this, { optional: true }) ?? inject(AiServiceOptions);
47
46
  #fileService = inject(AiFileService, this.#options);
48
47
  #logger = inject(Logger, AiService_1.name);
49
- #genAI = (isDefined(this.#options.vertex)
50
- ? new VertexAI({ project: this.#options.vertex.project, location: this.#options.vertex.location, googleAuthOptions: { apiKey: this.#options.apiKey, keyFile: this.#options.keyFile } })
51
- : new GoogleGenerativeAI(assertDefinedPass(this.#options.apiKey, 'Api key not defined')));
48
+ #genAI = new GoogleGenAI({
49
+ vertexai: isDefined(this.#options.vertex?.project),
50
+ project: this.#options.vertex?.project,
51
+ location: this.#options.vertex?.location,
52
+ googleAuthOptions: isDefined(this.#options.vertex?.project) ? { apiKey: this.#options.apiKey, keyFile: this.#options.keyFile } : undefined,
53
+ apiKey: isUndefined(this.#options.vertex?.project) ? assertDefinedPass(this.#options.apiKey, 'Api key not defined') : undefined,
54
+ });
55
+ #maxOutputTokensCache = new Map();
52
56
  defaultModel = this.#options.defaultModel ?? 'gemini-2.0-flash';
53
57
  createSession() {
54
58
  return new AiSession(this);
@@ -62,117 +66,17 @@ let AiService = AiService_1 = class AiService {
62
66
  getFileById(id) {
63
67
  return { file: id };
64
68
  }
65
- async classify(parts, types, options) {
66
- const generationSchema = object({
67
- types: nullable(array(object({
68
- type: enumeration(types, { description: 'Type of document' }),
69
- confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation' })
70
- }), { description: 'One or more document types that matches' }))
71
- });
72
- const generation = await this.generate({
73
- model: options?.model,
74
- generationOptions: {
75
- maxOutputTokens: 1048,
76
- temperature: 0.5,
77
- ...options
78
- },
79
- generationSchema,
80
- systemInstruction: 'You are a highly accurate document classification AI. Your task is to analyze the content of a given document and determine its type based on a predefined list of possible document types.',
81
- contents: this.getClassifyContents(parts)
82
- });
83
- return {
84
- result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
85
- raw: generation
86
- };
87
- }
88
- getClassifyContents(parts) {
89
- return [{
90
- role: 'user',
91
- parts: [
92
- ...toArray(parts),
93
- { text: 'Classify the document. Output as JSON using the provided schema\n\nIf none of the provided document types are a suitable match, return null for types.' }
94
- ]
95
- }];
96
- }
97
- async extractData(parts, schema, options) {
98
- const generation = await this.generate({
99
- model: options?.model,
100
- generationOptions: {
101
- temperature: 0.5,
102
- ...options
103
- },
104
- generationSchema: schema,
105
- systemInstruction: `You are a highly skilled data extraction AI, specializing in accurately identifying and extracting information from unstructured text documents and converting it into a structured JSON format. Your primary goal is to meticulously follow the provided JSON schema and populate it with data extracted from the given document.
106
-
107
- **Instructions:**
108
- Carefully read and analyze the provided document. Identify relevant information that corresponds to each field in the JSON schema. Focus on accuracy and avoid making assumptions. If a field has multiple possible values, extract all relevant ones into the correct array structures ONLY IF the schema defines that field as an array; otherwise, extract only the single most relevant value.`,
109
- contents: this.getExtractDataConents(parts)
110
- });
111
- return {
112
- result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
113
- raw: generation
114
- };
115
- }
116
- getExtractDataConents(parts) {
117
- return [{
118
- role: 'user',
119
- parts: [
120
- ...toArray(parts),
121
- { text: 'Extract the data as specified in the schema. Output as JSON.' }
122
- ]
123
- }];
124
- }
125
- async analyzeContent(parts, types, options) {
126
- const schema = object({
127
- content: string({ description: 'Content of the document with important details only' }),
128
- types: nullable(array(object({
129
- type: enumeration(types, { description: 'Type of document' }),
130
- confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation' })
131
- }), { description: 'One or more document types that matches' })),
132
- tags: array(string({ description: 'Tag which describes the content' }), { description: 'List of tags', maximum: options?.maximumNumberOfTags ?? 5 })
133
- });
134
- const generation = await this.generate({
135
- generationOptions: {
136
- maxOutputTokens: 2048,
137
- temperature: 0.5,
138
- ...options
139
- },
140
- generationSchema: schema,
141
- systemInstruction: `You are a highly skilled data extraction AI, specializing in accurately identifying and extracting information from unstructured content and converting it into a structured JSON format. Your primary goal is to meticulously follow the provided JSON schema and populate it with data extracted from the given document.
142
-
143
- **Instructions:**
144
- Carefully read and analyze the provided content.
145
- Identify key points and relevant information that describes the content. Focus on a general overview without providing specific details.
146
- Classify the content based on the provided list of types.
147
- Output up to ${options?.maximumNumberOfTags ?? 5} tags.
148
- Always output the content and tags in ${options?.targetLanguage ?? 'the same language as the content'}.`,
149
- contents: this.getAnalyzeContentConents(parts)
150
- });
151
- return {
152
- result: JSON.parse(assertNotNullPass(generation.text, 'No text returned.')),
153
- raw: generation
154
- };
155
- }
156
- getAnalyzeContentConents(parts) {
157
- return [{
158
- role: 'user',
159
- parts: [
160
- ...toArray(parts),
161
- { text: 'Classify the document. Output as JSON.' }
162
- ]
163
- }];
164
- }
165
69
  async callFunctions(options) {
166
70
  const generation = await this.generate({
167
71
  model: options.model,
168
72
  generationOptions: {
169
73
  temperature: 0.5,
170
- ...options
74
+ ...options,
171
75
  },
172
76
  systemInstruction: options.systemInstruction,
173
77
  functions: options.functions,
174
78
  functionCallingMode: options.functionCallingMode ?? 'force',
175
- contents: options.contents
79
+ contents: options.contents,
176
80
  });
177
81
  const result = [];
178
82
  for (const call of generation.functionCalls) {
@@ -184,13 +88,13 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
184
88
  functionName: call.name,
185
89
  parameters: parameters,
186
90
  handlerResult: handlerResult,
187
- getFunctionResultContentPart: () => ({ functionResult: { name: call.name, value: handlerResult } })
91
+ getFunctionResultContentPart: () => ({ functionResult: { name: call.name, value: handlerResult } }),
188
92
  });
189
93
  }
190
94
  return {
191
95
  result,
192
96
  raw: generation,
193
- getFunctionResultContentParts: () => result.map((result) => result.getFunctionResultContentPart())
97
+ getFunctionResultContentParts: () => result.map((result) => result.getFunctionResultContentPart()),
194
98
  };
195
99
  }
196
100
  callFunctionsStream(options) {
@@ -209,17 +113,26 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
209
113
  async *generateStream(request) {
210
114
  const generationNumber = ++generationCounter;
211
115
  const googleFunctionDeclarations = isDefined(request.functions) ? await this.convertFunctions(request.functions) : undefined;
212
- const generationConfig = {
213
- maxOutputTokens: request.generationOptions?.maxOutputTokens,
116
+ const config = {
117
+ systemInstruction: request.systemInstruction,
214
118
  temperature: request.generationOptions?.temperature,
215
119
  topP: request.generationOptions?.topP,
216
120
  topK: request.generationOptions?.topK,
121
+ presencePenalty: request.generationOptions?.presencePenalty,
122
+ frequencyPenalty: request.generationOptions?.frequencyPenalty,
217
123
  responseMimeType: isDefined(request.generationSchema) ? 'application/json' : undefined,
218
124
  responseSchema: isDefined(request.generationSchema) ? convertToOpenApiSchema(request.generationSchema) : undefined,
219
- frequencyPenalty: request.generationOptions?.frequencyPenalty
125
+ safetySettings: [],
126
+ tools: (isDefined(googleFunctionDeclarations) && (googleFunctionDeclarations.length > 0)) ? [{ functionDeclarations: googleFunctionDeclarations }] : undefined,
127
+ toolConfig: isDefined(request.functionCallingMode)
128
+ ? { functionCallingConfig: { mode: functionCallingModeMap[request.functionCallingMode] } }
129
+ : undefined,
130
+ thinkingConfig: {
131
+ thinkingBudget: request.generationOptions?.thinkingBudget,
132
+ },
220
133
  };
221
134
  const model = request.model ?? this.defaultModel;
222
- const maxModelTokens = model.includes('thinking') ? 65536 : 8192;
135
+ const maxModelTokens = await this.getModelOutputTokenLimit(model);
223
136
  const maxTotalOutputTokens = request.generationOptions?.maxOutputTokens ?? maxModelTokens;
224
137
  const inputContent = this.convertContents(request.contents);
225
138
  let iterations = 0;
@@ -231,17 +144,13 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
231
144
  for (let i = 0;; i++) {
232
145
  try {
233
146
  this.#logger.verbose(`[C:${generationNumber}] [I:${iterations + 1}] Generating...`);
234
- generation = await this.getModel(model).generateContentStream({
235
- generationConfig: {
236
- ...generationConfig,
237
- maxOutputTokens: Math.min(maxModelTokens, maxTotalOutputTokens - totalOutputTokens)
147
+ generation = await this.#genAI.models.generateContentStream({
148
+ model,
149
+ config: {
150
+ ...config,
151
+ maxOutputTokens: Math.min(maxModelTokens, maxTotalOutputTokens - totalOutputTokens),
238
152
  },
239
- systemInstruction: request.systemInstruction,
240
- tools: (isDefined(googleFunctionDeclarations) && (googleFunctionDeclarations.length > 0)) ? [{ functionDeclarations: googleFunctionDeclarations }] : undefined,
241
- toolConfig: isDefined(request.functionCallingMode)
242
- ? { functionCallingConfig: { mode: functionCallingModeMap[request.functionCallingMode] } }
243
- : undefined,
244
- contents: inputContent
153
+ contents: inputContent,
245
154
  });
246
155
  break;
247
156
  }
@@ -259,12 +168,19 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
259
168
  iterations++;
260
169
  let lastUsageMetadata;
261
170
  let candidate;
262
- for await (const generationResponse of generation.stream) {
263
- candidate = generationResponse.candidates.at(0);
264
- inputContent.push(candidate.content);
171
+ for await (const generationResponse of generation) {
172
+ candidate = generationResponse.candidates?.at(0);
173
+ const rawContent = candidate?.content;
174
+ if (isUndefined(candidate)) {
175
+ throw new Error('No candidate returned.');
176
+ }
177
+ if (isUndefined(rawContent)) {
178
+ throw new Error('No content returned.');
179
+ }
180
+ inputContent.push(rawContent);
265
181
  const { promptTokenCount = 0, candidatesTokenCount = 0 } = generationResponse.usageMetadata ?? {};
266
182
  lastUsageMetadata = generationResponse.usageMetadata;
267
- const content = this.convertGoogleContent(candidate.content);
183
+ const content = this.convertGoogleContent(rawContent);
268
184
  let text;
269
185
  let functionCallParts;
270
186
  const result = {
@@ -294,13 +210,13 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
294
210
  iterations,
295
211
  prompt: totalPromptTokens + promptTokenCount,
296
212
  output: totalOutputTokens + candidatesTokenCount,
297
- total: totalTokens + promptTokenCount + candidatesTokenCount
298
- }
213
+ total: totalTokens + promptTokenCount + candidatesTokenCount,
214
+ },
299
215
  };
300
216
  yield result;
301
217
  }
302
218
  totalPromptTokens += lastUsageMetadata?.promptTokenCount ?? 0;
303
- totalOutputTokens += lastUsageMetadata?.candidatesTokenCount ?? 0;
219
+ totalOutputTokens += lastUsageMetadata?.responseTokenCount ?? 0;
304
220
  totalTokens += lastUsageMetadata?.totalTokenCount ?? 0;
305
221
  if (candidate?.finishReason != FinishReason.MAX_TOKENS) {
306
222
  break;
@@ -312,12 +228,12 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
312
228
  model: options.model,
313
229
  generationOptions: {
314
230
  temperature: 0.5,
315
- ...options
231
+ ...options,
316
232
  },
317
233
  systemInstruction: options.systemInstruction,
318
234
  functions: options.functions,
319
235
  functionCallingMode: options.functionCallingMode ?? 'force',
320
- contents: options.contents
236
+ contents: options.contents,
321
237
  });
322
238
  const items = [];
323
239
  for await (const generation of generationStream) {
@@ -331,12 +247,31 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
331
247
  functionName: call.name,
332
248
  parameters: parameters,
333
249
  handlerResult: handlerResult,
334
- getFunctionResultContentPart: () => ({ functionResult: { name: call.name, value: handlerResult } })
250
+ getFunctionResultContentPart: () => ({ functionResult: { name: call.name, value: handlerResult } }),
335
251
  };
336
252
  }
337
253
  }
338
254
  itemsPromise.resolve(items);
339
255
  }
256
+ async getModelOutputTokenLimit(model) {
257
+ const existingValue = this.#maxOutputTokensCache.get(model);
258
+ if (isDefined(existingValue)) {
259
+ return existingValue;
260
+ }
261
+ const promise = this._getModelOutputTokenLimit(model);
262
+ this.#maxOutputTokensCache.set(model, promise);
263
+ promise
264
+ .then((limit) => this.#maxOutputTokensCache.set(model, limit))
265
+ .catch(() => this.#maxOutputTokensCache.delete(model));
266
+ return promise;
267
+ }
268
+ async _getModelOutputTokenLimit(model) {
269
+ const modelInfo = await this.#genAI.models.get({ model });
270
+ if (isUndefined(modelInfo.outputTokenLimit)) {
271
+ throw new Error(`Model ${model} does not support maxOutputTokens`);
272
+ }
273
+ return modelInfo.outputTokenLimit;
274
+ }
340
275
  convertContents(contents) {
341
276
  return toArray(contents).map((content) => this.convertContent(content));
342
277
  }
@@ -358,7 +293,7 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
358
293
  return { functionCall: { name: part.functionCall.name, args: part.functionCall.parameters } };
359
294
  }
360
295
  throw new NotSupportedError('Unsupported content part.');
361
- })
296
+ }),
362
297
  };
363
298
  }
364
299
  async convertFunctions(functions) {
@@ -371,7 +306,7 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
371
306
  return {
372
307
  name,
373
308
  description: declaration.description,
374
- parameters: isDefined(parametersSchema) ? convertToOpenApiSchema(parametersSchema) : undefined
309
+ parameters: isDefined(parametersSchema) ? convertToOpenApiSchema(parametersSchema) : undefined,
375
310
  };
376
311
  });
377
312
  const functionsArray = await toArrayAsync(mapped);
@@ -391,23 +326,20 @@ Always output the content and tags in ${options?.targetLanguage ?? 'the same lan
391
326
  return { text: part.text };
392
327
  }
393
328
  if (isDefined(part.fileData)) {
394
- const file = assertDefinedPass(this.#fileService.getFileByUri(part.fileData.fileUri), 'File not found.');
329
+ const file = assertDefinedPass(this.#fileService.getFileByUri(assertDefinedPass(part.fileData.fileUri, 'Missing file uri')), 'File not found.');
395
330
  return { file: file.id };
396
331
  }
397
332
  if (isDefined(part.functionResponse)) {
398
- return { functionResult: { name: part.functionResponse.name, value: part.functionResponse.response } };
333
+ return { functionResult: { name: assertDefinedPass(part.functionResponse.name, 'Missing function name'), value: part.functionResponse.response } };
399
334
  }
400
335
  if (isDefined(part.functionCall)) {
401
- return { functionCall: { name: part.functionCall.name, parameters: part.functionCall.args } };
336
+ return { functionCall: { name: assertDefinedPass(part.functionCall.name, 'Missing function name'), parameters: part.functionCall.args } };
402
337
  }
403
338
  throw new NotSupportedError('Unsupported content part.');
404
339
  })
405
- .filter(isNotNull)
340
+ .filter(isNotNull),
406
341
  };
407
342
  }
408
- getModel(model) {
409
- return this.#genAI.getGenerativeModel({ model });
410
- }
411
343
  };
412
344
  AiService = AiService_1 = __decorate([
413
345
  Singleton()
@@ -428,7 +360,7 @@ export function mergeGenerationStreamItems(items, schema) {
428
360
  },
429
361
  json() {
430
362
  if (isUndefined(schema)) {
431
- return undefined;
363
+ return undefined; // eslint-disable-line @typescript-eslint/no-unsafe-return
432
364
  }
433
365
  if (isNull(this.text)) {
434
366
  throw new Error('No text to parse available.');
@@ -442,6 +374,6 @@ export function mergeGenerationStreamItems(items, schema) {
442
374
  return functionCallParts;
443
375
  },
444
376
  finishReason: { value: items.at(-1).finishReason },
445
- usage: { value: items.at(-1).usage }
377
+ usage: { value: items.at(-1).usage },
446
378
  });
447
379
  }
package/ai/functions.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import type { FunctionDeclaration } from '@google/generative-ai';
1
+ import type { FunctionDeclaration } from '@google/genai';
2
2
  import type { AbstractConstructor } from '../types.js';
3
3
  export declare function getFunctionDeclarations(type: AbstractConstructor): FunctionDeclaration[];
package/ai/types.d.ts CHANGED
@@ -53,13 +53,15 @@ export type Content = {
53
53
  };
54
54
  export type FunctionCallingMode = 'auto' | 'force' | 'none';
55
55
  export type FinishReason = 'stop' | 'maxTokens' | 'unknown';
56
- export type AiModel = LiteralUnion<'gemini-2.0-flash' | 'gemini-2.0-flash-lite' | 'gemini-2.0-pro-exp-02-05' | 'gemini-2.0-flash-thinking-exp-01-21', string>;
56
+ export type AiModel = LiteralUnion<'gemini-2.5-pro-exp-03-25' | 'gemini-2.5-flash-exp-04-17' | 'gemini-2.0-flash' | 'gemini-2.0-flash-lite', string>;
57
57
  export type GenerationOptions = {
58
58
  maxOutputTokens?: number;
59
59
  temperature?: number;
60
60
  topP?: number;
61
61
  topK?: number;
62
+ presencePenalty?: number;
62
63
  frequencyPenalty?: number;
64
+ thinkingBudget?: number;
63
65
  };
64
66
  export type GenerationRequest<S = unknown> = {
65
67
  model?: AiModel;
@@ -106,9 +106,9 @@ let ApiGateway = class ApiGateway {
106
106
  hostname: '*',
107
107
  port: '*',
108
108
  search: '*',
109
- hash: '*'
109
+ hash: '*',
110
110
  }),
111
- endpoints: new Map()
111
+ endpoints: new Map(),
112
112
  };
113
113
  this.apis.set(resource, resourceApis);
114
114
  }
@@ -185,14 +185,14 @@ let ApiGateway = class ApiGateway {
185
185
  parameters: validatedParameters,
186
186
  body,
187
187
  request: context.request,
188
- getToken: async () => this.requestTokenProvider.getToken(requestContext)
188
+ getToken: async () => this.requestTokenProvider.getToken(requestContext),
189
189
  };
190
190
  const result = await context.endpoint.implementation(requestContext);
191
191
  if (result instanceof HttpServerResponse) {
192
- context.response.update(result); // eslint-disable-line require-atomic-updates
192
+ context.response.update(result);
193
193
  }
194
194
  else {
195
- context.response.body = isUint8Array(result) ? { buffer: result } // eslint-disable-line require-atomic-updates
195
+ context.response.body = isUint8Array(result) ? { buffer: result }
196
196
  : isBlob(result) ? { stream: result.stream() }
197
197
  : isReadableStream(result) ? { stream: result }
198
198
  : (result instanceof ServerSentEventsSource) ? { events: result }
@@ -204,7 +204,7 @@ let ApiGateway = class ApiGateway {
204
204
  };
205
205
  ApiGateway = __decorate([
206
206
  Singleton({
207
- defaultArgumentProvider: (context) => context.resolve(API_MODULE_OPTIONS).gatewayOptions
207
+ defaultArgumentProvider: (context) => context.resolve(API_MODULE_OPTIONS).gatewayOptions,
208
208
  }),
209
209
  __param(1, ResolveArg('ApiGateway')),
210
210
  __param(2, InjectArg()),