agentlang 0.0.40 → 0.0.51
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/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/generated/ast.d.ts +57 -21
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +80 -26
- 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 -115
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +900 -637
- package/out/language/main.cjs.map +3 -3
- package/out/language/syntax.d.ts +7 -0
- package/out/language/syntax.d.ts.map +1 -1
- package/out/language/syntax.js +16 -0
- package/out/language/syntax.js.map +1 -1
- package/out/runtime/agents/common.d.ts +9 -1
- package/out/runtime/agents/common.d.ts.map +1 -1
- package/out/runtime/agents/common.js +83 -1
- package/out/runtime/agents/common.js.map +1 -1
- package/out/runtime/agents/registry.js +3 -1
- package/out/runtime/agents/registry.js.map +1 -1
- package/out/runtime/auth/cognito.js +1 -1
- package/out/runtime/defs.d.ts +1 -0
- package/out/runtime/defs.d.ts.map +1 -1
- package/out/runtime/defs.js +1 -0
- package/out/runtime/defs.js.map +1 -1
- package/out/runtime/interpreter.d.ts +5 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +81 -9
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +111 -40
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +24 -2
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +103 -12
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +9 -0
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +50 -9
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js.map +1 -1
- package/out/runtime/modules/core.d.ts +1 -0
- package/out/runtime/modules/core.d.ts.map +1 -1
- package/out/runtime/modules/core.js +15 -5
- package/out/runtime/modules/core.js.map +1 -1
- package/out/runtime/resolvers/authinfo.d.ts +8 -0
- package/out/runtime/resolvers/authinfo.d.ts.map +1 -0
- package/out/runtime/resolvers/authinfo.js +14 -0
- package/out/runtime/resolvers/authinfo.js.map +1 -0
- package/out/runtime/resolvers/interface.d.ts +1 -7
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js +3 -16
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +3 -1
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +72 -3
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +3 -3
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +156 -153
- package/src/language/agentlang.langium +12 -4
- package/src/language/generated/ast.ts +144 -49
- package/src/language/generated/grammar.ts +337 -115
- package/src/language/syntax.ts +21 -0
- package/src/runtime/agents/common.ts +91 -1
- package/src/runtime/agents/registry.ts +3 -3
- package/src/runtime/auth/cognito.ts +3 -3
- package/src/runtime/defs.ts +1 -0
- package/src/runtime/interpreter.ts +117 -8
- package/src/runtime/loader.ts +113 -39
- package/src/runtime/module.ts +123 -13
- package/src/runtime/modules/ai.ts +67 -11
- package/src/runtime/modules/auth.ts +6 -1
- package/src/runtime/modules/core.ts +16 -4
- package/src/runtime/resolvers/authinfo.ts +14 -0
- package/src/runtime/resolvers/interface.ts +2 -19
- package/src/runtime/resolvers/sqldb/database.ts +76 -3
- package/src/syntaxes/agentlang.monarch.ts +3 -3
package/src/runtime/module.ts
CHANGED
|
@@ -816,42 +816,65 @@ export class Agent extends Record {
|
|
|
816
816
|
return this.removeAgentAttribute('type');
|
|
817
817
|
}
|
|
818
818
|
|
|
819
|
-
|
|
820
|
-
this.attributes.set(
|
|
819
|
+
private setStrings(attrName: string, v: string[]): Agent {
|
|
820
|
+
this.attributes.set(attrName, v.join(','));
|
|
821
821
|
return this;
|
|
822
822
|
}
|
|
823
823
|
|
|
824
|
-
|
|
825
|
-
const
|
|
826
|
-
if (
|
|
827
|
-
return
|
|
824
|
+
private getStrings(attrName: string): string[] | undefined {
|
|
825
|
+
const v = this.attributes.get(attrName);
|
|
826
|
+
if (v) {
|
|
827
|
+
return v.split(',');
|
|
828
828
|
} else {
|
|
829
829
|
return undefined;
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
832
|
|
|
833
|
+
setTools(tools: string[]): Agent {
|
|
834
|
+
return this.setStrings('tools', tools);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
getTools(): string[] | undefined {
|
|
838
|
+
return this.getStrings('tools');
|
|
839
|
+
}
|
|
840
|
+
|
|
833
841
|
removeTools(): Agent {
|
|
834
842
|
return this.removeAgentAttribute('tools');
|
|
835
843
|
}
|
|
836
844
|
|
|
837
845
|
setDocuments(docs: string[]): Agent {
|
|
838
|
-
this.
|
|
839
|
-
return this;
|
|
846
|
+
return this.setStrings('documents', docs);
|
|
840
847
|
}
|
|
841
848
|
|
|
842
|
-
getDocuments(): string {
|
|
843
|
-
return this.
|
|
849
|
+
getDocuments(): string[] | undefined {
|
|
850
|
+
return this.getStrings('documents');
|
|
844
851
|
}
|
|
845
852
|
|
|
846
853
|
removeDocuments(): Agent {
|
|
847
854
|
return this.removeAgentAttribute('documents');
|
|
848
855
|
}
|
|
849
856
|
|
|
857
|
+
setFlows(flows: string[]): Agent {
|
|
858
|
+
return this.setStrings('flows', flows);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
getFlows(): string[] | undefined {
|
|
862
|
+
return this.getStrings('flows');
|
|
863
|
+
}
|
|
864
|
+
|
|
850
865
|
override toString(): string {
|
|
851
866
|
const attrs = new Array<string>();
|
|
852
867
|
this.attributes.forEach((value: any, key: string) => {
|
|
853
|
-
const
|
|
854
|
-
|
|
868
|
+
const skip = key == 'moduleName' || (key == 'type' && value == 'flow-exec');
|
|
869
|
+
if (!skip) {
|
|
870
|
+
let v = value;
|
|
871
|
+
if (key == 'flows') {
|
|
872
|
+
v = `[${v}]`;
|
|
873
|
+
} else if (isString(v)) {
|
|
874
|
+
v = `"${v}"`;
|
|
875
|
+
}
|
|
876
|
+
attrs.push(` ${key} ${v}`);
|
|
877
|
+
}
|
|
855
878
|
});
|
|
856
879
|
return `agent ${Agent.NormalizeName(this.name)}
|
|
857
880
|
{
|
|
@@ -1293,6 +1316,59 @@ export class Workflow extends ModuleEntry {
|
|
|
1293
1316
|
}
|
|
1294
1317
|
}
|
|
1295
1318
|
|
|
1319
|
+
export class Flow extends ModuleEntry {
|
|
1320
|
+
flowSteps: string[];
|
|
1321
|
+
|
|
1322
|
+
constructor(name: string, moduleName: string, flow?: string) {
|
|
1323
|
+
super(name, moduleName);
|
|
1324
|
+
this.flowSteps = new Array<string>();
|
|
1325
|
+
flow?.split('\n').forEach((step: string) => {
|
|
1326
|
+
const s = step.trim();
|
|
1327
|
+
if (s.length > 0) {
|
|
1328
|
+
this.flowSteps.push(s);
|
|
1329
|
+
}
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
getFlow(): string {
|
|
1334
|
+
return this.flowSteps.join('\n');
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
removeStep(index: number): Flow {
|
|
1338
|
+
this.flowSteps.splice(index, 1);
|
|
1339
|
+
return this;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
insertStep(index: number, s: string): Flow {
|
|
1343
|
+
this.flowSteps.splice(index, 0, s);
|
|
1344
|
+
return this;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
stepsCount(): number {
|
|
1348
|
+
return this.flowSteps.length;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
override toString(): string {
|
|
1352
|
+
return `flow ${this.name} {
|
|
1353
|
+
${this.getFlow()}
|
|
1354
|
+
}`;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
class StandaloneStatement extends ModuleEntry {
|
|
1359
|
+
stmt: Statement;
|
|
1360
|
+
|
|
1361
|
+
constructor(stmt: Statement, moduleName: string) {
|
|
1362
|
+
super(crypto.randomUUID(), moduleName);
|
|
1363
|
+
this.stmt = stmt;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
override toString(): string {
|
|
1367
|
+
if (this.stmt.$cstNode) return this.stmt.$cstNode?.text;
|
|
1368
|
+
else return '';
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1296
1372
|
const EmptyWorkflow: Workflow = new Workflow('', [], DefaultModuleName);
|
|
1297
1373
|
|
|
1298
1374
|
export function isEmptyWorkflow(wf: Workflow): boolean {
|
|
@@ -1338,6 +1414,32 @@ export class Module {
|
|
|
1338
1414
|
return this.removeEntry(Agent.EscapeName(agentName));
|
|
1339
1415
|
}
|
|
1340
1416
|
|
|
1417
|
+
addFlow(name: string, flowString?: string): Flow {
|
|
1418
|
+
const flow: Flow = new Flow(name, this.name, flowString);
|
|
1419
|
+
this.addEntry(flow);
|
|
1420
|
+
return flow;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
getFlow(name: string): Flow | undefined {
|
|
1424
|
+
if (this.hasEntry(name)) {
|
|
1425
|
+
return this.getEntry(name) as Flow;
|
|
1426
|
+
}
|
|
1427
|
+
return undefined;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
addStandaloneStatement(stmt: Statement): StandaloneStatement {
|
|
1431
|
+
const s = new StandaloneStatement(stmt, this.name);
|
|
1432
|
+
this.addEntry(s);
|
|
1433
|
+
return s;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
getStandaloneStatement(name: string): StandaloneStatement | undefined {
|
|
1437
|
+
if (this.hasEntry(name)) {
|
|
1438
|
+
return this.getEntry(name) as StandaloneStatement;
|
|
1439
|
+
}
|
|
1440
|
+
return undefined;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1341
1443
|
private getEntryIndex(entryName: string): number {
|
|
1342
1444
|
return this.entries.findIndex((v: ModuleEntry) => {
|
|
1343
1445
|
return v.name == entryName;
|
|
@@ -2848,14 +2950,22 @@ export function assertInstance(obj: any) {
|
|
|
2848
2950
|
|
|
2849
2951
|
const IsAgentEventMeta = 'is-agent-event';
|
|
2850
2952
|
const EventAgentName = 'event-agent-name';
|
|
2953
|
+
const DocumentationMetaTag = 'documentation';
|
|
2851
2954
|
|
|
2852
|
-
export function defineAgentEvent(moduleName: string, agentName: string) {
|
|
2955
|
+
export function defineAgentEvent(moduleName: string, agentName: string, instruction?: string) {
|
|
2853
2956
|
const module = fetchModule(moduleName);
|
|
2854
2957
|
const event: Record = new Event(agentName, moduleName);
|
|
2855
2958
|
event.addAttribute('message', { type: 'Any' });
|
|
2856
2959
|
event.addAttribute('chatId', { type: 'String' });
|
|
2857
2960
|
event.addMeta(IsAgentEventMeta, 'y');
|
|
2858
2961
|
event.addMeta(EventAgentName, agentName);
|
|
2962
|
+
if (instruction) {
|
|
2963
|
+
event.addMeta(
|
|
2964
|
+
DocumentationMetaTag,
|
|
2965
|
+
`This event will trigger an agent which has the instruction - "${instruction}".
|
|
2966
|
+
So make sure to pass all relevant information in the 'message' attribute of this event.`
|
|
2967
|
+
);
|
|
2968
|
+
}
|
|
2859
2969
|
module.addEntry(event);
|
|
2860
2970
|
}
|
|
2861
2971
|
|
|
@@ -5,7 +5,14 @@ import {
|
|
|
5
5
|
makeEventEvaluator,
|
|
6
6
|
parseAndEvaluateStatement,
|
|
7
7
|
} from '../interpreter.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
fetchModule,
|
|
10
|
+
Instance,
|
|
11
|
+
instanceToObject,
|
|
12
|
+
isModule,
|
|
13
|
+
makeInstance,
|
|
14
|
+
newInstanceAttributes,
|
|
15
|
+
} from '../module.js';
|
|
9
16
|
import { provider } from '../agents/registry.js';
|
|
10
17
|
import {
|
|
11
18
|
AgentServiceProvider,
|
|
@@ -15,7 +22,7 @@ import {
|
|
|
15
22
|
systemMessage,
|
|
16
23
|
} from '../agents/provider.js';
|
|
17
24
|
import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages';
|
|
18
|
-
import { PlannerInstructions } from '../agents/common.js';
|
|
25
|
+
import { FlowExecInstructions, FlowStep, PlannerInstructions } from '../agents/common.js';
|
|
19
26
|
import { PathAttributeNameQuery } from '../defs.js';
|
|
20
27
|
import { logger } from '../logger.js';
|
|
21
28
|
|
|
@@ -33,7 +40,8 @@ entity ${LlmEntityName} {
|
|
|
33
40
|
|
|
34
41
|
entity ${AgentEntityName} {
|
|
35
42
|
name String @id,
|
|
36
|
-
|
|
43
|
+
moduleName String @default("${CoreAIModuleName}"),
|
|
44
|
+
type @enum("chat", "planner", "flow-exec") @default("chat"),
|
|
37
45
|
runWorkflows Boolean @default(true),
|
|
38
46
|
instruction String @optional,
|
|
39
47
|
tools String @optional, // comma-separated list of tool names
|
|
@@ -41,6 +49,7 @@ entity ${AgentEntityName} {
|
|
|
41
49
|
channels String @optional, // comma-separated list of channel names
|
|
42
50
|
output String @optional, // fq-name of another agent to which the result will be pushed
|
|
43
51
|
role String @optional,
|
|
52
|
+
flows String @optional,
|
|
44
53
|
llm String
|
|
45
54
|
}
|
|
46
55
|
|
|
@@ -77,6 +86,7 @@ const ProviderDb = new Map<string, AgentServiceProvider>();
|
|
|
77
86
|
export class AgentInstance {
|
|
78
87
|
llm: string = '';
|
|
79
88
|
name: string = '';
|
|
89
|
+
moduleName: string = CoreAIModuleName;
|
|
80
90
|
chatId: string | undefined;
|
|
81
91
|
instruction: string = '';
|
|
82
92
|
type: string = 'chat';
|
|
@@ -86,8 +96,10 @@ export class AgentInstance {
|
|
|
86
96
|
runWorkflows: boolean = true;
|
|
87
97
|
output: string | undefined;
|
|
88
98
|
role: string | undefined;
|
|
99
|
+
flows: string | undefined;
|
|
89
100
|
private toolsArray: string[] | undefined = undefined;
|
|
90
101
|
private hasModuleTools = false;
|
|
102
|
+
private withSession = true;
|
|
91
103
|
|
|
92
104
|
private constructor() {}
|
|
93
105
|
|
|
@@ -123,29 +135,71 @@ export class AgentInstance {
|
|
|
123
135
|
return agent;
|
|
124
136
|
}
|
|
125
137
|
|
|
138
|
+
static FromFlowStep(step: FlowStep, flowAgent: AgentInstance): AgentInstance {
|
|
139
|
+
const fqs = isFqName(step) ? step : `${flowAgent.moduleName}/${step}`;
|
|
140
|
+
const instruction = `Analyse the context and generate the pattern required to invoke ${fqs}.
|
|
141
|
+
Never include references in the pattern. All attribute values must be literals derived from the context.`;
|
|
142
|
+
const inst = makeInstance(
|
|
143
|
+
CoreAIModuleName,
|
|
144
|
+
AgentEntityName,
|
|
145
|
+
newInstanceAttributes()
|
|
146
|
+
.set('llm', flowAgent.llm)
|
|
147
|
+
.set('name', `${step}_agent`)
|
|
148
|
+
.set('moduleName', flowAgent.moduleName)
|
|
149
|
+
.set('instruction', instruction)
|
|
150
|
+
.set('tools', fqs)
|
|
151
|
+
.set('type', 'planner')
|
|
152
|
+
);
|
|
153
|
+
return AgentInstance.FromInstance(inst);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
disableSession(): AgentInstance {
|
|
157
|
+
this.withSession = false;
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
enableSession(): AgentInstance {
|
|
162
|
+
this.withSession = true;
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
hasSession(): boolean {
|
|
167
|
+
return this.withSession;
|
|
168
|
+
}
|
|
169
|
+
|
|
126
170
|
isPlanner(): boolean {
|
|
127
171
|
return this.hasModuleTools || this.type == 'planner';
|
|
128
172
|
}
|
|
129
173
|
|
|
174
|
+
isFlowExecutor(): boolean {
|
|
175
|
+
return this.type == 'flow-exec';
|
|
176
|
+
}
|
|
177
|
+
|
|
130
178
|
async invoke(message: string, env: Environment) {
|
|
131
179
|
const p = await findProviderForLLM(this.llm, env);
|
|
132
180
|
const agentName = this.name;
|
|
133
181
|
const chatId = this.chatId || agentName;
|
|
134
|
-
const sess: Instance | null = await findAgentChatSession(chatId, env);
|
|
135
|
-
let msgs: BaseMessage[] | undefined;
|
|
136
182
|
const isplnr = this.isPlanner();
|
|
183
|
+
const isflow = !isplnr && this.isFlowExecutor();
|
|
184
|
+
if (isplnr && this.withSession) {
|
|
185
|
+
this.withSession = false;
|
|
186
|
+
}
|
|
187
|
+
if (isflow) {
|
|
188
|
+
this.withSession = false;
|
|
189
|
+
}
|
|
190
|
+
const sess: Instance | null = this.withSession ? await findAgentChatSession(chatId, env) : null;
|
|
191
|
+
let msgs: BaseMessage[] | undefined;
|
|
137
192
|
if (sess) {
|
|
138
193
|
msgs = sess.lookup('messages');
|
|
139
194
|
} else {
|
|
140
|
-
msgs = [systemMessage(this.instruction)];
|
|
195
|
+
msgs = [systemMessage(this.instruction || '')];
|
|
141
196
|
}
|
|
142
197
|
if (msgs) {
|
|
143
198
|
try {
|
|
144
199
|
const sysMsg = msgs[0];
|
|
145
|
-
if (isplnr) {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
);
|
|
200
|
+
if (isplnr || isflow) {
|
|
201
|
+
const s = isplnr ? PlannerInstructions : FlowExecInstructions;
|
|
202
|
+
const newSysMsg = systemMessage(`${s}\n${this.toolsAsString()}\n${this.instruction}`);
|
|
149
203
|
msgs[0] = newSysMsg;
|
|
150
204
|
}
|
|
151
205
|
msgs.push(humanMessage(await this.maybeAddRelevantDocuments(message, env)));
|
|
@@ -155,7 +209,9 @@ export class AgentInstance {
|
|
|
155
209
|
if (isplnr) {
|
|
156
210
|
msgs[0] = sysMsg;
|
|
157
211
|
}
|
|
158
|
-
|
|
212
|
+
if (this.withSession) {
|
|
213
|
+
await saveAgentChatSession(chatId, msgs, env);
|
|
214
|
+
}
|
|
159
215
|
env.setLastResult(response.content);
|
|
160
216
|
} catch (err: any) {
|
|
161
217
|
logger.error(`Error while invoking ${agentName} - ${err}`);
|
|
@@ -324,7 +324,12 @@ export async function findUserByEmail(email: string, env: Environment): Promise<
|
|
|
324
324
|
);
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
export async function updateUser(
|
|
327
|
+
export async function updateUser(
|
|
328
|
+
userId: string,
|
|
329
|
+
firstName: string,
|
|
330
|
+
lastName: string,
|
|
331
|
+
env: Environment
|
|
332
|
+
): Promise<Result> {
|
|
328
333
|
return await evalEvent(
|
|
329
334
|
'UpdateUser',
|
|
330
335
|
{
|
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
evaluate,
|
|
8
8
|
evaluateStatements,
|
|
9
9
|
parseAndEvaluateStatement,
|
|
10
|
+
restartFlow,
|
|
10
11
|
} from '../interpreter.js';
|
|
11
12
|
import { logger } from '../logger.js';
|
|
12
13
|
import { Statement } from '../../language/generated/ast.js';
|
|
13
14
|
import { parseStatements } from '../../language/parser.js';
|
|
14
15
|
import { Resolver } from '../resolvers/interface.js';
|
|
15
|
-
import { ForceReadPermFlag, PathAttributeName } from '../defs.js';
|
|
16
|
+
import { FlowSuspensionTag, ForceReadPermFlag, PathAttributeName } from '../defs.js';
|
|
16
17
|
|
|
17
18
|
const CoreModuleDefinition = `module ${DefaultModuleName}
|
|
18
19
|
|
|
@@ -165,9 +166,14 @@ export async function createSuspension(
|
|
|
165
166
|
|
|
166
167
|
export type Suspension = {
|
|
167
168
|
continuation: Statement[];
|
|
169
|
+
flowContext?: string[];
|
|
168
170
|
env: Environment;
|
|
169
171
|
};
|
|
170
172
|
|
|
173
|
+
function isFlowSuspension(cont: string[]): boolean {
|
|
174
|
+
return cont.length > 0 && cont[0] == FlowSuspensionTag;
|
|
175
|
+
}
|
|
176
|
+
|
|
171
177
|
async function loadSuspension(suspId: string, env?: Environment): Promise<Suspension | undefined> {
|
|
172
178
|
const newEnv = new Environment('auditlog', env).setInKernelMode(true);
|
|
173
179
|
const r: any = await parseAndEvaluateStatement(
|
|
@@ -178,12 +184,14 @@ async function loadSuspension(suspId: string, env?: Environment): Promise<Suspen
|
|
|
178
184
|
if (r instanceof Array && r.length > 0) {
|
|
179
185
|
const inst: Instance = r[0];
|
|
180
186
|
const cont = inst.lookup('continuation');
|
|
181
|
-
const
|
|
187
|
+
const ifs = isFlowSuspension(cont);
|
|
188
|
+
const stmts: Statement[] = ifs ? new Array<Statement>() : await parseStatements(cont);
|
|
182
189
|
const envStr = inst.lookup('env');
|
|
183
190
|
const suspEnv: Environment = Environment.FromSerializableObject(JSON.parse(envStr));
|
|
184
191
|
return {
|
|
185
192
|
continuation: stmts,
|
|
186
193
|
env: suspEnv,
|
|
194
|
+
flowContext: ifs ? cont : undefined,
|
|
187
195
|
};
|
|
188
196
|
}
|
|
189
197
|
return undefined;
|
|
@@ -210,8 +218,12 @@ export async function restartSuspension(
|
|
|
210
218
|
): Promise<any> {
|
|
211
219
|
const susp = await loadSuspension(suspId, env);
|
|
212
220
|
if (susp) {
|
|
213
|
-
susp.
|
|
214
|
-
|
|
221
|
+
if (susp.flowContext) {
|
|
222
|
+
await restartFlow(susp.flowContext, userData, susp.env);
|
|
223
|
+
} else {
|
|
224
|
+
susp.env.bindSuspensionUserData(userData);
|
|
225
|
+
await evaluateStatements(susp.continuation, susp.env);
|
|
226
|
+
}
|
|
215
227
|
await deleteSuspension(suspId, env);
|
|
216
228
|
return susp.env.getLastResult();
|
|
217
229
|
} else {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export class ResolverAuthInfo {
|
|
2
|
+
userId: string;
|
|
3
|
+
readForUpdate = false;
|
|
4
|
+
readForDelete = false;
|
|
5
|
+
|
|
6
|
+
constructor(userId: string, readForUpdate?: boolean, readForDelete?: boolean) {
|
|
7
|
+
this.userId = userId;
|
|
8
|
+
if (readForUpdate != undefined) this.readForUpdate = readForUpdate;
|
|
9
|
+
if (readForDelete != undefined) this.readForDelete = readForDelete;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// This user-id is only for testing. Override per session from the HTTP layer.
|
|
14
|
+
export const DefaultAuthInfo = new ResolverAuthInfo('9459a305-5ee6-415d-986d-caaf6d6e2828');
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
callPostEventOnSubscription,
|
|
3
3
|
Environment,
|
|
4
|
-
evaluate,
|
|
5
4
|
runPostCreateEvents,
|
|
6
5
|
runPostDeleteEvents,
|
|
7
6
|
runPostUpdateEvents,
|
|
@@ -15,24 +14,7 @@ import {
|
|
|
15
14
|
Relationship,
|
|
16
15
|
} from '../module.js';
|
|
17
16
|
import { CrudType, splitFqName } from '../util.js';
|
|
18
|
-
|
|
19
|
-
export class ResolverAuthInfo {
|
|
20
|
-
userId: string;
|
|
21
|
-
readForUpdate: boolean = false;
|
|
22
|
-
readForDelete: boolean = false;
|
|
23
|
-
|
|
24
|
-
constructor(userId: string, readForUpdate?: boolean, readForDelete?: boolean) {
|
|
25
|
-
this.userId = userId;
|
|
26
|
-
if (readForUpdate != undefined) this.readForUpdate = readForUpdate;
|
|
27
|
-
if (readForDelete != undefined) this.readForDelete = readForDelete;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const DefaultAuthInfo = new ResolverAuthInfo(
|
|
32
|
-
// This user-id is only for testing, per-session user-id needs to be set from
|
|
33
|
-
// the HTTP layer.
|
|
34
|
-
'9459a305-5ee6-415d-986d-caaf6d6e2828'
|
|
35
|
-
);
|
|
17
|
+
import { DefaultAuthInfo, ResolverAuthInfo } from './authinfo.js';
|
|
36
18
|
|
|
37
19
|
export type JoinInfo = {
|
|
38
20
|
relationship: Relationship;
|
|
@@ -242,6 +224,7 @@ export class Resolver {
|
|
|
242
224
|
path.getEntryName(),
|
|
243
225
|
newInstanceAttributes().set('data', result)
|
|
244
226
|
);
|
|
227
|
+
const { evaluate } = await import('../interpreter.js');
|
|
245
228
|
return await evaluate(inst);
|
|
246
229
|
}
|
|
247
230
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
OwnersSuffix,
|
|
7
7
|
VectorSuffix,
|
|
8
8
|
} from './dbutil.js';
|
|
9
|
-
import { DefaultAuthInfo, ResolverAuthInfo } from '../
|
|
9
|
+
import { DefaultAuthInfo, ResolverAuthInfo } from '../authinfo.js';
|
|
10
10
|
import { canUserCreate, canUserDelete, canUserRead, canUserUpdate } from '../../modules/auth.js';
|
|
11
11
|
import { Environment, GlobalEnvironment } from '../../interpreter.js';
|
|
12
12
|
import {
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
RbacSpecification,
|
|
18
18
|
Relationship,
|
|
19
19
|
} from '../../module.js';
|
|
20
|
-
import pgvector from 'pgvector';
|
|
21
20
|
import { isString } from '../../util.js';
|
|
22
21
|
import {
|
|
23
22
|
DeletedFlagAttributeName,
|
|
@@ -194,10 +193,60 @@ function makeSqliteDataSource(
|
|
|
194
193
|
});
|
|
195
194
|
}
|
|
196
195
|
|
|
196
|
+
function isBrowser(): boolean {
|
|
197
|
+
// window for DOM pages, self+importScripts for web workers
|
|
198
|
+
return (
|
|
199
|
+
(typeof window !== 'undefined' && typeof (window as any).document !== 'undefined') ||
|
|
200
|
+
(typeof self !== 'undefined' && typeof (self as any).importScripts === 'function')
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function defaultLocateFile(file: string): string {
|
|
205
|
+
// Out-of-the-box: use the official CDN in browsers.
|
|
206
|
+
if (isBrowser()) {
|
|
207
|
+
return `https://sql.js.org/dist/${file}`;
|
|
208
|
+
}
|
|
209
|
+
// Node: resolve from node_modules/sql.js/dist
|
|
210
|
+
try {
|
|
211
|
+
/* eslint-disable-next-line @typescript-eslint/no-require-imports */
|
|
212
|
+
const path = require('path');
|
|
213
|
+
|
|
214
|
+
const base = require.resolve('sql.js/dist/sql-wasm.js');
|
|
215
|
+
return path.join(path.dirname(base), file);
|
|
216
|
+
} catch {
|
|
217
|
+
return file;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function makeSqljsDataSource(
|
|
222
|
+
entities: EntitySchema[],
|
|
223
|
+
_config: DatabaseConfig | undefined,
|
|
224
|
+
synchronize: boolean = true
|
|
225
|
+
): DataSource {
|
|
226
|
+
return new DataSource({
|
|
227
|
+
type: 'sqljs',
|
|
228
|
+
autoSave: false,
|
|
229
|
+
sqlJsConfig: {
|
|
230
|
+
locateFile: defaultLocateFile,
|
|
231
|
+
},
|
|
232
|
+
synchronize: synchronize,
|
|
233
|
+
entities: entities,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
197
237
|
const DbType = 'sqlite';
|
|
198
238
|
|
|
199
239
|
function getDbType(config?: DatabaseConfig): string {
|
|
200
|
-
|
|
240
|
+
if (config?.type) return config.type;
|
|
241
|
+
let envType: string | undefined;
|
|
242
|
+
try {
|
|
243
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
244
|
+
envType = process.env.AL_DB_TYPE;
|
|
245
|
+
}
|
|
246
|
+
} catch {}
|
|
247
|
+
if (envType) return envType;
|
|
248
|
+
if (isBrowser()) return 'sqljs';
|
|
249
|
+
return DbType;
|
|
201
250
|
}
|
|
202
251
|
|
|
203
252
|
function getDsFunction(
|
|
@@ -212,6 +261,8 @@ function getDsFunction(
|
|
|
212
261
|
return makeSqliteDataSource;
|
|
213
262
|
case 'postgres':
|
|
214
263
|
return makePostgresDataSource;
|
|
264
|
+
case 'sqljs':
|
|
265
|
+
return makeSqljsDataSource;
|
|
215
266
|
default:
|
|
216
267
|
throw new Error(`Unsupported database type - ${config?.type}`);
|
|
217
268
|
}
|
|
@@ -221,6 +272,15 @@ export function isUsingSqlite(): boolean {
|
|
|
221
272
|
return getDbType() == 'sqlite';
|
|
222
273
|
}
|
|
223
274
|
|
|
275
|
+
export function isUsingSqljs(): boolean {
|
|
276
|
+
return getDbType() == 'sqljs';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function isVectorStoreSupported(): boolean {
|
|
280
|
+
// Only Postgres supports pgvector
|
|
281
|
+
return getDbType() === 'postgres';
|
|
282
|
+
}
|
|
283
|
+
|
|
224
284
|
export async function initDatabase(config: DatabaseConfig | undefined) {
|
|
225
285
|
if (defaultDataSource == undefined) {
|
|
226
286
|
const mkds = getDsFunction(config);
|
|
@@ -268,9 +328,11 @@ export async function addRowForFullTextSearch(
|
|
|
268
328
|
vect: number[],
|
|
269
329
|
ctx: DbContext
|
|
270
330
|
) {
|
|
331
|
+
if (!isVectorStoreSupported()) return;
|
|
271
332
|
try {
|
|
272
333
|
const vecTableName = tableName + VectorSuffix;
|
|
273
334
|
const qb = getDatasourceForTransaction(ctx.txnId).createQueryBuilder();
|
|
335
|
+
const { default: pgvector } = await import('pgvector');
|
|
274
336
|
await qb
|
|
275
337
|
.insert()
|
|
276
338
|
.into(vecTableName)
|
|
@@ -282,6 +344,10 @@ export async function addRowForFullTextSearch(
|
|
|
282
344
|
}
|
|
283
345
|
|
|
284
346
|
export async function initVectorStore(tableNames: string[], ctx: DbContext) {
|
|
347
|
+
if (!isVectorStoreSupported()) {
|
|
348
|
+
logger.info(`Vector store not supported for ${getDbType()}, skipping init...`);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
285
351
|
let notInited = true;
|
|
286
352
|
tableNames.forEach(async (vecTableName: string) => {
|
|
287
353
|
const vecRepo = getDatasourceForTransaction(ctx.txnId).getRepository(vecTableName);
|
|
@@ -312,9 +378,14 @@ export async function vectorStoreSearch(
|
|
|
312
378
|
limit: number,
|
|
313
379
|
ctx: DbContext
|
|
314
380
|
): Promise<any> {
|
|
381
|
+
if (!isVectorStoreSupported()) {
|
|
382
|
+
// Not supported on sqljs/sqlite
|
|
383
|
+
return [];
|
|
384
|
+
}
|
|
315
385
|
try {
|
|
316
386
|
const vecTableName = tableName + VectorSuffix;
|
|
317
387
|
const qb = getDatasourceForTransaction(ctx.txnId).getRepository(tableName).manager;
|
|
388
|
+
const { default: pgvector } = await import('pgvector');
|
|
318
389
|
return await qb.query(
|
|
319
390
|
`select id from ${vecTableName} order by embedding <-> $1 LIMIT ${limit}`,
|
|
320
391
|
[pgvector.toSql(searchVec)]
|
|
@@ -329,6 +400,7 @@ export async function vectorStoreSearchEntryExists(
|
|
|
329
400
|
id: string,
|
|
330
401
|
ctx: DbContext
|
|
331
402
|
): Promise<boolean> {
|
|
403
|
+
if (!isVectorStoreSupported()) return false;
|
|
332
404
|
try {
|
|
333
405
|
const qb = getDatasourceForTransaction(ctx.txnId).getRepository(tableName).manager;
|
|
334
406
|
const vecTableName = tableName + VectorSuffix;
|
|
@@ -341,6 +413,7 @@ export async function vectorStoreSearchEntryExists(
|
|
|
341
413
|
}
|
|
342
414
|
|
|
343
415
|
export async function deleteFullTextSearchEntry(tableName: string, id: string, ctx: DbContext) {
|
|
416
|
+
if (!isVectorStoreSupported()) return;
|
|
344
417
|
try {
|
|
345
418
|
const qb = getDatasourceForTransaction(ctx.txnId).getRepository(tableName).manager;
|
|
346
419
|
const vecTableName = tableName + VectorSuffix;
|
|
@@ -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','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','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'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
|
-
'!=','*','+',',','-','.','/',':',';','<','<=','<>','=','>','>=','?','@'
|
|
7
|
+
'!=','*','+',',','-','-->','.','/',':',';','<','<=','<>','=','>','>=','?','@'
|
|
8
8
|
],
|
|
9
|
-
symbols: /!=|\(|\)
|
|
9
|
+
symbols: /!=|\(|\)|\*|\+|,|-|-->|\.|\/|:|;|<|<=|<>|=|>|>=|\?|@|\[|\]|\{|\}/,
|
|
10
10
|
|
|
11
11
|
tokenizer: {
|
|
12
12
|
initial: [
|