@tstdl/base 0.93.170 → 0.93.171

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.
@@ -1,7 +1,9 @@
1
1
  import type { ModelReference } from 'genkit';
2
2
  import type { Instructions } from '../../ai/prompts/instructions-formatter.js';
3
3
  import type { DocumentWorkflowStep } from './document-workflow.model.js';
4
+ import type { GeminiModelConfig } from '../../ai/index.js';
4
5
  export type InstructionStrategy = 'replace' | 'append';
6
+ export type DocumentManagementThinkingLevel = NonNullable<GeminiModelConfig['thinkingConfig']>['thinkingLevel'];
5
7
  export type InstructionOverride = string | {
6
8
  /**
7
9
  * Simple way: Provide a specific format pattern.
@@ -20,6 +22,8 @@ export type InstructionOverride = string | {
20
22
  export type AiConfiguration = {
21
23
  /** The model to use. */
22
24
  model?: ModelReference<any>;
25
+ /** The thinking level to use for thinking models. */
26
+ thinkingLevel?: DocumentManagementThinkingLevel;
23
27
  /** The language to use for AI outputs. */
24
28
  language?: string;
25
29
  /** Prompt overrides. */
@@ -2,7 +2,7 @@ import { type TstdlGenkitGenerationOptions } from '../../../ai/genkit/index.js';
2
2
  import { type PromptBuilder } from '../../../ai/prompts/index.js';
3
3
  import { type SchemaTestable } from '../../../schema/index.js';
4
4
  import type { ObjectLiteral } from '../../../types/types.js';
5
- import type { ModelReference } from 'genkit';
5
+ import { type ModelReference } from 'genkit';
6
6
  import type { AiConfiguration, DocumentPropertyDataType, InstructionOverride } from '../../models/index.js';
7
7
  import { Document, DocumentWorkflowStep } from '../../models/index.js';
8
8
  import { type AiConfigurationResolveDataMap } from './document-management-ai-provider.service.js';
@@ -19,8 +19,8 @@ import { distinct } from '../../../utils/array/index.js';
19
19
  import { numericDateToDateTime, tryDateObjectToNumericDate } from '../../../utils/date-time.js';
20
20
  import { fromEntries, hasOwnProperty, objectEntries, objectKeys } from '../../../utils/object/object.js';
21
21
  import { assertDefined, assertDefinedPass, assertNotNull, isDefined, isNotNull, isNotNullOrUndefined, isNull, isString, isUndefined } from '../../../utils/type-guards.js';
22
+ import { GenkitError } from 'genkit';
22
23
  import { Document, DocumentProperty, DocumentRequestState, DocumentType, DocumentTypeProperty, DocumentWorkflowStep } from '../../models/index.js';
23
- import { DocumentManagementConfiguration } from '../module.js';
24
24
  import { documentCategory, documentRequest, documentRequestCollectionAssignment, documentType } from '../schemas.js';
25
25
  import { DocumentCategoryTypeService } from './document-category-type.service.js';
26
26
  import { DocumentCollectionService } from './document-collection.service.js';
@@ -41,7 +41,6 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
41
41
  #documentCategoryTypeService = inject(DocumentCategoryTypeService);
42
42
  #documentFileService = inject(DocumentFileService);
43
43
  #documentPropertyService = inject(DocumentPropertyService);
44
- #documentManagementConfiguration = inject(DocumentManagementConfiguration, undefined, { optional: true });
45
44
  #aiProvider = inject(DocumentManagementAiProviderService, undefined, { optional: true });
46
45
  #documentPropertyRepository = injectRepository(DocumentProperty);
47
46
  #documentRepository = injectRepository(Document);
@@ -83,7 +82,7 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
83
82
  promptBuilder,
84
83
  schema,
85
84
  document,
86
- config: { maxOutputTokens: 128 },
85
+ config: { maxOutputTokens: 1024 },
87
86
  aiConfig,
88
87
  });
89
88
  const typeId = typeLabelEntries.find((entry) => entry.label == result.documentType)?.id;
@@ -149,7 +148,7 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
149
148
  data: { existingTags: tagLabels },
150
149
  schema: generationSchema,
151
150
  document,
152
- config: { maxOutputTokens: 2048 },
151
+ config: { maxOutputTokens: 4096 },
153
152
  aiConfig,
154
153
  });
155
154
  const filteredDocumentTags = extraction.documentTags.filter((tag) => (tag != extraction.documentTitle) && (tag != extraction.documentSubtitle));
@@ -207,7 +206,7 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
207
206
  promptBuilder: createAssignCollectionPrompt(),
208
207
  data: { document: documentData, documentProperties: fromEntries(propertyEntries), collections },
209
208
  schema: assignCollectionSchema,
210
- config: { maxOutputTokens: 512 },
209
+ config: { maxOutputTokens: 2048 },
211
210
  });
212
211
  return result.collectionIds;
213
212
  }
@@ -253,13 +252,15 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
253
252
  promptBuilder: createAssignRequestPrompt(),
254
253
  data: { document: documentData, documentProperties: fromEntries(propertyEntries), requests },
255
254
  schema: assignRequestSchema,
256
- config: { maxOutputTokens: 128 },
255
+ config: { maxOutputTokens: 1024 },
257
256
  });
258
257
  return result.requestId;
259
258
  }
260
259
  async runAi(tenantId, step, stepData, options) {
261
260
  const config = options.aiConfig ?? await this.resolveAiConfiguration(tenantId, step, stepData);
262
261
  const model = config.model ?? options.defaultModel;
262
+ const thinkingLevel = config.thinkingLevel ?? 'LOW';
263
+ const configuredModel = isString(model) ? model : model.withConfig({ thinkingConfig: { thinkingLevel } });
263
264
  const builder = options.promptBuilder;
264
265
  if (isDefined(config.language)) {
265
266
  builder.addInstructions({ 'Output Language': languagePrompt(config.language) });
@@ -282,17 +283,26 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
282
283
  if (isDefined(options.document)) {
283
284
  builder.addMedia(await this.#documentFileService.getContent(options.document), options.document.mimeType);
284
285
  }
285
- const result = await this.#genkit.generate(genkitGenerationOptions({
286
- model,
287
- config: options.config,
288
- output: { schema: options.schema },
289
- system: builder.buildSystemPrompt(),
290
- prompt: builder.buildUserPrompt(),
291
- }));
292
- if (isNull(result.output)) {
293
- throw new Error(`AI returned null output for ${step} ${options.targetId ?? ''}`);
286
+ try {
287
+ const result = await this.#genkit.generate(genkitGenerationOptions({
288
+ model: configuredModel,
289
+ config: options.config,
290
+ output: { schema: options.schema },
291
+ system: builder.buildSystemPrompt(),
292
+ prompt: builder.buildUserPrompt(),
293
+ }));
294
+ this.#logger.trace(`AI result for ${step} ${options.targetId ?? ''}: usage=${JSON.stringify(result.usage)}, finishReason=${result.finishReason}`);
295
+ if (isNull(result.output)) {
296
+ throw new Error(`AI returned null output for ${step} ${options.targetId ?? ''}. Finish reason: ${result.finishReason}`);
297
+ }
298
+ return result.output;
299
+ }
300
+ catch (error) {
301
+ if (error instanceof GenkitError) {
302
+ this.#logger.error(`AI ${step} ${options.targetId ?? ''} failed: status=${error.status}, message=${error.originalMessage}, details=${JSON.stringify(error.detail)}`);
303
+ }
304
+ throw error;
294
305
  }
295
- return result.output;
296
306
  }
297
307
  async resolveAiConfiguration(tenantId, step, data) {
298
308
  const globalConfig = await this.#aiProvider?.getGlobalConfiguration(tenantId);
@@ -312,6 +322,7 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
312
322
  stepConfig,
313
323
  ].filter(isDefined);
314
324
  const model = mergeMostSpecific(configs, 'model');
325
+ const thinkingLevel = mergeMostSpecific(configs, 'thinkingLevel');
315
326
  const language = mergeMostSpecific(configs, 'language');
316
327
  const systemAddition = resolveAdditions(configs.map((c) => c.prompt?.systemAddition));
317
328
  const userAddition = resolveAdditions(configs.map((c) => c.prompt?.userAddition));
@@ -321,6 +332,7 @@ let DocumentManagementAiService = DocumentManagementAiService_1 = class Document
321
332
  const classification = mergeMostSpecific(configs, 'classification');
322
333
  return {
323
334
  model,
335
+ thinkingLevel,
324
336
  language,
325
337
  prompt: {
326
338
  systemAddition,
@@ -1,6 +1,7 @@
1
1
  import type { AiConfiguration, DocumentManagementAiConfiguration, DocumentWorkflowStep } from '../../document-management/index.js';
2
2
  import { DocumentManagementAiProviderService, type AiConfigurationResolveDataMap } from '../../document-management/server/index.js';
3
3
  export declare class ExampleAiProviderService extends DocumentManagementAiProviderService {
4
+ #private;
4
5
  /**
5
6
  * Providing global defaults for the entire Document Management module.
6
7
  */
@@ -9,6 +9,7 @@ import { fewShotPrompt, stylePrompt } from '../../ai/prompts/index.js';
9
9
  import { DocumentManagementAiProviderService } from '../../document-management/server/index.js';
10
10
  import { Singleton } from '../../injector/index.js';
11
11
  let ExampleAiProviderService = class ExampleAiProviderService extends DocumentManagementAiProviderService {
12
+ #model = injectModel('gemini-3.1-flash-lite-preview').withConfig({ thinkingConfig: { thinkingLevel: 'LOW' } });
12
13
  /**
13
14
  * Providing global defaults for the entire Document Management module.
14
15
  */
@@ -16,9 +17,9 @@ let ExampleAiProviderService = class ExampleAiProviderService extends DocumentMa
16
17
  return {
17
18
  defaults: {
18
19
  language: 'German', // Steer all AI outputs to German
19
- model: injectModel('gemini-3.1-flash-lite-preview').withConfig({ thinkingConfig: { thinkingLevel: 'LOW' } }),
20
+ model: this.#model,
20
21
  prompt: {
21
- systemAddition: 'Additional global instructions for all AI steps.',
22
+ // systemAddition: 'Additional global instructions for all AI steps.',
22
23
  },
23
24
  },
24
25
  };
@@ -32,9 +33,9 @@ let ExampleAiProviderService = class ExampleAiProviderService extends DocumentMa
32
33
  getClassificationConfiguration() {
33
34
  return {
34
35
  // Use a faster/cheaper model for classification
35
- model: injectModel('gemini-3.1-flash-lite-preview').withConfig({ thinkingConfig: { thinkingLevel: 'LOW' } }),
36
+ model: this.#model,
36
37
  prompt: {
37
- systemAddition: 'For classification, focus strictly on the layout.',
38
+ systemAddition: 'For classification, focus strictly on document content.',
38
39
  },
39
40
  };
40
41
  }
@@ -49,7 +49,7 @@ const config = {
49
49
  },
50
50
  },
51
51
  s3: {
52
- endpoint: string('S3_ENDPOINT', 'http://localhost:9000'),
52
+ endpoint: string('S3_ENDPOINT', 'http://localhost:19552'),
53
53
  accessKey: string('S3_ACCESS_KEY', 'tstdl-dev'),
54
54
  secretKey: string('S3_SECRET_KEY', 'tstdl-dev'),
55
55
  bucket: string('S3_BUCKET', undefined),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.170",
3
+ "version": "0.93.171",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"