agentlang 0.9.6 → 0.9.8
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/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +8 -3
- package/out/cli/main.js.map +1 -1
- package/out/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/generated/ast.js +1 -0
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/main.cjs +2420 -776
- package/out/language/main.cjs.map +4 -4
- package/out/runtime/docs.d.ts.map +1 -1
- package/out/runtime/docs.js +109 -7
- package/out/runtime/docs.js.map +1 -1
- package/out/runtime/embeddings/chunker.d.ts +9 -0
- package/out/runtime/embeddings/chunker.d.ts.map +1 -0
- package/out/runtime/embeddings/chunker.js +41 -0
- package/out/runtime/embeddings/chunker.js.map +1 -0
- package/out/runtime/embeddings/index.d.ts +6 -0
- package/out/runtime/embeddings/index.d.ts.map +1 -0
- package/out/runtime/embeddings/index.js +6 -0
- package/out/runtime/embeddings/index.js.map +1 -0
- package/out/runtime/embeddings/openai.d.ts +15 -0
- package/out/runtime/embeddings/openai.d.ts.map +1 -0
- package/out/runtime/embeddings/openai.js +34 -0
- package/out/runtime/embeddings/openai.js.map +1 -0
- package/out/runtime/embeddings/provider.d.ts +20 -0
- package/out/runtime/embeddings/provider.d.ts.map +1 -0
- package/out/runtime/embeddings/provider.js +17 -0
- package/out/runtime/embeddings/provider.js.map +1 -0
- package/out/runtime/embeddings/registry.d.ts +3 -0
- package/out/runtime/embeddings/registry.d.ts.map +1 -0
- package/out/runtime/embeddings/registry.js +16 -0
- package/out/runtime/embeddings/registry.js.map +1 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +8 -4
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/module.d.ts +24 -2
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +94 -7
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +2 -0
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +81 -18
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +177 -51
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +21 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +176 -45
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/package.json +188 -185
- package/public/pdf.worker.mjs +65152 -0
- package/src/cli/main.ts +7 -2
- package/src/language/generated/ast.ts +1 -1
- package/src/runtime/docs.ts +120 -9
- package/src/runtime/embeddings/chunker.ts +50 -0
- package/src/runtime/embeddings/index.ts +5 -0
- package/src/runtime/embeddings/openai.ts +49 -0
- package/src/runtime/embeddings/provider.ts +37 -0
- package/src/runtime/embeddings/registry.ts +17 -0
- package/src/runtime/interpreter.ts +16 -12
- package/src/runtime/module.ts +148 -40
- package/src/runtime/modules/ai.ts +100 -20
- package/src/runtime/resolvers/sqldb/database.ts +190 -59
- package/src/runtime/resolvers/sqldb/impl.ts +235 -58
- package/out/setupClassic.d.ts +0 -98
- package/out/setupClassic.d.ts.map +0 -1
- package/out/setupClassic.js +0 -38
- package/out/setupClassic.js.map +0 -1
- package/out/setupCommon.d.ts +0 -2
- package/out/setupCommon.d.ts.map +0 -1
- package/out/setupCommon.js +0 -33
- package/out/setupCommon.js.map +0 -1
- package/out/setupExtended.d.ts +0 -40
- package/out/setupExtended.d.ts.map +0 -1
- package/out/setupExtended.js +0 -67
- package/out/setupExtended.js.map +0 -1
package/src/cli/main.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
setRuntimeMode_init_schema,
|
|
39
39
|
setRuntimeMode_migration,
|
|
40
40
|
setRuntimeMode_prod,
|
|
41
|
+
setRuntimeMode_test,
|
|
41
42
|
setRuntimeMode_undo_migration,
|
|
42
43
|
updateEndpoints,
|
|
43
44
|
} from '../runtime/defs.js';
|
|
@@ -216,8 +217,12 @@ async function internDynamicModule(name: string, definition: string): Promise<st
|
|
|
216
217
|
setInternDynamicModuleFn(internDynamicModule);
|
|
217
218
|
|
|
218
219
|
export const runModule = async (fileName: string, releaseDb: boolean = false): Promise<void> => {
|
|
219
|
-
if (isRuntimeMode_dev()
|
|
220
|
-
|
|
220
|
+
if (isRuntimeMode_dev()) {
|
|
221
|
+
if (process.env.NODE_ENV === 'production') {
|
|
222
|
+
setRuntimeMode_prod();
|
|
223
|
+
} else if (process.env.NODE_ENV === 'test') {
|
|
224
|
+
setRuntimeMode_test();
|
|
225
|
+
}
|
|
221
226
|
}
|
|
222
227
|
const r: boolean = await runPreInitTasks();
|
|
223
228
|
if (!r) {
|
package/src/runtime/docs.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { getFileSystem } from '../utils/fs-utils.js';
|
|
2
1
|
import { logger } from './logger.js';
|
|
2
|
+
import { isNodeEnv } from '../utils/runtime.js';
|
|
3
|
+
import { getFileSystem } from '../utils/fs-utils.js';
|
|
3
4
|
|
|
4
5
|
const DocFetchers = new Map<string, Function>();
|
|
5
6
|
|
|
@@ -25,6 +26,39 @@ export async function fetchDoc(url: string): Promise<string | undefined> {
|
|
|
25
26
|
else return undefined;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
let PDFParse: any = null;
|
|
30
|
+
let pdfWorkerSet = false;
|
|
31
|
+
|
|
32
|
+
async function getPDFParse() {
|
|
33
|
+
if (!PDFParse) {
|
|
34
|
+
const pdfModule = await import('pdf-parse');
|
|
35
|
+
PDFParse = pdfModule.PDFParse;
|
|
36
|
+
|
|
37
|
+
// Set up web worker for browser
|
|
38
|
+
if (!isNodeEnv && !pdfWorkerSet && PDFParse.setWorker) {
|
|
39
|
+
// Worker is served from public/ directory
|
|
40
|
+
PDFParse.setWorker('/pdf.worker.mjs');
|
|
41
|
+
pdfWorkerSet = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return PDFParse;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function parsePdfBuffer(buffer: Uint8Array): Promise<string> {
|
|
48
|
+
try {
|
|
49
|
+
const PDFParseClass = await getPDFParse();
|
|
50
|
+
const parser = new PDFParseClass({
|
|
51
|
+
data: buffer,
|
|
52
|
+
verbosity: 0,
|
|
53
|
+
});
|
|
54
|
+
const data = await parser.getText();
|
|
55
|
+
return data.text;
|
|
56
|
+
} catch (error: any) {
|
|
57
|
+
logger.error(`Failed to parse PDF: ${error.message}`);
|
|
58
|
+
throw new Error(`PDF parsing failed: ${error.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
28
62
|
async function httpFetcher(url: string): Promise<string | undefined> {
|
|
29
63
|
try {
|
|
30
64
|
const response = await fetch(url, {
|
|
@@ -32,12 +66,24 @@ async function httpFetcher(url: string): Promise<string | undefined> {
|
|
|
32
66
|
});
|
|
33
67
|
|
|
34
68
|
if (!response.ok) {
|
|
35
|
-
logger.error(
|
|
36
|
-
`Failed to fetch document ${url}, HTTP error! status: ${response.status} ${response.text} ${response.statusText}`
|
|
37
|
-
);
|
|
69
|
+
logger.error(`Failed to fetch document ${url}, HTTP error! status: ${response.status}`);
|
|
38
70
|
return undefined;
|
|
39
71
|
}
|
|
40
|
-
|
|
72
|
+
|
|
73
|
+
const contentType = response.headers.get('content-type') || '';
|
|
74
|
+
const content = await response.arrayBuffer();
|
|
75
|
+
|
|
76
|
+
const lowerUrl = url.toLowerCase();
|
|
77
|
+
|
|
78
|
+
// Process based on content type or file extension
|
|
79
|
+
if (contentType.includes('application/pdf') || lowerUrl.endsWith('.pdf')) {
|
|
80
|
+
return await parsePdfBuffer(new Uint8Array(content));
|
|
81
|
+
} else if (contentType.includes('text/markdown') || lowerUrl.endsWith('.md')) {
|
|
82
|
+
return new TextDecoder().decode(content);
|
|
83
|
+
} else {
|
|
84
|
+
// Default to text
|
|
85
|
+
return new TextDecoder().decode(content);
|
|
86
|
+
}
|
|
41
87
|
} catch (reason: any) {
|
|
42
88
|
logger.error(`Failed to fetch document ${url}: ${reason}`);
|
|
43
89
|
}
|
|
@@ -45,11 +91,76 @@ async function httpFetcher(url: string): Promise<string | undefined> {
|
|
|
45
91
|
}
|
|
46
92
|
|
|
47
93
|
async function fetchFile(path: string): Promise<string> {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
94
|
+
const lowerPath = path.toLowerCase();
|
|
95
|
+
|
|
96
|
+
if (lowerPath.endsWith('.pdf')) {
|
|
97
|
+
return await fetchPdfFile(path);
|
|
98
|
+
} else if (
|
|
99
|
+
lowerPath.endsWith('.md') ||
|
|
100
|
+
lowerPath.endsWith('.markdown') ||
|
|
101
|
+
lowerPath.endsWith('.mdown')
|
|
102
|
+
) {
|
|
103
|
+
return await fetchMarkdownFile(path);
|
|
104
|
+
} else {
|
|
105
|
+
// Default: plain text
|
|
106
|
+
return await fetchTextFile(path);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function fetchPdfFile(path: string): Promise<string> {
|
|
111
|
+
try {
|
|
112
|
+
const fs = await getFileSystem();
|
|
113
|
+
|
|
114
|
+
if (isNodeEnv && path.startsWith('.')) {
|
|
115
|
+
path = `${process.cwd()}${path.substring(1)}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const content = await fs.readFile(path);
|
|
119
|
+
|
|
120
|
+
let buffer: Uint8Array;
|
|
121
|
+
if (typeof content === 'string') {
|
|
122
|
+
buffer = new TextEncoder().encode(content);
|
|
123
|
+
} else if (Buffer.isBuffer(content)) {
|
|
124
|
+
buffer = new Uint8Array(content);
|
|
125
|
+
} else {
|
|
126
|
+
buffer = new Uint8Array(Buffer.from(content));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return await parsePdfBuffer(buffer);
|
|
130
|
+
} catch (error: any) {
|
|
131
|
+
logger.error(`Failed to read PDF file ${path}: ${error.message}`);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function fetchMarkdownFile(path: string): Promise<string> {
|
|
137
|
+
try {
|
|
138
|
+
const fs = await getFileSystem();
|
|
139
|
+
|
|
140
|
+
if (isNodeEnv && path.startsWith('.')) {
|
|
141
|
+
path = `${process.cwd()}${path.substring(1)}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return await fs.readFile(path);
|
|
145
|
+
} catch (error: any) {
|
|
146
|
+
logger.error(`Failed to read Markdown file ${path}: ${error.message}`);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function fetchTextFile(path: string): Promise<string> {
|
|
152
|
+
try {
|
|
153
|
+
const fs = await getFileSystem();
|
|
154
|
+
|
|
155
|
+
if (isNodeEnv && path.startsWith('.')) {
|
|
156
|
+
path = `${process.cwd()}${path.substring(1)}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return await fs.readFile(path);
|
|
160
|
+
} catch (error: any) {
|
|
161
|
+
logger.error(`Failed to read text file ${path}: ${error.message}`);
|
|
162
|
+
throw error;
|
|
51
163
|
}
|
|
52
|
-
return fs.readFile(path);
|
|
53
164
|
}
|
|
54
165
|
|
|
55
166
|
registerDocFetcher('http', httpFetcher);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export class TextChunker {
|
|
2
|
+
private chunkSize: number;
|
|
3
|
+
private chunkOverlap: number;
|
|
4
|
+
private separators: string[] = ['\n\n', '\n', '. ', ' ', ''];
|
|
5
|
+
|
|
6
|
+
constructor(chunkSize: number = 1000, chunkOverlap: number = 200) {
|
|
7
|
+
this.chunkSize = chunkSize;
|
|
8
|
+
this.chunkOverlap = chunkOverlap;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
splitText(text: string): string[] {
|
|
12
|
+
if (text.length <= this.chunkSize) {
|
|
13
|
+
return [text];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const chunks: string[] = [];
|
|
17
|
+
let start = 0;
|
|
18
|
+
|
|
19
|
+
while (start < text.length) {
|
|
20
|
+
let end = Math.min(start + this.chunkSize, text.length);
|
|
21
|
+
|
|
22
|
+
if (end < text.length) {
|
|
23
|
+
end = this.findBestSplitPoint(text, start, end);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
chunks.push(text.substring(start, end));
|
|
27
|
+
start = end - this.chunkOverlap;
|
|
28
|
+
|
|
29
|
+
if (start < 0) start = 0;
|
|
30
|
+
if (start >= text.length - this.chunkOverlap) {
|
|
31
|
+
if (start < text.length) {
|
|
32
|
+
chunks.push(text.substring(start));
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return chunks;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private findBestSplitPoint(text: string, start: number, end: number): number {
|
|
42
|
+
for (const sep of this.separators) {
|
|
43
|
+
const lastSep = text.lastIndexOf(sep, end);
|
|
44
|
+
if (lastSep > start) {
|
|
45
|
+
return Math.min(lastSep + sep.length, end);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return end;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { EmbeddingProvider, EmbeddingProviderConfig } from './provider.js';
|
|
2
|
+
export { EmbeddingService } from '../resolvers/sqldb/impl.js';
|
|
3
|
+
export { TextChunker } from './chunker.js';
|
|
4
|
+
export { embeddingProvider, getDefaultEmbeddingProvider } from './registry.js';
|
|
5
|
+
export { OpenAIEmbeddingProvider, OpenAIEmbeddingConfig } from './openai.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { OpenAIEmbeddings } from '@langchain/openai';
|
|
2
|
+
import { EmbeddingProvider, EmbeddingProviderConfig } from './provider.js';
|
|
3
|
+
import { getLocalEnv } from '../auth/defs.js';
|
|
4
|
+
|
|
5
|
+
export interface OpenAIEmbeddingConfig extends EmbeddingProviderConfig {
|
|
6
|
+
model?: string;
|
|
7
|
+
dimensions?: number;
|
|
8
|
+
maxRetries?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class OpenAIEmbeddingProvider extends EmbeddingProvider {
|
|
12
|
+
private openaiConfig: OpenAIEmbeddingConfig;
|
|
13
|
+
|
|
14
|
+
constructor(config?: EmbeddingProviderConfig) {
|
|
15
|
+
super(config || {});
|
|
16
|
+
this.openaiConfig = (this.config as OpenAIEmbeddingConfig) || {};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
protected createEmbeddings(): OpenAIEmbeddings {
|
|
20
|
+
const config: any = {
|
|
21
|
+
apiKey: this.resolveApiKey(),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (this.openaiConfig.model) {
|
|
25
|
+
config.model = this.openaiConfig.model;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (this.openaiConfig.dimensions) {
|
|
29
|
+
config.dimensions = this.openaiConfig.dimensions;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (this.openaiConfig.maxRetries !== undefined) {
|
|
33
|
+
config.maxRetries = this.openaiConfig.maxRetries;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return new OpenAIEmbeddings(config);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected resolveApiKey(): string {
|
|
40
|
+
if (this.openaiConfig.apiKey) {
|
|
41
|
+
return this.openaiConfig.apiKey;
|
|
42
|
+
}
|
|
43
|
+
return process.env.AGENTLANG_OPENAI_KEY || getLocalEnv('AGENTLANG_OPENAI_KEY') || '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getProviderName(): string {
|
|
47
|
+
return 'openai';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Embeddings } from '@langchain/core/embeddings';
|
|
2
|
+
|
|
3
|
+
export interface EmbeddingProviderConfig {
|
|
4
|
+
chunkSize?: number;
|
|
5
|
+
chunkOverlap?: number;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export abstract class EmbeddingProvider {
|
|
12
|
+
protected config: EmbeddingProviderConfig;
|
|
13
|
+
protected embeddings: Embeddings;
|
|
14
|
+
|
|
15
|
+
constructor(config: EmbeddingProviderConfig = {}) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.embeddings = this.createEmbeddings();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected abstract createEmbeddings(): Embeddings;
|
|
21
|
+
protected abstract resolveApiKey(): string;
|
|
22
|
+
|
|
23
|
+
abstract getProviderName(): string;
|
|
24
|
+
|
|
25
|
+
async embedText(text: string): Promise<number[]> {
|
|
26
|
+
return await this.embeddings.embedQuery(text);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getConfig(): EmbeddingProviderConfig {
|
|
30
|
+
return { ...this.config };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
updateConfig(newConfig: Partial<EmbeddingProviderConfig>): void {
|
|
34
|
+
this.config = { ...this.config, ...newConfig };
|
|
35
|
+
this.embeddings = this.createEmbeddings();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OpenAIEmbeddingProvider } from './openai.js';
|
|
2
|
+
|
|
3
|
+
const EmbeddingProviders = new Map().set('openai', OpenAIEmbeddingProvider);
|
|
4
|
+
|
|
5
|
+
export function embeddingProvider(service: string): any {
|
|
6
|
+
const requestedService = service.toLowerCase();
|
|
7
|
+
const provider = EmbeddingProviders.get(requestedService);
|
|
8
|
+
if (provider) {
|
|
9
|
+
return provider;
|
|
10
|
+
} else {
|
|
11
|
+
throw new Error(`No embedding provider found for ${service}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getDefaultEmbeddingProvider(): string {
|
|
16
|
+
return 'openai';
|
|
17
|
+
}
|
|
@@ -32,8 +32,8 @@ import {
|
|
|
32
32
|
WhereSpec,
|
|
33
33
|
} from '../language/generated/ast.js';
|
|
34
34
|
import {
|
|
35
|
-
maybeInstanceAsString,
|
|
36
35
|
defineAgentEvent,
|
|
36
|
+
Event,
|
|
37
37
|
getOneOfRef,
|
|
38
38
|
getRelationship,
|
|
39
39
|
getWorkflow,
|
|
@@ -46,15 +46,15 @@ import {
|
|
|
46
46
|
isEntityInstance,
|
|
47
47
|
isEventInstance,
|
|
48
48
|
isInstanceOfType,
|
|
49
|
+
isOneToOneBetweenRelationship,
|
|
49
50
|
isTimer,
|
|
50
51
|
makeInstance,
|
|
52
|
+
maybeInstanceAsString,
|
|
51
53
|
newInstanceAttributes,
|
|
52
54
|
PlaceholderRecordEntry,
|
|
53
55
|
Relationship,
|
|
54
|
-
Workflow,
|
|
55
56
|
setMetaAttributes,
|
|
56
|
-
|
|
57
|
-
isOneToOneBetweenRelationship,
|
|
57
|
+
Workflow,
|
|
58
58
|
} from './module.js';
|
|
59
59
|
import { JoinInfo, Resolver, WhereClause } from './resolvers/interface.js';
|
|
60
60
|
import { ResolverAuthInfo } from './resolvers/authinfo.js';
|
|
@@ -65,26 +65,26 @@ import {
|
|
|
65
65
|
escapeFqName,
|
|
66
66
|
escapeQueryName,
|
|
67
67
|
fqNameFromPath,
|
|
68
|
+
isCoreModule,
|
|
68
69
|
isFqName,
|
|
69
70
|
isPath,
|
|
70
71
|
isString,
|
|
71
72
|
makeCoreModuleName,
|
|
72
73
|
makeFqName,
|
|
74
|
+
nameToPath,
|
|
73
75
|
Path,
|
|
76
|
+
preprocessRawConfig,
|
|
74
77
|
QuerySuffix,
|
|
75
78
|
restoreSpecialChars,
|
|
76
|
-
nameToPath,
|
|
77
79
|
splitRefs,
|
|
78
|
-
isCoreModule,
|
|
79
|
-
preprocessRawConfig,
|
|
80
80
|
} from './util.js';
|
|
81
81
|
import { getResolver, getResolverNameForPath } from './resolvers/registry.js';
|
|
82
82
|
import { parseStatement, parseWorkflow } from '../language/parser.js';
|
|
83
83
|
import { ActiveSessionInfo, AdminSession, AdminUserId } from './auth/defs.js';
|
|
84
84
|
import {
|
|
85
|
-
AgentInstance,
|
|
86
85
|
AgentEntityName,
|
|
87
86
|
AgentFqName,
|
|
87
|
+
AgentInstance,
|
|
88
88
|
findAgentByName,
|
|
89
89
|
normalizeGeneratedCode,
|
|
90
90
|
} from './modules/ai.js';
|
|
@@ -1755,11 +1755,15 @@ async function handleDocEvent(inst: Instance, env: Environment): Promise<void> {
|
|
|
1755
1755
|
const s = await fetchDoc(inst.lookup('url'));
|
|
1756
1756
|
if (s) {
|
|
1757
1757
|
const title = inst.lookup('title');
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1758
|
+
const doc = makeInstance(
|
|
1759
|
+
CoreAIModuleName,
|
|
1760
|
+
'Document',
|
|
1761
|
+
newInstanceAttributes().set('title', title).set('content', s)
|
|
1762
1762
|
);
|
|
1763
|
+
await computeExprAttributes(doc, undefined, undefined, env);
|
|
1764
|
+
await setMetaAttributes(doc.attributes, env);
|
|
1765
|
+
const res: Resolver = await getResolverForPath('Document', CoreAIModuleName, env);
|
|
1766
|
+
await res.createInstance(doc);
|
|
1763
1767
|
}
|
|
1764
1768
|
}
|
|
1765
1769
|
|
package/src/runtime/module.ts
CHANGED
|
@@ -1,57 +1,58 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
AttributeDefinition,
|
|
4
|
+
Expr,
|
|
5
|
+
FlowDefinition,
|
|
6
|
+
FlowEntry,
|
|
6
7
|
FnCall,
|
|
7
|
-
|
|
8
|
+
isLiteral,
|
|
8
9
|
isRelNodes,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
NodeDefinition,
|
|
12
|
-
RecordSchemaDefinition,
|
|
10
|
+
KvPair,
|
|
11
|
+
Literal,
|
|
13
12
|
MapEntry,
|
|
14
|
-
isLiteral,
|
|
15
13
|
MetaDefinition,
|
|
14
|
+
NodeDefinition,
|
|
16
15
|
PrePostTriggerDefinition,
|
|
17
|
-
|
|
18
|
-
Expr,
|
|
19
|
-
RbacSpecEntry,
|
|
20
|
-
RbacSpecEntries,
|
|
16
|
+
PropertyDefinition,
|
|
21
17
|
RbacOpr,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
RbacSpecEntries,
|
|
19
|
+
RbacSpecEntry,
|
|
20
|
+
RecordSchemaDefinition,
|
|
21
|
+
RelNodes,
|
|
22
|
+
Statement,
|
|
23
|
+
TriggerEntry,
|
|
25
24
|
WorkflowDirectives,
|
|
25
|
+
WorkflowHeader,
|
|
26
26
|
} from '../language/generated/ast.js';
|
|
27
27
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isString,
|
|
31
|
-
isNumber,
|
|
32
|
-
isBoolean,
|
|
33
|
-
isFqName,
|
|
34
|
-
makeFqName,
|
|
28
|
+
asCrudType,
|
|
29
|
+
CrudType,
|
|
35
30
|
DefaultModuleName,
|
|
36
31
|
DefaultModules,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
findMetaSchema,
|
|
32
|
+
encryptPassword,
|
|
33
|
+
escapeFqName,
|
|
34
|
+
escapeSpecialChars,
|
|
41
35
|
findAllPrePostTriggerSchema,
|
|
42
|
-
|
|
43
|
-
asCrudType,
|
|
44
|
-
isPath,
|
|
36
|
+
findMetaSchema,
|
|
45
37
|
findUqCompositeAttributes,
|
|
46
|
-
escapeFqName,
|
|
47
|
-
encryptPassword,
|
|
48
|
-
splitFqName,
|
|
49
|
-
splitRefs,
|
|
50
38
|
forceAsFqName,
|
|
51
|
-
|
|
39
|
+
isBoolean,
|
|
40
|
+
isFqName,
|
|
41
|
+
isMinusZero,
|
|
42
|
+
isNumber,
|
|
43
|
+
isPath,
|
|
44
|
+
isString,
|
|
45
|
+
joinStatements,
|
|
46
|
+
makeFqName,
|
|
52
47
|
nameContainsSepEscape,
|
|
48
|
+
nameToPath,
|
|
49
|
+
now,
|
|
50
|
+
Path,
|
|
53
51
|
registerInitFunction,
|
|
54
52
|
ScratchModuleName,
|
|
53
|
+
splitFqName,
|
|
54
|
+
splitRefs,
|
|
55
|
+
validateIdFormat,
|
|
55
56
|
} from './util.js';
|
|
56
57
|
import { parseStatement } from '../language/parser.js';
|
|
57
58
|
import { ActiveSessionInfo, AdminSession } from './auth/defs.js';
|
|
@@ -513,7 +514,10 @@ export class Record extends ModuleEntry {
|
|
|
513
514
|
}
|
|
514
515
|
|
|
515
516
|
getFullTextSearchAttributes(): string[] | undefined {
|
|
516
|
-
|
|
517
|
+
let fts: string[] | string | undefined = this.getMeta('fullTextSearchAttributes');
|
|
518
|
+
if (!fts) {
|
|
519
|
+
fts = this.getMeta('fullTextSearch');
|
|
520
|
+
}
|
|
517
521
|
if (fts) {
|
|
518
522
|
if (fts instanceof Array) {
|
|
519
523
|
return fts as string[];
|
|
@@ -527,6 +531,14 @@ export class Record extends ModuleEntry {
|
|
|
527
531
|
}
|
|
528
532
|
}
|
|
529
533
|
|
|
534
|
+
getEmbeddingConfig(): { [key: string]: any } | undefined {
|
|
535
|
+
const config = this.getMeta('embeddingConfig');
|
|
536
|
+
if (config && typeof config === 'object') {
|
|
537
|
+
return config as { [key: string]: any };
|
|
538
|
+
}
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
|
|
530
542
|
private resetUserAttrs() {
|
|
531
543
|
this.userAttrNames = undefined;
|
|
532
544
|
this.userAttrsSchema = undefined;
|
|
@@ -1150,7 +1162,16 @@ export class Agent extends Record {
|
|
|
1150
1162
|
if (!skip && value !== null && value !== undefined) {
|
|
1151
1163
|
let v = value;
|
|
1152
1164
|
const isf = key == 'flows';
|
|
1153
|
-
|
|
1165
|
+
const isDocs = key == 'documents';
|
|
1166
|
+
if (isDocs) {
|
|
1167
|
+
const raw = isString(v) ? v : `${v}`;
|
|
1168
|
+
const items = raw
|
|
1169
|
+
.split(',')
|
|
1170
|
+
.map((entry: string) => entry.trim())
|
|
1171
|
+
.filter((entry: string) => entry.length > 0)
|
|
1172
|
+
.map((entry: string) => entry.replace(/\\/g, '\\\\').replace(/"/g, '\\"'));
|
|
1173
|
+
v = `[${items.map((entry: string) => `"${entry}"`).join(', ')}]`;
|
|
1174
|
+
} else if (isf || key == 'tools') {
|
|
1154
1175
|
if (isf || v.indexOf(',') > 0 || v.indexOf('/') > 0) v = `[${v}]`;
|
|
1155
1176
|
else v = `"${v}"`;
|
|
1156
1177
|
} else if (isString(v)) {
|
|
@@ -1874,6 +1895,42 @@ export class GlossaryEntry extends ModuleEntry {
|
|
|
1874
1895
|
}
|
|
1875
1896
|
}
|
|
1876
1897
|
|
|
1898
|
+
export type ModuleDocument = {
|
|
1899
|
+
title: string;
|
|
1900
|
+
url: string;
|
|
1901
|
+
};
|
|
1902
|
+
|
|
1903
|
+
export class DocumentEntry extends ModuleEntry {
|
|
1904
|
+
private doc: ModuleDocument;
|
|
1905
|
+
|
|
1906
|
+
constructor(title: string, moduleName: string, url: string) {
|
|
1907
|
+
super(title, moduleName);
|
|
1908
|
+
this.doc = { title, url };
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
getUrl(): string {
|
|
1912
|
+
return this.doc.url;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
getTitle(): string {
|
|
1916
|
+
return this.doc.title;
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
override toString(): string {
|
|
1920
|
+
const escapedTitle = escapeSpecialChars(this.doc.title);
|
|
1921
|
+
const escapedUrl = escapeSpecialChars(this.doc.url);
|
|
1922
|
+
return `{${DefaultModuleName}.ai/doc {\n title "${escapedTitle}",\n url "${escapedUrl}"\n}}`;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
get url(): string {
|
|
1926
|
+
return this.doc.url;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
set url(value: string) {
|
|
1930
|
+
this.doc.url = value;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1877
1934
|
function statementLabel(stmt: Statement | undefined): string {
|
|
1878
1935
|
if (stmt === undefined) return '';
|
|
1879
1936
|
let lbl: string | undefined = undefined;
|
|
@@ -2461,6 +2518,48 @@ export class Module {
|
|
|
2461
2518
|
return this;
|
|
2462
2519
|
}
|
|
2463
2520
|
|
|
2521
|
+
addDocument(title: string, url: string): Module {
|
|
2522
|
+
if (this.hasEntry(title)) {
|
|
2523
|
+
const existing = this.getEntry(title);
|
|
2524
|
+
if (existing instanceof DocumentEntry) {
|
|
2525
|
+
const doc = existing as DocumentEntry;
|
|
2526
|
+
doc.url = url;
|
|
2527
|
+
return this;
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
const docEntry = new DocumentEntry(title, this.name, url);
|
|
2532
|
+
this.addEntry(docEntry);
|
|
2533
|
+
return this;
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
getDocument(title: string): string | undefined {
|
|
2537
|
+
if (this.hasEntry(title)) {
|
|
2538
|
+
const entry = this.getEntry(title);
|
|
2539
|
+
if (entry instanceof DocumentEntry) {
|
|
2540
|
+
return (entry as DocumentEntry).url;
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return undefined;
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
getAllDocuments(): DocumentEntry[] {
|
|
2547
|
+
return this.entries.filter((e: ModuleEntry) => {
|
|
2548
|
+
return e instanceof DocumentEntry;
|
|
2549
|
+
}) as DocumentEntry[];
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
removeDocument(title: string): Module {
|
|
2553
|
+
for (let i = 0; i < this.entries.length; ++i) {
|
|
2554
|
+
const entry = this.entries[i];
|
|
2555
|
+
if (entry.name === title && entry instanceof DocumentEntry) {
|
|
2556
|
+
this.entries.splice(i, 1);
|
|
2557
|
+
break;
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
return this;
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2464
2563
|
addRetry(retry: Retry): Module {
|
|
2465
2564
|
this.addEntry(retry);
|
|
2466
2565
|
return this;
|
|
@@ -2496,7 +2595,7 @@ export class Module {
|
|
|
2496
2595
|
|
|
2497
2596
|
private getEntryIndex(entryName: string): number {
|
|
2498
2597
|
return this.entries.findIndex((v: ModuleEntry) => {
|
|
2499
|
-
return v.name
|
|
2598
|
+
return v.name === entryName;
|
|
2500
2599
|
});
|
|
2501
2600
|
}
|
|
2502
2601
|
|
|
@@ -2723,6 +2822,17 @@ export class Module {
|
|
|
2723
2822
|
|
|
2724
2823
|
let GlobalRetries: Array<Retry> | undefined = undefined;
|
|
2725
2824
|
|
|
2825
|
+
const DocumentAliasMap: Map<string, string> = new Map();
|
|
2826
|
+
|
|
2827
|
+
export function registerDocumentAlias(name: string, title: string): void {
|
|
2828
|
+
if (!name || !title) return;
|
|
2829
|
+
DocumentAliasMap.set(name, title);
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
export function resolveDocumentAliases(names: string[]): string[] {
|
|
2833
|
+
return names.map((name: string) => DocumentAliasMap.get(name) ?? name);
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2726
2836
|
export function addGlobalRetry(r: Retry): Retry {
|
|
2727
2837
|
if (GlobalRetries === undefined) {
|
|
2728
2838
|
GlobalRetries = new Array<Retry>();
|
|
@@ -2782,8 +2892,6 @@ export function removeModule(name: string): boolean {
|
|
|
2782
2892
|
return false;
|
|
2783
2893
|
}
|
|
2784
2894
|
|
|
2785
|
-
addModule(DefaultModuleName);
|
|
2786
|
-
addRecord('env', DefaultModuleName);
|
|
2787
2895
|
addModule(ScratchModuleName);
|
|
2788
2896
|
|
|
2789
2897
|
export function getModuleNames(): string[] {
|