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.
- package/README.md +7 -14
- package/out/api/http.d.ts +4 -0
- package/out/api/http.d.ts.map +1 -1
- package/out/api/http.js +307 -26
- package/out/api/http.js.map +1 -1
- package/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +3 -0
- 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/agentlang-validator.d.ts.map +1 -1
- package/out/language/agentlang-validator.js +4 -0
- package/out/language/agentlang-validator.js.map +1 -1
- package/out/language/error-reporter.d.ts +53 -0
- package/out/language/error-reporter.d.ts.map +1 -0
- package/out/language/error-reporter.js +879 -0
- package/out/language/error-reporter.js.map +1 -0
- package/out/language/generated/ast.d.ts +77 -2
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +60 -0
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +342 -206
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +901 -710
- package/out/language/main.cjs.map +3 -3
- package/out/language/parser.d.ts +4 -2
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +58 -99
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +16 -0
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +66 -27
- package/out/language/syntax.js.map +1 -1
- package/out/runtime/api.d.ts +2 -0
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +25 -0
- package/out/runtime/api.js.map +1 -1
- package/out/runtime/datefns.d.ts +34 -0
- package/out/runtime/datefns.d.ts.map +1 -0
- package/out/runtime/datefns.js +82 -0
- package/out/runtime/datefns.js.map +1 -0
- package/out/runtime/defs.d.ts +1 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +2 -1
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/document-retriever.d.ts +24 -0
- package/out/runtime/document-retriever.d.ts.map +1 -0
- package/out/runtime/document-retriever.js +258 -0
- package/out/runtime/document-retriever.js.map +1 -0
- package/out/runtime/embeddings/chunker.d.ts +18 -0
- package/out/runtime/embeddings/chunker.d.ts.map +1 -1
- package/out/runtime/embeddings/chunker.js +47 -15
- package/out/runtime/embeddings/chunker.js.map +1 -1
- package/out/runtime/embeddings/openai.d.ts.map +1 -1
- package/out/runtime/embeddings/openai.js +22 -9
- package/out/runtime/embeddings/openai.js.map +1 -1
- package/out/runtime/embeddings/provider.d.ts +1 -0
- package/out/runtime/embeddings/provider.d.ts.map +1 -1
- package/out/runtime/embeddings/provider.js +20 -1
- package/out/runtime/embeddings/provider.js.map +1 -1
- package/out/runtime/exec-graph.d.ts.map +1 -1
- package/out/runtime/exec-graph.js +22 -3
- package/out/runtime/exec-graph.js.map +1 -1
- package/out/runtime/integration-client.d.ts +21 -0
- package/out/runtime/integration-client.d.ts.map +1 -0
- package/out/runtime/integration-client.js +112 -0
- package/out/runtime/integration-client.js.map +1 -0
- package/out/runtime/integrations.d.ts.map +1 -1
- package/out/runtime/integrations.js +20 -9
- package/out/runtime/integrations.js.map +1 -1
- package/out/runtime/interpreter.d.ts +10 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +221 -22
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +70 -7
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/logger.d.ts.map +1 -1
- package/out/runtime/logger.js +8 -1
- package/out/runtime/logger.js.map +1 -1
- package/out/runtime/module.d.ts +18 -0
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +91 -3
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +16 -5
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +286 -88
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +5 -1
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/monitor.d.ts +6 -0
- package/out/runtime/monitor.d.ts.map +1 -1
- package/out/runtime/monitor.js +21 -1
- package/out/runtime/monitor.js.map +1 -1
- package/out/runtime/relgraph.d.ts.map +1 -1
- package/out/runtime/relgraph.js +7 -3
- package/out/runtime/relgraph.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +7 -2
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +17 -3
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +2 -0
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +142 -126
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.js +25 -4
- package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +2 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +24 -7
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/resolvers/vector/lancedb-store.d.ts +16 -0
- package/out/runtime/resolvers/vector/lancedb-store.d.ts.map +1 -0
- package/out/runtime/resolvers/vector/lancedb-store.js +159 -0
- package/out/runtime/resolvers/vector/lancedb-store.js.map +1 -0
- package/out/runtime/resolvers/vector/types.d.ts +32 -0
- package/out/runtime/resolvers/vector/types.d.ts.map +1 -0
- package/out/runtime/resolvers/vector/types.js +2 -0
- package/out/runtime/resolvers/vector/types.js.map +1 -0
- package/out/runtime/services/documentFetcher.d.ts.map +1 -1
- package/out/runtime/services/documentFetcher.js +21 -6
- package/out/runtime/services/documentFetcher.js.map +1 -1
- package/out/runtime/state.d.ts +19 -1
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +36 -1
- package/out/runtime/state.js.map +1 -1
- package/out/runtime/util.d.ts +3 -2
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +13 -2
- package/out/runtime/util.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/out/test-harness.d.ts +36 -0
- package/out/test-harness.d.ts.map +1 -0
- package/out/test-harness.js +341 -0
- package/out/test-harness.js.map +1 -0
- package/package.json +22 -19
- package/src/api/http.ts +336 -38
- package/src/cli/main.ts +3 -0
- package/src/language/agentlang-validator.ts +3 -0
- package/src/language/agentlang.langium +6 -2
- package/src/language/error-reporter.ts +1028 -0
- package/src/language/generated/ast.ts +94 -1
- package/src/language/generated/grammar.ts +342 -206
- package/src/language/parser.ts +64 -101
- package/src/language/syntax.ts +79 -24
- package/src/runtime/api.ts +36 -0
- package/src/runtime/datefns.ts +112 -0
- package/src/runtime/defs.ts +2 -1
- package/src/runtime/document-retriever.ts +311 -0
- package/src/runtime/embeddings/chunker.ts +52 -14
- package/src/runtime/embeddings/openai.ts +27 -9
- package/src/runtime/embeddings/provider.ts +22 -1
- package/src/runtime/exec-graph.ts +23 -2
- package/src/runtime/integration-client.ts +158 -0
- package/src/runtime/integrations.ts +20 -11
- package/src/runtime/interpreter.ts +221 -15
- package/src/runtime/loader.ts +83 -5
- package/src/runtime/logger.ts +12 -1
- package/src/runtime/module.ts +104 -3
- package/src/runtime/modules/ai.ts +341 -107
- package/src/runtime/modules/core.ts +5 -1
- package/src/runtime/monitor.ts +27 -1
- package/src/runtime/relgraph.ts +7 -3
- package/src/runtime/resolvers/interface.ts +23 -3
- package/src/runtime/resolvers/sqldb/database.ts +158 -130
- package/src/runtime/resolvers/sqldb/dbutil.ts +28 -6
- package/src/runtime/resolvers/sqldb/impl.ts +25 -7
- package/src/runtime/resolvers/vector/lancedb-store.ts +187 -0
- package/src/runtime/resolvers/vector/types.ts +39 -0
- package/src/runtime/services/documentFetcher.ts +21 -6
- package/src/runtime/state.ts +40 -1
- package/src/runtime/util.ts +19 -2
- package/src/syntaxes/agentlang.monarch.ts +1 -1
- package/src/test-harness.ts +423 -0
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
asJSONSchema,
|
|
27
27
|
Decision,
|
|
28
28
|
fetchModule,
|
|
29
|
+
getAllDocumentsForTopics,
|
|
29
30
|
getDecision,
|
|
30
31
|
getGlobalRetry,
|
|
31
32
|
Instance,
|
|
@@ -37,7 +38,9 @@ import {
|
|
|
37
38
|
newInstanceAttributes,
|
|
38
39
|
objectToInstanceAttributes,
|
|
39
40
|
Record,
|
|
41
|
+
registerTopic as registerTopicInRegistry,
|
|
40
42
|
resolveDocumentAliases,
|
|
43
|
+
resolveTopicNames,
|
|
41
44
|
Retry,
|
|
42
45
|
} from '../module.js';
|
|
43
46
|
import { provider } from '../agents/registry.js';
|
|
@@ -70,11 +73,11 @@ import {
|
|
|
70
73
|
} from '../agents/common.js';
|
|
71
74
|
import { logger } from '../logger.js';
|
|
72
75
|
import { FlowStep } from '../agents/flows.js';
|
|
73
|
-
import Handlebars from 'handlebars';
|
|
74
76
|
import { Statement } from '../../language/generated/ast.js';
|
|
75
|
-
import { isMonitoringEnabled, TtlCache } from '../state.js';
|
|
77
|
+
import { getKnowledgeGraphConfig, isMonitoringEnabled, TtlCache } from '../state.js';
|
|
76
78
|
import { isNodeEnv } from '../../utils/runtime.js';
|
|
77
79
|
import { getFileSystem } from '../../utils/fs-utils.js';
|
|
80
|
+
import { getDocumentRetriever } from '../document-retriever.js';
|
|
78
81
|
|
|
79
82
|
export const CoreAIModuleName = makeCoreModuleName('ai');
|
|
80
83
|
export const AgentEntityName = 'Agent';
|
|
@@ -83,6 +86,50 @@ export const AgentLearnerType = 'learner';
|
|
|
83
86
|
|
|
84
87
|
const AgentEvalType = 'eval';
|
|
85
88
|
|
|
89
|
+
// --- Agent cancellation infrastructure ---
|
|
90
|
+
|
|
91
|
+
export class AgentCancelledException extends Error {
|
|
92
|
+
constructor(chatId: string) {
|
|
93
|
+
super(`Agent cancelled for chatId: ${chatId}`);
|
|
94
|
+
this.name = 'AgentCancelledException';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function cancelAgent(chatId: string): Promise<string> {
|
|
99
|
+
const t = `${CoreAIModuleName}/${CancelledAgentEntity}`;
|
|
100
|
+
await parseAndEvaluateStatement(`{${t} {chatId "${chatId}"}, @upsert}`);
|
|
101
|
+
return `Cancellation requested for chatId: ${chatId}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function checkCancelled(chatId: string): Promise<void> {
|
|
105
|
+
if (!chatId) return;
|
|
106
|
+
try {
|
|
107
|
+
const results: Instance[] = await parseAndEvaluateStatement(
|
|
108
|
+
`{${CoreAIModuleName}/${CancelledAgentEntity} {chatId? "${chatId}"}}`
|
|
109
|
+
);
|
|
110
|
+
if (results && results.length > 0) {
|
|
111
|
+
await parseAndEvaluateStatement(
|
|
112
|
+
`purge {${CoreAIModuleName}/${CancelledAgentEntity} {chatId? "${chatId}"}}`
|
|
113
|
+
);
|
|
114
|
+
throw new AgentCancelledException(chatId);
|
|
115
|
+
}
|
|
116
|
+
} catch (err: any) {
|
|
117
|
+
if (err instanceof AgentCancelledException) throw err;
|
|
118
|
+
logger.debug(`checkCancelled DB error for ${chatId}: ${err}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function clearCancellation(chatId: string): Promise<void> {
|
|
123
|
+
if (!chatId) return;
|
|
124
|
+
try {
|
|
125
|
+
await parseAndEvaluateStatement(
|
|
126
|
+
`purge {${CoreAIModuleName}/${CancelledAgentEntity} {chatId? "${chatId}"}}`
|
|
127
|
+
);
|
|
128
|
+
} catch (err: any) {
|
|
129
|
+
logger.debug(`clearCancellation DB error for ${chatId}: ${err}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
86
133
|
export default `module ${CoreAIModuleName}
|
|
87
134
|
|
|
88
135
|
import "./modules/ai.js" @as ai
|
|
@@ -101,12 +148,14 @@ entity ${AgentEntityName} {
|
|
|
101
148
|
stateless Boolean @default(false),
|
|
102
149
|
instruction String @optional,
|
|
103
150
|
tools String @optional, // comma-separated list of tool names
|
|
104
|
-
documents String @optional, //
|
|
151
|
+
documents String @optional, // list of document names
|
|
152
|
+
topics String @optional, // list of topic names
|
|
105
153
|
channels String @optional, // comma-separated list of channel names
|
|
106
154
|
role String @optional,
|
|
107
155
|
flows String @optional,
|
|
108
156
|
validate String @optional,
|
|
109
157
|
retry String @optional,
|
|
158
|
+
saveResponseAs String @optional,
|
|
110
159
|
llm String
|
|
111
160
|
}
|
|
112
161
|
|
|
@@ -147,6 +196,15 @@ workflow processDoc {
|
|
|
147
196
|
await ai.fetchAndCreateDocument(doc.title, doc.url, doc.retrievalConfig, doc.embeddingConfig)
|
|
148
197
|
}
|
|
149
198
|
|
|
199
|
+
event topic {
|
|
200
|
+
name String,
|
|
201
|
+
documents String @optional // comma-separated or array of document titles
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
workflow processTopic {
|
|
205
|
+
await ai.registerTopic(topic.name, topic.documents)
|
|
206
|
+
}
|
|
207
|
+
|
|
150
208
|
entity Directive {
|
|
151
209
|
id UUID @id @default(uuid()),
|
|
152
210
|
agentFqName String @indexed,
|
|
@@ -202,6 +260,10 @@ entity AgentFlowStep {
|
|
|
202
260
|
suspensionId String
|
|
203
261
|
}
|
|
204
262
|
|
|
263
|
+
entity CancelledAgent {
|
|
264
|
+
chatId String @id
|
|
265
|
+
}
|
|
266
|
+
|
|
205
267
|
@public event restartFlow {
|
|
206
268
|
chatId String,
|
|
207
269
|
step String,
|
|
@@ -214,6 +276,14 @@ workflow restartFlow {
|
|
|
214
276
|
{${DefaultModuleName}/restartSuspension {id fs.suspensionId, data restartFlow.userInput}}
|
|
215
277
|
}
|
|
216
278
|
}
|
|
279
|
+
|
|
280
|
+
@public event cancelAgent {
|
|
281
|
+
chatId String
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
workflow cancelAgent {
|
|
285
|
+
await ai.cancelAgent(cancelAgent.chatId)
|
|
286
|
+
}
|
|
217
287
|
`;
|
|
218
288
|
|
|
219
289
|
enum AgentCacheType {
|
|
@@ -317,12 +387,14 @@ export class AgentInstance {
|
|
|
317
387
|
type: string = 'chat';
|
|
318
388
|
tools: string | undefined;
|
|
319
389
|
documents: string | undefined;
|
|
390
|
+
topics: string | undefined;
|
|
320
391
|
channels: string | undefined;
|
|
321
392
|
runWorkflows: boolean = true;
|
|
322
393
|
role: string | undefined;
|
|
323
394
|
flows: string | undefined;
|
|
324
395
|
validate: string | undefined;
|
|
325
396
|
retry: string | undefined;
|
|
397
|
+
saveResponseAs: string | undefined;
|
|
326
398
|
stateless: boolean = false;
|
|
327
399
|
private toolsArray: string[] | undefined = undefined;
|
|
328
400
|
private hasModuleTools = false;
|
|
@@ -645,7 +717,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
645
717
|
const spad = env.getScratchPad();
|
|
646
718
|
if (spad !== undefined && Object.keys(spad).length > 0) {
|
|
647
719
|
if (finalInstruction.indexOf('{{') > 0) {
|
|
648
|
-
return
|
|
720
|
+
return env.maybeRewriteTemplatePatterns(finalInstruction, spad);
|
|
649
721
|
} else {
|
|
650
722
|
const ctx = JSON.stringify(spad);
|
|
651
723
|
return `${finalInstruction}\nSome additional context:\n${ctx}`;
|
|
@@ -657,6 +729,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
657
729
|
}
|
|
658
730
|
|
|
659
731
|
private static UserTag = 'user';
|
|
732
|
+
private static FileTag = 'file';
|
|
660
733
|
|
|
661
734
|
private async getFullInstructions(
|
|
662
735
|
env: Environment,
|
|
@@ -670,13 +743,21 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
670
743
|
}
|
|
671
744
|
}
|
|
672
745
|
|
|
673
|
-
private
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
746
|
+
private async maybeFillInFileContents(instructions: string, env: Environment): Promise<string> {
|
|
747
|
+
const chatId = env.getActiveChatId();
|
|
748
|
+
const FC = '$FC';
|
|
749
|
+
if (chatId && instructions.indexOf(`<${AgentInstance.FileTag}>`) > 0) {
|
|
750
|
+
const ext = extractAndRemoveAllXmlTaggedText(instructions, AgentInstance.FileTag, FC);
|
|
751
|
+
if (ext.extracted) {
|
|
752
|
+
instructions = ext.updatedText;
|
|
753
|
+
for (let i = 0; i < ext.extracted.length; ++i) {
|
|
754
|
+
const fileName = ext.extracted[i];
|
|
755
|
+
const contents = await loadLocalAgentResult(chatId, fileName);
|
|
756
|
+
if (contents) instructions = instructions.replace(FC, contents);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return instructions;
|
|
680
761
|
}
|
|
681
762
|
|
|
682
763
|
maybeValidateJsonResponse(response: string | undefined): object | undefined {
|
|
@@ -812,6 +893,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
812
893
|
const p = await findProviderForLLM(this.llm, env);
|
|
813
894
|
const agentName = this.name;
|
|
814
895
|
const chatId = env.getAgentChatId() || agentName;
|
|
896
|
+
await checkCancelled(chatId);
|
|
815
897
|
let isplnr = this.isPlanner();
|
|
816
898
|
const isflow = !isplnr && this.isFlowExecutor();
|
|
817
899
|
const iseval = !isplnr && !isflow && this.isEvaluator();
|
|
@@ -875,7 +957,8 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
875
957
|
}
|
|
876
958
|
let tmpMsg = message;
|
|
877
959
|
if (extractedText?.extracted) {
|
|
878
|
-
|
|
960
|
+
const s = await this.maybeFillInFileContents(extractedText.extracted.join('\n'), env);
|
|
961
|
+
tmpMsg = `${tmpMsg}\n${s}`;
|
|
879
962
|
}
|
|
880
963
|
const hmsg = await this.maybeAddRelevantDocuments(
|
|
881
964
|
this.maybeAddFlowContext(tmpMsg, env),
|
|
@@ -909,7 +992,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
909
992
|
let response: AIResponse = await p.invoke(msgs, externalToolSpecs);
|
|
910
993
|
const v = this.getValidationEvent();
|
|
911
994
|
if (v) {
|
|
912
|
-
response = await this.handleValidation(response, v, msgs, p);
|
|
995
|
+
response = await this.handleValidation(response, v, msgs, p, chatId);
|
|
913
996
|
}
|
|
914
997
|
if (!iseval)
|
|
915
998
|
await AgentInstance.maybeEvaluateResponse(
|
|
@@ -927,6 +1010,13 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
927
1010
|
await saveAgentChatSession(chatId, msgs, env);
|
|
928
1011
|
}
|
|
929
1012
|
if (monitoringEnabled) env.setMonitorEntryLlmResponse(response.content);
|
|
1013
|
+
if (monitoringEnabled && response.sysMsg.usage_metadata) {
|
|
1014
|
+
const u = response.sysMsg.usage_metadata;
|
|
1015
|
+
env.setMonitorEntryLlmTokenUsage(u.input_tokens, u.output_tokens, u.total_tokens);
|
|
1016
|
+
}
|
|
1017
|
+
if (this.saveResponseAs) {
|
|
1018
|
+
await saveAgentResponse(this.saveResponseAs, response.content, env);
|
|
1019
|
+
}
|
|
930
1020
|
env.setLastResult(response.content);
|
|
931
1021
|
} catch (err: any) {
|
|
932
1022
|
logger.error(`Error while invoking ${agentName} - ${err}`);
|
|
@@ -987,7 +1077,8 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
987
1077
|
response: AIResponse,
|
|
988
1078
|
validationEventName: string,
|
|
989
1079
|
msgs: BaseMessage[],
|
|
990
|
-
provider: AgentServiceProvider
|
|
1080
|
+
provider: AgentServiceProvider,
|
|
1081
|
+
chatId?: string
|
|
991
1082
|
): Promise<AIResponse> {
|
|
992
1083
|
let r: Instance = await this.invokeValidator(response, validationEventName);
|
|
993
1084
|
const status = r.lookup('status');
|
|
@@ -999,6 +1090,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
999
1090
|
let attempt = 0;
|
|
1000
1091
|
let delay = this.retryObj.getNextDelayMs(attempt);
|
|
1001
1092
|
while (delay) {
|
|
1093
|
+
if (chatId) await checkCancelled(chatId);
|
|
1002
1094
|
msgs.push(assistantMessage(resp.content));
|
|
1003
1095
|
const vs = JSON.stringify(r.asSerializableObject());
|
|
1004
1096
|
msgs.push(
|
|
@@ -1050,93 +1142,139 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
1050
1142
|
return result;
|
|
1051
1143
|
}
|
|
1052
1144
|
|
|
1053
|
-
private async maybeAddRelevantDocuments(message: string,
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
const docNames = this.documents.split(',').map(d => d.trim());
|
|
1057
|
-
const docTitles = resolveDocumentAliases(docNames);
|
|
1145
|
+
private async maybeAddRelevantDocuments(message: string, _env: Environment): Promise<string> {
|
|
1146
|
+
const hasDocuments = this.documents && this.documents.length > 0;
|
|
1147
|
+
const hasTopics = this.topics && this.topics.length > 0;
|
|
1058
1148
|
|
|
1059
|
-
|
|
1149
|
+
if (!hasDocuments && !hasTopics) {
|
|
1150
|
+
return message;
|
|
1151
|
+
}
|
|
1060
1152
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
env
|
|
1065
|
-
);
|
|
1153
|
+
try {
|
|
1154
|
+
let containerTags: string[] = [];
|
|
1155
|
+
let topicDocumentTitles: string[] = [];
|
|
1066
1156
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
docs.push(
|
|
1073
|
-
doc instanceof Instance
|
|
1074
|
-
? doc
|
|
1075
|
-
: Instance.newWithAttributes(doc, new Map(Object.entries(doc)))
|
|
1076
|
-
);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1157
|
+
if (hasTopics) {
|
|
1158
|
+
const topicNames = resolveTopicNames(this.topics!);
|
|
1159
|
+
containerTags = topicNames;
|
|
1160
|
+
topicDocumentTitles = getAllDocumentsForTopics(topicNames);
|
|
1161
|
+
}
|
|
1079
1162
|
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
.map((v: Instance) => {
|
|
1084
|
-
return `Document: ${v.lookup('title')}\n${v.lookup('content') as string}`;
|
|
1085
|
-
})
|
|
1086
|
-
.join('\n\n---\n\n')
|
|
1087
|
-
);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
} catch (semanticErr) {
|
|
1091
|
-
logger.debug(
|
|
1092
|
-
`Semantic search is not available, falling back to title-based filtering: ${semanticErr}`
|
|
1093
|
-
);
|
|
1094
|
-
}
|
|
1163
|
+
if (containerTags.length === 0) {
|
|
1164
|
+
containerTags = [this.getFqName()];
|
|
1165
|
+
}
|
|
1095
1166
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
const docs: Instance[] = [];
|
|
1099
|
-
for (let i = 0; i < result.length; ++i) {
|
|
1100
|
-
const v: any = result[i];
|
|
1101
|
-
const docTitle: string | undefined = AgentInstance.getDocumentTitle(v);
|
|
1102
|
-
|
|
1103
|
-
if (docTitle && docTitles.includes(docTitle)) {
|
|
1104
|
-
if (v instanceof Instance) {
|
|
1105
|
-
docs.push(v);
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1167
|
+
let documentTitles: string[] = [];
|
|
1168
|
+
let documentRefs: string[] = [];
|
|
1109
1169
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1170
|
+
if (hasDocuments) {
|
|
1171
|
+
const documentEntries = this.documents!.split(',')
|
|
1172
|
+
.map(d => d.trim())
|
|
1173
|
+
.filter(Boolean);
|
|
1174
|
+
documentTitles = resolveDocumentAliases(documentEntries);
|
|
1175
|
+
documentRefs = documentEntries.filter(d => d.startsWith('document-service://'));
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
const allDocumentTitles = [...new Set([...topicDocumentTitles, ...documentTitles])];
|
|
1179
|
+
|
|
1180
|
+
const kgConfig = getKnowledgeGraphConfig();
|
|
1181
|
+
const serviceUrl = kgConfig?.serviceUrl?.trim() || process.env.KNOWLEDGE_SERVICE_URL || null;
|
|
1182
|
+
|
|
1183
|
+
if (serviceUrl) {
|
|
1184
|
+
return await this.queryRemoteKnowledgeService(
|
|
1185
|
+
message,
|
|
1186
|
+
serviceUrl,
|
|
1187
|
+
containerTags,
|
|
1188
|
+
allDocumentTitles,
|
|
1189
|
+
documentRefs
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// Local mode: embed documents into pgvector/lancedb and query
|
|
1194
|
+
const retriever = getDocumentRetriever();
|
|
1195
|
+
const aiModule = isModule(DefaultModuleName + '.ai')
|
|
1196
|
+
? fetchModule(DefaultModuleName + '.ai')
|
|
1197
|
+
: null;
|
|
1198
|
+
if (aiModule) {
|
|
1199
|
+
for (const title of allDocumentTitles) {
|
|
1200
|
+
const url = aiModule.getDocument(title);
|
|
1201
|
+
if (url) {
|
|
1202
|
+
await retriever.processDocument(title, url);
|
|
1118
1203
|
}
|
|
1119
1204
|
}
|
|
1120
|
-
} catch (err) {
|
|
1121
|
-
logger.debug(`Error retrieving documents: ${err}`);
|
|
1122
1205
|
}
|
|
1206
|
+
|
|
1207
|
+
const contextString = await retriever.query(
|
|
1208
|
+
message,
|
|
1209
|
+
allDocumentTitles.length > 0 ? allDocumentTitles : undefined,
|
|
1210
|
+
10
|
|
1211
|
+
);
|
|
1212
|
+
|
|
1213
|
+
if (contextString.trim().length > 0) {
|
|
1214
|
+
return message.concat('\n\nRelevant context from documents:\n').concat(contextString);
|
|
1215
|
+
}
|
|
1216
|
+
} catch (err) {
|
|
1217
|
+
logger.debug(`[KNOWLEDGE] Knowledge retrieval failed: ${err}`);
|
|
1123
1218
|
}
|
|
1219
|
+
|
|
1124
1220
|
return message;
|
|
1125
1221
|
}
|
|
1126
1222
|
|
|
1127
|
-
private
|
|
1128
|
-
|
|
1129
|
-
|
|
1223
|
+
private async queryRemoteKnowledgeService(
|
|
1224
|
+
message: string,
|
|
1225
|
+
serviceUrl: string,
|
|
1226
|
+
containerTags: string[],
|
|
1227
|
+
documentTitles: string[],
|
|
1228
|
+
documentRefs: string[]
|
|
1229
|
+
): Promise<string> {
|
|
1230
|
+
const options = {
|
|
1231
|
+
chunkLimit: 10,
|
|
1232
|
+
entityLimit: 20,
|
|
1233
|
+
includeChunks: true,
|
|
1234
|
+
includeEntities: true,
|
|
1235
|
+
includeEdges: true,
|
|
1236
|
+
documentTitles: documentTitles.length > 0 ? documentTitles : undefined,
|
|
1237
|
+
documentRefs: documentRefs.length > 0 ? documentRefs : undefined,
|
|
1238
|
+
};
|
|
1130
1239
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1240
|
+
let response = await fetch(`${serviceUrl}/api/knowledge/query`, {
|
|
1241
|
+
method: 'POST',
|
|
1242
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1243
|
+
body: JSON.stringify({ query: message, containerTags, ...options }),
|
|
1244
|
+
});
|
|
1245
|
+
|
|
1246
|
+
if (!response.ok) {
|
|
1247
|
+
response = await fetch(`${serviceUrl}/knowledge.core/ApiKnowledgeQuery`, {
|
|
1248
|
+
method: 'POST',
|
|
1249
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1250
|
+
body: JSON.stringify({
|
|
1251
|
+
queryText: message,
|
|
1252
|
+
containerTagsJson: JSON.stringify(containerTags),
|
|
1253
|
+
documentTitlesJson: JSON.stringify(options.documentTitles || []),
|
|
1254
|
+
documentRefsJson: JSON.stringify(options.documentRefs || []),
|
|
1255
|
+
optionsJson: JSON.stringify({
|
|
1256
|
+
includeChunks: options.includeChunks,
|
|
1257
|
+
includeEntities: options.includeEntities,
|
|
1258
|
+
includeEdges: options.includeEdges,
|
|
1259
|
+
chunkLimit: options.chunkLimit,
|
|
1260
|
+
entityLimit: options.entityLimit,
|
|
1261
|
+
}),
|
|
1262
|
+
}),
|
|
1263
|
+
});
|
|
1138
1264
|
}
|
|
1139
|
-
|
|
1265
|
+
|
|
1266
|
+
if (response.ok) {
|
|
1267
|
+
const rawPayload: any = await response.json();
|
|
1268
|
+
const first = Array.isArray(rawPayload) ? rawPayload[0] : rawPayload;
|
|
1269
|
+
const payload =
|
|
1270
|
+
first && typeof first === 'object' && first.KnowledgeQuery ? first.KnowledgeQuery : first;
|
|
1271
|
+
const contextString = payload?.contextString || '';
|
|
1272
|
+
if (contextString.trim().length > 0) {
|
|
1273
|
+
return message.concat('\n\nRelevant context from documents:\n').concat(contextString);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
return message;
|
|
1140
1278
|
}
|
|
1141
1279
|
|
|
1142
1280
|
private static ToolsCache = new Map<string, string>();
|
|
@@ -1443,20 +1581,15 @@ export async function processAgentLearning(
|
|
|
1443
1581
|
const LocalAgentgFlow = true;
|
|
1444
1582
|
const LocalFlowStepsRootDirName = 'flows';
|
|
1445
1583
|
const AgentFlowStep = 'AgentFlowStep';
|
|
1584
|
+
const CancelledAgentEntity = 'CancelledAgent';
|
|
1446
1585
|
|
|
1447
1586
|
export async function saveFlowStepResultLocally(
|
|
1448
1587
|
chatId: string,
|
|
1449
1588
|
step: string,
|
|
1450
1589
|
result: string,
|
|
1451
|
-
suspensionId
|
|
1452
|
-
): Promise<
|
|
1590
|
+
suspensionId?: string | undefined
|
|
1591
|
+
): Promise<string> {
|
|
1453
1592
|
const fs = await getFileSystem();
|
|
1454
|
-
const attrs = newInstanceAttributes()
|
|
1455
|
-
.set('chatId', chatId)
|
|
1456
|
-
.set('step', step)
|
|
1457
|
-
.set('result', result)
|
|
1458
|
-
.set('suspensionId', suspensionId);
|
|
1459
|
-
const inst = makeInstance(CoreAIModuleName, AgentFlowStep, attrs);
|
|
1460
1593
|
const rootDirName = LocalFlowStepsRootDirName;
|
|
1461
1594
|
if (!(await fs.exists(rootDirName))) {
|
|
1462
1595
|
await fs.mkdir(rootDirName);
|
|
@@ -1469,8 +1602,18 @@ export async function saveFlowStepResultLocally(
|
|
|
1469
1602
|
if (await fs.exists(fileName)) {
|
|
1470
1603
|
await fs.unlink(fileName);
|
|
1471
1604
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1605
|
+
let s = result;
|
|
1606
|
+
if (suspensionId) {
|
|
1607
|
+
const attrs = newInstanceAttributes()
|
|
1608
|
+
.set('chatId', chatId)
|
|
1609
|
+
.set('step', step)
|
|
1610
|
+
.set('result', result)
|
|
1611
|
+
.set('suspensionId', suspensionId);
|
|
1612
|
+
const inst = makeInstance(CoreAIModuleName, AgentFlowStep, attrs);
|
|
1613
|
+
s = JSON.stringify(inst.attributesAsObject(true));
|
|
1614
|
+
}
|
|
1615
|
+
await fs.writeFile(fileName, s);
|
|
1616
|
+
return s;
|
|
1474
1617
|
}
|
|
1475
1618
|
|
|
1476
1619
|
export async function saveFlowStepResult(
|
|
@@ -1479,9 +1622,10 @@ export async function saveFlowStepResult(
|
|
|
1479
1622
|
result: string,
|
|
1480
1623
|
suspensionId: string,
|
|
1481
1624
|
env: Environment
|
|
1482
|
-
): Promise<
|
|
1625
|
+
): Promise<boolean> {
|
|
1483
1626
|
if (LocalAgentgFlow) {
|
|
1484
|
-
|
|
1627
|
+
await saveFlowStepResultLocally(chatId, step, result, suspensionId);
|
|
1628
|
+
return true;
|
|
1485
1629
|
} else {
|
|
1486
1630
|
const t = `${CoreAIModuleName}/${AgentFlowStep}`;
|
|
1487
1631
|
try {
|
|
@@ -1495,11 +1639,11 @@ export async function saveFlowStepResult(
|
|
|
1495
1639
|
undefined,
|
|
1496
1640
|
env
|
|
1497
1641
|
);
|
|
1498
|
-
if (isInstanceOfType(inst, t)) return
|
|
1499
|
-
else return
|
|
1642
|
+
if (isInstanceOfType(inst, t)) return true;
|
|
1643
|
+
else return false;
|
|
1500
1644
|
} catch (reason: any) {
|
|
1501
1645
|
logger.error(`failed to save flow result for step ${step} - ${reason}`);
|
|
1502
|
-
return
|
|
1646
|
+
return false;
|
|
1503
1647
|
}
|
|
1504
1648
|
}
|
|
1505
1649
|
}
|
|
@@ -1537,10 +1681,10 @@ export async function loadFlowStepResults(chatId: string): Promise<Instance[]> {
|
|
|
1537
1681
|
}
|
|
1538
1682
|
}
|
|
1539
1683
|
|
|
1540
|
-
export async function
|
|
1684
|
+
export async function loadLocalAgentResult(
|
|
1541
1685
|
chatId: string,
|
|
1542
1686
|
step: string
|
|
1543
|
-
): Promise<
|
|
1687
|
+
): Promise<string | undefined> {
|
|
1544
1688
|
const fs = await getFileSystem();
|
|
1545
1689
|
const dirName = `${LocalFlowStepsRootDirName}/${chatId}`;
|
|
1546
1690
|
if (await fs.exists(dirName)) {
|
|
@@ -1548,10 +1692,7 @@ export async function loadLocalFlowStep(
|
|
|
1548
1692
|
for (let i = 0; i < fileNames.length; ++i) {
|
|
1549
1693
|
const fileName = fileNames[i];
|
|
1550
1694
|
if (fileName === step) {
|
|
1551
|
-
|
|
1552
|
-
JSON.parse(await fs.readFile(`${dirName}/${fileName}`))
|
|
1553
|
-
);
|
|
1554
|
-
return makeInstance(CoreAIModuleName, AgentFlowStep, attrs);
|
|
1695
|
+
return await fs.readFile(`${dirName}/${fileName}`);
|
|
1555
1696
|
}
|
|
1556
1697
|
}
|
|
1557
1698
|
return undefined;
|
|
@@ -1560,6 +1701,19 @@ export async function loadLocalFlowStep(
|
|
|
1560
1701
|
}
|
|
1561
1702
|
}
|
|
1562
1703
|
|
|
1704
|
+
export async function loadLocalFlowStep(
|
|
1705
|
+
chatId: string,
|
|
1706
|
+
step: string
|
|
1707
|
+
): Promise<Instance | undefined> {
|
|
1708
|
+
const contents = await loadLocalAgentResult(chatId, step);
|
|
1709
|
+
if (contents) {
|
|
1710
|
+
const attrs = objectToInstanceAttributes(JSON.parse(contents));
|
|
1711
|
+
return makeInstance(CoreAIModuleName, AgentFlowStep, attrs);
|
|
1712
|
+
} else {
|
|
1713
|
+
return undefined;
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1563
1717
|
export async function loadFlowStep(chatId: string, step: string): Promise<Instance | undefined> {
|
|
1564
1718
|
if (LocalAgentgFlow) {
|
|
1565
1719
|
return await loadLocalFlowStep(chatId, step);
|
|
@@ -1580,6 +1734,72 @@ export async function loadFlowStep(chatId: string, step: string): Promise<Instan
|
|
|
1580
1734
|
}
|
|
1581
1735
|
}
|
|
1582
1736
|
|
|
1737
|
+
export async function registerTopic(
|
|
1738
|
+
name: string,
|
|
1739
|
+
documents: string | undefined,
|
|
1740
|
+
_env: Environment
|
|
1741
|
+
): Promise<any> {
|
|
1742
|
+
// Register in local registry
|
|
1743
|
+
registerTopicInRegistry(name, documents ?? undefined);
|
|
1744
|
+
|
|
1745
|
+
// Sync to knowledge service if configured
|
|
1746
|
+
const kgConfig = getKnowledgeGraphConfig();
|
|
1747
|
+
const serviceUrl = kgConfig?.serviceUrl?.trim() || process.env.KNOWLEDGE_SERVICE_URL || null;
|
|
1748
|
+
|
|
1749
|
+
if (serviceUrl) {
|
|
1750
|
+
try {
|
|
1751
|
+
// Parse document list
|
|
1752
|
+
const docList = documents
|
|
1753
|
+
? documents
|
|
1754
|
+
.split(',')
|
|
1755
|
+
.map(d => d.trim())
|
|
1756
|
+
.filter(Boolean)
|
|
1757
|
+
: [];
|
|
1758
|
+
|
|
1759
|
+
// Create or update topic in knowledge service
|
|
1760
|
+
let response = await fetch(`${serviceUrl}/api/knowledge/topics`, {
|
|
1761
|
+
method: 'POST',
|
|
1762
|
+
headers: {
|
|
1763
|
+
'Content-Type': 'application/json',
|
|
1764
|
+
},
|
|
1765
|
+
body: JSON.stringify({
|
|
1766
|
+
name,
|
|
1767
|
+
description: `Topic ${name} with ${docList.length} documents`,
|
|
1768
|
+
documentTitles: docList,
|
|
1769
|
+
}),
|
|
1770
|
+
});
|
|
1771
|
+
|
|
1772
|
+
if (!response.ok) {
|
|
1773
|
+
// Fallback to Agentlang entity path for deployed knowledge-service
|
|
1774
|
+
response = await fetch(`${serviceUrl}/knowledge.core/Topic`, {
|
|
1775
|
+
method: 'POST',
|
|
1776
|
+
headers: {
|
|
1777
|
+
'Content-Type': 'application/json',
|
|
1778
|
+
},
|
|
1779
|
+
body: JSON.stringify({
|
|
1780
|
+
name,
|
|
1781
|
+
description: `Topic ${name} with ${docList.length} documents`,
|
|
1782
|
+
type: 'manual',
|
|
1783
|
+
documentCount: docList.length,
|
|
1784
|
+
}),
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
if (!response.ok) {
|
|
1789
|
+
const errorText = await response.text();
|
|
1790
|
+
logger.debug(`[KNOWLEDGE] Failed to sync topic to service: ${errorText}`);
|
|
1791
|
+
} else {
|
|
1792
|
+
logger.debug(`[KNOWLEDGE] Synced topic "${name}" to knowledge service`);
|
|
1793
|
+
}
|
|
1794
|
+
} catch (err) {
|
|
1795
|
+
// Don't fail topic registration if service sync fails
|
|
1796
|
+
logger.debug(`[KNOWLEDGE] Error syncing topic to service: ${err}`);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
return { topic: { name, documents: documents ?? '' } };
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1583
1803
|
export async function fetchAndCreateDocument(
|
|
1584
1804
|
title: string,
|
|
1585
1805
|
url: string,
|
|
@@ -1639,3 +1859,17 @@ export async function fetchAndCreateDocument(
|
|
|
1639
1859
|
throw new Error(`Failed to fetch document: ${title} from ${url}`);
|
|
1640
1860
|
}
|
|
1641
1861
|
}
|
|
1862
|
+
|
|
1863
|
+
export async function saveAgentResponse(
|
|
1864
|
+
fileName: string,
|
|
1865
|
+
response: string,
|
|
1866
|
+
env: Environment
|
|
1867
|
+
): Promise<string> {
|
|
1868
|
+
const chatId = env.getActiveChatId();
|
|
1869
|
+
if (chatId) {
|
|
1870
|
+
await saveFlowStepResultLocally(chatId, fileName, response);
|
|
1871
|
+
} else {
|
|
1872
|
+
logger.warn(`No chatId set, ${fileName} was not saved.`);
|
|
1873
|
+
}
|
|
1874
|
+
return response;
|
|
1875
|
+
}
|
|
@@ -749,5 +749,9 @@ export function migrationDowns(inst: Instance): string[] | undefined {
|
|
|
749
749
|
|
|
750
750
|
export async function doRawQuery(q: any): Promise<any> {
|
|
751
751
|
const qs = objectToQueryPattern(q);
|
|
752
|
-
|
|
752
|
+
const result = await parseAndEvaluateStatement(qs);
|
|
753
|
+
return {
|
|
754
|
+
query: qs,
|
|
755
|
+
result: result.map((res: any) => (res.attributes ? Object.fromEntries(res.attributes) : res)),
|
|
756
|
+
};
|
|
753
757
|
}
|