agentlang 0.10.1 → 0.10.3

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 (178) hide show
  1. package/README.md +7 -14
  2. package/out/api/http.d.ts +4 -0
  3. package/out/api/http.d.ts.map +1 -1
  4. package/out/api/http.js +307 -26
  5. package/out/api/http.js.map +1 -1
  6. package/out/cli/main.d.ts.map +1 -1
  7. package/out/cli/main.js +3 -0
  8. package/out/cli/main.js.map +1 -1
  9. package/out/extension/main.cjs +250 -250
  10. package/out/extension/main.cjs.map +2 -2
  11. package/out/language/agentlang-validator.d.ts.map +1 -1
  12. package/out/language/agentlang-validator.js +4 -0
  13. package/out/language/agentlang-validator.js.map +1 -1
  14. package/out/language/error-reporter.d.ts +53 -0
  15. package/out/language/error-reporter.d.ts.map +1 -0
  16. package/out/language/error-reporter.js +879 -0
  17. package/out/language/error-reporter.js.map +1 -0
  18. package/out/language/generated/ast.d.ts +77 -2
  19. package/out/language/generated/ast.d.ts.map +1 -1
  20. package/out/language/generated/ast.js +60 -0
  21. package/out/language/generated/ast.js.map +1 -1
  22. package/out/language/generated/grammar.d.ts.map +1 -1
  23. package/out/language/generated/grammar.js +342 -206
  24. package/out/language/generated/grammar.js.map +1 -1
  25. package/out/language/main.cjs +901 -710
  26. package/out/language/main.cjs.map +3 -3
  27. package/out/language/parser.d.ts +4 -2
  28. package/out/language/parser.d.ts.map +1 -1
  29. package/out/language/parser.js +58 -99
  30. package/out/language/parser.js.map +1 -1
  31. package/out/language/syntax.d.ts +16 -0
  32. package/out/language/syntax.d.ts.map +1 -1
  33. package/out/language/syntax.js +66 -27
  34. package/out/language/syntax.js.map +1 -1
  35. package/out/runtime/api.d.ts +2 -0
  36. package/out/runtime/api.d.ts.map +1 -1
  37. package/out/runtime/api.js +25 -0
  38. package/out/runtime/api.js.map +1 -1
  39. package/out/runtime/datefns.d.ts +34 -0
  40. package/out/runtime/datefns.d.ts.map +1 -0
  41. package/out/runtime/datefns.js +82 -0
  42. package/out/runtime/datefns.js.map +1 -0
  43. package/out/runtime/defs.d.ts +1 -0
  44. package/out/runtime/defs.d.ts.map +1 -1
  45. package/out/runtime/defs.js +2 -1
  46. package/out/runtime/defs.js.map +1 -1
  47. package/out/runtime/document-retriever.d.ts +24 -0
  48. package/out/runtime/document-retriever.d.ts.map +1 -0
  49. package/out/runtime/document-retriever.js +258 -0
  50. package/out/runtime/document-retriever.js.map +1 -0
  51. package/out/runtime/embeddings/chunker.d.ts +18 -0
  52. package/out/runtime/embeddings/chunker.d.ts.map +1 -1
  53. package/out/runtime/embeddings/chunker.js +47 -15
  54. package/out/runtime/embeddings/chunker.js.map +1 -1
  55. package/out/runtime/embeddings/openai.d.ts.map +1 -1
  56. package/out/runtime/embeddings/openai.js +22 -9
  57. package/out/runtime/embeddings/openai.js.map +1 -1
  58. package/out/runtime/embeddings/provider.d.ts +1 -0
  59. package/out/runtime/embeddings/provider.d.ts.map +1 -1
  60. package/out/runtime/embeddings/provider.js +20 -1
  61. package/out/runtime/embeddings/provider.js.map +1 -1
  62. package/out/runtime/exec-graph.d.ts.map +1 -1
  63. package/out/runtime/exec-graph.js +22 -3
  64. package/out/runtime/exec-graph.js.map +1 -1
  65. package/out/runtime/integration-client.d.ts +21 -0
  66. package/out/runtime/integration-client.d.ts.map +1 -0
  67. package/out/runtime/integration-client.js +112 -0
  68. package/out/runtime/integration-client.js.map +1 -0
  69. package/out/runtime/integrations.d.ts.map +1 -1
  70. package/out/runtime/integrations.js +20 -9
  71. package/out/runtime/integrations.js.map +1 -1
  72. package/out/runtime/interpreter.d.ts +10 -0
  73. package/out/runtime/interpreter.d.ts.map +1 -1
  74. package/out/runtime/interpreter.js +221 -22
  75. package/out/runtime/interpreter.js.map +1 -1
  76. package/out/runtime/loader.d.ts.map +1 -1
  77. package/out/runtime/loader.js +70 -7
  78. package/out/runtime/loader.js.map +1 -1
  79. package/out/runtime/logger.d.ts.map +1 -1
  80. package/out/runtime/logger.js +8 -1
  81. package/out/runtime/logger.js.map +1 -1
  82. package/out/runtime/module.d.ts +18 -0
  83. package/out/runtime/module.d.ts.map +1 -1
  84. package/out/runtime/module.js +91 -3
  85. package/out/runtime/module.js.map +1 -1
  86. package/out/runtime/modules/ai.d.ts +16 -5
  87. package/out/runtime/modules/ai.d.ts.map +1 -1
  88. package/out/runtime/modules/ai.js +286 -88
  89. package/out/runtime/modules/ai.js.map +1 -1
  90. package/out/runtime/modules/core.d.ts.map +1 -1
  91. package/out/runtime/modules/core.js +5 -1
  92. package/out/runtime/modules/core.js.map +1 -1
  93. package/out/runtime/monitor.d.ts +6 -0
  94. package/out/runtime/monitor.d.ts.map +1 -1
  95. package/out/runtime/monitor.js +21 -1
  96. package/out/runtime/monitor.js.map +1 -1
  97. package/out/runtime/relgraph.d.ts.map +1 -1
  98. package/out/runtime/relgraph.js +7 -3
  99. package/out/runtime/relgraph.js.map +1 -1
  100. package/out/runtime/resolvers/interface.d.ts +7 -2
  101. package/out/runtime/resolvers/interface.d.ts.map +1 -1
  102. package/out/runtime/resolvers/interface.js +17 -3
  103. package/out/runtime/resolvers/interface.js.map +1 -1
  104. package/out/runtime/resolvers/sqldb/database.d.ts +2 -0
  105. package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
  106. package/out/runtime/resolvers/sqldb/database.js +142 -126
  107. package/out/runtime/resolvers/sqldb/database.js.map +1 -1
  108. package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
  109. package/out/runtime/resolvers/sqldb/dbutil.js +25 -4
  110. package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
  111. package/out/runtime/resolvers/sqldb/impl.d.ts +2 -1
  112. package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
  113. package/out/runtime/resolvers/sqldb/impl.js +24 -7
  114. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  115. package/out/runtime/resolvers/vector/lancedb-store.d.ts +16 -0
  116. package/out/runtime/resolvers/vector/lancedb-store.d.ts.map +1 -0
  117. package/out/runtime/resolvers/vector/lancedb-store.js +159 -0
  118. package/out/runtime/resolvers/vector/lancedb-store.js.map +1 -0
  119. package/out/runtime/resolvers/vector/types.d.ts +32 -0
  120. package/out/runtime/resolvers/vector/types.d.ts.map +1 -0
  121. package/out/runtime/resolvers/vector/types.js +2 -0
  122. package/out/runtime/resolvers/vector/types.js.map +1 -0
  123. package/out/runtime/services/documentFetcher.d.ts.map +1 -1
  124. package/out/runtime/services/documentFetcher.js +21 -6
  125. package/out/runtime/services/documentFetcher.js.map +1 -1
  126. package/out/runtime/state.d.ts +19 -1
  127. package/out/runtime/state.d.ts.map +1 -1
  128. package/out/runtime/state.js +36 -1
  129. package/out/runtime/state.js.map +1 -1
  130. package/out/runtime/util.d.ts +3 -2
  131. package/out/runtime/util.d.ts.map +1 -1
  132. package/out/runtime/util.js +13 -2
  133. package/out/runtime/util.js.map +1 -1
  134. package/out/syntaxes/agentlang.monarch.js +1 -1
  135. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  136. package/out/test-harness.d.ts +36 -0
  137. package/out/test-harness.d.ts.map +1 -0
  138. package/out/test-harness.js +341 -0
  139. package/out/test-harness.js.map +1 -0
  140. package/package.json +22 -19
  141. package/src/api/http.ts +336 -38
  142. package/src/cli/main.ts +3 -0
  143. package/src/language/agentlang-validator.ts +3 -0
  144. package/src/language/agentlang.langium +6 -2
  145. package/src/language/error-reporter.ts +1028 -0
  146. package/src/language/generated/ast.ts +94 -1
  147. package/src/language/generated/grammar.ts +342 -206
  148. package/src/language/parser.ts +64 -101
  149. package/src/language/syntax.ts +79 -24
  150. package/src/runtime/api.ts +36 -0
  151. package/src/runtime/datefns.ts +112 -0
  152. package/src/runtime/defs.ts +2 -1
  153. package/src/runtime/document-retriever.ts +311 -0
  154. package/src/runtime/embeddings/chunker.ts +52 -14
  155. package/src/runtime/embeddings/openai.ts +27 -9
  156. package/src/runtime/embeddings/provider.ts +22 -1
  157. package/src/runtime/exec-graph.ts +23 -2
  158. package/src/runtime/integration-client.ts +158 -0
  159. package/src/runtime/integrations.ts +20 -11
  160. package/src/runtime/interpreter.ts +221 -15
  161. package/src/runtime/loader.ts +83 -5
  162. package/src/runtime/logger.ts +12 -1
  163. package/src/runtime/module.ts +104 -3
  164. package/src/runtime/modules/ai.ts +341 -107
  165. package/src/runtime/modules/core.ts +5 -1
  166. package/src/runtime/monitor.ts +27 -1
  167. package/src/runtime/relgraph.ts +7 -3
  168. package/src/runtime/resolvers/interface.ts +23 -3
  169. package/src/runtime/resolvers/sqldb/database.ts +158 -130
  170. package/src/runtime/resolvers/sqldb/dbutil.ts +28 -6
  171. package/src/runtime/resolvers/sqldb/impl.ts +25 -7
  172. package/src/runtime/resolvers/vector/lancedb-store.ts +187 -0
  173. package/src/runtime/resolvers/vector/types.ts +39 -0
  174. package/src/runtime/services/documentFetcher.ts +21 -6
  175. package/src/runtime/state.ts +40 -1
  176. package/src/runtime/util.ts +19 -2
  177. package/src/syntaxes/agentlang.monarch.ts +1 -1
  178. package/src/test-harness.ts +423 -0
@@ -101,6 +101,10 @@ export class EmbeddingService {
101
101
  return await this.provider.embedText(query);
102
102
  }
103
103
 
104
+ async embedTexts(texts: string[]): Promise<number[][]> {
105
+ return await this.provider.embedTexts(texts);
106
+ }
107
+
104
108
  private averageEmbeddings(embeddings: number[][]): number[] {
105
109
  if (embeddings.length === 0) return [];
106
110
  const dimension = embeddings[0].length;
@@ -402,6 +406,8 @@ export class SqlDbResolver extends Resolver {
402
406
  joinClauses: undefined,
403
407
  intoSpec: undefined,
404
408
  whereClauses: undefined,
409
+ limit: inst.limit,
410
+ offset: inst.offset,
405
411
  };
406
412
  const readOnlyAttrs = inst.record.getWriteOnlyAttributes();
407
413
  const rslt: any =
@@ -480,16 +486,17 @@ export class SqlDbResolver extends Resolver {
480
486
  public override async queryConnectedInstances(
481
487
  relationship: Relationship,
482
488
  connectedInstance: Instance,
483
- inst: Instance
489
+ inst: Instance,
490
+ connectedAlias?: string
484
491
  ): Promise<Instance[]> {
485
492
  let result = SqlDbResolver.EmptyResultSet;
486
493
  if (relationship.isOneToOne()) {
487
- const col = relationship.getAliasFor(connectedInstance);
494
+ const col = relationship.getAliasForConnected(connectedInstance, connectedAlias);
488
495
  inst.addQuery(col, '=', connectedInstance.lookup(PathAttributeName));
489
496
  return await this.queryInstances(inst, false);
490
497
  } else {
491
- const from = relationship.getAliasFor(connectedInstance);
492
- const to = relationship.getInverseAliasFor(connectedInstance);
498
+ const from = relationship.getAliasForConnected(connectedInstance, connectedAlias);
499
+ const to = relationship.getInverseAliasForConnected(connectedInstance, connectedAlias);
493
500
  await getAllConnected(
494
501
  asTableReference(inst.moduleName, inst.name),
495
502
  inst.queryAttributesAsObject(),
@@ -566,6 +573,8 @@ export class SqlDbResolver extends Resolver {
566
573
  joinClauses,
567
574
  whereClauses,
568
575
  intoSpec,
576
+ limit: inst.limit,
577
+ offset: inst.offset,
569
578
  };
570
579
  const rslt: any = await getManyByJoin(tableName, qspec, this.getDbContext(inst.getFqName()));
571
580
  return rslt;
@@ -797,9 +806,18 @@ function ensureOneToOneAttributes(inst: Instance) {
797
806
  const betRels = getAllBetweenRelationships();
798
807
  getAllOneToOneRelationshipsForEntity(inst.moduleName, inst.name, betRels).forEach(
799
808
  (re: Relationship) => {
800
- const n = re.getInverseAliasFor(inst);
801
- if (!inst.attributes.has(n)) {
802
- inst.attributes.set(n, crypto.randomUUID());
809
+ if (re.isSelfReferencing()) {
810
+ // Self-referencing one-to-one: ensure both alias columns have placeholder values
811
+ [re.node1.alias, re.node2.alias].forEach((n: string) => {
812
+ if (!inst.attributes.has(n)) {
813
+ inst.attributes.set(n, crypto.randomUUID());
814
+ }
815
+ });
816
+ } else {
817
+ const n = re.getInverseAliasFor(inst);
818
+ if (!inst.attributes.has(n)) {
819
+ inst.attributes.set(n, crypto.randomUUID());
820
+ }
803
821
  }
804
822
  }
805
823
  );
@@ -0,0 +1,187 @@
1
+ import * as lancedb from '@lancedb/lancedb';
2
+ import { Schema, Field, Float32, Utf8, FixedSizeList } from 'apache-arrow';
3
+ import { logger } from '../../logger.js';
4
+ import { VectorStore, VectorRecord, SearchResult, VectorStoreConfig } from './types.js';
5
+
6
+ export class LanceDBVectorStore implements VectorStore {
7
+ private db: lancedb.Connection | null = null;
8
+ private table: lancedb.Table | null = null;
9
+ private config: VectorStoreConfig;
10
+
11
+ constructor(config: VectorStoreConfig) {
12
+ this.config = config;
13
+ }
14
+
15
+ async init(): Promise<void> {
16
+ try {
17
+ const dbPath = this.config.inMemory
18
+ ? 'memory://'
19
+ : this.config.dbname || `./data/vector-store/${this.config.moduleName}.lance`;
20
+
21
+ this.db = await lancedb.connect(dbPath);
22
+
23
+ const tableName = 'embeddings';
24
+ const tableNames = await this.db.tableNames();
25
+
26
+ if (tableNames.includes(tableName)) {
27
+ this.table = await this.db.openTable(tableName);
28
+ logger.info(`LanceDB table ${tableName} opened`);
29
+ } else {
30
+ const schema = new Schema([
31
+ new Field('id', new Utf8(), false),
32
+ new Field(
33
+ 'embedding',
34
+ new FixedSizeList(this.config.vectorDimension, new Field('item', new Float32())),
35
+ false
36
+ ),
37
+ new Field('tenantId', new Utf8(), true),
38
+ new Field('agentId', new Utf8(), true),
39
+ new Field('documentId', new Utf8(), true),
40
+ ]);
41
+
42
+ this.table = await this.db.createEmptyTable(tableName, schema);
43
+ logger.info(`LanceDB table ${tableName} created`);
44
+ }
45
+ } catch (error) {
46
+ logger.error('Failed to initialize LanceDB vector store:', error);
47
+ throw error;
48
+ }
49
+ }
50
+
51
+ async addEmbedding(record: VectorRecord): Promise<void> {
52
+ if (!this.table) {
53
+ throw new Error('Vector store not initialized. Call init() first.');
54
+ }
55
+
56
+ try {
57
+ await this.table.add([
58
+ {
59
+ id: record.id,
60
+ embedding: record.embedding,
61
+ tenantId: record.tenantId || null,
62
+ agentId: record.agentId || null,
63
+ documentId: record.documentId || null,
64
+ },
65
+ ]);
66
+ } catch (error) {
67
+ logger.error(`Failed to add embedding ${record.id}:`, error);
68
+ throw error;
69
+ }
70
+ }
71
+
72
+ async addEmbeddings(records: VectorRecord[]): Promise<void> {
73
+ if (!this.table) {
74
+ throw new Error('Vector store not initialized. Call init() first.');
75
+ }
76
+
77
+ try {
78
+ const data = records.map(record => ({
79
+ id: record.id,
80
+ embedding: record.embedding,
81
+ tenantId: record.tenantId || null,
82
+ agentId: record.agentId || null,
83
+ documentId: record.documentId || null,
84
+ }));
85
+
86
+ await this.table.add(data);
87
+ } catch (error) {
88
+ logger.error(`Failed to add ${records.length} embeddings:`, error);
89
+ throw error;
90
+ }
91
+ }
92
+
93
+ async search(
94
+ embedding: number[],
95
+ tenantId?: string,
96
+ agentId?: string,
97
+ limit: number = 10
98
+ ): Promise<SearchResult[]> {
99
+ if (!this.table) {
100
+ throw new Error('Vector store not initialized. Call init() first.');
101
+ }
102
+
103
+ try {
104
+ let query = this.table.vectorSearch(embedding).limit(limit);
105
+
106
+ // Build filter conditions for agent-level isolation
107
+ const filters: string[] = [];
108
+
109
+ if (tenantId) {
110
+ // Use parameterized filtering to prevent SQL injection
111
+ const escapedTenantId = tenantId.replace(/'/g, "''");
112
+ filters.push(`tenantId = '${escapedTenantId}'`);
113
+ }
114
+
115
+ if (agentId) {
116
+ // Add agent-level filtering for strict agent isolation
117
+ const escapedAgentId = agentId.replace(/'/g, "''");
118
+ filters.push(`agentId = '${escapedAgentId}'`);
119
+ }
120
+
121
+ if (filters.length > 0) {
122
+ query = query.where(filters.join(' AND '));
123
+ }
124
+
125
+ const results = await query.toArray();
126
+
127
+ return results.map((row: any) => ({
128
+ id: row.id,
129
+ distance: row._distance || 0,
130
+ tenantId: row.tenantId,
131
+ agentId: row.agentId,
132
+ documentId: row.documentId,
133
+ }));
134
+ } catch (error) {
135
+ logger.error('Failed to search embeddings:', error);
136
+ throw error;
137
+ }
138
+ }
139
+
140
+ async delete(id: string): Promise<void> {
141
+ if (!this.table) {
142
+ throw new Error('Vector store not initialized. Call init() first.');
143
+ }
144
+
145
+ try {
146
+ await this.table.delete(`id = '${id}'`);
147
+ } catch (error) {
148
+ logger.error(`Failed to delete embedding ${id}:`, error);
149
+ throw error;
150
+ }
151
+ }
152
+
153
+ async exists(id: string): Promise<boolean> {
154
+ if (!this.table) {
155
+ throw new Error('Vector store not initialized. Call init() first.');
156
+ }
157
+
158
+ try {
159
+ const results = await this.table.query().where(`id = '${id}'`).limit(1).toArray();
160
+ return results.length > 0;
161
+ } catch (error) {
162
+ logger.error(`Failed to check existence of ${id}:`, error);
163
+ throw error;
164
+ }
165
+ }
166
+
167
+ async close(): Promise<void> {
168
+ try {
169
+ if (this.table) {
170
+ // LanceDB tables don't have explicit close method
171
+ this.table = null;
172
+ }
173
+ if (this.db) {
174
+ // Note: LanceDB connection doesn't have explicit close method
175
+ this.db = null;
176
+ }
177
+ logger.info('LanceDB vector store closed');
178
+ } catch (error) {
179
+ logger.error('Failed to close LanceDB vector store:', error);
180
+ throw error;
181
+ }
182
+ }
183
+ }
184
+
185
+ export function createLanceDBStore(config: VectorStoreConfig): VectorStore {
186
+ return new LanceDBVectorStore(config);
187
+ }
@@ -0,0 +1,39 @@
1
+ export interface VectorRecord {
2
+ id: string;
3
+ embedding: number[];
4
+ tenantId?: string;
5
+ agentId?: string;
6
+ documentId?: string;
7
+ metadata?: Record<string, any>;
8
+ }
9
+
10
+ export interface SearchResult {
11
+ id: string;
12
+ distance: number;
13
+ tenantId?: string;
14
+ agentId?: string;
15
+ documentId?: string;
16
+ metadata?: Record<string, any>;
17
+ }
18
+
19
+ export interface VectorStore {
20
+ init(): Promise<void>;
21
+ addEmbedding(record: VectorRecord): Promise<void>;
22
+ addEmbeddings(records: VectorRecord[]): Promise<void>;
23
+ search(
24
+ embedding: number[],
25
+ tenantId?: string,
26
+ agentId?: string,
27
+ limit?: number
28
+ ): Promise<SearchResult[]>;
29
+ delete(id: string): Promise<void>;
30
+ exists(id: string): Promise<boolean>;
31
+ close(): Promise<void>;
32
+ }
33
+
34
+ export interface VectorStoreConfig {
35
+ dbname?: string;
36
+ moduleName: string;
37
+ vectorDimension: number;
38
+ inMemory?: boolean;
39
+ }
@@ -68,6 +68,7 @@ class DocumentFetcherService {
68
68
 
69
69
  async fetchDocument(config: DocumentConfig): Promise<FetchedDocument | null> {
70
70
  this.ensureNodeEnv();
71
+ logger.info(`[DOC-FETCH] Starting fetch for: ${config.title}`);
71
72
  const cacheKey = `${config.title}:${config.url || config.documentServiceId}`;
72
73
  const cached = this.documentCache.get(cacheKey);
73
74
 
@@ -79,6 +80,7 @@ class DocumentFetcherService {
79
80
  try {
80
81
  let content: string;
81
82
  let sourceUrl: string;
83
+ logger.info(`[DOC-FETCH] Fetching from URL: ${config.url}`);
82
84
 
83
85
  if (config.url?.startsWith('document-service://')) {
84
86
  if (!config.retrievalConfig || config.retrievalConfig.provider !== 'document-service') {
@@ -144,8 +146,10 @@ class DocumentFetcherService {
144
146
  content = await this.fetchFromUrl(config.url);
145
147
  sourceUrl = config.url;
146
148
  } else if (config.url) {
149
+ logger.info(`[DOC-FETCH] Fetching from local file: ${config.url}`);
147
150
  content = await this.fetchFromLocal(config.url);
148
151
  sourceUrl = config.url;
152
+ logger.info(`[DOC-FETCH] Local file fetched successfully: ${content.length} chars`);
149
153
  } else {
150
154
  if (this.documentServiceConfig) {
151
155
  const docId = await this.lookupDocumentByTitle(config.title);
@@ -171,7 +175,9 @@ class DocumentFetcherService {
171
175
 
172
176
  this.documentCache.set(cacheKey, document);
173
177
 
178
+ logger.info(`[DOC-FETCH] Creating Document entity for: ${config.title}`);
174
179
  await this.createDocumentEntity(document);
180
+ logger.info(`[DOC-FETCH] Document entity created successfully for: ${config.title}`);
175
181
 
176
182
  return document;
177
183
  } catch (error) {
@@ -443,11 +449,14 @@ class DocumentFetcherService {
443
449
 
444
450
  private async fetchFromLocal(filePath: string): Promise<string> {
445
451
  try {
452
+ logger.info(`[DOC-FETCH] Reading local file: ${filePath}`);
446
453
  const content = await readFile(filePath);
454
+ logger.info(`[DOC-FETCH] File read successfully: ${content.length} chars`);
447
455
  const lowerPath = filePath.toLowerCase();
448
456
  const isMarkdown = lowerPath.endsWith('.md') || lowerPath.endsWith('.markdown');
449
457
 
450
458
  if (isMarkdown) {
459
+ logger.info(`[DOC-FETCH] Parsing markdown...`);
451
460
  return this.parseMarkdownText(content);
452
461
  }
453
462
 
@@ -547,10 +556,11 @@ class DocumentFetcherService {
547
556
  // Lazy load PDF parser
548
557
  if (!this.pdfParser) {
549
558
  try {
550
- const pdfParse = await import('pdf-parse');
551
- // Handle both ESM and CSM module formats
552
- const parser = (pdfParse as any).default || pdfParse;
553
- this.pdfParser = parser;
559
+ const { PDFParse } = await import('pdf-parse');
560
+ if (!PDFParse) {
561
+ throw new Error('pdf-parse does not export PDFParse');
562
+ }
563
+ this.pdfParser = PDFParse;
554
564
  } catch (error) {
555
565
  logger.error('Failed to load PDF parser', { error });
556
566
  throw new Error(
@@ -560,11 +570,16 @@ class DocumentFetcherService {
560
570
  }
561
571
 
562
572
  try {
563
- const result = await this.pdfParser(buffer);
573
+ const parser = new this.pdfParser({ data: buffer });
574
+ const result = await parser.getText();
575
+ if (typeof parser.destroy === 'function') {
576
+ await parser.destroy();
577
+ }
564
578
  return result.text || '';
565
579
  } catch (error) {
566
580
  logger.error('PDF parsing failed', { error });
567
- throw new Error(`Failed to parse PDF: ${error}`);
581
+ const message = error instanceof Error ? error.message : String(error);
582
+ throw new Error(`Failed to parse PDF: ${message}`);
568
583
  }
569
584
  }
570
585
 
@@ -35,6 +35,21 @@ export const ConfigSchema = z.object({
35
35
  type: z.literal('sqlite'),
36
36
  dbname: z.string().optional(),
37
37
  }),
38
+ z.object({
39
+ type: z.literal('lancedb'),
40
+ path: z.string().optional(),
41
+ }),
42
+ ])
43
+ .optional(),
44
+ vectorStore: z
45
+ .discriminatedUnion('type', [
46
+ z.object({
47
+ type: z.literal('pgvector'),
48
+ }),
49
+ z.object({
50
+ type: z.literal('lancedb'),
51
+ dbname: z.string().optional(),
52
+ }),
38
53
  ])
39
54
  .optional(),
40
55
  integrations: z
@@ -42,7 +57,17 @@ export const ConfigSchema = z.object({
42
57
  host: z.string(),
43
58
  username: z.string().optional(),
44
59
  password: z.string().optional(),
45
- connections: z.record(z.string(), z.string()),
60
+ connections: z.record(
61
+ z.string(),
62
+ z.union([
63
+ z.string(),
64
+ z.object({
65
+ config: z.string(),
66
+ resolvers: z.array(z.string()),
67
+ }),
68
+ ])
69
+ ),
70
+ oauth: z.boolean().default(false),
46
71
  })
47
72
  .optional(),
48
73
  graphql: z
@@ -71,6 +96,11 @@ export const ConfigSchema = z.object({
71
96
  enabled: z.boolean().default(false),
72
97
  })
73
98
  .optional(),
99
+ knowledgeGraph: z
100
+ .object({
101
+ serviceUrl: z.string().default('#js process.env.KNOWLEDGE_SERVICE_URL || ""'),
102
+ })
103
+ .optional(),
74
104
  authentication: z
75
105
  .discriminatedUnion('service', [
76
106
  z.object({
@@ -155,6 +185,15 @@ export function isMonitoringEnabled(): boolean {
155
185
  return internalMonitoringEnabled || AppConfig?.monitoring?.enabled === true;
156
186
  }
157
187
 
188
+ export function isKnowledgeGraphEnabled(): boolean {
189
+ const url = AppConfig?.knowledgeGraph?.serviceUrl?.trim();
190
+ return !!(url && url.length > 0) || !!process.env.KNOWLEDGE_SERVICE_URL;
191
+ }
192
+
193
+ export function getKnowledgeGraphConfig(): Config['knowledgeGraph'] | undefined {
194
+ return AppConfig?.knowledgeGraph;
195
+ }
196
+
158
197
  type TtlCacheEntry<T> = {
159
198
  value: T;
160
199
  expireTime: number;
@@ -2,6 +2,7 @@ import { isNodeEnv, path } from '../utils/runtime.js';
2
2
  import {
3
3
  AliasSpec,
4
4
  CatchSpec,
5
+ EmptySpec,
5
6
  ExtendsClause,
6
7
  isLiteral,
7
8
  MapEntry,
@@ -441,6 +442,18 @@ export function firstCatchSpec(stmt: Statement): CatchSpec | undefined {
441
442
  return undefined;
442
443
  }
443
444
 
445
+ export function firstEmptySpec(stmt: Statement): EmptySpec | undefined {
446
+ if (stmt.hints) {
447
+ for (let i = 0; i < stmt.hints.length; ++i) {
448
+ const rh = stmt.hints[i];
449
+ if (rh.emptySpec) {
450
+ return rh.emptySpec;
451
+ }
452
+ }
453
+ }
454
+ return undefined;
455
+ }
456
+
444
457
  function maybeExtractEntryName(n: string): string {
445
458
  const i = n.indexOf('$');
446
459
  if (i > 0) {
@@ -671,7 +684,11 @@ export type ExtractedText = {
671
684
  };
672
685
 
673
686
  // extract all data between a given xml tag from within an arbitray text.
674
- export function extractAndRemoveAllXmlTaggedText(text: string, tagName: string): ExtractedText {
687
+ export function extractAndRemoveAllXmlTaggedText(
688
+ text: string,
689
+ tagName: string,
690
+ replaceWith: string = ''
691
+ ): ExtractedText {
675
692
  const pattern = `<${tagName}\\b[^>]*>([\\s\\S]*?)</${tagName}>`;
676
693
  const regex = new RegExp(pattern, 'gi');
677
694
 
@@ -683,7 +700,7 @@ export function extractAndRemoveAllXmlTaggedText(text: string, tagName: string):
683
700
  extracted.push(match[1]);
684
701
  }
685
702
 
686
- updatedText = text.replace(regex, '');
703
+ updatedText = text.replace(regex, replaceWith);
687
704
 
688
705
  return { extracted, updatedText };
689
706
  }
@@ -1,7 +1,7 @@
1
1
  // Monarch syntax highlighting for the agentlang language.
2
2
  export default {
3
3
  keywords: [
4
- '@actions','@after','@as','@asc','@async','@before','@catch','@desc','@distinct','@enum','@expr','@from','@full_join','@groupBy','@inner_join','@into','@join','@left_join','@meta','@oneof','@orderBy','@public','@rbac','@ref','@right_join','@then','@upsert','@where','@withRole','@with_unique','agent','agentlang/retry','allow','and','attempts','await','backoff','between','case','commitTransaction','contains','create','decision','delete','directive','else','entity','error','eval','event','extends','false','flow','for','glossaryEntry','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','rollbackTransaction','scenario','startTransaction','subscribe','throw','true','update','upsert','where','workflow'
4
+ '@actions','@after','@as','@asc','@async','@before','@catch','@desc','@distinct','@empty','@enum','@expr','@from','@full_join','@groupBy','@inner_join','@into','@join','@left_join','@limit','@meta','@offset','@oneof','@orderBy','@public','@rbac','@ref','@right_join','@then','@upsert','@where','@withRole','@with_unique','agent','agentlang/retry','allow','and','attempts','await','backoff','between','case','commitTransaction','contains','create','decision','delete','directive','else','entity','error','eval','event','extends','false','flow','for','glossaryEntry','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','rollbackTransaction','scenario','startTransaction','subscribe','throw','true','update','upsert','where','workflow'
5
5
  ],
6
6
  operators: [
7
7
  '!=','*','+',',','-','-->','.','/',':',';','<','<=','<>','=','==','>','>=','?','@'