agentlang 0.10.0 → 0.10.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/language/generated/ast.d.ts +60 -42
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +45 -31
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +294 -327
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +336 -358
- package/out/language/main.cjs.map +2 -2
- package/out/language/parser.d.ts +11 -1
- package/out/language/parser.d.ts.map +1 -1
- package/out/language/parser.js +47 -7
- package/out/language/parser.js.map +1 -1
- package/out/runtime/agents/common.d.ts +2 -2
- package/out/runtime/agents/common.js +1 -1
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +14 -13
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +2 -5
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +26 -17
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/services/documentFetcher.js +2 -2
- package/out/runtime/services/documentFetcher.js.map +1 -1
- package/out/runtime/util.d.ts +10 -0
- package/out/runtime/util.d.ts.map +1 -1
- package/out/runtime/util.js +27 -2
- package/out/runtime/util.js.map +1 -1
- package/out/utils/fs/index.d.ts +12 -2
- package/out/utils/fs/index.d.ts.map +1 -1
- package/out/utils/fs/index.js +27 -6
- package/out/utils/fs/index.js.map +1 -1
- package/package.json +1 -1
- package/src/language/agentlang.langium +6 -9
- package/src/language/generated/ast.ts +66 -43
- package/src/language/generated/grammar.ts +294 -327
- package/src/language/parser.ts +54 -5
- package/src/runtime/agents/common.ts +1 -1
- package/src/runtime/interpreter.ts +25 -13
- package/src/runtime/modules/ai.ts +33 -24
- package/src/runtime/services/documentFetcher.ts +2 -2
- package/src/runtime/util.ts +45 -2
- package/src/utils/fs/index.ts +30 -6
package/src/language/parser.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ForEach,
|
|
9
9
|
FullTextSearch,
|
|
10
10
|
Group,
|
|
11
|
+
GroupByClause,
|
|
11
12
|
Handler,
|
|
12
13
|
If,
|
|
13
14
|
isExpr,
|
|
@@ -24,14 +25,17 @@ import {
|
|
|
24
25
|
ModuleDefinition,
|
|
25
26
|
NegExpr,
|
|
26
27
|
NotExpr,
|
|
28
|
+
OrderByClause,
|
|
27
29
|
Pattern,
|
|
28
30
|
PrimExpr,
|
|
31
|
+
QueryOption,
|
|
29
32
|
RelationshipPattern,
|
|
30
33
|
Return,
|
|
31
34
|
SelectIntoEntry,
|
|
32
35
|
SelectIntoSpec,
|
|
33
36
|
SetAttribute,
|
|
34
37
|
Statement,
|
|
38
|
+
WhereSpec,
|
|
35
39
|
WorkflowDefinition,
|
|
36
40
|
} from './generated/ast.js';
|
|
37
41
|
import { firstAliasSpec, firstCatchSpec, isString, QuerySuffix } from '../runtime/util.js';
|
|
@@ -269,8 +273,9 @@ function introspectPattern(pat: Pattern): BasePattern {
|
|
|
269
273
|
} else {
|
|
270
274
|
r = introspectCreatePattern(pat.crudMap);
|
|
271
275
|
}
|
|
272
|
-
|
|
273
|
-
|
|
276
|
+
const opts = extractQueryOptions(pat.crudMap);
|
|
277
|
+
if (opts.into) {
|
|
278
|
+
r = introspectInto(opts.into, r as CrudPattern);
|
|
274
279
|
}
|
|
275
280
|
} else if (pat.expr) {
|
|
276
281
|
r = introspectExpression(pat.expr);
|
|
@@ -360,10 +365,11 @@ function introspectQueryPattern(crudMap: CrudMap): CrudPattern {
|
|
|
360
365
|
crudMap.body?.attributes.forEach((sa: SetAttribute) => {
|
|
361
366
|
cp.addAttribute(sa.name, introspectExpression(sa.value), sa.op);
|
|
362
367
|
});
|
|
363
|
-
|
|
368
|
+
const opts = extractQueryOptions(crudMap);
|
|
369
|
+
crudMap.relationships?.forEach((rp: RelationshipPattern) => {
|
|
364
370
|
cp.addRelationship(rp.name, introspectPattern(rp.pattern) as CrudPattern | CrudPattern[]);
|
|
365
371
|
});
|
|
366
|
-
|
|
372
|
+
opts.joins?.forEach((js: JoinSpec) => {
|
|
367
373
|
const jp: JoinPattern = {
|
|
368
374
|
type: js.type,
|
|
369
375
|
targetEntity: js.name,
|
|
@@ -381,6 +387,49 @@ function introspectQueryPattern(crudMap: CrudMap): CrudPattern {
|
|
|
381
387
|
throw new Error(`Failed to introspect query-pattern: ${crudMap}`);
|
|
382
388
|
}
|
|
383
389
|
|
|
390
|
+
export type ExtractedQueryOptions = {
|
|
391
|
+
joins: JoinSpec[] | undefined;
|
|
392
|
+
into: SelectIntoSpec | undefined;
|
|
393
|
+
where: WhereSpec | undefined;
|
|
394
|
+
groupByClause: GroupByClause | undefined;
|
|
395
|
+
orderByClause: OrderByClause | undefined;
|
|
396
|
+
upsert: '@upsert' | undefined;
|
|
397
|
+
distinct: '@distinct' | undefined;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
export function extractQueryOptions(crudMap: CrudMap): ExtractedQueryOptions {
|
|
401
|
+
const r: ExtractedQueryOptions = {
|
|
402
|
+
joins: undefined,
|
|
403
|
+
into: undefined,
|
|
404
|
+
where: undefined,
|
|
405
|
+
groupByClause: undefined,
|
|
406
|
+
orderByClause: undefined,
|
|
407
|
+
upsert: undefined,
|
|
408
|
+
distinct: undefined,
|
|
409
|
+
};
|
|
410
|
+
crudMap.queryOptions.forEach((qo: QueryOption) => {
|
|
411
|
+
if (qo.join) {
|
|
412
|
+
if (r.joins === undefined) {
|
|
413
|
+
r.joins = new Array<JoinSpec>();
|
|
414
|
+
}
|
|
415
|
+
r.joins.push(qo.join);
|
|
416
|
+
} else if (qo.into) {
|
|
417
|
+
r.into = qo.into;
|
|
418
|
+
} else if (qo.where) {
|
|
419
|
+
r.where = qo.where;
|
|
420
|
+
} else if (qo.groupByClause) {
|
|
421
|
+
r.groupByClause = qo.groupByClause;
|
|
422
|
+
} else if (qo.orderByClause) {
|
|
423
|
+
r.orderByClause = qo.orderByClause;
|
|
424
|
+
} else if (qo.upsert) {
|
|
425
|
+
r.upsert = qo.upsert;
|
|
426
|
+
} else if (qo.distinct) {
|
|
427
|
+
r.distinct = qo.distinct;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
return r;
|
|
431
|
+
}
|
|
432
|
+
|
|
384
433
|
function introspectCreatePattern(crudMap: CrudMap): CrudPattern {
|
|
385
434
|
if (crudMap) {
|
|
386
435
|
const cp: CrudPattern = new CrudPattern(crudMap.name);
|
|
@@ -393,7 +442,7 @@ function introspectCreatePattern(crudMap: CrudMap): CrudPattern {
|
|
|
393
442
|
}
|
|
394
443
|
cp.addAttribute(sa.name, introspectExpression(sa.value), sa.op);
|
|
395
444
|
});
|
|
396
|
-
crudMap.relationships
|
|
445
|
+
crudMap.relationships?.forEach((rp: RelationshipPattern) => {
|
|
397
446
|
cp.addRelationship(rp.name, introspectPattern(rp.pattern) as CrudPattern | CrudPattern[]);
|
|
398
447
|
});
|
|
399
448
|
cp.isQueryUpdate = qup;
|
|
@@ -209,7 +209,7 @@ A pattern may execute asynchronously and its eventual result can be handled by p
|
|
|
209
209
|
If you are instructed that a particular event will be called asynchronously, always provide the patterns that follows in its '@then' clause. You must add the
|
|
210
210
|
'@then' clause only if an event's documentation or instruction explicitly requires to do so.
|
|
211
211
|
|
|
212
|
-
Earlier we discussed
|
|
212
|
+
Earlier we discussed the concept of 'between' relationship. Here's the 'CreateEmployee' workflow updated to create the Employee with the his/her Profile attached:
|
|
213
213
|
|
|
214
214
|
workflow CreateEmployee {
|
|
215
215
|
{Erp/Employee {firstName CreateEmployee.firstName,
|
|
@@ -80,7 +80,12 @@ import {
|
|
|
80
80
|
splitRefs,
|
|
81
81
|
} from './util.js';
|
|
82
82
|
import { getResolver, getResolverNameForPath } from './resolvers/registry.js';
|
|
83
|
-
import {
|
|
83
|
+
import {
|
|
84
|
+
ExtractedQueryOptions,
|
|
85
|
+
extractQueryOptions,
|
|
86
|
+
parseStatement,
|
|
87
|
+
parseWorkflow,
|
|
88
|
+
} from '../language/parser.js';
|
|
84
89
|
import { ActiveSessionInfo, AdminSession, AdminUserId } from './auth/defs.js';
|
|
85
90
|
import {
|
|
86
91
|
AgentEntityName,
|
|
@@ -1497,17 +1502,18 @@ async function maybeValidateOneOfRefs(inst: Instance, env: Environment) {
|
|
|
1497
1502
|
}
|
|
1498
1503
|
}
|
|
1499
1504
|
|
|
1500
|
-
function maybeSetQueryClauses(inst: Instance,
|
|
1501
|
-
if (
|
|
1502
|
-
inst.setGroupBy(
|
|
1505
|
+
function maybeSetQueryClauses(inst: Instance, qopts: ExtractedQueryOptions) {
|
|
1506
|
+
if (qopts.groupByClause) {
|
|
1507
|
+
inst.setGroupBy(qopts.groupByClause.colNames);
|
|
1503
1508
|
}
|
|
1504
|
-
if (
|
|
1505
|
-
inst.setOrderBy(
|
|
1509
|
+
if (qopts.orderByClause) {
|
|
1510
|
+
inst.setOrderBy(qopts.orderByClause.colNames, qopts.orderByClause.order === '@desc');
|
|
1506
1511
|
}
|
|
1507
1512
|
}
|
|
1508
1513
|
|
|
1509
1514
|
async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
1510
|
-
|
|
1515
|
+
const qopts = extractQueryOptions(crud);
|
|
1516
|
+
if (!env.isInUpsertMode() && qopts.upsert !== undefined) {
|
|
1511
1517
|
return await evaluateUpsert(crud, env);
|
|
1512
1518
|
}
|
|
1513
1519
|
const inst: Instance = crud.source
|
|
@@ -1519,12 +1525,12 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1519
1525
|
const qattrs = inst.queryAttributes;
|
|
1520
1526
|
const onlyAggregates = inst.aggregates !== undefined && qattrs === undefined;
|
|
1521
1527
|
const isQueryAll = onlyAggregates || crud.name.endsWith(QuerySuffix);
|
|
1522
|
-
const distinct: boolean =
|
|
1523
|
-
maybeSetQueryClauses(inst,
|
|
1528
|
+
const distinct: boolean = qopts.distinct !== undefined;
|
|
1529
|
+
maybeSetQueryClauses(inst, qopts);
|
|
1524
1530
|
if (attrs.size > 0) {
|
|
1525
1531
|
await maybeValidateOneOfRefs(inst, env);
|
|
1526
1532
|
}
|
|
1527
|
-
if (
|
|
1533
|
+
if (qopts.into) {
|
|
1528
1534
|
if (attrs.size > 0) {
|
|
1529
1535
|
throw new Error(
|
|
1530
1536
|
`Query pattern for ${entryName} with 'into' clause cannot be used to update attributes`
|
|
@@ -1533,10 +1539,16 @@ async function evaluateCrudMap(crud: CrudMap, env: Environment): Promise<void> {
|
|
|
1533
1539
|
if (qattrs === undefined && !isQueryAll) {
|
|
1534
1540
|
throw new Error(`Pattern for ${entryName} with 'into' clause must be a query`);
|
|
1535
1541
|
}
|
|
1536
|
-
if (
|
|
1537
|
-
await evaluateJoinQuery(
|
|
1542
|
+
if (qopts.joins && qopts.joins.length > 0) {
|
|
1543
|
+
await evaluateJoinQuery(qopts.joins, qopts.into, qopts.where, inst, distinct, env);
|
|
1538
1544
|
} else {
|
|
1539
|
-
await evaluateJoinQueryWithRelationships(
|
|
1545
|
+
await evaluateJoinQueryWithRelationships(
|
|
1546
|
+
qopts.into,
|
|
1547
|
+
inst,
|
|
1548
|
+
crud.relationships || [],
|
|
1549
|
+
distinct,
|
|
1550
|
+
env
|
|
1551
|
+
);
|
|
1540
1552
|
}
|
|
1541
1553
|
return;
|
|
1542
1554
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DefaultModuleName,
|
|
3
3
|
escapeSpecialChars,
|
|
4
|
+
extractAndRemoveAllXmlTaggedText,
|
|
5
|
+
ExtractedCode,
|
|
6
|
+
ExtractedText,
|
|
7
|
+
extractFencedCodeBlocks,
|
|
4
8
|
isFqName,
|
|
5
9
|
isString,
|
|
6
10
|
makeCoreModuleName,
|
|
@@ -580,7 +584,7 @@ export class AgentInstance {
|
|
|
580
584
|
}
|
|
581
585
|
}
|
|
582
586
|
|
|
583
|
-
private async
|
|
587
|
+
private async getFullInstructionsHelper(
|
|
584
588
|
env: Environment,
|
|
585
589
|
activator: AgentInstructionActivator
|
|
586
590
|
): Promise<string> {
|
|
@@ -652,6 +656,20 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
652
656
|
}
|
|
653
657
|
}
|
|
654
658
|
|
|
659
|
+
private static UserTag = 'user';
|
|
660
|
+
|
|
661
|
+
private async getFullInstructions(
|
|
662
|
+
env: Environment,
|
|
663
|
+
activator: AgentInstructionActivator
|
|
664
|
+
): Promise<ExtractedText> {
|
|
665
|
+
const finalInstruction = await this.getFullInstructionsHelper(env, activator);
|
|
666
|
+
if (finalInstruction.indexOf(`<${AgentInstance.UserTag}>`) > 0) {
|
|
667
|
+
return extractAndRemoveAllXmlTaggedText(finalInstruction, AgentInstance.UserTag);
|
|
668
|
+
} else {
|
|
669
|
+
return { extracted: undefined, updatedText: finalInstruction };
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
655
673
|
private static maybeRewriteTemplatePatterns(
|
|
656
674
|
scratchPad: any,
|
|
657
675
|
instruction: string,
|
|
@@ -820,6 +838,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
820
838
|
const sess: Instance | null = this.withSession ? await findAgentChatSession(chatId, env) : null;
|
|
821
839
|
let msgs: BaseMessage[] | undefined;
|
|
822
840
|
let cachedMsg: string | undefined = undefined;
|
|
841
|
+
let extractedText: ExtractedText | undefined;
|
|
823
842
|
const activator: AgentInstructionActivator = {
|
|
824
843
|
provider: p,
|
|
825
844
|
userMessage: message,
|
|
@@ -829,7 +848,8 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
829
848
|
if (sess) {
|
|
830
849
|
msgs = sess.lookup('messages');
|
|
831
850
|
} else {
|
|
832
|
-
|
|
851
|
+
extractedText = await this.getFullInstructions(env, activator);
|
|
852
|
+
cachedMsg = extractedText.updatedText;
|
|
833
853
|
msgs = [systemMessage(cachedMsg || '')];
|
|
834
854
|
}
|
|
835
855
|
if (msgs) {
|
|
@@ -844,12 +864,21 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
844
864
|
? EvalInstructions
|
|
845
865
|
: LearnerAgentInstructions;
|
|
846
866
|
const ts = this.toolsAsString();
|
|
847
|
-
|
|
867
|
+
let tmpMsg = cachedMsg;
|
|
868
|
+
if (!tmpMsg) {
|
|
869
|
+
extractedText = await this.getFullInstructions(env, activator);
|
|
870
|
+
tmpMsg = extractedText.updatedText;
|
|
871
|
+
}
|
|
872
|
+
const msg = `${s}\n${ts}\n${tmpMsg}`;
|
|
848
873
|
const newSysMsg = systemMessage(msg);
|
|
849
874
|
msgs[0] = newSysMsg;
|
|
850
875
|
}
|
|
876
|
+
let tmpMsg = message;
|
|
877
|
+
if (extractedText?.extracted) {
|
|
878
|
+
tmpMsg = `${tmpMsg}\n${extractedText.extracted.join('\n')}`;
|
|
879
|
+
}
|
|
851
880
|
const hmsg = await this.maybeAddRelevantDocuments(
|
|
852
|
-
this.maybeAddFlowContext(
|
|
881
|
+
this.maybeAddFlowContext(tmpMsg, env),
|
|
853
882
|
env
|
|
854
883
|
);
|
|
855
884
|
if (hmsg.length > 0) {
|
|
@@ -1299,26 +1328,6 @@ function processScenarioResponse(resp: string): string {
|
|
|
1299
1328
|
return resp;
|
|
1300
1329
|
}
|
|
1301
1330
|
|
|
1302
|
-
type ExtractedCode = {
|
|
1303
|
-
language: string | null;
|
|
1304
|
-
code: string;
|
|
1305
|
-
};
|
|
1306
|
-
|
|
1307
|
-
export function extractFencedCodeBlocks(markdown: string): ExtractedCode[] {
|
|
1308
|
-
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
1309
|
-
const blocks: ExtractedCode[] = [];
|
|
1310
|
-
let match;
|
|
1311
|
-
|
|
1312
|
-
while ((match = codeBlockRegex.exec(markdown)) !== null) {
|
|
1313
|
-
blocks.push({
|
|
1314
|
-
language: match[1] || null,
|
|
1315
|
-
code: match[2],
|
|
1316
|
-
});
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
return blocks;
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
1331
|
export function normalizeGeneratedCode(code: string | undefined): string {
|
|
1323
1332
|
if (code !== undefined) {
|
|
1324
1333
|
const blocks = extractFencedCodeBlocks(code);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
2
|
-
import { readFile } from '
|
|
2
|
+
import { readFile } from '../../utils/fs-utils.js';
|
|
3
3
|
import { logger } from '../logger.js';
|
|
4
4
|
import { parseAndEvaluateStatement } from '../interpreter.js';
|
|
5
5
|
import { CoreAIModuleName } from '../modules/ai.js';
|
|
@@ -443,7 +443,7 @@ class DocumentFetcherService {
|
|
|
443
443
|
|
|
444
444
|
private async fetchFromLocal(filePath: string): Promise<string> {
|
|
445
445
|
try {
|
|
446
|
-
const content = await readFile(filePath
|
|
446
|
+
const content = await readFile(filePath);
|
|
447
447
|
const lowerPath = filePath.toLowerCase();
|
|
448
448
|
const isMarkdown = lowerPath.endsWith('.md') || lowerPath.endsWith('.markdown');
|
|
449
449
|
|
package/src/runtime/util.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNodeEnv } from '../utils/runtime.js';
|
|
1
|
+
import { isNodeEnv, path } from '../utils/runtime.js';
|
|
2
2
|
import {
|
|
3
3
|
AliasSpec,
|
|
4
4
|
CatchSpec,
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
} from '../language/generated/ast.js';
|
|
16
16
|
import { readFile } from '../utils/fs-utils.js';
|
|
17
17
|
import bcrypt from 'bcryptjs';
|
|
18
|
-
import path from 'node:path';
|
|
19
18
|
|
|
20
19
|
export const QuerySuffix = '?';
|
|
21
20
|
|
|
@@ -665,3 +664,47 @@ export function objectAsString(obj: any, keyAsString: boolean = false) {
|
|
|
665
664
|
});
|
|
666
665
|
return `{${entries.join(', ')}}`;
|
|
667
666
|
}
|
|
667
|
+
|
|
668
|
+
export type ExtractedText = {
|
|
669
|
+
extracted: string[] | undefined;
|
|
670
|
+
updatedText: string;
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
// extract all data between a given xml tag from within an arbitray text.
|
|
674
|
+
export function extractAndRemoveAllXmlTaggedText(text: string, tagName: string): ExtractedText {
|
|
675
|
+
const pattern = `<${tagName}\\b[^>]*>([\\s\\S]*?)</${tagName}>`;
|
|
676
|
+
const regex = new RegExp(pattern, 'gi');
|
|
677
|
+
|
|
678
|
+
const extracted = [];
|
|
679
|
+
let updatedText = text;
|
|
680
|
+
|
|
681
|
+
let match;
|
|
682
|
+
while ((match = regex.exec(text)) !== null) {
|
|
683
|
+
extracted.push(match[1]);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
updatedText = text.replace(regex, '');
|
|
687
|
+
|
|
688
|
+
return { extracted, updatedText };
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
export type ExtractedCode = {
|
|
692
|
+
language: string | null;
|
|
693
|
+
code: string;
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
// extract tick-quoted code from markdown-formatted text.
|
|
697
|
+
export function extractFencedCodeBlocks(markdown: string): ExtractedCode[] {
|
|
698
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
699
|
+
const blocks: ExtractedCode[] = [];
|
|
700
|
+
let match;
|
|
701
|
+
|
|
702
|
+
while ((match = codeBlockRegex.exec(markdown)) !== null) {
|
|
703
|
+
blocks.push({
|
|
704
|
+
language: match[1] || null,
|
|
705
|
+
code: match[2],
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
return blocks;
|
|
710
|
+
}
|
package/src/utils/fs/index.ts
CHANGED
|
@@ -4,25 +4,49 @@
|
|
|
4
4
|
|
|
5
5
|
export * from './interfaces.js';
|
|
6
6
|
import { ExtendedFileSystem } from './interfaces.js';
|
|
7
|
-
import { createNodeFS } from './node-fs.js';
|
|
8
|
-
import { createLightningFS } from './lightning-fs.js';
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
9
|
* Create the appropriate filesystem implementation based on environment
|
|
10
|
+
* Uses dynamic imports to avoid bundling Node.js-specific code in browser builds
|
|
12
11
|
* @returns Promise resolving to appropriate filesystem implementation
|
|
13
12
|
*/
|
|
14
13
|
export async function createFS(options?: any): Promise<ExtendedFileSystem> {
|
|
15
14
|
// Check if we're in a browser or Node environment
|
|
16
15
|
if (typeof window === 'undefined') {
|
|
17
|
-
// Node.js environment
|
|
16
|
+
// Node.js environment - use dynamic import to avoid bundling in browser
|
|
17
|
+
const { createNodeFS } = await import('./node-fs.js');
|
|
18
18
|
return createNodeFS();
|
|
19
19
|
} else {
|
|
20
20
|
// Browser environment - use Lightning FS
|
|
21
|
+
const { createLightningFS } = await import('./lightning-fs.js');
|
|
21
22
|
return createLightningFS(options);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
//
|
|
26
|
-
export { createNodeFS } from './node-fs.js';
|
|
27
|
-
export { createLightningFS } from './lightning-fs.js';
|
|
26
|
+
// Re-export interface types (these are safe for browser)
|
|
28
27
|
export * from './interfaces.js';
|
|
28
|
+
|
|
29
|
+
// Export factory functions that use dynamic imports internally
|
|
30
|
+
// These are async to support dynamic loading based on environment
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create Node.js filesystem - only works in Node.js environment
|
|
34
|
+
* @returns Promise resolving to NodeFileSystem instance
|
|
35
|
+
*/
|
|
36
|
+
export async function createNodeFS(): Promise<ExtendedFileSystem> {
|
|
37
|
+
if (typeof window !== 'undefined') {
|
|
38
|
+
throw new Error('createNodeFS is only available in Node.js environment');
|
|
39
|
+
}
|
|
40
|
+
const module = await import('./node-fs.js');
|
|
41
|
+
return module.createNodeFS();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create Lightning FS - works in browser environment
|
|
46
|
+
* @param options Optional configuration for Lightning FS
|
|
47
|
+
* @returns Promise resolving to LightningFileSystem instance
|
|
48
|
+
*/
|
|
49
|
+
export async function createLightningFS(options?: any): Promise<ExtendedFileSystem> {
|
|
50
|
+
const module = await import('./lightning-fs.js');
|
|
51
|
+
return module.createLightningFS(options);
|
|
52
|
+
}
|