agentlang 0.2.0 → 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.
Files changed (66) hide show
  1. package/out/api/http.js +3 -3
  2. package/out/api/http.js.map +1 -1
  3. package/out/language/agentlang-validator.d.ts.map +1 -1
  4. package/out/language/agentlang-validator.js +3 -1
  5. package/out/language/agentlang-validator.js.map +1 -1
  6. package/out/language/generated/ast.d.ts +35 -9
  7. package/out/language/generated/ast.d.ts.map +1 -1
  8. package/out/language/generated/ast.js +40 -1
  9. package/out/language/generated/ast.js.map +1 -1
  10. package/out/language/generated/grammar.d.ts.map +1 -1
  11. package/out/language/generated/grammar.js +289 -120
  12. package/out/language/generated/grammar.js.map +1 -1
  13. package/out/language/main.cjs +323 -122
  14. package/out/language/main.cjs.map +2 -2
  15. package/out/language/parser.d.ts +1 -0
  16. package/out/language/parser.d.ts.map +1 -1
  17. package/out/language/parser.js +14 -13
  18. package/out/language/parser.js.map +1 -1
  19. package/out/runtime/agents/common.d.ts +2 -1
  20. package/out/runtime/agents/common.d.ts.map +1 -1
  21. package/out/runtime/agents/common.js +42 -3
  22. package/out/runtime/agents/common.js.map +1 -1
  23. package/out/runtime/exec-graph.d.ts.map +1 -1
  24. package/out/runtime/exec-graph.js +15 -7
  25. package/out/runtime/exec-graph.js.map +1 -1
  26. package/out/runtime/interpreter.d.ts.map +1 -1
  27. package/out/runtime/interpreter.js +50 -22
  28. package/out/runtime/interpreter.js.map +1 -1
  29. package/out/runtime/loader.d.ts.map +1 -1
  30. package/out/runtime/loader.js +16 -9
  31. package/out/runtime/loader.js.map +1 -1
  32. package/out/runtime/module.d.ts +10 -0
  33. package/out/runtime/module.d.ts.map +1 -1
  34. package/out/runtime/module.js +76 -19
  35. package/out/runtime/module.js.map +1 -1
  36. package/out/runtime/modules/ai.d.ts +6 -2
  37. package/out/runtime/modules/ai.d.ts.map +1 -1
  38. package/out/runtime/modules/ai.js +59 -12
  39. package/out/runtime/modules/ai.js.map +1 -1
  40. package/out/runtime/resolvers/interface.js +2 -2
  41. package/out/runtime/resolvers/interface.js.map +1 -1
  42. package/out/runtime/resolvers/sqldb/impl.js +2 -2
  43. package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
  44. package/out/runtime/util.d.ts +2 -1
  45. package/out/runtime/util.d.ts.map +1 -1
  46. package/out/runtime/util.js +4 -1
  47. package/out/runtime/util.js.map +1 -1
  48. package/out/syntaxes/agentlang.monarch.js +3 -3
  49. package/out/syntaxes/agentlang.monarch.js.map +1 -1
  50. package/package.json +2 -2
  51. package/src/api/http.ts +3 -3
  52. package/src/language/agentlang-validator.ts +3 -1
  53. package/src/language/agentlang.langium +8 -2
  54. package/src/language/generated/ast.ts +80 -9
  55. package/src/language/generated/grammar.ts +289 -120
  56. package/src/language/parser.ts +15 -14
  57. package/src/runtime/agents/common.ts +43 -3
  58. package/src/runtime/exec-graph.ts +14 -7
  59. package/src/runtime/interpreter.ts +54 -22
  60. package/src/runtime/loader.ts +23 -8
  61. package/src/runtime/module.ts +86 -18
  62. package/src/runtime/modules/ai.ts +69 -10
  63. package/src/runtime/resolvers/interface.ts +2 -2
  64. package/src/runtime/resolvers/sqldb/impl.ts +2 -2
  65. package/src/runtime/util.ts +5 -1
  66. package/src/syntaxes/agentlang.monarch.ts +3 -3
@@ -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,7 +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';
41
- import * as Handlebars from 'handlebars';
45
+ import Handlebars from 'handlebars';
46
+ import { Statement } from '../../language/generated/ast.js';
42
47
 
43
48
  export const CoreAIModuleName = makeCoreModuleName('ai');
44
49
  export const AgentEntityName = 'Agent';
@@ -113,6 +118,7 @@ export class AgentInstance {
113
118
  private hasModuleTools = false;
114
119
  private withSession = true;
115
120
  private fqName: string | undefined;
121
+ private decisionExecutor = false;
116
122
 
117
123
  private constructor() {}
118
124
 
@@ -137,7 +143,7 @@ export class AgentInstance {
137
143
  for (let i = 0; i < agent.toolsArray.length; ++i) {
138
144
  const n = agent.toolsArray[i];
139
145
  if (isFqName(n)) {
140
- const parts = splitFqName(n);
146
+ const parts = nameToPath(n);
141
147
  agent.hasModuleTools = isModule(parts.getModuleName());
142
148
  } else {
143
149
  agent.hasModuleTools = isModule(n);
@@ -148,7 +154,11 @@ export class AgentInstance {
148
154
  return agent;
149
155
  }
150
156
 
151
- 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
+ }
152
162
  const fqs = isFqName(step) ? step : `${flowAgent.moduleName}/${step}`;
153
163
  const instruction = `Analyse the context and generate the pattern required to invoke ${fqs}.
154
164
  Never include references in the pattern. All attribute values must be literals derived from the context.`;
@@ -166,6 +176,20 @@ export class AgentInstance {
166
176
  return AgentInstance.FromInstance(inst).disableSession();
167
177
  }
168
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();
191
+ }
192
+
169
193
  disableSession(): AgentInstance {
170
194
  this.withSession = false;
171
195
  return this;
@@ -188,6 +212,15 @@ export class AgentInstance {
188
212
  return this.type == 'flow-exec';
189
213
  }
190
214
 
215
+ markAsDecisionExecutor(): AgentInstance {
216
+ this.decisionExecutor = true;
217
+ return this;
218
+ }
219
+
220
+ isDecisionExecutor(): boolean {
221
+ return this.decisionExecutor;
222
+ }
223
+
191
224
  private directivesAsString(fqName: string): string {
192
225
  const conds = getAgentDirectives(fqName);
193
226
  if (conds) {
@@ -221,7 +254,8 @@ export class AgentInstance {
221
254
  if (scenarios) {
222
255
  const scs = new Array<string>();
223
256
  scenarios.forEach((sc: AgentScenario) => {
224
- scs.push(`User: ${sc.user}\nAI: ${sc.ai}\n`);
257
+ const aiResp = processScenarioResponse(sc.ai);
258
+ scs.push(`User: ${sc.user}\nAI: ${aiResp}\n`);
225
259
  });
226
260
  finalInstruction = `${finalInstruction}\nHere are some example user requests and the corresponding responses you are supposed to produce:\n${scs.join('\n')}`;
227
261
  }
@@ -231,8 +265,13 @@ export class AgentInstance {
231
265
  Only return a pure JSON object with no extra text, annotations etc.`;
232
266
  }
233
267
  const spad = env.getScratchPad();
234
- if (spad != undefined && finalInstruction.indexOf('{{') > 0) {
235
- return AgentInstance.maybeRewriteTemplatePatterns(spad, finalInstruction);
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
+ }
236
275
  } else {
237
276
  return finalInstruction;
238
277
  }
@@ -248,7 +287,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
248
287
  const responseSchema = getAgentResponseSchema(this.getFqName());
249
288
  if (responseSchema) {
250
289
  const attrs = JSON.parse(response);
251
- const parts = splitFqName(responseSchema);
290
+ const parts = nameToPath(responseSchema);
252
291
  const moduleName = parts.getModuleName();
253
292
  const entryName = parts.getEntryName();
254
293
  const attrsMap = new Map(Object.entries(attrs));
@@ -427,7 +466,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
427
466
  let moduleName: string | undefined;
428
467
  let entryName: string | undefined;
429
468
  if (isFqName(n)) {
430
- const parts = splitFqName(n);
469
+ const parts = nameToPath(n);
431
470
  moduleName = parts.getModuleName();
432
471
  entryName = parts.getEntryName();
433
472
  } else {
@@ -438,7 +477,10 @@ Only return a pure JSON object with no extra text, annotations etc.`;
438
477
  if (entryName) {
439
478
  const hasmod = slimModules.has(moduleName);
440
479
  const defs = hasmod ? slimModules.get(moduleName) : new Array<string>();
441
- defs?.push(m.getEntry(entryName).toString());
480
+ const entry = m.getEntry(entryName);
481
+ const s =
482
+ entry instanceof Record ? (entry as Record).toString_(true) : entry.toString();
483
+ defs?.push(s);
442
484
  if (!hasmod && defs) {
443
485
  slimModules.set(moduleName, defs);
444
486
  }
@@ -577,3 +619,20 @@ export async function saveAgentChatSession(chatId: string, messages: any[], env:
577
619
  export function agentName(agentInstance: Instance): string {
578
620
  return agentInstance.lookup('name');
579
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, splitFqName } from '../util.js';
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 = splitFqName(eventName);
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, splitFqName } from '../../util.js';
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 = splitFqName(v);
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
  });
@@ -141,7 +141,7 @@ export function isFqName(s: string): boolean {
141
141
  return s.indexOf('/') > 0;
142
142
  }
143
143
 
144
- export function splitFqName(s: string): Path {
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: [