flowquery 1.0.12 → 1.0.13
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/README.md +3 -3
- package/dist/flowquery.min.js +1 -1
- package/dist/parsing/functions/aggregate_function.d.ts +1 -1
- package/dist/parsing/functions/aggregate_function.d.ts.map +1 -1
- package/dist/parsing/functions/aggregate_function.js.map +1 -1
- package/dist/parsing/functions/async_function.d.ts +4 -15
- package/dist/parsing/functions/async_function.d.ts.map +1 -1
- package/dist/parsing/functions/async_function.js +6 -59
- package/dist/parsing/functions/async_function.js.map +1 -1
- package/dist/parsing/functions/function.d.ts +1 -1
- package/dist/parsing/functions/function.d.ts.map +1 -1
- package/dist/parsing/functions/function.js +1 -1
- package/dist/parsing/functions/function.js.map +1 -1
- package/dist/parsing/functions/function_factory.d.ts +2 -0
- package/dist/parsing/functions/function_factory.d.ts.map +1 -1
- package/dist/parsing/functions/function_factory.js +12 -11
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/functions/function_metadata.d.ts +53 -24
- package/dist/parsing/functions/function_metadata.d.ts.map +1 -1
- package/dist/parsing/functions/function_metadata.js +55 -45
- package/dist/parsing/functions/function_metadata.js.map +1 -1
- package/dist/parsing/functions/predicate_function.d.ts +1 -1
- package/dist/parsing/functions/predicate_function.d.ts.map +1 -1
- package/dist/parsing/functions/predicate_function.js +1 -1
- package/dist/parsing/functions/predicate_function.js.map +1 -1
- package/dist/parsing/operations/load.js +1 -1
- package/dist/parsing/operations/load.js.map +1 -1
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +1 -2
- package/dist/parsing/parser.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/misc/apps/RAG/package.json +1 -2
- package/misc/apps/RAG/src/components/ChatContainer.tsx +33 -6
- package/misc/apps/RAG/src/components/ChatMessage.css +24 -0
- package/misc/apps/RAG/src/components/ChatMessage.tsx +51 -2
- package/misc/apps/RAG/src/components/FlowQueryAgent.ts +566 -286
- package/misc/apps/RAG/src/plugins/index.ts +3 -1
- package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +6 -5
- package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +3 -3
- package/misc/apps/RAG/src/plugins/loaders/Form.ts +5 -5
- package/misc/apps/RAG/src/plugins/loaders/Llm.ts +14 -14
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +5 -5
- package/misc/apps/RAG/src/plugins/loaders/Table.ts +4 -4
- package/misc/apps/RAG/src/plugins/loaders/Weather.ts +126 -0
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +4 -0
- package/package.json +1 -1
- package/src/parsing/functions/aggregate_function.ts +1 -1
- package/src/parsing/functions/async_function.ts +5 -50
- package/src/parsing/functions/function.ts +2 -2
- package/src/parsing/functions/function_factory.ts +18 -9
- package/src/parsing/functions/function_metadata.ts +55 -47
- package/src/parsing/functions/predicate_function.ts +2 -2
- package/src/parsing/operations/load.ts +1 -1
- package/src/parsing/parser.ts +2 -1
- package/tests/extensibility.test.ts +22 -22
- package/tests/parsing/parser.test.ts +2 -2
- package/misc/apps/RAG/.env.example +0 -14
|
@@ -78,19 +78,9 @@ export type AsyncDataProvider = (...args: any[]) => AsyncGenerator<any, void, un
|
|
|
78
78
|
class FunctionRegistry {
|
|
79
79
|
private static metadata: Map<string, FunctionMetadata> = new Map<string, FunctionMetadata>();
|
|
80
80
|
private static factories: Map<string, () => any> = new Map<string, () => any>();
|
|
81
|
-
private static asyncProviders: Map<string, AsyncDataProvider> = new Map<string, AsyncDataProvider>();
|
|
82
|
-
|
|
83
|
-
/** Registers an async data provider class. */
|
|
84
|
-
static registerAsync<T extends new (...args: any[]) => any>(constructor: T, options: FunctionDefOptions): void {
|
|
85
|
-
const displayName: string = constructor.name;
|
|
86
|
-
const registryKey: string = displayName.toLowerCase();
|
|
87
|
-
|
|
88
|
-
this.metadata.set(registryKey, { name: displayName, ...options });
|
|
89
|
-
this.asyncProviders.set(registryKey, (...args: any[]) => new constructor().fetch(...args));
|
|
90
|
-
}
|
|
91
81
|
|
|
92
82
|
/** Registers a regular function class. */
|
|
93
|
-
static
|
|
83
|
+
static register<T extends new (...args: any[]) => any>(constructor: T, options: FunctionDefOptions): void {
|
|
94
84
|
const instance: any = new constructor();
|
|
95
85
|
const displayName: string = (instance.name?.toLowerCase() || constructor.name.toLowerCase());
|
|
96
86
|
const registryKey: string = options.category ? `${displayName}:${options.category}` : displayName;
|
|
@@ -121,10 +111,6 @@ class FunctionRegistry {
|
|
|
121
111
|
if (category) return this.factories.get(`${lowerName}:${category}`);
|
|
122
112
|
return this.factories.get(lowerName);
|
|
123
113
|
}
|
|
124
|
-
|
|
125
|
-
static getAsyncProvider(name: string): AsyncDataProvider | undefined {
|
|
126
|
-
return this.asyncProviders.get(name.toLowerCase());
|
|
127
|
-
}
|
|
128
114
|
}
|
|
129
115
|
|
|
130
116
|
/**
|
|
@@ -137,45 +123,74 @@ export type FunctionDefOptions = Omit<FunctionMetadata, 'name'>;
|
|
|
137
123
|
* The function name is derived from the class's constructor call to super() for regular functions,
|
|
138
124
|
* or from the class name for async providers.
|
|
139
125
|
*
|
|
140
|
-
* For async providers (category: "async"), the class must have a `
|
|
141
|
-
* an AsyncGenerator.
|
|
142
|
-
* (first letter lowercased).
|
|
126
|
+
* For async providers (category: "async"), the class must have a `generate` method that returns
|
|
127
|
+
* an AsyncGenerator. This allows the function to be used as a data source in LOAD operations.
|
|
143
128
|
*
|
|
144
129
|
* @param options - Function metadata (excluding name)
|
|
145
130
|
* @returns Class decorator
|
|
146
131
|
*
|
|
147
132
|
* @example
|
|
148
133
|
* ```typescript
|
|
149
|
-
* //
|
|
134
|
+
* // Scalar function example
|
|
150
135
|
* @FunctionDef({
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
136
|
+
* description: "Adds two numbers",
|
|
137
|
+
* category: "scalar",
|
|
138
|
+
* parameters: [
|
|
139
|
+
* { name: "a", description: "First number", type: "number" },
|
|
140
|
+
* { name: "b", description: "Second number", type: "number" }
|
|
141
|
+
* ],
|
|
142
|
+
* output: { description: "Sum of a and b", type: "number" },
|
|
143
|
+
* examples: ["ADD(2, 3) // returns 5"]
|
|
156
144
|
* })
|
|
157
|
-
* class
|
|
158
|
-
*
|
|
159
|
-
*
|
|
145
|
+
* class AddFunction extends Function {
|
|
146
|
+
* constructor() {
|
|
147
|
+
* super("add");
|
|
148
|
+
* }
|
|
149
|
+
* public execute(a: number, b: number): number {
|
|
150
|
+
* return a + b;
|
|
151
|
+
* }
|
|
152
|
+
* }
|
|
153
|
+
* // Aggregate function example
|
|
160
154
|
* @FunctionDef({
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
155
|
+
* description: "Calculates the average of a list of numbers",
|
|
156
|
+
* category: "aggregate",
|
|
157
|
+
* parameters: [
|
|
158
|
+
* { name: "values", description: "Array of numbers", type: "array", items: { type: "number" } }
|
|
159
|
+
* ],
|
|
160
|
+
* output: { description: "Average value", type: "number" },
|
|
161
|
+
* examples: ["AVERAGE([1, 2, 3, 4, 5]) // returns 3"]
|
|
166
162
|
* })
|
|
167
|
-
* class
|
|
168
|
-
*
|
|
163
|
+
* class AverageFunction extends AggregateFunction {
|
|
164
|
+
* constructor() {
|
|
165
|
+
* super("average");
|
|
166
|
+
* }
|
|
167
|
+
* public execute(values: number[]): number {
|
|
168
|
+
* const sum = values.reduce((acc, val) => acc + val, 0);
|
|
169
|
+
* return sum / values.length;
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
* // Async data provider example
|
|
173
|
+
* @FunctionDef({
|
|
174
|
+
* description: "Fetches data from an external API",
|
|
175
|
+
* category: "async",
|
|
176
|
+
* parameters: [
|
|
177
|
+
* { name: "endpoint", description: "API endpoint URL", type: "string" }
|
|
178
|
+
* ],
|
|
179
|
+
* output: { description: "Data object", type: "object" },
|
|
180
|
+
* examples: ["MyAsyncDataProvider('https://api.example.com/data')"]
|
|
181
|
+
* })
|
|
182
|
+
* class MyAsyncDataProvider extends AsyncFunction {
|
|
183
|
+
* public async *generate(endpoint: string): AsyncGenerator<any> {
|
|
184
|
+
* const response = await fetch(endpoint);
|
|
185
|
+
* const data = await response.json();
|
|
186
|
+
* for (const item of data) {
|
|
187
|
+
* yield item;
|
|
188
|
+
* }
|
|
169
189
|
* }
|
|
170
|
-
* ```
|
|
171
190
|
*/
|
|
172
191
|
export function FunctionDef(options: FunctionDefOptions) {
|
|
173
192
|
return function <T extends new (...args: any[]) => any>(constructor: T): T {
|
|
174
|
-
|
|
175
|
-
FunctionRegistry.registerAsync(constructor, options);
|
|
176
|
-
} else {
|
|
177
|
-
FunctionRegistry.registerFunction(constructor, options);
|
|
178
|
-
}
|
|
193
|
+
FunctionRegistry.register(constructor, options);
|
|
179
194
|
return constructor;
|
|
180
195
|
};
|
|
181
196
|
}
|
|
@@ -200,10 +215,3 @@ export function getRegisteredFunctionFactory(name: string, category?: string): (
|
|
|
200
215
|
export function getFunctionMetadata(name: string, category?: string): FunctionMetadata | undefined {
|
|
201
216
|
return FunctionRegistry.getMetadata(name, category);
|
|
202
217
|
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Gets a registered async data provider by name.
|
|
206
|
-
*/
|
|
207
|
-
export function getRegisteredAsyncProvider(name: string): AsyncDataProvider | undefined {
|
|
208
|
-
return FunctionRegistry.getAsyncProvider(name);
|
|
209
|
-
}
|
|
@@ -8,9 +8,9 @@ class PredicateFunction extends ASTNode {
|
|
|
8
8
|
private _name: string;
|
|
9
9
|
protected _valueHolder: ValueHolder = new ValueHolder();
|
|
10
10
|
|
|
11
|
-
constructor(name
|
|
11
|
+
constructor(name?: string) {
|
|
12
12
|
super();
|
|
13
|
-
this._name = name;
|
|
13
|
+
this._name = name || this.constructor.name;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
public get name(): string {
|
|
@@ -87,7 +87,7 @@ class Load extends Operation {
|
|
|
87
87
|
*/
|
|
88
88
|
private async loadFromFunction(): Promise<void> {
|
|
89
89
|
const asyncFunc = this.asyncFunction!;
|
|
90
|
-
for await (const item of asyncFunc.
|
|
90
|
+
for await (const item of asyncFunc.generate()) {
|
|
91
91
|
this._value = item;
|
|
92
92
|
await this.next?.run();
|
|
93
93
|
}
|
package/src/parsing/parser.ts
CHANGED
|
@@ -597,7 +597,7 @@ class Parser extends BaseParser {
|
|
|
597
597
|
if(!this.peek()?.isLeftParenthesis()) {
|
|
598
598
|
return null;
|
|
599
599
|
}
|
|
600
|
-
const asyncFunc =
|
|
600
|
+
const asyncFunc = FunctionFactory.createAsync(this.token.value);
|
|
601
601
|
this.setNextToken(); // skip function name
|
|
602
602
|
this.setNextToken(); // skip left parenthesis
|
|
603
603
|
this.skipWhitespaceAndComments();
|
|
@@ -609,6 +609,7 @@ class Parser extends BaseParser {
|
|
|
609
609
|
this.setNextToken();
|
|
610
610
|
return asyncFunc;
|
|
611
611
|
}
|
|
612
|
+
|
|
612
613
|
private parsePredicateFunction(): PredicateFunction | null {
|
|
613
614
|
if(!this.ahead([Token.IDENTIFIER(""), Token.LEFT_PARENTHESIS, Token.IDENTIFIER(""), Token.IN])) {
|
|
614
615
|
return null;
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
FunctionCategory
|
|
13
13
|
} from "../src/extensibility";
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
getFunctionMetadata,
|
|
16
|
+
getRegisteredFunctionFactory
|
|
17
17
|
} from "../src/parsing/functions/function_metadata";
|
|
18
18
|
|
|
19
19
|
describe("Extensibility API Exports", () => {
|
|
@@ -216,8 +216,8 @@ describe("FunctionDef Decorator", () => {
|
|
|
216
216
|
],
|
|
217
217
|
output: { description: "Data object", type: "object" }
|
|
218
218
|
})
|
|
219
|
-
class Simple {
|
|
220
|
-
async *
|
|
219
|
+
class Simple extends AsyncFunction {
|
|
220
|
+
public async *generate(count: number = 1): AsyncGenerator<any> {
|
|
221
221
|
for (let i = 0; i < count; i++) {
|
|
222
222
|
yield { id: i, data: `item${i}` };
|
|
223
223
|
}
|
|
@@ -225,9 +225,9 @@ describe("FunctionDef Decorator", () => {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// Verify the decorated class still works correctly
|
|
228
|
-
const loader = new Simple();
|
|
228
|
+
const loader = new Simple("simple");
|
|
229
229
|
const results: any[] = [];
|
|
230
|
-
for await (const item of loader.
|
|
230
|
+
for await (const item of loader.generate(2)) {
|
|
231
231
|
results.push(item);
|
|
232
232
|
}
|
|
233
233
|
expect(results.length).toBe(2);
|
|
@@ -235,14 +235,14 @@ describe("FunctionDef Decorator", () => {
|
|
|
235
235
|
expect(results[1]).toEqual({ id: 1, data: "item1" });
|
|
236
236
|
|
|
237
237
|
// Verify the async provider was registered
|
|
238
|
-
const provider =
|
|
238
|
+
const provider = getRegisteredFunctionFactory("simple", "async");
|
|
239
239
|
expect(provider).toBeDefined();
|
|
240
240
|
expect(typeof provider).toBe("function");
|
|
241
241
|
|
|
242
242
|
// Verify the metadata was registered
|
|
243
|
-
const metadata = getFunctionMetadata("simple");
|
|
243
|
+
const metadata = getFunctionMetadata("simple", "async");
|
|
244
244
|
expect(metadata).toBeDefined();
|
|
245
|
-
expect(metadata?.name).toBe("
|
|
245
|
+
expect(metadata?.name).toBe("simple");
|
|
246
246
|
expect(metadata?.category).toBe("async");
|
|
247
247
|
expect(metadata?.description).toBe("Test async provider for extensibility");
|
|
248
248
|
});
|
|
@@ -540,17 +540,17 @@ describe("Plugin Functions Integration with FlowQuery", () => {
|
|
|
540
540
|
description: "Provides example data for testing",
|
|
541
541
|
category: "async",
|
|
542
542
|
parameters: [],
|
|
543
|
-
output: { description: "Example data
|
|
543
|
+
output: { description: "Example data o.bject", type: "object" }
|
|
544
544
|
})
|
|
545
|
-
class GetExampleData {
|
|
546
|
-
async *
|
|
545
|
+
class GetExampleData extends AsyncFunction {
|
|
546
|
+
public async *generate(): AsyncGenerator<any> {
|
|
547
547
|
yield { id: 1, name: "Alice" };
|
|
548
548
|
yield { id: 2, name: "Bob" };
|
|
549
549
|
}
|
|
550
550
|
}
|
|
551
551
|
|
|
552
552
|
// Verify registration worked
|
|
553
|
-
expect(
|
|
553
|
+
expect(getRegisteredFunctionFactory("getExampleData", "async")).toBeDefined();
|
|
554
554
|
|
|
555
555
|
// Use the async provider in a FlowQuery statement
|
|
556
556
|
const runner = new Runner("LOAD JSON FROM getExampleData() AS data RETURN data.id AS id, data.name AS name");
|
|
@@ -568,22 +568,22 @@ describe("Plugin Functions Integration with FlowQuery", () => {
|
|
|
568
568
|
parameters: [],
|
|
569
569
|
output: { description: "Test data", type: "object" }
|
|
570
570
|
})
|
|
571
|
-
class MixedCaseFunc {
|
|
572
|
-
async *
|
|
571
|
+
class MixedCaseFunc extends AsyncFunction {
|
|
572
|
+
public async *generate(): AsyncGenerator<any> {
|
|
573
573
|
yield { value: 42 };
|
|
574
574
|
}
|
|
575
575
|
}
|
|
576
576
|
|
|
577
577
|
// Verify registration works with different casings
|
|
578
|
-
expect(
|
|
579
|
-
expect(
|
|
580
|
-
expect(
|
|
581
|
-
expect(
|
|
578
|
+
expect(getRegisteredFunctionFactory("MixedCaseFunc", "async")).toBeDefined();
|
|
579
|
+
expect(getRegisteredFunctionFactory("mixedcasefunc", "async")).toBeDefined();
|
|
580
|
+
expect(getRegisteredFunctionFactory("MIXEDCASEFUNC", "async")).toBeDefined();
|
|
581
|
+
expect(getRegisteredFunctionFactory("mIxEdCaSeFuNc", "async")).toBeDefined();
|
|
582
582
|
|
|
583
583
|
// Verify metadata lookup is case-insensitive
|
|
584
|
-
expect(getFunctionMetadata("MixedCaseFunc")).toBeDefined();
|
|
585
|
-
expect(getFunctionMetadata("mixedcasefunc")).toBeDefined();
|
|
586
|
-
expect(getFunctionMetadata("MIXEDCASEFUNC")).toBeDefined();
|
|
584
|
+
expect(getFunctionMetadata("MixedCaseFunc", "async")).toBeDefined();
|
|
585
|
+
expect(getFunctionMetadata("mixedcasefunc", "async")).toBeDefined();
|
|
586
|
+
expect(getFunctionMetadata("MIXEDCASEFUNC", "async")).toBeDefined();
|
|
587
587
|
|
|
588
588
|
// Test using different casings in FlowQuery statements
|
|
589
589
|
const runner1 = new Runner("LOAD JSON FROM mixedcasefunc() AS d RETURN d.value AS v");
|
|
@@ -17,12 +17,12 @@ test('Test Parser', () => {
|
|
|
17
17
|
|
|
18
18
|
test('Test Parser with function', () => {
|
|
19
19
|
const parser = new Parser();
|
|
20
|
-
const ast = parser.parse('RETURN
|
|
20
|
+
const ast = parser.parse('RETURN rand()');
|
|
21
21
|
expect(ast.print()).toBe(
|
|
22
22
|
'ASTNode\n' +
|
|
23
23
|
'- Return\n' +
|
|
24
24
|
'-- Expression\n' +
|
|
25
|
-
'--- Function (
|
|
25
|
+
'--- Function (rand)'
|
|
26
26
|
);
|
|
27
27
|
});
|
|
28
28
|
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# OpenAI API Configuration
|
|
2
|
-
# Copy this file to .env and fill in your values
|
|
3
|
-
|
|
4
|
-
# Your OpenAI API key (required)
|
|
5
|
-
OPENAI_API_KEY=sk-your-api-key-here
|
|
6
|
-
|
|
7
|
-
# Optional: OpenAI Organization ID
|
|
8
|
-
OPENAI_ORGANIZATION_ID=org-your-org-id
|
|
9
|
-
|
|
10
|
-
# Optional: Default model
|
|
11
|
-
OPENAI_MODEL=gpt-4o-mini
|
|
12
|
-
|
|
13
|
-
# Note: These values are read at build time and used as defaults
|
|
14
|
-
# when localStorage is empty. Changes require rebuilding the app.
|