flowquery 1.0.6 → 1.0.7
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 +30 -138
- package/dist/compute/runner.d.ts +1 -22
- package/dist/compute/runner.d.ts.map +1 -1
- package/dist/compute/runner.js.map +1 -1
- package/dist/extensibility.d.ts +28 -2
- package/dist/extensibility.d.ts.map +1 -1
- package/dist/extensibility.js +39 -15
- package/dist/extensibility.js.map +1 -1
- package/dist/flowquery.min.js +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +0 -80
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.d.ts +3 -3
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +0 -80
- package/dist/index.node.js.map +1 -1
- package/dist/parsing/functions/function_factory.d.ts +3 -80
- package/dist/parsing/functions/function_factory.d.ts.map +1 -1
- package/dist/parsing/functions/function_factory.js +8 -127
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/functions/function_metadata.d.ts +32 -22
- package/dist/parsing/functions/function_metadata.d.ts.map +1 -1
- package/dist/parsing/functions/function_metadata.js +53 -1
- package/dist/parsing/functions/function_metadata.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 -1
- package/misc/apps/RAG/src/plugins/index.ts +29 -33
- package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +28 -32
- package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +29 -33
- package/misc/apps/RAG/src/plugins/loaders/Llm.ts +55 -59
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +61 -71
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +8 -8
- package/package.json +1 -1
- package/src/compute/runner.ts +1 -26
- package/src/extensibility.ts +38 -2
- package/src/index.browser.ts +2 -88
- package/src/index.node.ts +3 -92
- package/src/parsing/functions/function_factory.ts +13 -154
- package/src/parsing/functions/function_metadata.ts +68 -25
- package/tests/extensibility.test.ts +563 -0
- package/dist/parsing/functions/extensibility/index.d.ts +0 -37
- package/dist/parsing/functions/extensibility/index.d.ts.map +0 -1
- package/dist/parsing/functions/extensibility/index.js +0 -50
- package/dist/parsing/functions/extensibility/index.js.map +0 -1
- package/misc/apps/RAG/src/plugins/PluginRegistry.ts +0 -136
- package/misc/apps/RAG/src/plugins/types.ts +0 -52
- package/src/parsing/functions/extensibility/index.ts +0 -54
- package/tests/parsing/function_plugins.test.ts +0 -369
|
@@ -6,13 +6,39 @@
|
|
|
6
6
|
* RETURN fact.text
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { FunctionDef } from 'flowquery/extensibility';
|
|
10
10
|
|
|
11
11
|
const CAT_FACTS_API = 'https://catfact.ninja/facts';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* CatFacts loader class - fetches random cat facts from the Cat Facts API.
|
|
15
15
|
*/
|
|
16
|
+
@FunctionDef({
|
|
17
|
+
isAsyncProvider: true,
|
|
18
|
+
description: 'Fetches random cat facts from the Cat Facts API (catfact.ninja)',
|
|
19
|
+
category: 'examples',
|
|
20
|
+
parameters: [
|
|
21
|
+
{
|
|
22
|
+
name: 'count',
|
|
23
|
+
description: 'Number of cat facts to fetch',
|
|
24
|
+
type: 'number',
|
|
25
|
+
required: false,
|
|
26
|
+
default: 1
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
output: {
|
|
30
|
+
description: 'Cat fact object',
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
text: { description: 'The cat fact text', type: 'string' },
|
|
34
|
+
length: { description: 'Length of the fact text', type: 'number' }
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
examples: [
|
|
38
|
+
"LOAD JSON FROM catFacts() AS fact RETURN fact.text",
|
|
39
|
+
"LOAD JSON FROM catFacts(5) AS fact RETURN fact.text, fact.length AS length"
|
|
40
|
+
]
|
|
41
|
+
})
|
|
16
42
|
export class CatFactsLoader {
|
|
17
43
|
private readonly apiUrl: string;
|
|
18
44
|
|
|
@@ -46,34 +72,4 @@ export class CatFactsLoader {
|
|
|
46
72
|
}
|
|
47
73
|
}
|
|
48
74
|
|
|
49
|
-
export
|
|
50
|
-
name: 'catFacts',
|
|
51
|
-
provider: (count: number = 1) => new CatFactsLoader().fetch(count),
|
|
52
|
-
metadata: {
|
|
53
|
-
description: 'Fetches random cat facts from the Cat Facts API (catfact.ninja)',
|
|
54
|
-
category: 'examples',
|
|
55
|
-
parameters: [
|
|
56
|
-
{
|
|
57
|
-
name: 'count',
|
|
58
|
-
description: 'Number of cat facts to fetch',
|
|
59
|
-
type: 'number',
|
|
60
|
-
required: false,
|
|
61
|
-
default: 1
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
output: {
|
|
65
|
-
description: 'Cat fact object',
|
|
66
|
-
type: 'object',
|
|
67
|
-
properties: {
|
|
68
|
-
text: { description: 'The cat fact text', type: 'string' },
|
|
69
|
-
length: { description: 'Length of the fact text', type: 'number' }
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
examples: [
|
|
73
|
-
"LOAD JSON FROM catFacts() AS fact RETURN fact.text",
|
|
74
|
-
"LOAD JSON FROM catFacts(5) AS fact RETURN fact.text, fact.length AS length"
|
|
75
|
-
]
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export default catFactsPlugin;
|
|
75
|
+
export default CatFactsLoader;
|
|
@@ -6,11 +6,38 @@
|
|
|
6
6
|
* RETURN item.name, item.value
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { FunctionDef } from 'flowquery/extensibility';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* FetchJson loader class - fetches JSON data from a URL and yields items.
|
|
13
13
|
*/
|
|
14
|
+
@FunctionDef({
|
|
15
|
+
isAsyncProvider: true,
|
|
16
|
+
description: 'Fetches JSON data from a URL. If the response is an array, yields each item individually.',
|
|
17
|
+
category: 'data',
|
|
18
|
+
parameters: [
|
|
19
|
+
{
|
|
20
|
+
name: 'url',
|
|
21
|
+
description: 'The URL to fetch JSON from',
|
|
22
|
+
type: 'string',
|
|
23
|
+
required: true
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'options',
|
|
27
|
+
description: 'Optional fetch options (headers, method, etc.)',
|
|
28
|
+
type: 'object',
|
|
29
|
+
required: false
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
output: {
|
|
33
|
+
description: 'JSON data items',
|
|
34
|
+
type: 'object'
|
|
35
|
+
},
|
|
36
|
+
examples: [
|
|
37
|
+
"LOAD JSON FROM fetchJson('https://api.example.com/users') AS user RETURN user.name",
|
|
38
|
+
"LOAD JSON FROM fetchJson('https://api.example.com/data') AS item RETURN item WHERE item.active = true"
|
|
39
|
+
]
|
|
40
|
+
})
|
|
14
41
|
export class FetchJsonLoader {
|
|
15
42
|
/**
|
|
16
43
|
* Fetches JSON data from a URL and yields each item if array, or the object itself.
|
|
@@ -37,35 +64,4 @@ export class FetchJsonLoader {
|
|
|
37
64
|
}
|
|
38
65
|
}
|
|
39
66
|
|
|
40
|
-
export
|
|
41
|
-
name: 'fetchJson',
|
|
42
|
-
provider: (url: string, options?: RequestInit) => new FetchJsonLoader().fetch(url, options),
|
|
43
|
-
metadata: {
|
|
44
|
-
description: 'Fetches JSON data from a URL. If the response is an array, yields each item individually.',
|
|
45
|
-
category: 'data',
|
|
46
|
-
parameters: [
|
|
47
|
-
{
|
|
48
|
-
name: 'url',
|
|
49
|
-
description: 'The URL to fetch JSON from',
|
|
50
|
-
type: 'string',
|
|
51
|
-
required: true
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'options',
|
|
55
|
-
description: 'Optional fetch options (headers, method, etc.)',
|
|
56
|
-
type: 'object',
|
|
57
|
-
required: false
|
|
58
|
-
}
|
|
59
|
-
],
|
|
60
|
-
output: {
|
|
61
|
-
description: 'JSON data items',
|
|
62
|
-
type: 'object'
|
|
63
|
-
},
|
|
64
|
-
examples: [
|
|
65
|
-
"LOAD JSON FROM fetchJson('https://api.example.com/users') AS user RETURN user.name",
|
|
66
|
-
"LOAD JSON FROM fetchJson('https://api.example.com/data') AS item RETURN item WHERE item.active = true"
|
|
67
|
-
]
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
export default fetchJsonPlugin;
|
|
67
|
+
export default FetchJsonLoader;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* console.log(response.choices[0].message.content);
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { FunctionDef } from 'flowquery/extensibility';
|
|
20
20
|
|
|
21
21
|
// Default configuration - can be overridden via options
|
|
22
22
|
const DEFAULT_CONFIG = {
|
|
@@ -80,6 +80,59 @@ export interface LlmResponse {
|
|
|
80
80
|
/**
|
|
81
81
|
* LLM Loader class - calls OpenAI-compatible APIs for chat completions.
|
|
82
82
|
*/
|
|
83
|
+
@FunctionDef({
|
|
84
|
+
isAsyncProvider: true,
|
|
85
|
+
description: 'Calls OpenAI-compatible chat completion APIs. Supports GPT models and any OpenAI-compatible endpoint.',
|
|
86
|
+
category: 'ai',
|
|
87
|
+
parameters: [
|
|
88
|
+
{
|
|
89
|
+
name: 'prompt',
|
|
90
|
+
description: 'The user prompt to send to the LLM',
|
|
91
|
+
type: 'string',
|
|
92
|
+
required: true,
|
|
93
|
+
example: 'What is the capital of France?'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'options',
|
|
97
|
+
description: 'Optional configuration for the LLM request',
|
|
98
|
+
type: 'object',
|
|
99
|
+
required: false,
|
|
100
|
+
properties: {
|
|
101
|
+
apiKey: { description: 'OpenAI API key', type: 'string' },
|
|
102
|
+
apiUrl: { description: 'API endpoint URL (defaults to OpenAI chat completions)', type: 'string' },
|
|
103
|
+
model: { description: 'Model to use (defaults to gpt-4o-mini)', type: 'string' },
|
|
104
|
+
temperature: { description: 'Sampling temperature 0-2 (defaults to 0.7)', type: 'number' },
|
|
105
|
+
maxTokens: { description: 'Maximum tokens to generate', type: 'number' },
|
|
106
|
+
systemPrompt: { description: 'System prompt to set context', type: 'string' },
|
|
107
|
+
messages: { description: 'Additional conversation messages', type: 'array' },
|
|
108
|
+
organizationId: { description: 'OpenAI organization ID', type: 'string' },
|
|
109
|
+
headers: { description: 'Additional request headers', type: 'object' },
|
|
110
|
+
stream: { description: 'Enable streaming response', type: 'boolean' },
|
|
111
|
+
additionalParams: { description: 'Additional API parameters', type: 'object' }
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
output: {
|
|
116
|
+
description: 'OpenAI chat completion response',
|
|
117
|
+
type: 'object',
|
|
118
|
+
properties: {
|
|
119
|
+
id: { description: 'Unique identifier for the completion', type: 'string' },
|
|
120
|
+
model: { description: 'Model used for completion', type: 'string' },
|
|
121
|
+
choices: {
|
|
122
|
+
description: 'Array of completion choices',
|
|
123
|
+
type: 'array',
|
|
124
|
+
example: [{ message: { role: 'assistant', content: 'Paris is the capital of France.' } }]
|
|
125
|
+
},
|
|
126
|
+
usage: { description: 'Token usage statistics', type: 'object' }
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
examples: [
|
|
130
|
+
"LOAD JSON FROM llm('What is 2+2?') AS response RETURN response.choices[0].message.content",
|
|
131
|
+
"LOAD JSON FROM llm('Translate to French: Hello', { model: 'gpt-4o', temperature: 0.3 }) AS response RETURN response.choices[0].message.content",
|
|
132
|
+
"LOAD JSON FROM llm('Write a haiku', { systemPrompt: 'You are a poet' }) AS response RETURN response.choices[0].message.content"
|
|
133
|
+
],
|
|
134
|
+
notes: 'Requires API key configured in Settings or passed as apiKey option. Works with any OpenAI-compatible API by setting the apiUrl option.'
|
|
135
|
+
})
|
|
83
136
|
export class LlmLoader {
|
|
84
137
|
private readonly defaultOptions: Partial<LlmOptions>;
|
|
85
138
|
|
|
@@ -381,61 +434,4 @@ export function extractContent(response: LlmResponse): string {
|
|
|
381
434
|
return LlmLoader.extractContent(response);
|
|
382
435
|
}
|
|
383
436
|
|
|
384
|
-
export
|
|
385
|
-
name: 'llm',
|
|
386
|
-
provider: (prompt: string, options?: LlmOptions) => new LlmLoader().fetch(prompt, options),
|
|
387
|
-
metadata: {
|
|
388
|
-
description: 'Calls OpenAI-compatible chat completion APIs. Supports GPT models and any OpenAI-compatible endpoint.',
|
|
389
|
-
category: 'ai',
|
|
390
|
-
parameters: [
|
|
391
|
-
{
|
|
392
|
-
name: 'prompt',
|
|
393
|
-
description: 'The user prompt to send to the LLM',
|
|
394
|
-
type: 'string',
|
|
395
|
-
required: true,
|
|
396
|
-
example: 'What is the capital of France?'
|
|
397
|
-
},
|
|
398
|
-
{
|
|
399
|
-
name: 'options',
|
|
400
|
-
description: 'Optional configuration for the LLM request',
|
|
401
|
-
type: 'object',
|
|
402
|
-
required: false,
|
|
403
|
-
properties: {
|
|
404
|
-
apiKey: { description: 'OpenAI API key', type: 'string' },
|
|
405
|
-
apiUrl: { description: 'API endpoint URL (defaults to OpenAI chat completions)', type: 'string' },
|
|
406
|
-
model: { description: 'Model to use (defaults to gpt-4o-mini)', type: 'string' },
|
|
407
|
-
temperature: { description: 'Sampling temperature 0-2 (defaults to 0.7)', type: 'number' },
|
|
408
|
-
maxTokens: { description: 'Maximum tokens to generate', type: 'number' },
|
|
409
|
-
systemPrompt: { description: 'System prompt to set context', type: 'string' },
|
|
410
|
-
messages: { description: 'Additional conversation messages', type: 'array' },
|
|
411
|
-
organizationId: { description: 'OpenAI organization ID', type: 'string' },
|
|
412
|
-
headers: { description: 'Additional request headers', type: 'object' },
|
|
413
|
-
stream: { description: 'Enable streaming response', type: 'boolean' },
|
|
414
|
-
additionalParams: { description: 'Additional API parameters', type: 'object' }
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
],
|
|
418
|
-
output: {
|
|
419
|
-
description: 'OpenAI chat completion response',
|
|
420
|
-
type: 'object',
|
|
421
|
-
properties: {
|
|
422
|
-
id: { description: 'Unique identifier for the completion', type: 'string' },
|
|
423
|
-
model: { description: 'Model used for completion', type: 'string' },
|
|
424
|
-
choices: {
|
|
425
|
-
description: 'Array of completion choices',
|
|
426
|
-
type: 'array',
|
|
427
|
-
example: [{ message: { role: 'assistant', content: 'Paris is the capital of France.' } }]
|
|
428
|
-
},
|
|
429
|
-
usage: { description: 'Token usage statistics', type: 'object' }
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
examples: [
|
|
433
|
-
"LOAD JSON FROM llm('What is 2+2?') AS response RETURN response.choices[0].message.content",
|
|
434
|
-
"LOAD JSON FROM llm('Translate to French: Hello', { model: 'gpt-4o', temperature: 0.3 }) AS response RETURN response.choices[0].message.content",
|
|
435
|
-
"LOAD JSON FROM llm('Write a haiku', { systemPrompt: 'You are a poet' }) AS response RETURN response.choices[0].message.content"
|
|
436
|
-
],
|
|
437
|
-
notes: 'Requires API key configured in Settings or passed as apiKey option. Works with any OpenAI-compatible API by setting the apiUrl option.'
|
|
438
|
-
}
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
export default llmPlugin;
|
|
437
|
+
export default LlmLoader;
|
|
@@ -6,11 +6,40 @@
|
|
|
6
6
|
* RETURN user.name, user.email
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { FunctionDef } from 'flowquery/extensibility';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* MockUsers loader class - generates mock user data for testing.
|
|
13
13
|
*/
|
|
14
|
+
@FunctionDef({
|
|
15
|
+
isAsyncProvider: true,
|
|
16
|
+
description: 'Generates mock user data for testing purposes',
|
|
17
|
+
category: 'testing',
|
|
18
|
+
parameters: [
|
|
19
|
+
{
|
|
20
|
+
name: 'count',
|
|
21
|
+
description: 'Number of mock users to generate',
|
|
22
|
+
type: 'number',
|
|
23
|
+
required: false,
|
|
24
|
+
default: 5
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
output: {
|
|
28
|
+
description: 'Mock user object',
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
id: { description: 'User ID', type: 'number' },
|
|
32
|
+
name: { description: 'Full name', type: 'string' },
|
|
33
|
+
email: { description: 'Email address', type: 'string' },
|
|
34
|
+
age: { description: 'Age in years', type: 'number' },
|
|
35
|
+
active: { description: 'Whether user is active', type: 'boolean' }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
examples: [
|
|
39
|
+
"LOAD JSON FROM mockUsers(10) AS user RETURN user.name, user.email",
|
|
40
|
+
"LOAD JSON FROM mockUsers(20) AS user RETURN user WHERE user.active = true"
|
|
41
|
+
]
|
|
42
|
+
})
|
|
14
43
|
export class MockUsersLoader {
|
|
15
44
|
private readonly firstNames: string[];
|
|
16
45
|
private readonly lastNames: string[];
|
|
@@ -51,6 +80,36 @@ export class MockUsersLoader {
|
|
|
51
80
|
/**
|
|
52
81
|
* MockProducts loader class - generates mock product data for testing.
|
|
53
82
|
*/
|
|
83
|
+
@FunctionDef({
|
|
84
|
+
isAsyncProvider: true,
|
|
85
|
+
description: 'Generates mock product data for testing purposes',
|
|
86
|
+
category: 'testing',
|
|
87
|
+
parameters: [
|
|
88
|
+
{
|
|
89
|
+
name: 'count',
|
|
90
|
+
description: 'Number of mock products to generate',
|
|
91
|
+
type: 'number',
|
|
92
|
+
required: false,
|
|
93
|
+
default: 5
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
output: {
|
|
97
|
+
description: 'Mock product object',
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
id: { description: 'Product ID', type: 'number' },
|
|
101
|
+
name: { description: 'Product name', type: 'string' },
|
|
102
|
+
category: { description: 'Product category', type: 'string' },
|
|
103
|
+
price: { description: 'Price in dollars', type: 'number' },
|
|
104
|
+
inStock: { description: 'Whether product is in stock', type: 'boolean' },
|
|
105
|
+
rating: { description: 'Customer rating (0-5)', type: 'number' }
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
examples: [
|
|
109
|
+
"LOAD JSON FROM mockProducts(10) AS p RETURN p.name, p.price",
|
|
110
|
+
"LOAD JSON FROM mockProducts(50) AS p RETURN p WHERE p.category = 'Electronics'"
|
|
111
|
+
]
|
|
112
|
+
})
|
|
54
113
|
export class MockProductsLoader {
|
|
55
114
|
private readonly categories: string[];
|
|
56
115
|
private readonly adjectives: string[];
|
|
@@ -89,73 +148,4 @@ export class MockProductsLoader {
|
|
|
89
148
|
}
|
|
90
149
|
}
|
|
91
150
|
|
|
92
|
-
export
|
|
93
|
-
name: 'mockUsers',
|
|
94
|
-
provider: (count: number = 5) => new MockUsersLoader().fetch(count),
|
|
95
|
-
metadata: {
|
|
96
|
-
description: 'Generates mock user data for testing purposes',
|
|
97
|
-
category: 'testing',
|
|
98
|
-
parameters: [
|
|
99
|
-
{
|
|
100
|
-
name: 'count',
|
|
101
|
-
description: 'Number of mock users to generate',
|
|
102
|
-
type: 'number',
|
|
103
|
-
required: false,
|
|
104
|
-
default: 5
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
output: {
|
|
108
|
-
description: 'Mock user object',
|
|
109
|
-
type: 'object',
|
|
110
|
-
properties: {
|
|
111
|
-
id: { description: 'User ID', type: 'number' },
|
|
112
|
-
name: { description: 'Full name', type: 'string' },
|
|
113
|
-
email: { description: 'Email address', type: 'string' },
|
|
114
|
-
age: { description: 'Age in years', type: 'number' },
|
|
115
|
-
active: { description: 'Whether user is active', type: 'boolean' }
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
examples: [
|
|
119
|
-
"LOAD JSON FROM mockUsers(10) AS user RETURN user.name, user.email",
|
|
120
|
-
"LOAD JSON FROM mockUsers(20) AS user RETURN user WHERE user.active = true"
|
|
121
|
-
]
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export const mockProductsPlugin: AsyncLoaderPlugin = {
|
|
126
|
-
name: 'mockProducts',
|
|
127
|
-
provider: (count: number = 5) => new MockProductsLoader().fetch(count),
|
|
128
|
-
metadata: {
|
|
129
|
-
description: 'Generates mock product data for testing purposes',
|
|
130
|
-
category: 'testing',
|
|
131
|
-
parameters: [
|
|
132
|
-
{
|
|
133
|
-
name: 'count',
|
|
134
|
-
description: 'Number of mock products to generate',
|
|
135
|
-
type: 'number',
|
|
136
|
-
required: false,
|
|
137
|
-
default: 5
|
|
138
|
-
}
|
|
139
|
-
],
|
|
140
|
-
output: {
|
|
141
|
-
description: 'Mock product object',
|
|
142
|
-
type: 'object',
|
|
143
|
-
properties: {
|
|
144
|
-
id: { description: 'Product ID', type: 'number' },
|
|
145
|
-
name: { description: 'Product name', type: 'string' },
|
|
146
|
-
category: { description: 'Product category', type: 'string' },
|
|
147
|
-
price: { description: 'Price in dollars', type: 'number' },
|
|
148
|
-
inStock: { description: 'Whether product is in stock', type: 'boolean' },
|
|
149
|
-
rating: { description: 'Customer rating (0-5)', type: 'number' }
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
examples: [
|
|
153
|
-
"LOAD JSON FROM mockProducts(10) AS p RETURN p.name, p.price",
|
|
154
|
-
"LOAD JSON FROM mockProducts(50) AS p RETURN p WHERE p.category = 'Electronics'"
|
|
155
|
-
]
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
export const plugins = [mockUsersPlugin, mockProductsPlugin];
|
|
160
|
-
|
|
161
|
-
export default plugins;
|
|
151
|
+
export { MockUsersLoader as default };
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* available async data loaders and their metadata.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { FunctionMetadata, ParameterSchema, OutputSchema } from 'flowquery/extensibility';
|
|
12
|
+
import { getAllPluginMetadata, getAvailableLoaders } from '../plugins';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* FlowQuery language reference documentation.
|
|
@@ -171,7 +171,7 @@ export class FlowQuerySystemPrompt {
|
|
|
171
171
|
/**
|
|
172
172
|
* Format a plugin metadata into a readable documentation block.
|
|
173
173
|
*/
|
|
174
|
-
private static formatPluginDocumentation(plugin:
|
|
174
|
+
private static formatPluginDocumentation(plugin: FunctionMetadata): string {
|
|
175
175
|
const lines: string[] = [];
|
|
176
176
|
|
|
177
177
|
lines.push(`### \`${plugin.name}\``);
|
|
@@ -210,7 +210,7 @@ export class FlowQuerySystemPrompt {
|
|
|
210
210
|
/**
|
|
211
211
|
* Generate documentation for all available plugins.
|
|
212
212
|
*/
|
|
213
|
-
private static generatePluginDocumentation(plugins:
|
|
213
|
+
private static generatePluginDocumentation(plugins: FunctionMetadata[]): string {
|
|
214
214
|
if (plugins.length === 0) {
|
|
215
215
|
return 'No data loader plugins are currently available.';
|
|
216
216
|
}
|
|
@@ -218,7 +218,7 @@ export class FlowQuerySystemPrompt {
|
|
|
218
218
|
const sections: string[] = [];
|
|
219
219
|
|
|
220
220
|
// Group plugins by category
|
|
221
|
-
const byCategory = new Map<string,
|
|
221
|
+
const byCategory = new Map<string, FunctionMetadata[]>();
|
|
222
222
|
for (const plugin of plugins) {
|
|
223
223
|
const category = plugin.category || 'general';
|
|
224
224
|
if (!byCategory.has(category)) {
|
|
@@ -307,7 +307,7 @@ Now help the user with their request.`;
|
|
|
307
307
|
*/
|
|
308
308
|
public static generate(additionalContext?: string): string {
|
|
309
309
|
// Uses FlowQuery's introspection to get available async providers
|
|
310
|
-
const plugins =
|
|
310
|
+
const plugins = getAllPluginMetadata();
|
|
311
311
|
const pluginDocs = this.generatePluginDocumentation(plugins);
|
|
312
312
|
|
|
313
313
|
return this.buildSystemPrompt(pluginDocs, additionalContext);
|
|
@@ -346,7 +346,7 @@ You are now receiving the execution results. Your job is to:
|
|
|
346
346
|
* Useful for contexts where token count is a concern.
|
|
347
347
|
*/
|
|
348
348
|
public static getMinimalPrompt(): string {
|
|
349
|
-
const plugins =
|
|
349
|
+
const plugins = getAllPluginMetadata();
|
|
350
350
|
const pluginList = plugins.map(p => `- \`${p.name}\`: ${p.description}`).join('\n');
|
|
351
351
|
|
|
352
352
|
return `You are a FlowQuery assistant. Generate FlowQuery statements based on user requests.
|
|
@@ -369,7 +369,7 @@ Always wrap FlowQuery code in \`\`\`flowquery code blocks.`;
|
|
|
369
369
|
*/
|
|
370
370
|
public static async generateAsync(additionalContext?: string): Promise<string> {
|
|
371
371
|
// Use FlowQuery's functions() introspection to discover available loaders
|
|
372
|
-
const plugins = await
|
|
372
|
+
const plugins = await getAvailableLoaders();
|
|
373
373
|
const pluginDocs = this.generatePluginDocumentation(plugins);
|
|
374
374
|
|
|
375
375
|
return this.buildSystemPrompt(pluginDocs, additionalContext);
|
package/package.json
CHANGED
package/src/compute/runner.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Operation from "../parsing/operations/operation";
|
|
2
2
|
import Parser from "../parsing/parser";
|
|
3
|
-
import {
|
|
4
|
-
import { FunctionMetadata, RegisterFunctionOptions, RegisterAsyncProviderOptions } from "../parsing/functions/function_metadata";
|
|
3
|
+
import { FunctionMetadata } from "../parsing/functions/function_metadata";
|
|
5
4
|
import Function from "../parsing/functions/function";
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -21,30 +20,6 @@ class Runner {
|
|
|
21
20
|
private first: Operation;
|
|
22
21
|
private last: Operation;
|
|
23
22
|
|
|
24
|
-
/**
|
|
25
|
-
* Register a synchronous plugin function.
|
|
26
|
-
* Added dynamically in index.browser.ts / index.node.ts
|
|
27
|
-
*/
|
|
28
|
-
static registerFunction: (name: string, factoryOrOptions: FunctionCreator | RegisterFunctionOptions) => void;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Unregister a synchronous plugin function.
|
|
32
|
-
* Added dynamically in index.browser.ts / index.node.ts
|
|
33
|
-
*/
|
|
34
|
-
static unregisterFunction: (name: string) => void;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Register an async data provider function for use in LOAD operations.
|
|
38
|
-
* Added dynamically in index.browser.ts / index.node.ts
|
|
39
|
-
*/
|
|
40
|
-
static registerAsyncProvider: (name: string, providerOrOptions: AsyncDataProvider | RegisterAsyncProviderOptions) => void;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Unregister an async data provider function.
|
|
44
|
-
* Added dynamically in index.browser.ts / index.node.ts
|
|
45
|
-
*/
|
|
46
|
-
static unregisterAsyncProvider: (name: string) => void;
|
|
47
|
-
|
|
48
23
|
/**
|
|
49
24
|
* List all registered functions with their metadata.
|
|
50
25
|
* Added dynamically in index.browser.ts / index.node.ts
|
package/src/extensibility.ts
CHANGED
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* FlowQuery Extensibility API
|
|
3
3
|
*
|
|
4
|
-
* This module
|
|
4
|
+
* This module provides all the exports needed to create custom FlowQuery functions.
|
|
5
5
|
*
|
|
6
6
|
* @packageDocumentation
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { Function, FunctionDef } from 'flowquery/extensibility';
|
|
11
|
+
*
|
|
12
|
+
* @FunctionDef({
|
|
13
|
+
* description: "Converts a string to uppercase",
|
|
14
|
+
* category: "string",
|
|
15
|
+
* parameters: [{ name: "text", description: "String to convert", type: "string" }],
|
|
16
|
+
* output: { description: "Uppercase string", type: "string" }
|
|
17
|
+
* })
|
|
18
|
+
* class UpperCase extends Function {
|
|
19
|
+
* constructor() {
|
|
20
|
+
* super("uppercase");
|
|
21
|
+
* this._expectedParameterCount = 1;
|
|
22
|
+
* }
|
|
23
|
+
* public value(): string {
|
|
24
|
+
* return String(this.getChildren()[0].value()).toUpperCase();
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
7
28
|
*/
|
|
8
29
|
|
|
9
|
-
|
|
30
|
+
// Base function classes for creating custom functions
|
|
31
|
+
export { default as Function } from "./parsing/functions/function";
|
|
32
|
+
export { default as AggregateFunction } from "./parsing/functions/aggregate_function";
|
|
33
|
+
export { default as AsyncFunction } from "./parsing/functions/async_function";
|
|
34
|
+
export { default as PredicateFunction } from "./parsing/functions/predicate_function";
|
|
35
|
+
export { default as ReducerElement } from "./parsing/functions/reducer_element";
|
|
36
|
+
|
|
37
|
+
// Decorator and metadata types for function registration
|
|
38
|
+
export {
|
|
39
|
+
FunctionDef,
|
|
40
|
+
FunctionMetadata,
|
|
41
|
+
FunctionDefOptions,
|
|
42
|
+
ParameterSchema,
|
|
43
|
+
OutputSchema,
|
|
44
|
+
FunctionCategory
|
|
45
|
+
} from "./parsing/functions/function_metadata";
|