agentlang 0.1.9 → 0.2.1
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.js +3 -3
- package/out/api/http.js.map +1 -1
- package/out/language/agentlang-validator.d.ts.map +1 -1
- package/out/language/agentlang-validator.js +3 -1
- package/out/language/agentlang-validator.js.map +1 -1
- package/out/language/generated/ast.d.ts +35 -9
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +40 -1
- 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 +289 -120
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +323 -122
- package/out/language/main.cjs.map +2 -2
- package/out/language/parser.d.ts +1 -0
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +14 -13
- package/out/language/parser.js.map +1 -1
- package/out/runtime/agents/common.d.ts +2 -1
- package/out/runtime/agents/common.d.ts.map +1 -1
- package/out/runtime/agents/common.js +42 -3
- package/out/runtime/agents/common.js.map +1 -1
- package/out/runtime/exec-graph.d.ts.map +1 -1
- package/out/runtime/exec-graph.js +15 -7
- package/out/runtime/exec-graph.js.map +1 -1
- package/out/runtime/interpreter.d.ts +1 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +76 -32
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +16 -9
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +15 -0
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +96 -24
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +7 -3
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +85 -22
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/resolvers/interface.js +2 -2
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +2 -2
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/util.d.ts +2 -1
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +4 -1
- package/out/runtime/util.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +3 -3
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +8 -6
- package/src/api/http.ts +3 -3
- package/src/language/agentlang-validator.ts +3 -1
- package/src/language/agentlang.langium +8 -2
- package/src/language/generated/ast.ts +80 -9
- package/src/language/generated/grammar.ts +289 -120
- package/src/language/parser.ts +15 -14
- package/src/runtime/agents/common.ts +43 -3
- package/src/runtime/exec-graph.ts +14 -7
- package/src/runtime/interpreter.ts +82 -32
- package/src/runtime/loader.ts +23 -8
- package/src/runtime/module.ts +111 -22
- package/src/runtime/modules/ai.ts +97 -23
- package/src/runtime/resolvers/interface.ts +2 -2
- package/src/runtime/resolvers/sqldb/impl.ts +2 -2
- package/src/runtime/util.ts +5 -1
- package/src/syntaxes/agentlang.monarch.ts +3 -3
package/src/runtime/module.ts
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from '../language/generated/ast.js';
|
|
24
24
|
import {
|
|
25
25
|
Path,
|
|
26
|
-
|
|
26
|
+
nameToPath,
|
|
27
27
|
isString,
|
|
28
28
|
isNumber,
|
|
29
29
|
isBoolean,
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
findUqCompositeAttributes,
|
|
43
43
|
escapeFqName,
|
|
44
44
|
encryptPassword,
|
|
45
|
+
splitFqName,
|
|
45
46
|
} from './util.js';
|
|
46
47
|
import { parseStatement } from '../language/parser.js';
|
|
47
48
|
import { ActiveSessionInfo, AdminSession } from './auth/defs.js';
|
|
@@ -52,6 +53,7 @@ import {
|
|
|
52
53
|
AgentCondition,
|
|
53
54
|
AgentGlossaryEntry,
|
|
54
55
|
AgentScenario,
|
|
56
|
+
getAgentDirectives,
|
|
55
57
|
getAgentDirectivesJson,
|
|
56
58
|
getAgentGlossary,
|
|
57
59
|
getAgentResponseSchema,
|
|
@@ -295,7 +297,7 @@ export class Record extends ModuleEntry {
|
|
|
295
297
|
let t: string | undefined = isArrayType ? a.arrayType : a.type;
|
|
296
298
|
if (a.refSpec) {
|
|
297
299
|
let fp = a.refSpec.ref;
|
|
298
|
-
const rp =
|
|
300
|
+
const rp = nameToPath(fp);
|
|
299
301
|
if (!rp.hasModule()) {
|
|
300
302
|
rp.setModuleName(this.moduleName);
|
|
301
303
|
fp = rp.asFqName();
|
|
@@ -515,14 +517,34 @@ export class Record extends ModuleEntry {
|
|
|
515
517
|
}
|
|
516
518
|
|
|
517
519
|
override toString(): string {
|
|
520
|
+
return this.toString_();
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
toString_(internParentSchema: boolean = false): string {
|
|
518
524
|
if (this.type == RecordType.EVENT && this.meta && this.meta.get(SystemDefinedEvent)) {
|
|
519
525
|
return '';
|
|
520
526
|
}
|
|
521
527
|
let s: string = `${RecordType[this.type].toLowerCase()} ${this.name}`;
|
|
522
|
-
|
|
528
|
+
let scm: RecordSchema = this.schema;
|
|
529
|
+
if (this.parentEntryName && !internParentSchema) {
|
|
523
530
|
s = s.concat(` extends ${this.parentEntryName}`);
|
|
531
|
+
scm = newRecordSchema();
|
|
532
|
+
let modName = this.moduleName;
|
|
533
|
+
let pname = this.parentEntryName;
|
|
534
|
+
if (isFqName(pname)) {
|
|
535
|
+
const parts = splitFqName(pname);
|
|
536
|
+
modName = parts[0];
|
|
537
|
+
pname = parts[1];
|
|
538
|
+
}
|
|
539
|
+
const p = fetchModule(modName).getEntry(pname) as Record;
|
|
540
|
+
const pks = new Set(p.schema.keys());
|
|
541
|
+
this.schema.forEach((v: AttributeSpec, n: string) => {
|
|
542
|
+
if (!pks.has(n)) {
|
|
543
|
+
scm.set(n, v);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
524
546
|
}
|
|
525
|
-
let scms = recordSchemaToString(
|
|
547
|
+
let scms = recordSchemaToString(scm);
|
|
526
548
|
if (this.rbac && this.rbac.length > 0) {
|
|
527
549
|
const rbs = this.rbac.map((rs: RbacSpecification) => {
|
|
528
550
|
return rs.toString();
|
|
@@ -563,7 +585,7 @@ function fetchModuleByEntryName(
|
|
|
563
585
|
suspectModuleName: string
|
|
564
586
|
): FetchModuleByEntryNameResult {
|
|
565
587
|
if (isFqName(entryName)) {
|
|
566
|
-
const path: Path =
|
|
588
|
+
const path: Path = nameToPath(entryName);
|
|
567
589
|
entryName = path.getEntryName();
|
|
568
590
|
suspectModuleName = path.getModuleName();
|
|
569
591
|
}
|
|
@@ -623,7 +645,7 @@ function asPropertiesMap(props: PropertyDefinition[]): Map<string, any> | undefi
|
|
|
623
645
|
function maybeProcessRefProperty(props: Map<string, any>): Map<string, any> {
|
|
624
646
|
const v: string | undefined = props.get('ref');
|
|
625
647
|
if (v != undefined) {
|
|
626
|
-
const parts: Path =
|
|
648
|
+
const parts: Path = nameToPath(v);
|
|
627
649
|
if (!parts.hasModule()) {
|
|
628
650
|
parts.setModuleName(activeModule);
|
|
629
651
|
}
|
|
@@ -902,26 +924,46 @@ export class Agent extends Record {
|
|
|
902
924
|
return this.getStrings('flows');
|
|
903
925
|
}
|
|
904
926
|
|
|
927
|
+
getAgentFqName(): string {
|
|
928
|
+
return makeFqName(this.moduleName, this.getName());
|
|
929
|
+
}
|
|
930
|
+
|
|
905
931
|
setDirectives(conds: AgentCondition[]): Agent {
|
|
906
|
-
registerAgentDirectives(this.
|
|
932
|
+
registerAgentDirectives(this.getAgentFqName(), conds);
|
|
907
933
|
return this;
|
|
908
934
|
}
|
|
909
935
|
|
|
936
|
+
getDirectives(): AgentCondition[] | undefined {
|
|
937
|
+
return getAgentDirectives(this.getAgentFqName());
|
|
938
|
+
}
|
|
939
|
+
|
|
910
940
|
setScenarios(scenarios: AgentScenario[]): Agent {
|
|
911
|
-
registerAgentScenarios(this.
|
|
941
|
+
registerAgentScenarios(this.getAgentFqName(), scenarios);
|
|
912
942
|
return this;
|
|
913
943
|
}
|
|
914
944
|
|
|
945
|
+
getScenarios(): AgentScenario[] | undefined {
|
|
946
|
+
return getAgentScenarios(this.getAgentFqName());
|
|
947
|
+
}
|
|
948
|
+
|
|
915
949
|
setGlossary(glossary: AgentGlossaryEntry[]): Agent {
|
|
916
|
-
registerAgentGlossary(this.
|
|
950
|
+
registerAgentGlossary(this.getAgentFqName(), glossary);
|
|
917
951
|
return this;
|
|
918
952
|
}
|
|
919
953
|
|
|
954
|
+
getGlossary(): AgentGlossaryEntry[] | undefined {
|
|
955
|
+
return getAgentGlossary(this.getAgentFqName());
|
|
956
|
+
}
|
|
957
|
+
|
|
920
958
|
setResponseSchema(entryName: string): Agent {
|
|
921
|
-
registerAgentResponseSchema(this.
|
|
959
|
+
registerAgentResponseSchema(this.getAgentFqName(), entryName);
|
|
922
960
|
return this;
|
|
923
961
|
}
|
|
924
962
|
|
|
963
|
+
getResponseSchema(): string | undefined {
|
|
964
|
+
return getAgentResponseSchema(this.getAgentFqName());
|
|
965
|
+
}
|
|
966
|
+
|
|
925
967
|
override toString(): string {
|
|
926
968
|
const attrs = new Array<string>();
|
|
927
969
|
this.attributes.forEach((value: any, key: string) => {
|
|
@@ -1025,7 +1067,7 @@ export type RelationshipNode = {
|
|
|
1025
1067
|
};
|
|
1026
1068
|
|
|
1027
1069
|
export function newRelNodeEntry(nodeFqName: string, alias?: string): RelationshipNode {
|
|
1028
|
-
const p: Path =
|
|
1070
|
+
const p: Path = nameToPath(nodeFqName);
|
|
1029
1071
|
return {
|
|
1030
1072
|
path: p,
|
|
1031
1073
|
alias: alias ? alias : p.getEntryName(),
|
|
@@ -1043,7 +1085,7 @@ function relNodeEntryToString(node: RelationshipNode): string {
|
|
|
1043
1085
|
}
|
|
1044
1086
|
|
|
1045
1087
|
function asRelNodeEntry(n: NodeDefinition): RelationshipNode {
|
|
1046
|
-
const path: Path =
|
|
1088
|
+
const path: Path = nameToPath(n.name);
|
|
1047
1089
|
let modName = activeModule;
|
|
1048
1090
|
const entryName = path.getEntryName();
|
|
1049
1091
|
if (path.hasModule()) {
|
|
@@ -1523,6 +1565,25 @@ export function flowGraphNext(
|
|
|
1523
1565
|
return undefined;
|
|
1524
1566
|
}
|
|
1525
1567
|
|
|
1568
|
+
export class Decision extends ModuleEntry {
|
|
1569
|
+
cases: string[];
|
|
1570
|
+
|
|
1571
|
+
constructor(name: string, moduleName: string, cases: string[]) {
|
|
1572
|
+
super(name, moduleName);
|
|
1573
|
+
this.cases = cases;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
joinedCases(): string {
|
|
1577
|
+
return this.cases.join('\n');
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
override toString(): string {
|
|
1581
|
+
return `decision ${this.name} {
|
|
1582
|
+
${this.cases.join('\n')}
|
|
1583
|
+
}`;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1526
1587
|
class StandaloneStatement extends ModuleEntry {
|
|
1527
1588
|
stmt: Statement;
|
|
1528
1589
|
|
|
@@ -1588,10 +1649,12 @@ export class Module {
|
|
|
1588
1649
|
getFlow(name: string): Flow | undefined {
|
|
1589
1650
|
const n = Flow.asFlowName(name);
|
|
1590
1651
|
if (this.hasEntry(n)) {
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1652
|
+
const e = this.getEntry(n);
|
|
1653
|
+
if (e instanceof Flow) {
|
|
1654
|
+
return e as Flow;
|
|
1655
|
+
}
|
|
1594
1656
|
}
|
|
1657
|
+
return undefined;
|
|
1595
1658
|
}
|
|
1596
1659
|
|
|
1597
1660
|
getAllFlows(): Flow[] {
|
|
@@ -1607,6 +1670,22 @@ export class Module {
|
|
|
1607
1670
|
return false;
|
|
1608
1671
|
}
|
|
1609
1672
|
|
|
1673
|
+
addDecision(name: string, cases: string[]): Decision {
|
|
1674
|
+
const d = new Decision(name, this.name, cases);
|
|
1675
|
+
this.addEntry(d);
|
|
1676
|
+
return d;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
getDecision(name: string): Decision | undefined {
|
|
1680
|
+
if (this.hasEntry(name)) {
|
|
1681
|
+
const e = this.getEntry(name);
|
|
1682
|
+
if (e instanceof Decision) {
|
|
1683
|
+
return e as Decision;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
return undefined;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1610
1689
|
addStandaloneStatement(stmt: Statement): StandaloneStatement {
|
|
1611
1690
|
const s = new StandaloneStatement(stmt, this.name);
|
|
1612
1691
|
this.addEntry(s);
|
|
@@ -1918,7 +1997,7 @@ export function isBuiltInType(type: string): boolean {
|
|
|
1918
1997
|
|
|
1919
1998
|
export function isValidType(type: string): boolean {
|
|
1920
1999
|
if (isBuiltInType(type)) return true;
|
|
1921
|
-
const path: Path =
|
|
2000
|
+
const path: Path = nameToPath(type);
|
|
1922
2001
|
let modName: string = '';
|
|
1923
2002
|
if (path.hasModule()) modName = path.getModuleName();
|
|
1924
2003
|
else modName = activeModule;
|
|
@@ -2286,7 +2365,7 @@ export function prePostWorkflowName(
|
|
|
2286
2365
|
entityName: string,
|
|
2287
2366
|
moduleName?: string
|
|
2288
2367
|
): string {
|
|
2289
|
-
const parts =
|
|
2368
|
+
const parts = nameToPath(entityName);
|
|
2290
2369
|
const mname = parts.hasModule() ? parts.getModuleName() : moduleName;
|
|
2291
2370
|
if (!mname) {
|
|
2292
2371
|
throw new Error(`Cannot infer module name for ${entityName}`);
|
|
@@ -2312,7 +2391,7 @@ export function parsePrePostWorkflowName(name: string): ThinWfHeader {
|
|
|
2312
2391
|
|
|
2313
2392
|
function getEntityDef(entityName: string, moduleName: string): Entity | undefined {
|
|
2314
2393
|
try {
|
|
2315
|
-
const parts =
|
|
2394
|
+
const parts = nameToPath(entityName);
|
|
2316
2395
|
const mname = parts.hasModule() ? parts.getModuleName() : moduleName;
|
|
2317
2396
|
return getEntity(parts.getEntryName(), mname);
|
|
2318
2397
|
} catch (reason: any) {
|
|
@@ -2327,7 +2406,7 @@ export function getWorkflow(eventInstance: Instance): Workflow {
|
|
|
2327
2406
|
|
|
2328
2407
|
export function getWorkflowForEvent(eventName: string, moduleName?: string): Workflow {
|
|
2329
2408
|
if (isFqName(eventName)) {
|
|
2330
|
-
const parts =
|
|
2409
|
+
const parts = nameToPath(eventName);
|
|
2331
2410
|
eventName = parts.getEntryName();
|
|
2332
2411
|
moduleName = parts.getModuleName();
|
|
2333
2412
|
}
|
|
@@ -2351,7 +2430,7 @@ export function getEntity(name: string, moduleName: string): Entity | undefined
|
|
|
2351
2430
|
}
|
|
2352
2431
|
|
|
2353
2432
|
function isEntryOfType(t: RecordType, fqName: string): boolean {
|
|
2354
|
-
const path =
|
|
2433
|
+
const path = nameToPath(fqName);
|
|
2355
2434
|
const mod = fetchModule(path.getModuleName());
|
|
2356
2435
|
return mod.isEntryOfType(t, path.getEntryName());
|
|
2357
2436
|
}
|
|
@@ -3177,7 +3256,7 @@ export function instanceToObject<Type>(inst: Instance, obj: any): Type {
|
|
|
3177
3256
|
}
|
|
3178
3257
|
|
|
3179
3258
|
export function getEntityRbacRules(entityFqName: string): RbacSpecification[] | undefined {
|
|
3180
|
-
const p =
|
|
3259
|
+
const p = nameToPath(entityFqName);
|
|
3181
3260
|
const mn = p.getModuleName();
|
|
3182
3261
|
const en = p.getEntryName();
|
|
3183
3262
|
const m = isModule(mn) && fetchModule(mn);
|
|
@@ -3191,7 +3270,7 @@ export function getEntityRbacRules(entityFqName: string): RbacSpecification[] |
|
|
|
3191
3270
|
}
|
|
3192
3271
|
|
|
3193
3272
|
export function asJSONSchema(fqName: string): string {
|
|
3194
|
-
const parts =
|
|
3273
|
+
const parts = nameToPath(fqName);
|
|
3195
3274
|
if (parts.hasModule()) {
|
|
3196
3275
|
const mod = fetchModule(parts.getModuleName());
|
|
3197
3276
|
const record = mod.getRecord(parts.getEntryName());
|
|
@@ -3209,3 +3288,13 @@ export function asJSONSchema(fqName: string): string {
|
|
|
3209
3288
|
throw new Error(`Failed to find module for ${fqName}`);
|
|
3210
3289
|
}
|
|
3211
3290
|
}
|
|
3291
|
+
|
|
3292
|
+
export function getDecision(name: string, moduleName: string): Decision | undefined {
|
|
3293
|
+
if (isFqName(name)) {
|
|
3294
|
+
const parts = splitFqName(name);
|
|
3295
|
+
name = parts[1];
|
|
3296
|
+
moduleName = parts[0];
|
|
3297
|
+
}
|
|
3298
|
+
const m = fetchModule(moduleName);
|
|
3299
|
+
return m.getDecision(name);
|
|
3300
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFqName, makeCoreModuleName, makeFqName, splitFqName } from '../util.js';
|
|
1
|
+
import { isFqName, makeCoreModuleName, makeFqName, nameToPath, splitFqName } from '../util.js';
|
|
2
2
|
import {
|
|
3
3
|
Environment,
|
|
4
4
|
GlobalEnvironment,
|
|
@@ -7,12 +7,15 @@ import {
|
|
|
7
7
|
} from '../interpreter.js';
|
|
8
8
|
import {
|
|
9
9
|
asJSONSchema,
|
|
10
|
+
Decision,
|
|
10
11
|
fetchModule,
|
|
12
|
+
getDecision,
|
|
11
13
|
Instance,
|
|
12
14
|
instanceToObject,
|
|
13
15
|
isModule,
|
|
14
16
|
makeInstance,
|
|
15
17
|
newInstanceAttributes,
|
|
18
|
+
Record,
|
|
16
19
|
} from '../module.js';
|
|
17
20
|
import { provider } from '../agents/registry.js';
|
|
18
21
|
import {
|
|
@@ -27,6 +30,7 @@ import {
|
|
|
27
30
|
AgentCondition,
|
|
28
31
|
AgentGlossaryEntry,
|
|
29
32
|
AgentScenario,
|
|
33
|
+
DecisionAgentInstructions,
|
|
30
34
|
FlowExecInstructions,
|
|
31
35
|
getAgentDirectives,
|
|
32
36
|
getAgentGlossary,
|
|
@@ -38,6 +42,8 @@ import {
|
|
|
38
42
|
import { PathAttributeNameQuery } from '../defs.js';
|
|
39
43
|
import { logger } from '../logger.js';
|
|
40
44
|
import { FlowStep } from '../agents/flows.js';
|
|
45
|
+
import Handlebars from 'handlebars';
|
|
46
|
+
import { Statement } from '../../language/generated/ast.js';
|
|
41
47
|
|
|
42
48
|
export const CoreAIModuleName = makeCoreModuleName('ai');
|
|
43
49
|
export const AgentEntityName = 'Agent';
|
|
@@ -112,6 +118,7 @@ export class AgentInstance {
|
|
|
112
118
|
private hasModuleTools = false;
|
|
113
119
|
private withSession = true;
|
|
114
120
|
private fqName: string | undefined;
|
|
121
|
+
private decisionExecutor = false;
|
|
115
122
|
|
|
116
123
|
private constructor() {}
|
|
117
124
|
|
|
@@ -136,7 +143,7 @@ export class AgentInstance {
|
|
|
136
143
|
for (let i = 0; i < agent.toolsArray.length; ++i) {
|
|
137
144
|
const n = agent.toolsArray[i];
|
|
138
145
|
if (isFqName(n)) {
|
|
139
|
-
const parts =
|
|
146
|
+
const parts = nameToPath(n);
|
|
140
147
|
agent.hasModuleTools = isModule(parts.getModuleName());
|
|
141
148
|
} else {
|
|
142
149
|
agent.hasModuleTools = isModule(n);
|
|
@@ -147,7 +154,11 @@ export class AgentInstance {
|
|
|
147
154
|
return agent;
|
|
148
155
|
}
|
|
149
156
|
|
|
150
|
-
static FromFlowStep(step: FlowStep, flowAgent: AgentInstance): AgentInstance {
|
|
157
|
+
static FromFlowStep(step: FlowStep, flowAgent: AgentInstance, context: string): AgentInstance {
|
|
158
|
+
const desc = getDecision(step, flowAgent.moduleName);
|
|
159
|
+
if (desc) {
|
|
160
|
+
return AgentInstance.FromDecision(desc, flowAgent, context);
|
|
161
|
+
}
|
|
151
162
|
const fqs = isFqName(step) ? step : `${flowAgent.moduleName}/${step}`;
|
|
152
163
|
const instruction = `Analyse the context and generate the pattern required to invoke ${fqs}.
|
|
153
164
|
Never include references in the pattern. All attribute values must be literals derived from the context.`;
|
|
@@ -162,7 +173,21 @@ export class AgentInstance {
|
|
|
162
173
|
.set('tools', fqs)
|
|
163
174
|
.set('type', 'planner')
|
|
164
175
|
);
|
|
165
|
-
return AgentInstance.FromInstance(inst);
|
|
176
|
+
return AgentInstance.FromInstance(inst).disableSession();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
static FromDecision(desc: Decision, flowAgent: AgentInstance, context: string): AgentInstance {
|
|
180
|
+
const instruction = `${DecisionAgentInstructions}\n${context}\n\n${desc.joinedCases()}`;
|
|
181
|
+
const inst = makeInstance(
|
|
182
|
+
CoreAIModuleName,
|
|
183
|
+
AgentEntityName,
|
|
184
|
+
newInstanceAttributes()
|
|
185
|
+
.set('llm', flowAgent.llm)
|
|
186
|
+
.set('name', `${desc.name}_agent`)
|
|
187
|
+
.set('moduleName', flowAgent.moduleName)
|
|
188
|
+
.set('instruction', instruction)
|
|
189
|
+
);
|
|
190
|
+
return AgentInstance.FromInstance(inst).disableSession().markAsDecisionExecutor();
|
|
166
191
|
}
|
|
167
192
|
|
|
168
193
|
disableSession(): AgentInstance {
|
|
@@ -187,6 +212,15 @@ export class AgentInstance {
|
|
|
187
212
|
return this.type == 'flow-exec';
|
|
188
213
|
}
|
|
189
214
|
|
|
215
|
+
markAsDecisionExecutor(): AgentInstance {
|
|
216
|
+
this.decisionExecutor = true;
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
isDecisionExecutor(): boolean {
|
|
221
|
+
return this.decisionExecutor;
|
|
222
|
+
}
|
|
223
|
+
|
|
190
224
|
private directivesAsString(fqName: string): string {
|
|
191
225
|
const conds = getAgentDirectives(fqName);
|
|
192
226
|
if (conds) {
|
|
@@ -202,14 +236,9 @@ export class AgentInstance {
|
|
|
202
236
|
return '';
|
|
203
237
|
}
|
|
204
238
|
|
|
205
|
-
private
|
|
206
|
-
|
|
207
|
-
private getFullInstructions(): string {
|
|
208
|
-
if (this.cachedInstruction) {
|
|
209
|
-
return this.cachedInstruction;
|
|
210
|
-
}
|
|
239
|
+
private getFullInstructions(env: Environment): string {
|
|
211
240
|
const fqName = this.getFqName();
|
|
212
|
-
|
|
241
|
+
let finalInstruction = `${this.instruction || ''} ${this.directivesAsString(fqName)}`;
|
|
213
242
|
const gls = getAgentGlossary(fqName);
|
|
214
243
|
if (gls) {
|
|
215
244
|
const glss = new Array<string>();
|
|
@@ -218,23 +247,39 @@ export class AgentInstance {
|
|
|
218
247
|
`${age.name}: ${age.meaning}. ${age.synonyms ? `These words are synonyms for ${age.name}: ${age.synonyms}` : ''}`
|
|
219
248
|
);
|
|
220
249
|
});
|
|
221
|
-
|
|
250
|
+
finalInstruction = `${finalInstruction}\nThe following glossary will be helpful for understanding user requests.
|
|
222
251
|
${glss.join('\n')}\n`;
|
|
223
252
|
}
|
|
224
253
|
const scenarios = getAgentScenarios(fqName);
|
|
225
254
|
if (scenarios) {
|
|
226
255
|
const scs = new Array<string>();
|
|
227
256
|
scenarios.forEach((sc: AgentScenario) => {
|
|
228
|
-
|
|
257
|
+
const aiResp = processScenarioResponse(sc.ai);
|
|
258
|
+
scs.push(`User: ${sc.user}\nAI: ${aiResp}\n`);
|
|
229
259
|
});
|
|
230
|
-
|
|
260
|
+
finalInstruction = `${finalInstruction}\nHere are some example user requests and the corresponding responses you are supposed to produce:\n${scs.join('\n')}`;
|
|
231
261
|
}
|
|
232
262
|
const responseSchema = getAgentResponseSchema(fqName);
|
|
233
263
|
if (responseSchema) {
|
|
234
|
-
|
|
264
|
+
finalInstruction = `${finalInstruction}\nReturn your response in the following JSON schema:\n${asJSONSchema(responseSchema)}
|
|
235
265
|
Only return a pure JSON object with no extra text, annotations etc.`;
|
|
236
266
|
}
|
|
237
|
-
|
|
267
|
+
const spad = env.getScratchPad();
|
|
268
|
+
if (spad != undefined) {
|
|
269
|
+
if (finalInstruction.indexOf('{{') > 0) {
|
|
270
|
+
return AgentInstance.maybeRewriteTemplatePatterns(spad, finalInstruction);
|
|
271
|
+
} else {
|
|
272
|
+
const ctx = JSON.stringify(spad);
|
|
273
|
+
return `${finalInstruction}\nSome additional context:\n${ctx}`;
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
return finalInstruction;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
private static maybeRewriteTemplatePatterns(scratchPad: any, instruction: string): string {
|
|
281
|
+
const templ = Handlebars.compile(instruction);
|
|
282
|
+
return templ(scratchPad);
|
|
238
283
|
}
|
|
239
284
|
|
|
240
285
|
maybeValidateJsonResponse(response: string | undefined): object | undefined {
|
|
@@ -242,7 +287,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
242
287
|
const responseSchema = getAgentResponseSchema(this.getFqName());
|
|
243
288
|
if (responseSchema) {
|
|
244
289
|
const attrs = JSON.parse(response);
|
|
245
|
-
const parts =
|
|
290
|
+
const parts = nameToPath(responseSchema);
|
|
246
291
|
const moduleName = parts.getModuleName();
|
|
247
292
|
const entryName = parts.getEntryName();
|
|
248
293
|
const attrsMap = new Map(Object.entries(attrs));
|
|
@@ -317,23 +362,32 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
317
362
|
}
|
|
318
363
|
const sess: Instance | null = this.withSession ? await findAgentChatSession(chatId, env) : null;
|
|
319
364
|
let msgs: BaseMessage[] | undefined;
|
|
365
|
+
let cachedMsg: string | undefined = undefined;
|
|
320
366
|
if (sess) {
|
|
321
367
|
msgs = sess.lookup('messages');
|
|
322
368
|
} else {
|
|
323
|
-
|
|
369
|
+
cachedMsg = this.getFullInstructions(env);
|
|
370
|
+
msgs = [systemMessage(cachedMsg || '')];
|
|
324
371
|
}
|
|
325
372
|
if (msgs) {
|
|
326
373
|
try {
|
|
327
374
|
const sysMsg = msgs[0];
|
|
328
375
|
if (isplnr || isflow) {
|
|
329
376
|
const s = isplnr ? PlannerInstructions : FlowExecInstructions;
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
);
|
|
377
|
+
const ts = this.toolsAsString();
|
|
378
|
+
const msg = `${s}\n${ts}\n${cachedMsg || this.getFullInstructions(env)}`;
|
|
379
|
+
const newSysMsg = systemMessage(msg);
|
|
333
380
|
msgs[0] = newSysMsg;
|
|
334
381
|
}
|
|
335
382
|
msgs.push(humanMessage(await this.maybeAddRelevantDocuments(message, env)));
|
|
336
383
|
const externalToolSpecs = this.getExternalToolSpecs();
|
|
384
|
+
logger.debug(
|
|
385
|
+
`Invoking LLM ${this.llm} via agent ${this.fqName} with messages:\n${msgs
|
|
386
|
+
.map((bm: BaseMessage) => {
|
|
387
|
+
return bm.content;
|
|
388
|
+
})
|
|
389
|
+
.join('\n')}`
|
|
390
|
+
);
|
|
337
391
|
const response: AIResponse = await p.invoke(msgs, externalToolSpecs);
|
|
338
392
|
msgs.push(assistantMessage(response.content));
|
|
339
393
|
if (isplnr) {
|
|
@@ -412,7 +466,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
412
466
|
let moduleName: string | undefined;
|
|
413
467
|
let entryName: string | undefined;
|
|
414
468
|
if (isFqName(n)) {
|
|
415
|
-
const parts =
|
|
469
|
+
const parts = nameToPath(n);
|
|
416
470
|
moduleName = parts.getModuleName();
|
|
417
471
|
entryName = parts.getEntryName();
|
|
418
472
|
} else {
|
|
@@ -423,7 +477,10 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
423
477
|
if (entryName) {
|
|
424
478
|
const hasmod = slimModules.has(moduleName);
|
|
425
479
|
const defs = hasmod ? slimModules.get(moduleName) : new Array<string>();
|
|
426
|
-
|
|
480
|
+
const entry = m.getEntry(entryName);
|
|
481
|
+
const s =
|
|
482
|
+
entry instanceof Record ? (entry as Record).toString_(true) : entry.toString();
|
|
483
|
+
defs?.push(s);
|
|
427
484
|
if (!hasmod && defs) {
|
|
428
485
|
slimModules.set(moduleName, defs);
|
|
429
486
|
}
|
|
@@ -562,3 +619,20 @@ export async function saveAgentChatSession(chatId: string, messages: any[], env:
|
|
|
562
619
|
export function agentName(agentInstance: Instance): string {
|
|
563
620
|
return agentInstance.lookup('name');
|
|
564
621
|
}
|
|
622
|
+
|
|
623
|
+
function processScenarioResponse(resp: string): string {
|
|
624
|
+
const r = resp.trimStart();
|
|
625
|
+
if (r.startsWith('[') || r.startsWith('{')) {
|
|
626
|
+
return resp;
|
|
627
|
+
}
|
|
628
|
+
if (isFqName(r)) {
|
|
629
|
+
const parts = splitFqName(r);
|
|
630
|
+
const m = fetchModule(parts[0]);
|
|
631
|
+
const wf = m.getWorkflowForEvent(parts[1]);
|
|
632
|
+
const ss = wf.statements.map((stmt: Statement) => {
|
|
633
|
+
return stmt.$cstNode?.text;
|
|
634
|
+
});
|
|
635
|
+
return `[${ss.join(';\n')}]`;
|
|
636
|
+
}
|
|
637
|
+
return resp;
|
|
638
|
+
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
newInstanceAttributes,
|
|
14
14
|
Relationship,
|
|
15
15
|
} from '../module.js';
|
|
16
|
-
import { CrudType,
|
|
16
|
+
import { CrudType, nameToPath } from '../util.js';
|
|
17
17
|
import { DefaultAuthInfo, ResolverAuthInfo } from './authinfo.js';
|
|
18
18
|
|
|
19
19
|
export type JoinInfo = {
|
|
@@ -223,7 +223,7 @@ export class Resolver {
|
|
|
223
223
|
} else {
|
|
224
224
|
const eventName = getSubscriptionEvent(this.name);
|
|
225
225
|
if (eventName) {
|
|
226
|
-
const path =
|
|
226
|
+
const path = nameToPath(eventName);
|
|
227
227
|
const inst = makeInstance(
|
|
228
228
|
path.getModuleName(),
|
|
229
229
|
path.getEntryName(),
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
newInstanceAttributes,
|
|
14
14
|
Relationship,
|
|
15
15
|
} from '../../module.js';
|
|
16
|
-
import { escapeFqName, makeFqName,
|
|
16
|
+
import { escapeFqName, makeFqName, nameToPath } from '../../util.js';
|
|
17
17
|
import { JoinInfo, Resolver } from '../interface.js';
|
|
18
18
|
import { asTableReference } from './dbutil.js';
|
|
19
19
|
import {
|
|
@@ -259,7 +259,7 @@ export class SqlDbResolver extends Resolver {
|
|
|
259
259
|
const joinClauses: JoinClause[] = [];
|
|
260
260
|
this.processJoinInfo(tableName, inst, joinsSpec, joinClauses);
|
|
261
261
|
intoSpec.forEach((v: string, k: string) => {
|
|
262
|
-
const p =
|
|
262
|
+
const p = nameToPath(v);
|
|
263
263
|
const mn = p.hasModule() ? p.getModuleName() : inst.moduleName;
|
|
264
264
|
intoSpec.set(k, asTableReference(mn, p.getEntryName()));
|
|
265
265
|
});
|
package/src/runtime/util.ts
CHANGED
|
@@ -141,7 +141,7 @@ export function isFqName(s: string): boolean {
|
|
|
141
141
|
return s.indexOf('/') > 0;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
export function
|
|
144
|
+
export function nameToPath(s: string): Path {
|
|
145
145
|
if (s.indexOf('/') > 0) {
|
|
146
146
|
const parts: string[] = s.split('/');
|
|
147
147
|
return new Path(parts[0], parts[1]);
|
|
@@ -149,6 +149,10 @@ export function splitFqName(s: string): Path {
|
|
|
149
149
|
return new Path(undefined, s);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
export function splitFqName(s: string): string[] {
|
|
153
|
+
return s.split('/');
|
|
154
|
+
}
|
|
155
|
+
|
|
152
156
|
export function splitRefs(s: string): string[] {
|
|
153
157
|
if (s.indexOf('.') > 0) {
|
|
154
158
|
return s.split('.');
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Monarch syntax highlighting for the agentlang language.
|
|
2
2
|
export default {
|
|
3
3
|
keywords: [
|
|
4
|
-
'@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@then','@upsert','@with_unique','agent','allow','and','await','between','contains','create','delete','else','entity','error','event','extends','false','flow','for','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
|
|
4
|
+
'@actions','@after','@as','@async','@before','@catch','@distinct','@enum','@expr','@from','@into','@meta','@oneof','@rbac','@ref','@then','@upsert','@with_unique','agent','allow','and','await','between','case','contains','create','decision','delete','else','entity','error','event','extends','false','flow','for','if','import','in','like','module','not','not_found','onSubscription','or','purge','query','read','record','relationship','resolver','return','roles','subscribe','true','update','upsert','where','workflow'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
|
-
'!=','*','+',',','-','-->','.','/',':',';','<','<=','<>','=','>','>=','?','@'
|
|
7
|
+
'!=','*','+',',','-','-->','.','/',':',';','<','<=','<>','=','==','>','>=','?','@'
|
|
8
8
|
],
|
|
9
|
-
symbols: /!=|\(|\)
|
|
9
|
+
symbols: /!=|\(|\)|\*|\+|,|-|-->|\.|\/|:|;|<|<=|<>|=|==|>|>=|\?|@|\[|\]|\{|\}/,
|
|
10
10
|
|
|
11
11
|
tokenizer: {
|
|
12
12
|
initial: [
|