agentlang 0.0.50 → 0.0.52
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 +207 -1
- package/out/api/http.js.map +1 -1
- package/out/extension/main.cjs +250 -250
- package/out/extension/main.cjs.map +2 -2
- package/out/language/main.cjs +502 -502
- package/out/language/main.cjs.map +2 -2
- 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 +7 -0
- package/out/runtime/agents/common.d.ts.map +1 -1
- package/out/runtime/agents/common.js +34 -0
- package/out/runtime/agents/common.js.map +1 -1
- package/out/runtime/agents/impl/anthropic.js +1 -1
- package/out/runtime/agents/impl/anthropic.js.map +1 -1
- package/out/runtime/agents/impl/openai.js +1 -1
- package/out/runtime/agents/impl/openai.js.map +1 -1
- package/out/runtime/agents/registry.d.ts.map +1 -1
- package/out/runtime/agents/registry.js +9 -6
- package/out/runtime/agents/registry.js.map +1 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +5 -2
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +25 -6
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +23 -1
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +95 -11
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +2 -6
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +1 -31
- package/out/runtime/modules/ai.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/package.json +156 -153
- package/src/api/http.ts +234 -0
- package/src/language/syntax.ts +21 -0
- package/src/runtime/agents/common.ts +41 -0
- package/src/runtime/agents/impl/anthropic.ts +1 -1
- package/src/runtime/agents/impl/openai.ts +1 -1
- package/src/runtime/agents/registry.ts +12 -6
- package/src/runtime/interpreter.ts +5 -10
- package/src/runtime/loader.ts +24 -11
- package/src/runtime/module.ts +112 -12
- package/src/runtime/modules/ai.ts +3 -38
- 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
|
@@ -105,7 +105,7 @@ export class OpenAIProvider implements AgentServiceProvider {
|
|
|
105
105
|
async invoke(messages: BaseMessage[], externalToolSpecs: any[] | undefined): Promise<AIResponse> {
|
|
106
106
|
if (!this.config.apiKey) {
|
|
107
107
|
throw new Error(
|
|
108
|
-
'OpenAI API key is required. Set OPENAI_API_KEY environment variable or provide apiKey in config.'
|
|
108
|
+
'OpenAI API key is required. Set OPENAI_API_KEY environment variable or use setLocalEnv("OPENAI_API_KEY", key) or provide apiKey in config.'
|
|
109
109
|
);
|
|
110
110
|
}
|
|
111
111
|
if (externalToolSpecs) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OpenAIProvider } from './impl/openai.js';
|
|
2
2
|
import { AnthropicProvider } from './impl/anthropic.js';
|
|
3
|
+
import { getLocalEnv } from '../auth/defs.js';
|
|
3
4
|
|
|
4
5
|
const Providers = new Map().set('openai', OpenAIProvider).set('anthropic', AnthropicProvider);
|
|
5
6
|
|
|
@@ -18,6 +19,7 @@ export function provider(service: string) {
|
|
|
18
19
|
p = Providers.get(availableService);
|
|
19
20
|
if (p) return p;
|
|
20
21
|
}
|
|
22
|
+
|
|
21
23
|
const errorMessage = `${service} provider requested but ${service.toUpperCase()}_API_KEY not found. Available providers: ${getAvailableProviders().join(', ') || 'none'}`;
|
|
22
24
|
console.error(errorMessage);
|
|
23
25
|
throw new Error(errorMessage);
|
|
@@ -30,19 +32,19 @@ export function provider(service: string) {
|
|
|
30
32
|
function isProviderAvailable(service: string): boolean {
|
|
31
33
|
switch (service) {
|
|
32
34
|
case 'openai':
|
|
33
|
-
return !!process.env.OPENAI_API_KEY;
|
|
35
|
+
return !!(process.env.OPENAI_API_KEY || getLocalEnv('OPENAI_API_KEY'));
|
|
34
36
|
case 'anthropic':
|
|
35
|
-
return !!process.env.ANTHROPIC_API_KEY;
|
|
37
|
+
return !!(process.env.ANTHROPIC_API_KEY || getLocalEnv('ANTHROPIC_API_KEY'));
|
|
36
38
|
default:
|
|
37
39
|
return false;
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
function getAvailableProvider(): string | null {
|
|
42
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
44
|
+
if (process.env.ANTHROPIC_API_KEY || getLocalEnv('ANTHROPIC_API_KEY')) {
|
|
43
45
|
return 'anthropic';
|
|
44
46
|
}
|
|
45
|
-
if (process.env.OPENAI_API_KEY) {
|
|
47
|
+
if (process.env.OPENAI_API_KEY || getLocalEnv('OPENAI_API_KEY')) {
|
|
46
48
|
return 'openai';
|
|
47
49
|
}
|
|
48
50
|
return null;
|
|
@@ -50,7 +52,11 @@ function getAvailableProvider(): string | null {
|
|
|
50
52
|
|
|
51
53
|
function getAvailableProviders(): string[] {
|
|
52
54
|
const available: string[] = [];
|
|
53
|
-
if (process.env.ANTHROPIC_API_KEY
|
|
54
|
-
|
|
55
|
+
if (process.env.ANTHROPIC_API_KEY || getLocalEnv('ANTHROPIC_API_KEY')) {
|
|
56
|
+
available.push('anthropic');
|
|
57
|
+
}
|
|
58
|
+
if (process.env.OPENAI_API_KEY || getLocalEnv('OPENAI_API_KEY')) {
|
|
59
|
+
available.push('openai');
|
|
60
|
+
}
|
|
55
61
|
return available;
|
|
56
62
|
}
|
|
@@ -47,7 +47,8 @@ import {
|
|
|
47
47
|
Relationship,
|
|
48
48
|
Workflow,
|
|
49
49
|
} from './module.js';
|
|
50
|
-
import { JoinInfo, Resolver
|
|
50
|
+
import { JoinInfo, Resolver } from './resolvers/interface.js';
|
|
51
|
+
import { ResolverAuthInfo } from './resolvers/authinfo.js';
|
|
51
52
|
import { SqlDbResolver } from './resolvers/sqldb/impl.js';
|
|
52
53
|
import {
|
|
53
54
|
CrudType,
|
|
@@ -70,15 +71,7 @@ import {
|
|
|
70
71
|
import { getResolver, getResolverNameForPath } from './resolvers/registry.js';
|
|
71
72
|
import { parseStatement, parseWorkflow } from '../language/parser.js';
|
|
72
73
|
import { ActiveSessionInfo, AdminSession, AdminUserId } from './auth/defs.js';
|
|
73
|
-
import {
|
|
74
|
-
AgentInstance,
|
|
75
|
-
AgentEntityName,
|
|
76
|
-
AgentFqName,
|
|
77
|
-
findAgentByName,
|
|
78
|
-
FlowSpec,
|
|
79
|
-
getAgentFlow,
|
|
80
|
-
FlowStep,
|
|
81
|
-
} from './modules/ai.js';
|
|
74
|
+
import { AgentInstance, AgentEntityName, AgentFqName, findAgentByName } from './modules/ai.js';
|
|
82
75
|
import { logger } from './logger.js';
|
|
83
76
|
import {
|
|
84
77
|
FlowSuspensionTag,
|
|
@@ -97,6 +90,7 @@ import {
|
|
|
97
90
|
import { invokeModuleFn } from './jsmodules.js';
|
|
98
91
|
import { invokeOpenApiEvent, isOpenApiEventInstance } from './openapi.js';
|
|
99
92
|
import { fetchDoc } from './docs.js';
|
|
93
|
+
import { FlowSpec, FlowStep, getAgentFlow } from './agents/common.js';
|
|
100
94
|
|
|
101
95
|
export type Result = any;
|
|
102
96
|
|
|
@@ -169,6 +163,7 @@ export class Environment extends Instance {
|
|
|
169
163
|
this.activeResolvers = new Map<string, Resolver>();
|
|
170
164
|
this.activeTransactions = new Map<string, string>();
|
|
171
165
|
this.activeCatchHandlers = new Array<CatchHandlers>();
|
|
166
|
+
this.attributes.set('process', process);
|
|
172
167
|
}
|
|
173
168
|
}
|
|
174
169
|
|
package/src/runtime/loader.ts
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
removeModule,
|
|
49
49
|
newInstanceAttributes,
|
|
50
50
|
addAgent,
|
|
51
|
+
fetchModule,
|
|
51
52
|
} from './module.js';
|
|
52
53
|
import {
|
|
53
54
|
escapeSpecialChars,
|
|
@@ -67,13 +68,7 @@ import { maybeGetValidationErrors, parse, parseModule, parseWorkflow } from '../
|
|
|
67
68
|
import { logger } from './logger.js';
|
|
68
69
|
import { Environment, evaluateStatements, GlobalEnvironment } from './interpreter.js';
|
|
69
70
|
import { createPermission, createRole } from './modules/auth.js';
|
|
70
|
-
import {
|
|
71
|
-
AgentEntityName,
|
|
72
|
-
CoreAIModuleName,
|
|
73
|
-
LlmEntityName,
|
|
74
|
-
registerAgentFlow,
|
|
75
|
-
registerFlow,
|
|
76
|
-
} from './modules/ai.js';
|
|
71
|
+
import { AgentEntityName, CoreAIModuleName, LlmEntityName } from './modules/ai.js';
|
|
77
72
|
import { GenericResolver, GenericResolverMethods } from './resolvers/interface.js';
|
|
78
73
|
import { registerResolver, setResolver } from './resolvers/registry.js';
|
|
79
74
|
import { Config, ConfigSchema, setAppConfig } from './state.js';
|
|
@@ -81,6 +76,7 @@ import { getModuleFn, importModule } from './jsmodules.js';
|
|
|
81
76
|
import { SetSubscription } from './defs.js';
|
|
82
77
|
import { ExtendedFileSystem } from '../utils/fs/interfaces.js';
|
|
83
78
|
import z from 'zod';
|
|
79
|
+
import { registerAgentFlow, registerFlow } from './agents/common.js';
|
|
84
80
|
|
|
85
81
|
export async function extractDocument(
|
|
86
82
|
fileName: string,
|
|
@@ -431,7 +427,7 @@ export function addWorkflowFromDef(def: WorkflowDefinition, moduleName: string):
|
|
|
431
427
|
|
|
432
428
|
const StandaloneStatements = new Map<string, Statement[]>();
|
|
433
429
|
|
|
434
|
-
function addStandaloneStatement(stmt: Statement, moduleName: string) {
|
|
430
|
+
function addStandaloneStatement(stmt: Statement, moduleName: string, userDefined = true) {
|
|
435
431
|
let stmts: Array<Statement> | undefined = StandaloneStatements.get(moduleName);
|
|
436
432
|
if (stmts == undefined) {
|
|
437
433
|
stmts = new Array<Statement>();
|
|
@@ -440,6 +436,10 @@ function addStandaloneStatement(stmt: Statement, moduleName: string) {
|
|
|
440
436
|
if (!StandaloneStatements.has(moduleName)) {
|
|
441
437
|
StandaloneStatements.set(moduleName, stmts);
|
|
442
438
|
}
|
|
439
|
+
if (userDefined) {
|
|
440
|
+
const m = fetchModule(moduleName);
|
|
441
|
+
m.addStandaloneStatement(stmt);
|
|
442
|
+
}
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
export async function runStandaloneStatements() {
|
|
@@ -486,6 +486,8 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
|
486
486
|
});
|
|
487
487
|
attrsStrs.push(`type "flow-exec"`);
|
|
488
488
|
attrs.set('type', 'flow-exec');
|
|
489
|
+
attrsStrs.push(`flows "${fnames}"`);
|
|
490
|
+
attrs.set('flows', fnames);
|
|
489
491
|
} else {
|
|
490
492
|
throw new Error(`Invalid flows list in agent ${name}`);
|
|
491
493
|
}
|
|
@@ -526,10 +528,11 @@ async function addAgentDefinition(def: AgentDefinition, moduleName: string) {
|
|
|
526
528
|
}, @upsert}`;
|
|
527
529
|
let wf = createAgent;
|
|
528
530
|
if (llmName) {
|
|
529
|
-
|
|
531
|
+
const service = process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai';
|
|
532
|
+
wf = `{${CoreAIModuleName}/${LlmEntityName} {name "${llmName}", service "${service}"}, @upsert}; ${wf}`;
|
|
530
533
|
}
|
|
531
534
|
(await parseWorkflow(`workflow A {${wf}}`)).statements.forEach((stmt: Statement) => {
|
|
532
|
-
addStandaloneStatement(stmt, moduleName);
|
|
535
|
+
addStandaloneStatement(stmt, moduleName, false);
|
|
533
536
|
});
|
|
534
537
|
addAgent(def.name, attrs, moduleName);
|
|
535
538
|
}
|
|
@@ -569,7 +572,17 @@ function processAgentArrayValue(expr: Expr | undefined, attrName: string): strin
|
|
|
569
572
|
|
|
570
573
|
function addFlowDefinition(def: FlowDefinition, moduleName: string) {
|
|
571
574
|
if (def.body && def.$cstNode) {
|
|
572
|
-
|
|
575
|
+
const m = fetchModule(moduleName);
|
|
576
|
+
const sdef = def.$cstNode.text;
|
|
577
|
+
const idx = sdef.indexOf('{');
|
|
578
|
+
let f = '';
|
|
579
|
+
if (idx > 0) {
|
|
580
|
+
f = sdef.substring(idx + 1, sdef.lastIndexOf('}')).trim();
|
|
581
|
+
} else {
|
|
582
|
+
f = sdef;
|
|
583
|
+
}
|
|
584
|
+
m.addFlow(def.name, f);
|
|
585
|
+
registerFlow(`${moduleName}/${def.name}`, f);
|
|
573
586
|
}
|
|
574
587
|
}
|
|
575
588
|
|
package/src/runtime/module.ts
CHANGED
|
@@ -816,42 +816,63 @@ 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
|
-
|
|
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
|
+
}
|
|
855
876
|
attrs.push(` ${key} ${v}`);
|
|
856
877
|
}
|
|
857
878
|
});
|
|
@@ -1295,6 +1316,59 @@ export class Workflow extends ModuleEntry {
|
|
|
1295
1316
|
}
|
|
1296
1317
|
}
|
|
1297
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
|
+
|
|
1298
1372
|
const EmptyWorkflow: Workflow = new Workflow('', [], DefaultModuleName);
|
|
1299
1373
|
|
|
1300
1374
|
export function isEmptyWorkflow(wf: Workflow): boolean {
|
|
@@ -1340,6 +1414,32 @@ export class Module {
|
|
|
1340
1414
|
return this.removeEntry(Agent.EscapeName(agentName));
|
|
1341
1415
|
}
|
|
1342
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
|
+
|
|
1343
1443
|
private getEntryIndex(entryName: string): number {
|
|
1344
1444
|
return this.entries.findIndex((v: ModuleEntry) => {
|
|
1345
1445
|
return v.name == entryName;
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
systemMessage,
|
|
23
23
|
} from '../agents/provider.js';
|
|
24
24
|
import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages';
|
|
25
|
-
import { FlowExecInstructions, PlannerInstructions } from '../agents/common.js';
|
|
25
|
+
import { FlowExecInstructions, FlowStep, PlannerInstructions } from '../agents/common.js';
|
|
26
26
|
import { PathAttributeNameQuery } from '../defs.js';
|
|
27
27
|
import { logger } from '../logger.js';
|
|
28
28
|
|
|
@@ -49,6 +49,7 @@ entity ${AgentEntityName} {
|
|
|
49
49
|
channels String @optional, // comma-separated list of channel names
|
|
50
50
|
output String @optional, // fq-name of another agent to which the result will be pushed
|
|
51
51
|
role String @optional,
|
|
52
|
+
flows String @optional,
|
|
52
53
|
llm String
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -95,6 +96,7 @@ export class AgentInstance {
|
|
|
95
96
|
runWorkflows: boolean = true;
|
|
96
97
|
output: string | undefined;
|
|
97
98
|
role: string | undefined;
|
|
99
|
+
flows: string | undefined;
|
|
98
100
|
private toolsArray: string[] | undefined = undefined;
|
|
99
101
|
private hasModuleTools = false;
|
|
100
102
|
private withSession = true;
|
|
@@ -416,40 +418,3 @@ export async function saveAgentChatSession(chatId: string, messages: any[], env:
|
|
|
416
418
|
export function agentName(agentInstance: Instance): string {
|
|
417
419
|
return agentInstance.lookup('name');
|
|
418
420
|
}
|
|
419
|
-
|
|
420
|
-
export type FlowSpec = string;
|
|
421
|
-
export type FlowStep = string;
|
|
422
|
-
|
|
423
|
-
const AgentFlows = new Map<string, string[]>();
|
|
424
|
-
const FlowRegistry = new Map<string, FlowSpec>();
|
|
425
|
-
|
|
426
|
-
export function registerFlow(name: string, flow: FlowSpec): string {
|
|
427
|
-
FlowRegistry.set(name, flow);
|
|
428
|
-
return name;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
export function getFlow(name: string): FlowSpec | undefined {
|
|
432
|
-
return FlowRegistry.get(name);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
export function registerAgentFlow(agentName: string, flowSpecName: string): string {
|
|
436
|
-
let currentFlows = AgentFlows.get(agentName);
|
|
437
|
-
if (currentFlows) {
|
|
438
|
-
currentFlows.push(flowSpecName);
|
|
439
|
-
} else {
|
|
440
|
-
currentFlows = new Array<string>();
|
|
441
|
-
currentFlows.push(flowSpecName);
|
|
442
|
-
}
|
|
443
|
-
AgentFlows.set(agentName, currentFlows);
|
|
444
|
-
return agentName;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Return the first flow registered with the agent.
|
|
448
|
-
export function getAgentFlow(agentName: string): FlowSpec | undefined {
|
|
449
|
-
const currentFlows = AgentFlows.get(agentName);
|
|
450
|
-
if (currentFlows) {
|
|
451
|
-
return getFlow(currentFlows[0]);
|
|
452
|
-
} else {
|
|
453
|
-
return undefined;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
@@ -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;
|