agentlang 0.10.0 → 0.10.2
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/api/http.d.ts.map +1 -1
- package/out/api/http.js +136 -0
- package/out/api/http.js.map +1 -1
- package/out/language/generated/ast.d.ts +87 -44
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +65 -31
- 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 +337 -330
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +396 -361
- package/out/language/main.cjs.map +2 -2
- package/out/language/parser.d.ts +11 -1
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +74 -8
- package/out/language/parser.js.map +1 -1
- package/out/language/syntax.d.ts +14 -0
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +60 -27
- package/out/language/syntax.js.map +1 -1
- package/out/runtime/agents/common.d.ts +2 -2
- package/out/runtime/agents/common.js +1 -1
- package/out/runtime/api.d.ts +2 -0
- package/out/runtime/api.d.ts.map +1 -1
- package/out/runtime/api.js +3 -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/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/interpreter.d.ts +9 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +85 -20
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/module.d.ts +8 -0
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +23 -0
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +9 -8
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +92 -37
- 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 +3 -2
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +3 -2
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/dbutil.js +17 -4
- package/out/runtime/resolvers/sqldb/dbutil.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +17 -7
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/services/documentFetcher.js +2 -2
- package/out/runtime/services/documentFetcher.js.map +1 -1
- package/out/runtime/util.d.ts +12 -1
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +38 -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/out/utils/fs/index.d.ts +12 -2
- package/out/utils/fs/index.d.ts.map +1 -1
- package/out/utils/fs/index.js +27 -6
- package/out/utils/fs/index.js.map +1 -1
- package/package.json +4 -1
- package/src/api/http.ts +138 -0
- package/src/language/agentlang.langium +9 -10
- package/src/language/generated/ast.ts +98 -44
- package/src/language/generated/grammar.ts +337 -330
- package/src/language/parser.ts +87 -6
- package/src/language/syntax.ts +71 -24
- package/src/runtime/agents/common.ts +1 -1
- package/src/runtime/api.ts +5 -0
- package/src/runtime/datefns.ts +112 -0
- package/src/runtime/exec-graph.ts +23 -2
- package/src/runtime/interpreter.ts +107 -19
- package/src/runtime/module.ts +26 -0
- package/src/runtime/modules/ai.ts +110 -54
- 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 +4 -2
- package/src/runtime/resolvers/sqldb/dbutil.ts +20 -6
- package/src/runtime/resolvers/sqldb/impl.ts +17 -7
- package/src/runtime/services/documentFetcher.ts +2 -2
- package/src/runtime/util.ts +62 -2
- package/src/syntaxes/agentlang.monarch.ts +1 -1
- package/src/test-harness.ts +423 -0
- package/src/utils/fs/index.ts +30 -6
package/src/runtime/monitor.ts
CHANGED
|
@@ -10,6 +10,9 @@ export class MonitorEntry {
|
|
|
10
10
|
private llm: boolean = false;
|
|
11
11
|
private llmPrompt: string | undefined;
|
|
12
12
|
private llmResponse: string | undefined;
|
|
13
|
+
private llmInputTokens: number | undefined;
|
|
14
|
+
private llmOutputTokens: number | undefined;
|
|
15
|
+
private llmTotalTokens: number | undefined;
|
|
13
16
|
private planner: boolean = false;
|
|
14
17
|
private flowStep: boolean = false;
|
|
15
18
|
private flow: boolean = false;
|
|
@@ -25,6 +28,10 @@ export class MonitorEntry {
|
|
|
25
28
|
return this.input;
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
getTimestamp(): number {
|
|
32
|
+
return this.timestamp;
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
setResult(result: any): MonitorEntry {
|
|
29
36
|
if (this.result === undefined) {
|
|
30
37
|
this.result = result;
|
|
@@ -68,6 +75,13 @@ export class MonitorEntry {
|
|
|
68
75
|
return this;
|
|
69
76
|
}
|
|
70
77
|
|
|
78
|
+
setLlmTokenUsage(input: number, output: number, total: number): MonitorEntry {
|
|
79
|
+
this.llmInputTokens = input;
|
|
80
|
+
this.llmOutputTokens = output;
|
|
81
|
+
this.llmTotalTokens = total;
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
flagAsPlanner(): MonitorEntry {
|
|
72
86
|
this.llm = true;
|
|
73
87
|
if (this.flowStep || this.flow || this.decision) {
|
|
@@ -137,6 +151,11 @@ export class MonitorEntry {
|
|
|
137
151
|
llmObj.isFlowStep = this.flowStep;
|
|
138
152
|
llmObj.isDecision = this.decision;
|
|
139
153
|
llmObj.isFlow = this.flow;
|
|
154
|
+
if (this.llmInputTokens !== undefined) {
|
|
155
|
+
llmObj.inputTokens = this.llmInputTokens;
|
|
156
|
+
llmObj.outputTokens = this.llmOutputTokens;
|
|
157
|
+
llmObj.totalTokens = this.llmTotalTokens;
|
|
158
|
+
}
|
|
140
159
|
obj.llm = llmObj;
|
|
141
160
|
}
|
|
142
161
|
obj.label = this.input;
|
|
@@ -269,9 +288,16 @@ export class Monitor {
|
|
|
269
288
|
return this;
|
|
270
289
|
}
|
|
271
290
|
|
|
291
|
+
setEntryLlmTokenUsage(input: number, output: number, total: number): Monitor {
|
|
292
|
+
if (this.lastEntry !== undefined) {
|
|
293
|
+
this.lastEntry.setLlmTokenUsage(input, output, total);
|
|
294
|
+
}
|
|
295
|
+
return this;
|
|
296
|
+
}
|
|
297
|
+
|
|
272
298
|
private finalizeLastEntry(): void {
|
|
273
299
|
if (this.lastEntry) {
|
|
274
|
-
const ms = Date.now() - this.
|
|
300
|
+
const ms = Date.now() - this.lastEntry.getTimestamp();
|
|
275
301
|
this.lastEntry.setLatencyMs(ms);
|
|
276
302
|
if (MonitoringCallback !== undefined) {
|
|
277
303
|
MonitoringCallback(this.lastEntry);
|
package/src/runtime/relgraph.ts
CHANGED
|
@@ -51,8 +51,11 @@ export class RelationshipGraph {
|
|
|
51
51
|
node: RelationshipGraphNode,
|
|
52
52
|
onNode: Function,
|
|
53
53
|
onContainsRelationship: Function,
|
|
54
|
-
onBetweenRelationship: Function
|
|
54
|
+
onBetweenRelationship: Function,
|
|
55
|
+
visited: Set<RelationshipGraphNode>
|
|
55
56
|
) {
|
|
57
|
+
if (visited.has(node)) return;
|
|
58
|
+
visited.add(node);
|
|
56
59
|
const n = node.entity.asFqName();
|
|
57
60
|
onNode(n, node.edges);
|
|
58
61
|
node.edges.forEach((edge: RelationshipGraphEdge) => {
|
|
@@ -60,13 +63,14 @@ export class RelationshipGraph {
|
|
|
60
63
|
? onContainsRelationship
|
|
61
64
|
: onBetweenRelationship;
|
|
62
65
|
rf(n, edge.node.entity.asFqName(), edge.relationship);
|
|
63
|
-
this.walkEdges(edge.node, onNode, onContainsRelationship, onBetweenRelationship);
|
|
66
|
+
this.walkEdges(edge.node, onNode, onContainsRelationship, onBetweenRelationship, visited);
|
|
64
67
|
});
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
walk(onNode: Function, onContainsRelationship: Function, onBetweenRelationship: Function) {
|
|
71
|
+
const visited = new Set<RelationshipGraphNode>();
|
|
68
72
|
this.nodes.forEach((node: RelationshipGraphNode) => {
|
|
69
|
-
this.walkEdges(node, onNode, onContainsRelationship, onBetweenRelationship);
|
|
73
|
+
this.walkEdges(node, onNode, onContainsRelationship, onBetweenRelationship, visited);
|
|
70
74
|
});
|
|
71
75
|
}
|
|
72
76
|
}
|
|
@@ -121,13 +121,15 @@ export class Resolver {
|
|
|
121
121
|
/**
|
|
122
122
|
* Return all instances connected to connectedInstance via the given between-relationship
|
|
123
123
|
* @param relationship Between relationship
|
|
124
|
-
* @param connectedInstance The instance to
|
|
124
|
+
* @param connectedInstance The instance to traverse the relationship from
|
|
125
125
|
* @param inst Target instance with query attributes
|
|
126
|
+
* @param connectedAlias For self-referencing relationships, the alias of the connected instance's role
|
|
126
127
|
*/
|
|
127
128
|
public async queryConnectedInstances(
|
|
128
129
|
relationship: Relationship,
|
|
129
130
|
connectedInstance: Instance,
|
|
130
|
-
inst: Instance
|
|
131
|
+
inst: Instance,
|
|
132
|
+
connectedAlias?: string
|
|
131
133
|
): Promise<any> {
|
|
132
134
|
return this.notImpl(`queryConnectedInstances(${relationship}, ${connectedInstance}, ${inst})`);
|
|
133
135
|
}
|
|
@@ -188,13 +188,27 @@ function ormSchemaFromRecordSchema(
|
|
|
188
188
|
const fqName = makeFqName(moduleName, entityName);
|
|
189
189
|
getAllOneToOneRelationshipsForEntity(moduleName, entityName, allBetRels).forEach(
|
|
190
190
|
(re: Relationship) => {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
)
|
|
191
|
+
if (re.isSelfReferencing()) {
|
|
192
|
+
// Self-referencing one-to-one: add columns for both aliases
|
|
193
|
+
// so each side of the relationship can be stored on the entity.
|
|
194
|
+
// Both must be nullable since they're set after entity creation.
|
|
195
|
+
[re.node1.alias, re.node2.alias].forEach((colName: string) => {
|
|
196
|
+
if (cols.has(colName)) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
`Cannot establish relationship ${re.name}, ${entityName}.${colName} already exists`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
cols.set(colName, { type: 'varchar', unique: true });
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
const colName = re.getInverseAliasForName(fqName);
|
|
205
|
+
if (cols.has(colName)) {
|
|
206
|
+
throw new Error(
|
|
207
|
+
`Cannot establish relationship ${re.name}, ${entityName}.${colName} already exists`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
cols.set(colName, { type: 'varchar', unique: true });
|
|
196
211
|
}
|
|
197
|
-
cols.set(colName, { type: 'varchar', unique: true });
|
|
198
212
|
}
|
|
199
213
|
);
|
|
200
214
|
if (relsSpec.size > 0) {
|
|
@@ -480,16 +480,17 @@ export class SqlDbResolver extends Resolver {
|
|
|
480
480
|
public override async queryConnectedInstances(
|
|
481
481
|
relationship: Relationship,
|
|
482
482
|
connectedInstance: Instance,
|
|
483
|
-
inst: Instance
|
|
483
|
+
inst: Instance,
|
|
484
|
+
connectedAlias?: string
|
|
484
485
|
): Promise<Instance[]> {
|
|
485
486
|
let result = SqlDbResolver.EmptyResultSet;
|
|
486
487
|
if (relationship.isOneToOne()) {
|
|
487
|
-
const col = relationship.
|
|
488
|
+
const col = relationship.getAliasForConnected(connectedInstance, connectedAlias);
|
|
488
489
|
inst.addQuery(col, '=', connectedInstance.lookup(PathAttributeName));
|
|
489
490
|
return await this.queryInstances(inst, false);
|
|
490
491
|
} else {
|
|
491
|
-
const from = relationship.
|
|
492
|
-
const to = relationship.
|
|
492
|
+
const from = relationship.getAliasForConnected(connectedInstance, connectedAlias);
|
|
493
|
+
const to = relationship.getInverseAliasForConnected(connectedInstance, connectedAlias);
|
|
493
494
|
await getAllConnected(
|
|
494
495
|
asTableReference(inst.moduleName, inst.name),
|
|
495
496
|
inst.queryAttributesAsObject(),
|
|
@@ -797,9 +798,18 @@ function ensureOneToOneAttributes(inst: Instance) {
|
|
|
797
798
|
const betRels = getAllBetweenRelationships();
|
|
798
799
|
getAllOneToOneRelationshipsForEntity(inst.moduleName, inst.name, betRels).forEach(
|
|
799
800
|
(re: Relationship) => {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
801
|
+
if (re.isSelfReferencing()) {
|
|
802
|
+
// Self-referencing one-to-one: ensure both alias columns have placeholder values
|
|
803
|
+
[re.node1.alias, re.node2.alias].forEach((n: string) => {
|
|
804
|
+
if (!inst.attributes.has(n)) {
|
|
805
|
+
inst.attributes.set(n, crypto.randomUUID());
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
} else {
|
|
809
|
+
const n = re.getInverseAliasFor(inst);
|
|
810
|
+
if (!inst.attributes.has(n)) {
|
|
811
|
+
inst.attributes.set(n, crypto.randomUUID());
|
|
812
|
+
}
|
|
803
813
|
}
|
|
804
814
|
}
|
|
805
815
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
2
|
-
import { readFile } from '
|
|
2
|
+
import { readFile } from '../../utils/fs-utils.js';
|
|
3
3
|
import { logger } from '../logger.js';
|
|
4
4
|
import { parseAndEvaluateStatement } from '../interpreter.js';
|
|
5
5
|
import { CoreAIModuleName } from '../modules/ai.js';
|
|
@@ -443,7 +443,7 @@ class DocumentFetcherService {
|
|
|
443
443
|
|
|
444
444
|
private async fetchFromLocal(filePath: string): Promise<string> {
|
|
445
445
|
try {
|
|
446
|
-
const content = await readFile(filePath
|
|
446
|
+
const content = await readFile(filePath);
|
|
447
447
|
const lowerPath = filePath.toLowerCase();
|
|
448
448
|
const isMarkdown = lowerPath.endsWith('.md') || lowerPath.endsWith('.markdown');
|
|
449
449
|
|
package/src/runtime/util.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { isNodeEnv } from '../utils/runtime.js';
|
|
1
|
+
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,
|
|
@@ -15,7 +16,6 @@ import {
|
|
|
15
16
|
} from '../language/generated/ast.js';
|
|
16
17
|
import { readFile } from '../utils/fs-utils.js';
|
|
17
18
|
import bcrypt from 'bcryptjs';
|
|
18
|
-
import path from 'node:path';
|
|
19
19
|
|
|
20
20
|
export const QuerySuffix = '?';
|
|
21
21
|
|
|
@@ -442,6 +442,18 @@ export function firstCatchSpec(stmt: Statement): CatchSpec | undefined {
|
|
|
442
442
|
return undefined;
|
|
443
443
|
}
|
|
444
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
|
+
|
|
445
457
|
function maybeExtractEntryName(n: string): string {
|
|
446
458
|
const i = n.indexOf('$');
|
|
447
459
|
if (i > 0) {
|
|
@@ -665,3 +677,51 @@ export function objectAsString(obj: any, keyAsString: boolean = false) {
|
|
|
665
677
|
});
|
|
666
678
|
return `{${entries.join(', ')}}`;
|
|
667
679
|
}
|
|
680
|
+
|
|
681
|
+
export type ExtractedText = {
|
|
682
|
+
extracted: string[] | undefined;
|
|
683
|
+
updatedText: string;
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
// extract all data between a given xml tag from within an arbitray text.
|
|
687
|
+
export function extractAndRemoveAllXmlTaggedText(
|
|
688
|
+
text: string,
|
|
689
|
+
tagName: string,
|
|
690
|
+
replaceWith: string = ''
|
|
691
|
+
): ExtractedText {
|
|
692
|
+
const pattern = `<${tagName}\\b[^>]*>([\\s\\S]*?)</${tagName}>`;
|
|
693
|
+
const regex = new RegExp(pattern, 'gi');
|
|
694
|
+
|
|
695
|
+
const extracted = [];
|
|
696
|
+
let updatedText = text;
|
|
697
|
+
|
|
698
|
+
let match;
|
|
699
|
+
while ((match = regex.exec(text)) !== null) {
|
|
700
|
+
extracted.push(match[1]);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
updatedText = text.replace(regex, replaceWith);
|
|
704
|
+
|
|
705
|
+
return { extracted, updatedText };
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
export type ExtractedCode = {
|
|
709
|
+
language: string | null;
|
|
710
|
+
code: string;
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
// extract tick-quoted code from markdown-formatted text.
|
|
714
|
+
export function extractFencedCodeBlocks(markdown: string): ExtractedCode[] {
|
|
715
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
716
|
+
const blocks: ExtractedCode[] = [];
|
|
717
|
+
let match;
|
|
718
|
+
|
|
719
|
+
while ((match = codeBlockRegex.exec(markdown)) !== null) {
|
|
720
|
+
blocks.push({
|
|
721
|
+
language: match[1] || null,
|
|
722
|
+
code: match[2],
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return blocks;
|
|
727
|
+
}
|
|
@@ -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','@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'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
7
|
'!=','*','+',',','-','-->','.','/',':',';','<','<=','<>','=','==','>','>=','?','@'
|