@tstdl/base 0.92.8 → 0.92.9
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/ai.service.d.ts +19 -4
- package/ai/ai.service.js +241 -3
- package/ai/functions.d.ts +5 -0
- package/ai/functions.js +40 -0
- package/ai/types.d.ts +27 -0
- package/ai/types.js +3 -0
- package/orm/schemas/json.d.ts +2 -2
- package/orm/schemas/numeric-date.d.ts +2 -2
- package/orm/schemas/timestamp.d.ts +2 -2
- package/orm/schemas/uuid.d.ts +2 -2
- package/package.json +5 -4
- package/reflection/registry.js +2 -2
- package/reflection/utils.d.ts +1 -3
- package/schema/decorators/index.d.ts +2 -3
- package/schema/decorators/index.js +1 -3
- package/schema/decorators/schema.d.ts +21 -0
- package/schema/decorators/schema.js +36 -0
- package/schema/decorators/types.d.ts +10 -2
- package/schema/decorators/utils.d.ts +7 -2
- package/schema/decorators/utils.js +26 -7
- package/schema/schema.d.ts +2 -2
- package/schema/schemas/any.d.ts +2 -2
- package/schema/schemas/array.d.ts +2 -2
- package/schema/schemas/bigint.d.ts +2 -2
- package/schema/schemas/boolean.d.ts +2 -2
- package/schema/schemas/date.d.ts +2 -2
- package/schema/schemas/defaulted.d.ts +2 -2
- package/schema/schemas/deferred.d.ts +2 -2
- package/schema/schemas/enumeration.d.ts +2 -2
- package/schema/schemas/function.d.ts +20 -6
- package/schema/schemas/function.js +58 -7
- package/schema/schemas/instance.d.ts +2 -2
- package/schema/schemas/literal.d.ts +2 -2
- package/schema/schemas/never.d.ts +1 -1
- package/schema/schemas/nullable.d.ts +2 -2
- package/schema/schemas/nullable.js +2 -2
- package/schema/schemas/number.d.ts +4 -4
- package/schema/schemas/object.d.ts +2 -2
- package/schema/schemas/object.js +7 -18
- package/schema/schemas/one-or-many.d.ts +2 -2
- package/schema/schemas/optional.d.ts +2 -2
- package/schema/schemas/optional.js +2 -2
- package/schema/schemas/readable-stream.d.ts +2 -2
- package/schema/schemas/regexp.d.ts +2 -2
- package/schema/schemas/string.d.ts +2 -2
- package/schema/schemas/symbol.d.ts +2 -2
- package/schema/schemas/uint8-array.d.ts +2 -2
- package/schema/schemas/union.d.ts +2 -2
- package/schema/schemas/unknown.d.ts +2 -2
- package/schema/testable.d.ts +2 -2
- package/schema/testable.js +9 -9
- package/templates/resolvers/jsx.template-resolver.js +2 -2
- package/types.d.ts +1 -1
- package/utils/object/lazy-property.d.ts +2 -2
- package/utils/object/object.d.ts +2 -1
- package/schema/decorators/property.d.ts +0 -12
- package/schema/decorators/property.js +0 -21
package/ai/ai.service.d.ts
CHANGED
|
@@ -5,19 +5,18 @@ import { LiteralUnion } from 'type-fest';
|
|
|
5
5
|
import { Resolvable, type resolveArgumentType } from '../injector/interfaces.js';
|
|
6
6
|
import { OneOrMany, SchemaTestable } from '../schema/index.js';
|
|
7
7
|
import { Enumeration as EnumerationType, EnumerationValue } from '../types.js';
|
|
8
|
-
|
|
9
|
-
path: string;
|
|
10
|
-
mimeType: string;
|
|
11
|
-
} | Blob;
|
|
8
|
+
import { Content, FileInput, SchemaFunctionDeclarations } from './types.js';
|
|
12
9
|
export type GenerativeAIModel = LiteralUnion<'gemini-2.0-flash-exp' | 'gemini-exp-1206' | 'gemini-2.0-flash-thinking-exp-1219', string>;
|
|
13
10
|
export type GenerationOptions = {
|
|
14
11
|
model?: GenerativeAIModel;
|
|
12
|
+
systemInstruction?: string;
|
|
15
13
|
maxOutputTokens?: number;
|
|
16
14
|
temperature?: number;
|
|
17
15
|
topP?: number;
|
|
18
16
|
topK?: number;
|
|
19
17
|
presencePenalty?: number;
|
|
20
18
|
frequencyPenalty?: number;
|
|
19
|
+
forceFunctionCall?: boolean;
|
|
21
20
|
};
|
|
22
21
|
export type GenerationResult<T> = {
|
|
23
22
|
result: T;
|
|
@@ -40,6 +39,7 @@ export declare class AiService implements Resolvable<AiServiceArgument> {
|
|
|
40
39
|
readonly [resolveArgumentType]: AiServiceArgument;
|
|
41
40
|
getFile(fileInput: FileInput): Promise<FileMetadataResponse>;
|
|
42
41
|
getFiles(files: readonly FileInput[]): Promise<FileMetadataResponse[]>;
|
|
42
|
+
test(): Promise<void>;
|
|
43
43
|
classify<T extends EnumerationType>(fileInput: OneOrMany<FileInput>, types: T, options?: GenerationOptions): Promise<GenerationResult<{
|
|
44
44
|
types: {
|
|
45
45
|
type: EnumerationValue<T>;
|
|
@@ -47,7 +47,22 @@ export declare class AiService implements Resolvable<AiServiceArgument> {
|
|
|
47
47
|
}[] | null;
|
|
48
48
|
}>>;
|
|
49
49
|
extractData<T>(fileInput: OneOrMany<FileInput>, schema: SchemaTestable<T>, options?: GenerationOptions): Promise<GenerationResult<T>>;
|
|
50
|
+
analyzeDocument<T extends EnumerationType>(fileInput: FileInput, types: T, options?: GenerationOptions): Promise<GenerationResult<{
|
|
51
|
+
content: string[];
|
|
52
|
+
documentTypes: {
|
|
53
|
+
type: EnumerationValue<T>;
|
|
54
|
+
confidence: 'high' | 'medium' | 'low';
|
|
55
|
+
}[];
|
|
56
|
+
tags: string[];
|
|
57
|
+
}>>;
|
|
58
|
+
findActions(fileInput: OneOrMany<FileInput>, options?: GenerationOptions): Promise<GenerationResult<{
|
|
59
|
+
text: string;
|
|
60
|
+
functions: any;
|
|
61
|
+
}>>;
|
|
62
|
+
callFunctions<const T extends SchemaFunctionDeclarations>(functions: T, contents: Content[], options?: GenerationOptions): Promise<void>;
|
|
50
63
|
private waitForFileActive;
|
|
51
64
|
private waitForFilesActive;
|
|
65
|
+
private convertContents;
|
|
66
|
+
private convertContent;
|
|
52
67
|
private getModel;
|
|
53
68
|
}
|
package/ai/ai.service.js
CHANGED
|
@@ -61,20 +61,24 @@ import { openAsBlob } from 'node:fs';
|
|
|
61
61
|
import { unlink, writeFile } from 'node:fs/promises';
|
|
62
62
|
import { tmpdir } from 'node:os';
|
|
63
63
|
import { join } from 'node:path';
|
|
64
|
-
import {
|
|
64
|
+
import { inspect } from 'node:util';
|
|
65
|
+
import { FunctionCallingMode, GoogleGenerativeAI, SchemaType } from '@google/generative-ai';
|
|
65
66
|
import { FileState, GoogleAIFileManager } from '@google/generative-ai/server';
|
|
67
|
+
import { AsyncEnumerable } from '../enumerable/async-enumerable.js';
|
|
66
68
|
import { DetailsError } from '../errors/details.error.js';
|
|
69
|
+
import { NotSupportedError } from '../errors/not-supported.error.js';
|
|
67
70
|
import { Singleton } from '../injector/decorators.js';
|
|
68
71
|
import { inject, injectArgument } from '../injector/inject.js';
|
|
69
72
|
import { Logger } from '../logger/logger.js';
|
|
70
73
|
import { convertToOpenApiSchema } from '../schema/converters/openapi-converter.js';
|
|
71
|
-
import { array, enumeration, nullable, object, Schema } from '../schema/index.js';
|
|
74
|
+
import { array, enumeration, nullable, object, Schema, string } from '../schema/index.js';
|
|
72
75
|
import { toArray } from '../utils/array/array.js';
|
|
73
76
|
import { digest } from '../utils/cryptography.js';
|
|
74
77
|
import { formatBytes } from '../utils/format.js';
|
|
78
|
+
import { hasOwnProperty, objectEntries } from '../utils/object/object.js';
|
|
75
79
|
import { timeout } from '../utils/timing.js';
|
|
76
80
|
import { tryIgnoreAsync } from '../utils/try-ignore.js';
|
|
77
|
-
import { isBlob } from '../utils/type-guards.js';
|
|
81
|
+
import { assertDefinedPass, isBlob } from '../utils/type-guards.js';
|
|
78
82
|
import { millisecondsPerSecond } from '../utils/units.js';
|
|
79
83
|
let AiService = class AiService {
|
|
80
84
|
#options = injectArgument(this);
|
|
@@ -136,6 +140,59 @@ let AiService = class AiService {
|
|
|
136
140
|
async getFiles(files) {
|
|
137
141
|
return Promise.all(files.map(async (file) => this.getFile(file)));
|
|
138
142
|
}
|
|
143
|
+
async test() {
|
|
144
|
+
const result = await this.getModel('gemini-2.0-flash-exp').generateContent({
|
|
145
|
+
generationConfig: {
|
|
146
|
+
maxOutputTokens: 4096
|
|
147
|
+
},
|
|
148
|
+
tools: [{
|
|
149
|
+
functionDeclarations: [
|
|
150
|
+
{
|
|
151
|
+
name: 'outputNumber',
|
|
152
|
+
description: 'outputs a number',
|
|
153
|
+
parameters: {
|
|
154
|
+
type: SchemaType.OBJECT,
|
|
155
|
+
properties: {
|
|
156
|
+
number: { type: SchemaType.INTEGER }
|
|
157
|
+
},
|
|
158
|
+
required: ['number']
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
}],
|
|
163
|
+
toolConfig: {
|
|
164
|
+
functionCallingConfig: {
|
|
165
|
+
mode: FunctionCallingMode.ANY
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
contents: [
|
|
169
|
+
{ role: 'user', parts: [{ text: 'Output 5 increasing numbers starting at 10' }] },
|
|
170
|
+
{
|
|
171
|
+
role: 'model',
|
|
172
|
+
parts: [
|
|
173
|
+
{ functionCall: { name: 'outputNumber', args: { number: 10 } } },
|
|
174
|
+
{ functionCall: { name: 'outputNumber', args: { number: 11 } } },
|
|
175
|
+
{ functionCall: { name: 'outputNumber', args: { number: 12 } } },
|
|
176
|
+
{ functionCall: { name: 'outputNumber', args: { number: 13 } } },
|
|
177
|
+
{ functionCall: { name: 'outputNumber', args: { number: 14 } } }
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
/*{
|
|
181
|
+
role: 'user',
|
|
182
|
+
parts: [
|
|
183
|
+
{ functionResponse: { name: 'outputNumber', response: { result: 'outputted number 10' } } },
|
|
184
|
+
{ functionResponse: { name: 'outputNumber', response: { result: 'outputted number 11' } } },
|
|
185
|
+
{ functionResponse: { name: 'outputNumber', response: { result: 'outputted number 12' } } },
|
|
186
|
+
{ functionResponse: { name: 'outputNumber', response: { result: 'outputted number 13' } } },
|
|
187
|
+
{ functionResponse: { name: 'outputNumber', response: { result: 'outputted number 14' } } }
|
|
188
|
+
]
|
|
189
|
+
},*/
|
|
190
|
+
// { role: 'model', parts: [{ text: 'Okay, I\'ve outputted the numbers 10, 11, 12, 13, and 14.' }] },
|
|
191
|
+
{ role: 'user', parts: [{ text: 'Give me 5 more numbers. ONLY call functions, dont output text' }] }
|
|
192
|
+
]
|
|
193
|
+
});
|
|
194
|
+
console.log(inspect(result.response, { depth: null }));
|
|
195
|
+
}
|
|
139
196
|
async classify(fileInput, types, options) {
|
|
140
197
|
const files = await this.getFiles(toArray(fileInput));
|
|
141
198
|
const resultSchema = object({
|
|
@@ -201,6 +258,162 @@ Carefully read and analyze the provided document. Identify relevant information
|
|
|
201
258
|
result: Schema.parse(schema, JSON.parse(result.response.text()))
|
|
202
259
|
};
|
|
203
260
|
}
|
|
261
|
+
async analyzeDocument(fileInput, types, options) {
|
|
262
|
+
const file = await this.getFile(fileInput);
|
|
263
|
+
const schema = object({
|
|
264
|
+
content: array(string({ description: 'Single content without data details' }), { description: 'List of contents' }),
|
|
265
|
+
documentTypes: array(object({
|
|
266
|
+
type: enumeration(types, { description: 'Type of document' }),
|
|
267
|
+
confidence: enumeration(['high', 'medium', 'low'], { description: 'How sure/certain you are about the classficiation.' })
|
|
268
|
+
}), { description: 'One or more document types that matches' }),
|
|
269
|
+
tags: array(string({ description: 'Tag which describes the content' }), { description: 'List of tags' })
|
|
270
|
+
});
|
|
271
|
+
const responseSchema = convertToOpenApiSchema(schema);
|
|
272
|
+
this.#logger.verbose('Extracting data...');
|
|
273
|
+
const result = await this.getModel(options?.model ?? this.defaultModel).generateContent({
|
|
274
|
+
generationConfig: {
|
|
275
|
+
maxOutputTokens: 2048,
|
|
276
|
+
temperature: 0.75,
|
|
277
|
+
...options,
|
|
278
|
+
responseMimeType: 'application/json',
|
|
279
|
+
responseSchema
|
|
280
|
+
},
|
|
281
|
+
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.
|
|
282
|
+
|
|
283
|
+
**Instructions:**
|
|
284
|
+
Carefully read and analyze the provided document.
|
|
285
|
+
Identify key points and relevant information that describes the content. Focus on a general overview without providing specific details.
|
|
286
|
+
Only output as many content items as it is necessary to describe relevant content. It should be around 5 to 10 items.
|
|
287
|
+
Classify the document based on the provided list of types.
|
|
288
|
+
Output up to 5 tags.
|
|
289
|
+
Always output the content and tags in Deutsch.`,
|
|
290
|
+
contents: [
|
|
291
|
+
{
|
|
292
|
+
role: 'user',
|
|
293
|
+
parts: [
|
|
294
|
+
{ fileData: { mimeType: file.mimeType, fileUri: file.uri } },
|
|
295
|
+
{ text: `Classify the document. Output as JSON using the following schema:\n${JSON.stringify(responseSchema, null, 2)}` }
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
});
|
|
300
|
+
return {
|
|
301
|
+
usage: result.response.usageMetadata,
|
|
302
|
+
result: Schema.parse(schema, JSON.parse(result.response.text()))
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
async findActions(fileInput, options) {
|
|
306
|
+
const files = await this.getFiles(toArray(fileInput));
|
|
307
|
+
this.#logger.verbose('Extracting data...');
|
|
308
|
+
const result = await this.getModel(options?.model ?? this.defaultModel).generateContent({
|
|
309
|
+
generationConfig: {
|
|
310
|
+
maxOutputTokens: 4096,
|
|
311
|
+
temperature: 0.75,
|
|
312
|
+
...options
|
|
313
|
+
},
|
|
314
|
+
tools: [
|
|
315
|
+
{
|
|
316
|
+
functionDeclarations: [
|
|
317
|
+
{
|
|
318
|
+
name: 'createNewRealEstate',
|
|
319
|
+
description: 'creates a new real estate',
|
|
320
|
+
parameters: {
|
|
321
|
+
type: SchemaType.OBJECT,
|
|
322
|
+
properties: {
|
|
323
|
+
address: { type: SchemaType.STRING },
|
|
324
|
+
realEstateNumber: { type: SchemaType.STRING }
|
|
325
|
+
},
|
|
326
|
+
required: ['address', 'realEstateNumber']
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: 'createNewUnit',
|
|
331
|
+
description: 'creates a new unit in a real estate. Make sure to get the correct unit number, each unit has to get its own',
|
|
332
|
+
parameters: {
|
|
333
|
+
type: SchemaType.OBJECT,
|
|
334
|
+
description: 'data of the unit from documents',
|
|
335
|
+
properties: {
|
|
336
|
+
unitNumber: { type: SchemaType.STRING },
|
|
337
|
+
owner: { type: SchemaType.STRING },
|
|
338
|
+
dweller: { type: SchemaType.STRING }
|
|
339
|
+
},
|
|
340
|
+
required: ['unitNumber', 'owner', 'dweller']
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
name: 'createNewDevice',
|
|
345
|
+
description: 'creates a new device in a real estate / unit, for example HKV or WWZ',
|
|
346
|
+
parameters: {
|
|
347
|
+
type: SchemaType.OBJECT,
|
|
348
|
+
description: 'data of the device from documents like Ablesebeleg.',
|
|
349
|
+
properties: {
|
|
350
|
+
unitNumber: { type: SchemaType.STRING },
|
|
351
|
+
deviceNumber: { type: SchemaType.STRING },
|
|
352
|
+
factor: { type: SchemaType.NUMBER },
|
|
353
|
+
deviceType: { type: SchemaType.STRING },
|
|
354
|
+
roomType: { type: SchemaType.STRING }
|
|
355
|
+
},
|
|
356
|
+
required: ['unitNumber', 'deviceNumber', 'factor', 'deviceType', 'roomType']
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
],
|
|
362
|
+
toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.ANY } },
|
|
363
|
+
systemInstruction: `You are a specialized AI assistant designed to extract structured data from various document types related to real estate and device management. Your goal is to understand the document's content and identify key information to populate specific function calls. You will be provided with document text and a set of predefined functions.
|
|
364
|
+
|
|
365
|
+
**Your task is:**
|
|
366
|
+
|
|
367
|
+
1. **Analyze the document:** Carefully read the provided document text.
|
|
368
|
+
2. **Identify relevant information:** Extract the key data points related to real estate (e.g., address, size, type) and devices (e.g., type, model, serial number, location).
|
|
369
|
+
3. **Determine the appropriate function:** Based on the extracted information, select the most suitable function from the list below to perform the intended action.
|
|
370
|
+
4. **Generate function call:** Output the selected function name along with its arguments, populated with the extracted data. Use JSON format for the output.`,
|
|
371
|
+
contents: [
|
|
372
|
+
{
|
|
373
|
+
role: 'user',
|
|
374
|
+
parts: [
|
|
375
|
+
...files.map((file) => ({ fileData: { mimeType: file.mimeType, fileUri: file.uri } })),
|
|
376
|
+
{ text: 'Extract the data from the document and call suitable functions.' }
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
});
|
|
381
|
+
return {
|
|
382
|
+
usage: result.response.usageMetadata,
|
|
383
|
+
result: {
|
|
384
|
+
functions: result.response.functionCalls(),
|
|
385
|
+
text: result.response.text()
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
async callFunctions(functions, contents, options) {
|
|
390
|
+
const googleContent = await this.convertContents(contents);
|
|
391
|
+
const googleFunctionDeclarations = objectEntries(functions).map(([name, declaration]) => ({
|
|
392
|
+
name: name,
|
|
393
|
+
description: declaration.description,
|
|
394
|
+
parameters: convertToOpenApiSchema(declaration.parameters)
|
|
395
|
+
}));
|
|
396
|
+
const result = await this.getModel(options?.model ?? this.defaultModel).generateContent({
|
|
397
|
+
generationConfig: {
|
|
398
|
+
maxOutputTokens: 4096,
|
|
399
|
+
temperature: 0.75,
|
|
400
|
+
...options
|
|
401
|
+
},
|
|
402
|
+
systemInstruction: options?.systemInstruction,
|
|
403
|
+
tools: [{ functionDeclarations: googleFunctionDeclarations }],
|
|
404
|
+
toolConfig: {
|
|
405
|
+
functionCallingConfig: {
|
|
406
|
+
mode: (options?.forceFunctionCall == false) ? FunctionCallingMode.AUTO : FunctionCallingMode.ANY
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
contents: googleContent
|
|
410
|
+
});
|
|
411
|
+
for (const call of result.response.functionCalls() ?? []) {
|
|
412
|
+
const fn = assertDefinedPass(functions[call.name]);
|
|
413
|
+
const parameters = fn.parameters.parse(call.args);
|
|
414
|
+
const functionResult = await fn.handler(parameters);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
204
417
|
async waitForFileActive(fileMetadata) {
|
|
205
418
|
let file = await this.fileManager.getFile(fileMetadata.name);
|
|
206
419
|
while (file.state == FileState.PROCESSING) {
|
|
@@ -220,6 +433,31 @@ Carefully read and analyze the provided document. Identify relevant information
|
|
|
220
433
|
}
|
|
221
434
|
return responses;
|
|
222
435
|
}
|
|
436
|
+
async convertContents(contents) {
|
|
437
|
+
return AsyncEnumerable.from(contents)
|
|
438
|
+
.map(async (content) => this.convertContent(content))
|
|
439
|
+
.toArray();
|
|
440
|
+
}
|
|
441
|
+
async convertContent(content) {
|
|
442
|
+
return {
|
|
443
|
+
role: content.role,
|
|
444
|
+
parts: await AsyncEnumerable.from(content.parts)
|
|
445
|
+
.map(async (part) => {
|
|
446
|
+
if (hasOwnProperty(part, 'text')) {
|
|
447
|
+
return { text: part.text };
|
|
448
|
+
}
|
|
449
|
+
if (hasOwnProperty(part, 'file')) {
|
|
450
|
+
const fileMetadata = await this.getFile(part.file);
|
|
451
|
+
return { fileData: { fileUri: fileMetadata.uri, mimeType: fileMetadata.mimeType } };
|
|
452
|
+
}
|
|
453
|
+
if (hasOwnProperty(part, 'functionResult')) {
|
|
454
|
+
return { functionResponse: { name: part.functionResult.name, response: { result: part.functionResult.value } } };
|
|
455
|
+
}
|
|
456
|
+
throw new NotSupportedError('Unsupported content part.');
|
|
457
|
+
})
|
|
458
|
+
.toArray()
|
|
459
|
+
};
|
|
460
|
+
}
|
|
223
461
|
getModel(model) {
|
|
224
462
|
return this.genAI.getGenerativeModel({ model });
|
|
225
463
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FunctionDeclaration } from '@google/generative-ai';
|
|
2
|
+
import type { AbstractConstructor } from '../types.js';
|
|
3
|
+
import type { SchemaFunctionDeclarations } from './types.js';
|
|
4
|
+
export declare function convertFunctionDeclarations(declarations: SchemaFunctionDeclarations): void;
|
|
5
|
+
export declare function getFunctionDeclarations(type: AbstractConstructor): FunctionDeclaration[];
|
package/ai/functions.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { convertToOpenApiSchema } from '../schema/converters/openapi-converter.js';
|
|
2
|
+
import { FunctionSchema, getObjectSchema, object } from '../schema/index.js';
|
|
3
|
+
import { fromEntries, objectEntries } from '../utils/object/object.js';
|
|
4
|
+
import { isNotNull, isNull, isString } from '../utils/type-guards.js';
|
|
5
|
+
export function convertFunctionDeclarations(declarations) {
|
|
6
|
+
const entries = objectEntries(declarations)
|
|
7
|
+
.map(([name, declaration]) => ({
|
|
8
|
+
name,
|
|
9
|
+
description: declaration.description,
|
|
10
|
+
parameters: convertToOpenApiSchema(declaration.parameters)
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
export function getFunctionDeclarations(type) {
|
|
14
|
+
const objectSchema = getObjectSchema(type);
|
|
15
|
+
return objectEntries(objectSchema.properties)
|
|
16
|
+
.map(([key, schema]) => {
|
|
17
|
+
if (!(schema instanceof FunctionSchema)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
name: `${type.name}.${key}`,
|
|
22
|
+
description: schema.description ?? undefined,
|
|
23
|
+
parameters: isNull(schema.parameterSchemas)
|
|
24
|
+
? undefined
|
|
25
|
+
: getFunctionDeclarationParameters(schema)
|
|
26
|
+
};
|
|
27
|
+
})
|
|
28
|
+
.filter(isNotNull);
|
|
29
|
+
}
|
|
30
|
+
function getFunctionDeclarationParameters(functionSchema) {
|
|
31
|
+
const entries = functionSchema.parameterSchemas.map((schema, index) => {
|
|
32
|
+
const parameterName = functionSchema.parameterNames[index];
|
|
33
|
+
if (!isString(parameterName)) {
|
|
34
|
+
throw new Error(`Parameter ${index} requires a name.`);
|
|
35
|
+
}
|
|
36
|
+
return [parameterName, schema];
|
|
37
|
+
});
|
|
38
|
+
const parametersSchema = object(fromEntries(entries));
|
|
39
|
+
return convertToOpenApiSchema(parametersSchema);
|
|
40
|
+
}
|
package/ai/types.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ObjectSchema } from '../schema/index.js';
|
|
2
|
+
import type { Record, UndefinableJson } from '../types.js';
|
|
3
|
+
export type FileInput = {
|
|
4
|
+
path: string;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
} | Blob;
|
|
7
|
+
export type SchemaFunctionDeclarations = Record<string, SchemaFunctionDeclaration<any>>;
|
|
8
|
+
export type SchemaFunctionDeclaration<T extends Record = Record, R = unknown> = {
|
|
9
|
+
description: string;
|
|
10
|
+
parameters: ObjectSchema<T>;
|
|
11
|
+
handler: (parameters: T) => R | Promise<R>;
|
|
12
|
+
};
|
|
13
|
+
export type Content = {
|
|
14
|
+
role: 'user' | 'model';
|
|
15
|
+
parts: ContentPart[];
|
|
16
|
+
};
|
|
17
|
+
export type ContentPart = {
|
|
18
|
+
text: string;
|
|
19
|
+
} | {
|
|
20
|
+
file: FileInput;
|
|
21
|
+
} | {
|
|
22
|
+
functionResult: {
|
|
23
|
+
name: string;
|
|
24
|
+
value: NonNullable<UndefinableJson>;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare function declareFunction<T extends Record = Record, R = unknown>(description: string, parameters: ObjectSchema<T>, handler: (parameters: T) => R | Promise<R>): SchemaFunctionDeclaration<T, R>;
|
package/ai/types.js
ADDED
package/orm/schemas/json.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type Decorator } from '../../reflection/index.js';
|
|
2
|
-
import { ObjectSchema, type ObjectSchemaOptions, type
|
|
2
|
+
import { ObjectSchema, type ObjectSchemaOptions, type SchemaDecoratorOptions } from '../../schema/index.js';
|
|
3
3
|
export type JsonSchemaOptions = Pick<ObjectSchemaOptions, 'factory'>;
|
|
4
4
|
export declare class JsonSchema extends ObjectSchema {
|
|
5
5
|
readonly name = "Json";
|
|
6
6
|
constructor(options?: JsonSchemaOptions);
|
|
7
7
|
}
|
|
8
8
|
export declare function json(options?: JsonSchemaOptions): JsonSchema;
|
|
9
|
-
export declare function Json(options?: JsonSchemaOptions &
|
|
9
|
+
export declare function Json(options?: JsonSchemaOptions & SchemaDecoratorOptions): Decorator<'class' | 'property' | 'accessor'>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { NumberSchema, type NumberSchemaOptions, type SchemaPropertyDecorator, type
|
|
1
|
+
import { NumberSchema, type NumberSchemaOptions, type SchemaPropertyDecorator, type SchemaDecoratorOptions, type SimpleSchemaOptions } from '../../schema/index.js';
|
|
2
2
|
export type NumericDateSchemaOptions = SimpleSchemaOptions<number> & Pick<NumberSchemaOptions, 'minimum' | 'maximum'>;
|
|
3
3
|
export declare class NumericDateSchema extends NumberSchema {
|
|
4
4
|
readonly name = "NumericDate";
|
|
5
5
|
constructor(options?: NumericDateSchemaOptions);
|
|
6
6
|
}
|
|
7
7
|
export declare function numericDate(options?: NumericDateSchemaOptions): NumericDateSchema;
|
|
8
|
-
export declare function NumericDate(options?: NumericDateSchemaOptions &
|
|
8
|
+
export declare function NumericDate(options?: NumericDateSchemaOptions & SchemaDecoratorOptions): SchemaPropertyDecorator;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JsonPath } from '../../json-path/json-path.js';
|
|
2
|
-
import { NumberSchema, type NumberSchemaOptions, type SchemaPropertyDecorator, type
|
|
2
|
+
import { NumberSchema, type NumberSchemaOptions, type SchemaPropertyDecorator, type SchemaDecoratorOptions, type SchemaTestOptions, type SchemaTestResult, type SimpleSchemaOptions } from '../../schema/index.js';
|
|
3
3
|
export type TimestampSchemaOptions = SimpleSchemaOptions<number> & Pick<NumberSchemaOptions, 'minimum' | 'maximum'>;
|
|
4
4
|
export declare class TimestampSchema extends NumberSchema {
|
|
5
5
|
readonly name = "Timestamp";
|
|
@@ -7,4 +7,4 @@ export declare class TimestampSchema extends NumberSchema {
|
|
|
7
7
|
_test(value: any, path: JsonPath, options: SchemaTestOptions): SchemaTestResult<number>;
|
|
8
8
|
}
|
|
9
9
|
export declare function timestamp(options?: TimestampSchemaOptions): TimestampSchema;
|
|
10
|
-
export declare function Timestamp(options?: TimestampSchemaOptions &
|
|
10
|
+
export declare function Timestamp(options?: TimestampSchemaOptions & SchemaDecoratorOptions): SchemaPropertyDecorator;
|
package/orm/schemas/uuid.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StringSchema, type SchemaPropertyDecorator, type
|
|
1
|
+
import { StringSchema, type SchemaPropertyDecorator, type SchemaDecoratorOptions } from '../../schema/index.js';
|
|
2
2
|
export type UuidSchemaOptions = {
|
|
3
3
|
defaultRandom?: boolean;
|
|
4
4
|
};
|
|
@@ -8,4 +8,4 @@ export declare class UuidSchema extends StringSchema {
|
|
|
8
8
|
constructor(options?: UuidSchemaOptions);
|
|
9
9
|
}
|
|
10
10
|
export declare function uuid(options?: UuidSchemaOptions): UuidSchema;
|
|
11
|
-
export declare function Uuid(options?: UuidSchemaOptions &
|
|
11
|
+
export declare function Uuid(options?: UuidSchemaOptions & SchemaDecoratorOptions): SchemaPropertyDecorator;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.9",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"./disposable": "./disposable/index.js",
|
|
47
47
|
"./distributed-loop": "./distributed-loop/index.js",
|
|
48
48
|
"./dom": "./dom/index.js",
|
|
49
|
+
"./document-management": "./document-management/index.js",
|
|
49
50
|
"./enumerable": "./enumerable/index.js",
|
|
50
51
|
"./errors": "./errors/index.js",
|
|
51
52
|
"./file": "./file/index.js",
|
|
@@ -119,11 +120,11 @@
|
|
|
119
120
|
"luxon": "^3.5",
|
|
120
121
|
"reflect-metadata": "^0.2",
|
|
121
122
|
"rxjs": "^7.8",
|
|
122
|
-
"type-fest": "4.
|
|
123
|
+
"type-fest": "4.32"
|
|
123
124
|
},
|
|
124
125
|
"devDependencies": {
|
|
125
126
|
"@mxssfd/typedoc-theme": "1.1",
|
|
126
|
-
"@stylistic/eslint-plugin": "2.
|
|
127
|
+
"@stylistic/eslint-plugin": "2.13",
|
|
127
128
|
"@types/chroma-js": "2.4",
|
|
128
129
|
"@types/koa__router": "12.0",
|
|
129
130
|
"@types/luxon": "3.4",
|
|
@@ -148,7 +149,7 @@
|
|
|
148
149
|
"@elastic/elasticsearch": "^8.17",
|
|
149
150
|
"@google/generative-ai": "^0.21",
|
|
150
151
|
"@koa/router": "^13.1",
|
|
151
|
-
"@tstdl/angular": "^0.
|
|
152
|
+
"@tstdl/angular": "^0.92",
|
|
152
153
|
"@zxcvbn-ts/core": "^3.0",
|
|
153
154
|
"@zxcvbn-ts/language-common": "^3.0",
|
|
154
155
|
"@zxcvbn-ts/language-de": "^3.0",
|
package/reflection/registry.js
CHANGED
|
@@ -40,13 +40,13 @@ export class ReflectionRegistry {
|
|
|
40
40
|
return (data.static ? metadata.staticMethods : metadata.methods).get(data.methodKey);
|
|
41
41
|
}
|
|
42
42
|
else if (data.type == 'method-parameter') {
|
|
43
|
-
return (data.static ? metadata.staticMethods : metadata.methods).get(data.methodKey);
|
|
43
|
+
return (data.static ? metadata.staticMethods : metadata.methods).get(data.methodKey).parameters.at(data.index);
|
|
44
44
|
}
|
|
45
45
|
else if (data.type == 'constructor-parameter') { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
|
|
46
46
|
if (isUndefined(metadata.parameters)) {
|
|
47
47
|
throw new Error('Constructor parameters are not available. (missing decoration?)');
|
|
48
48
|
}
|
|
49
|
-
return metadata.parameters
|
|
49
|
+
return metadata.parameters.at(data.index);
|
|
50
50
|
}
|
|
51
51
|
throw new Error(`Unknown DecoratorData type ${data.type}`);
|
|
52
52
|
}
|
package/reflection/utils.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { AbstractConstructor, Constructor, ConstructorParameterDecorator, OneOrMany, PropertiesOfType, Record, TypedOmit } from '../types.js';
|
|
2
2
|
import type { CombinedDecoratorParameters, Decorator, DecoratorData, DecoratorHandler, DecoratorMetadata, DecoratorType, DecoratorUnion } from './types.js';
|
|
3
|
-
export type CreateDecoratorTypeOptions =
|
|
4
|
-
[P in DecoratorType]?: boolean;
|
|
5
|
-
};
|
|
3
|
+
export type CreateDecoratorTypeOptions = Partial<Record<DecoratorType, boolean>>;
|
|
6
4
|
export type CreateDecoratorOptions = {
|
|
7
5
|
data?: Record<string | symbol>;
|
|
8
6
|
/** Merge data values instead of replacing them (requires them to be objects, arrays, maps or sets) */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SetRequired } from 'type-fest';
|
|
2
|
+
import { type Decorator } from '../../reflection/index.js';
|
|
3
|
+
import type { TypedOmit } from '../../types.js';
|
|
4
|
+
import type { SchemaTestable } from '../schema.js';
|
|
5
|
+
import type { CombinedSchemaDecorator, SchemaReflectionData, SchemaTestableProvider } from './types.js';
|
|
6
|
+
export type SchemaDecoratorOptions = SchemaReflectionData;
|
|
7
|
+
export type SchemaDecoratorOptionsWithRequiredSchema = SetRequired<SchemaReflectionData, 'schema'>;
|
|
8
|
+
export type SchemaDecoratorOptionsWithoutSchema = TypedOmit<SchemaReflectionData, 'schema'>;
|
|
9
|
+
export declare function createSchemaDecorator(data?: SchemaReflectionData): CombinedSchemaDecorator;
|
|
10
|
+
export declare function SchemaDecorator(schema: SchemaTestable, options?: SchemaDecoratorOptionsWithoutSchema): CombinedSchemaDecorator;
|
|
11
|
+
export declare function SchemaDecorator(options: SchemaDecoratorOptionsWithRequiredSchema): CombinedSchemaDecorator;
|
|
12
|
+
export declare function Parameter(name: string, schema: SchemaTestable, options?: SchemaDecoratorOptionsWithoutSchema): Decorator<'parameter'>;
|
|
13
|
+
export declare function Parameter(name: string, options: SchemaDecoratorOptions): Decorator<'parameter'>;
|
|
14
|
+
export declare const Property: typeof SchemaDecorator;
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated use @Property instead
|
|
17
|
+
* @param schemaTestableProvider
|
|
18
|
+
* @param options
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
export declare function PropertySchema(schemaTestableProvider: SchemaTestableProvider, options?: SchemaDecoratorOptionsWithoutSchema): CombinedSchemaDecorator;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
import { createDecorator } from '../../reflection/index.js';
|
|
3
|
+
import { filterUndefinedObjectProperties } from '../../utils/object/object.js';
|
|
4
|
+
import { isSchemaTestable } from '../testable.js';
|
|
5
|
+
export function createSchemaDecorator(data = {}) {
|
|
6
|
+
return createDecorator({
|
|
7
|
+
property: true,
|
|
8
|
+
accessor: true,
|
|
9
|
+
method: true,
|
|
10
|
+
parameter: true,
|
|
11
|
+
data: { schema: filterUndefinedObjectProperties(data) },
|
|
12
|
+
mergeData: true
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export function SchemaDecorator(schemaOrOptions, optionsOrNothing) {
|
|
16
|
+
if (isSchemaTestable(schemaOrOptions)) {
|
|
17
|
+
return createSchemaDecorator({ ...optionsOrNothing, schema: () => schemaOrOptions });
|
|
18
|
+
}
|
|
19
|
+
return createSchemaDecorator(schemaOrOptions);
|
|
20
|
+
}
|
|
21
|
+
export function Parameter(name, schemaOrOptions, optionsOrNothing) {
|
|
22
|
+
if (isSchemaTestable(schemaOrOptions)) {
|
|
23
|
+
return createSchemaDecorator({ ...optionsOrNothing, schema: () => schemaOrOptions, parameter: { name } });
|
|
24
|
+
}
|
|
25
|
+
return createSchemaDecorator({ ...schemaOrOptions, parameter: { name } });
|
|
26
|
+
}
|
|
27
|
+
export const Property = SchemaDecorator;
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated use @Property instead
|
|
30
|
+
* @param schemaTestableProvider
|
|
31
|
+
* @param options
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
export function PropertySchema(schemaTestableProvider, options) {
|
|
35
|
+
return SchemaDecorator({ ...options, schema: schemaTestableProvider });
|
|
36
|
+
}
|
|
@@ -3,14 +3,22 @@ import type { SchemaOptions, SchemaTestable } from '../schema.js';
|
|
|
3
3
|
import type { ObjectSchemaFactory, ObjectSchemaOptions } from '../schemas/object.js';
|
|
4
4
|
export type SchemaClassDecorator = Decorator<'class'>;
|
|
5
5
|
export type SchemaPropertyDecorator = Decorator<'property' | 'accessor'>;
|
|
6
|
+
export type SchemaMethodDecorator = Decorator<'method'>;
|
|
7
|
+
export type CombinedSchemaDecorator = Decorator<'property' | 'accessor' | 'parameter'>;
|
|
6
8
|
export type SchemaTypeReflectionData = Partial<Pick<ObjectSchemaOptions, 'mask' | 'unknownProperties' | 'unknownPropertiesKey' | 'description' | 'example'>> & {
|
|
7
9
|
schema?: SchemaTestable;
|
|
8
10
|
factory?: ObjectSchemaFactory<any>;
|
|
9
11
|
};
|
|
10
|
-
export type SchemaTestableProvider = (data:
|
|
11
|
-
export type
|
|
12
|
+
export type SchemaTestableProvider = (data: SchemaReflectionData) => SchemaTestable;
|
|
13
|
+
export type SchemaReflectionData = Partial<Pick<SchemaOptions<any>, 'description' | 'example'>> & {
|
|
12
14
|
schema?: SchemaTestableProvider;
|
|
13
15
|
array?: boolean;
|
|
14
16
|
optional?: boolean;
|
|
15
17
|
nullable?: boolean;
|
|
18
|
+
method?: {
|
|
19
|
+
returnType?: SchemaTestableProvider;
|
|
20
|
+
};
|
|
21
|
+
parameter?: {
|
|
22
|
+
name?: string;
|
|
23
|
+
};
|
|
16
24
|
};
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { AbstractConstructor } from '../../types.js';
|
|
2
|
+
import type { SchemaTestable } from '../schema.js';
|
|
3
|
+
import type { SchemaReflectionData } from './types.js';
|
|
4
|
+
export declare function schemaReflectionDataToSchema(reflectionData: SchemaReflectionData | undefined, fallbackType: AbstractConstructor | null, source: {
|
|
5
|
+
type: AbstractConstructor;
|
|
6
|
+
key: string | symbol;
|
|
7
|
+
}): SchemaTestable;
|