flowquery 1.0.24 → 1.0.26
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/.github/workflows/release.yml +1 -0
- package/.husky/pre-commit +3 -2
- package/dist/flowquery.min.js +1 -1
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +1 -0
- package/dist/parsing/parser.js.map +1 -1
- package/dist/tokenization/string_walker.d.ts.map +1 -1
- package/dist/tokenization/string_walker.js +13 -12
- package/dist/tokenization/string_walker.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-py/pyproject.toml +1 -1
- package/flowquery-py/src/parsing/parser.py +1 -0
- package/flowquery-py/src/tokenization/string_walker.py +1 -1
- package/flowquery-py/tests/compute/test_runner.py +26 -0
- package/flowquery-py/tests/parsing/test_parser.py +64 -0
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/jest.config.js +6 -9
- package/misc/apps/RAG/data/chats.json +302 -0
- package/misc/apps/RAG/data/emails.json +182 -0
- package/misc/apps/RAG/data/events.json +226 -0
- package/misc/apps/RAG/data/files.json +172 -0
- package/misc/apps/RAG/data/users.json +158 -0
- package/misc/apps/RAG/jest.config.js +21 -0
- package/misc/apps/RAG/package.json +9 -2
- package/misc/apps/RAG/src/App.tsx +5 -5
- package/misc/apps/RAG/src/components/ChatContainer.tsx +53 -124
- package/misc/apps/RAG/src/components/FlowQueryAgent.ts +151 -157
- package/misc/apps/RAG/src/components/index.ts +1 -1
- package/misc/apps/RAG/src/graph/index.ts +19 -0
- package/misc/apps/RAG/src/graph/initializeGraph.ts +254 -0
- package/misc/apps/RAG/src/index.tsx +25 -13
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +146 -231
- package/misc/apps/RAG/src/prompts/index.ts +4 -4
- package/misc/apps/RAG/src/tests/graph.test.ts +35 -0
- package/misc/apps/RAG/src/utils/FlowQueryExecutor.ts +20 -21
- package/misc/apps/RAG/src/utils/FlowQueryExtractor.ts +35 -30
- package/misc/apps/RAG/src/utils/Llm.ts +248 -0
- package/misc/apps/RAG/src/utils/index.ts +7 -4
- package/misc/apps/RAG/tsconfig.json +4 -3
- package/misc/apps/RAG/webpack.config.js +40 -40
- package/package.json +1 -1
- package/src/parsing/parser.ts +1 -0
- package/src/tokenization/string_walker.ts +19 -16
- package/tests/compute/runner.test.ts +1 -1
- package/tests/parsing/parser.test.ts +61 -0
- package/misc/apps/RAG/src/plugins/README.md +0 -139
- package/misc/apps/RAG/src/plugins/index.ts +0 -72
- package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +0 -70
- package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +0 -65
- package/misc/apps/RAG/src/plugins/loaders/Form.ts +0 -594
- package/misc/apps/RAG/src/plugins/loaders/Llm.ts +0 -450
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +0 -101
- package/misc/apps/RAG/src/plugins/loaders/Table.ts +0 -274
- package/misc/apps/RAG/src/plugins/loaders/Weather.ts +0 -138
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Table plugin - transforms tabular data into Adaptive Card format.
|
|
3
|
-
*
|
|
4
|
-
* Adaptive Cards are platform-agnostic UI snippets that can be rendered in
|
|
5
|
-
* Microsoft Teams, Outlook, Windows, and other applications.
|
|
6
|
-
*
|
|
7
|
-
* Usage in FlowQuery:
|
|
8
|
-
* // First collect data from an async provider, then pass to table:
|
|
9
|
-
* CALL mockUsers(5) YIELD id, name, email
|
|
10
|
-
* WITH collect({ id, name, email }) AS users
|
|
11
|
-
* CALL table(users, 'Users') YIELD type, body
|
|
12
|
-
*
|
|
13
|
-
* Note: Async providers cannot be nested as function arguments.
|
|
14
|
-
*/
|
|
15
|
-
import { AsyncFunction, FunctionDef } from "flowquery/extensibility";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Interface for Adaptive Card structure
|
|
19
|
-
*/
|
|
20
|
-
interface AdaptiveCard {
|
|
21
|
-
type: "AdaptiveCard";
|
|
22
|
-
$schema: string;
|
|
23
|
-
version: string;
|
|
24
|
-
body: AdaptiveCardElement[];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
interface AdaptiveCardElement {
|
|
28
|
-
type: string;
|
|
29
|
-
[key: string]: any;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface TableCell {
|
|
33
|
-
type: "TableCell";
|
|
34
|
-
items: AdaptiveCardElement[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface TableRow {
|
|
38
|
-
type: "TableRow";
|
|
39
|
-
cells: TableCell[];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Table class - transforms tabular data into an Adaptive Card table format.
|
|
44
|
-
*/
|
|
45
|
-
@FunctionDef({
|
|
46
|
-
description: "Transforms tabular data into an Adaptive Card JSON format with a table layout",
|
|
47
|
-
category: "async",
|
|
48
|
-
parameters: [
|
|
49
|
-
{
|
|
50
|
-
name: "data",
|
|
51
|
-
description: "Array of objects or async generator to display as a table",
|
|
52
|
-
type: "array",
|
|
53
|
-
required: true,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: "title",
|
|
57
|
-
description: "Optional title for the card",
|
|
58
|
-
type: "string",
|
|
59
|
-
required: false,
|
|
60
|
-
default: "Data Table",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
name: "columns",
|
|
64
|
-
description:
|
|
65
|
-
"Optional array of column names to include (defaults to all columns from first row)",
|
|
66
|
-
type: "array",
|
|
67
|
-
required: false,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
name: "maxRows",
|
|
71
|
-
description: "Maximum number of rows to display",
|
|
72
|
-
type: "number",
|
|
73
|
-
required: false,
|
|
74
|
-
default: 100,
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
output: {
|
|
78
|
-
description: "Adaptive Card JSON object",
|
|
79
|
-
type: "object",
|
|
80
|
-
properties: {
|
|
81
|
-
type: { description: 'Always "AdaptiveCard"', type: "string" },
|
|
82
|
-
$schema: { description: "Adaptive Card schema URL", type: "string" },
|
|
83
|
-
version: { description: "Adaptive Card version", type: "string" },
|
|
84
|
-
body: { description: "Card body elements including table", type: "array" },
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
examples: [
|
|
88
|
-
"CALL mockUsers(5) YIELD id, name, email WITH collect({ id, name, email }) AS users CALL table(users, 'User List') YIELD type, body",
|
|
89
|
-
"CALL mockProducts(10) YIELD name, price, category WITH collect({ name, price, category }) AS products CALL table(products, 'Products', ['name', 'price', 'category']) YIELD type, body",
|
|
90
|
-
],
|
|
91
|
-
})
|
|
92
|
-
export class Table extends AsyncFunction {
|
|
93
|
-
/**
|
|
94
|
-
* Transforms data into an Adaptive Card with table layout.
|
|
95
|
-
*
|
|
96
|
-
* @param data - Array or async iterable of objects
|
|
97
|
-
* @param title - Card title
|
|
98
|
-
* @param columns - Optional column names to include
|
|
99
|
-
* @param maxRows - Maximum rows to include
|
|
100
|
-
*/
|
|
101
|
-
async *generate(
|
|
102
|
-
data: any[] | AsyncIterable<any>,
|
|
103
|
-
title: string = "Data Table",
|
|
104
|
-
columns?: string[],
|
|
105
|
-
maxRows: number = 100
|
|
106
|
-
): AsyncGenerator<AdaptiveCard, void, unknown> {
|
|
107
|
-
// Collect data from array or async iterable
|
|
108
|
-
const rows: any[] = [];
|
|
109
|
-
|
|
110
|
-
if (Symbol.asyncIterator in Object(data)) {
|
|
111
|
-
for await (const item of data as AsyncIterable<any>) {
|
|
112
|
-
rows.push(item);
|
|
113
|
-
if (rows.length >= maxRows) break;
|
|
114
|
-
}
|
|
115
|
-
} else if (Array.isArray(data)) {
|
|
116
|
-
rows.push(...data.slice(0, maxRows));
|
|
117
|
-
} else {
|
|
118
|
-
// Single object
|
|
119
|
-
rows.push(data);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (rows.length === 0) {
|
|
123
|
-
yield this.createEmptyCard(title);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Determine columns from first row if not specified
|
|
128
|
-
const columnNames = columns || Object.keys(rows[0]);
|
|
129
|
-
|
|
130
|
-
yield this.createTableCard(title, columnNames, rows);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Creates an Adaptive Card with a table displaying the data.
|
|
135
|
-
* Uses ColumnSet/Column for better compatibility across renderers.
|
|
136
|
-
*/
|
|
137
|
-
private createTableCard(title: string, columnNames: string[], rows: any[]): AdaptiveCard {
|
|
138
|
-
const card: AdaptiveCard = {
|
|
139
|
-
type: "AdaptiveCard",
|
|
140
|
-
$schema: "http://adaptivecards.io/schemas/adaptive-card.json",
|
|
141
|
-
version: "1.3",
|
|
142
|
-
body: [],
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
// Add title
|
|
146
|
-
card.body.push({
|
|
147
|
-
type: "TextBlock",
|
|
148
|
-
text: title,
|
|
149
|
-
weight: "Bolder",
|
|
150
|
-
size: "Large",
|
|
151
|
-
wrap: true,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
// Add separator
|
|
155
|
-
card.body.push({
|
|
156
|
-
type: "TextBlock",
|
|
157
|
-
text: " ",
|
|
158
|
-
separator: true,
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// Create header row using ColumnSet
|
|
162
|
-
const headerColumnSet: AdaptiveCardElement = {
|
|
163
|
-
type: "ColumnSet",
|
|
164
|
-
columns: columnNames.map((col) => ({
|
|
165
|
-
type: "Column",
|
|
166
|
-
width: "stretch",
|
|
167
|
-
items: [
|
|
168
|
-
{
|
|
169
|
-
type: "TextBlock",
|
|
170
|
-
text: this.formatColumnName(col),
|
|
171
|
-
weight: "Bolder",
|
|
172
|
-
wrap: true,
|
|
173
|
-
},
|
|
174
|
-
],
|
|
175
|
-
})),
|
|
176
|
-
style: "accent",
|
|
177
|
-
};
|
|
178
|
-
card.body.push(headerColumnSet);
|
|
179
|
-
|
|
180
|
-
// Add data rows using ColumnSets
|
|
181
|
-
for (const row of rows) {
|
|
182
|
-
const dataColumnSet: AdaptiveCardElement = {
|
|
183
|
-
type: "ColumnSet",
|
|
184
|
-
columns: columnNames.map((col) => ({
|
|
185
|
-
type: "Column",
|
|
186
|
-
width: "stretch",
|
|
187
|
-
items: [
|
|
188
|
-
{
|
|
189
|
-
type: "TextBlock",
|
|
190
|
-
text: this.formatCellValue(row[col]),
|
|
191
|
-
wrap: true,
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
})),
|
|
195
|
-
separator: true,
|
|
196
|
-
};
|
|
197
|
-
card.body.push(dataColumnSet);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Add row count footer
|
|
201
|
-
card.body.push({
|
|
202
|
-
type: "TextBlock",
|
|
203
|
-
text: `Showing ${rows.length} row${rows.length !== 1 ? "s" : ""}`,
|
|
204
|
-
size: "Small",
|
|
205
|
-
isSubtle: true,
|
|
206
|
-
horizontalAlignment: "Right",
|
|
207
|
-
separator: true,
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
return card;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Creates an empty card when no data is available.
|
|
215
|
-
*/
|
|
216
|
-
private createEmptyCard(title: string): AdaptiveCard {
|
|
217
|
-
return {
|
|
218
|
-
type: "AdaptiveCard",
|
|
219
|
-
$schema: "http://adaptivecards.io/schemas/adaptive-card.json",
|
|
220
|
-
version: "1.3",
|
|
221
|
-
body: [
|
|
222
|
-
{
|
|
223
|
-
type: "TextBlock",
|
|
224
|
-
text: title,
|
|
225
|
-
weight: "Bolder",
|
|
226
|
-
size: "Large",
|
|
227
|
-
wrap: true,
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
type: "TextBlock",
|
|
231
|
-
text: "No data available",
|
|
232
|
-
isSubtle: true,
|
|
233
|
-
wrap: true,
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Formats a column name for display (converts camelCase/snake_case to Title Case).
|
|
241
|
-
*/
|
|
242
|
-
private formatColumnName(name: string): string {
|
|
243
|
-
return name
|
|
244
|
-
.replace(/([A-Z])/g, " $1") // camelCase
|
|
245
|
-
.replace(/_/g, " ") // snake_case
|
|
246
|
-
.replace(/^\w/, (c) => c.toUpperCase())
|
|
247
|
-
.trim();
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Formats a cell value for display in the table.
|
|
252
|
-
*/
|
|
253
|
-
private formatCellValue(value: any): string {
|
|
254
|
-
if (value === null || value === undefined) {
|
|
255
|
-
return "-";
|
|
256
|
-
}
|
|
257
|
-
if (typeof value === "boolean") {
|
|
258
|
-
return value ? "✓" : "✗";
|
|
259
|
-
}
|
|
260
|
-
if (typeof value === "number") {
|
|
261
|
-
// Format numbers nicely
|
|
262
|
-
if (Number.isInteger(value)) {
|
|
263
|
-
return value.toString();
|
|
264
|
-
}
|
|
265
|
-
return value.toFixed(2);
|
|
266
|
-
}
|
|
267
|
-
if (typeof value === "object") {
|
|
268
|
-
return JSON.stringify(value);
|
|
269
|
-
}
|
|
270
|
-
return String(value);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export { Table as default };
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example plugin: Fetch weather forecast for a location.
|
|
3
|
-
*
|
|
4
|
-
* Usage in FlowQuery:
|
|
5
|
-
* CALL weather('Oslo') YIELD date, location, temperature, humidity
|
|
6
|
-
*/
|
|
7
|
-
import { AsyncFunction, FunctionDef } from "flowquery/extensibility";
|
|
8
|
-
|
|
9
|
-
const GEOCODING_API = "https://geocoding-api.open-meteo.com/v1/search";
|
|
10
|
-
const WEATHER_API = "https://api.met.no/weatherapi/locationforecast/2.0/compact";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Weather class - fetches weather forecast for a given location.
|
|
14
|
-
*/
|
|
15
|
-
@FunctionDef({
|
|
16
|
-
description:
|
|
17
|
-
"Fetches weather forecast for a location using Open-Meteo geocoding and MET Norway weather API",
|
|
18
|
-
category: "async",
|
|
19
|
-
parameters: [
|
|
20
|
-
{
|
|
21
|
-
name: "location",
|
|
22
|
-
description: 'The name of the location to get weather for (e.g., "Oslo", "New York")',
|
|
23
|
-
type: "string",
|
|
24
|
-
required: true,
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
output: {
|
|
28
|
-
description: "Weather forecast data point with location and weather parameters",
|
|
29
|
-
type: "object",
|
|
30
|
-
properties: {
|
|
31
|
-
date: { description: "ISO 8601 timestamp in UTC", type: "string" },
|
|
32
|
-
location: { description: "Name of the location", type: "string" },
|
|
33
|
-
lat: { description: "Latitude in decimal degrees", type: "number" },
|
|
34
|
-
lon: { description: "Longitude in decimal degrees", type: "number" },
|
|
35
|
-
temperature: { description: "Air temperature in celsius", type: "number" },
|
|
36
|
-
humidity: { description: "Relative humidity in %", type: "number" },
|
|
37
|
-
pressure: { description: "Air pressure at sea level in hPa", type: "number" },
|
|
38
|
-
cloud_cover: { description: "Total cloud cover in %", type: "number" },
|
|
39
|
-
wind_speed: { description: "Wind speed in m/s", type: "number" },
|
|
40
|
-
wind_direction: {
|
|
41
|
-
description: "Wind direction in degrees (0=N, 90=E, 180=S, 270=W)",
|
|
42
|
-
type: "number",
|
|
43
|
-
},
|
|
44
|
-
precipitation: {
|
|
45
|
-
description: "Expected precipitation in mm (next hour if available)",
|
|
46
|
-
type: "number",
|
|
47
|
-
},
|
|
48
|
-
symbol: {
|
|
49
|
-
description: 'Weather symbol code (e.g., "partlycloudy_day", "rain")',
|
|
50
|
-
type: "string",
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
examples: [
|
|
55
|
-
"CALL weather('Oslo') YIELD date, location, temperature, humidity",
|
|
56
|
-
"CALL weather('London') YIELD date, location, temperature, wind_speed, precipitation",
|
|
57
|
-
],
|
|
58
|
-
})
|
|
59
|
-
export class Weather extends AsyncFunction {
|
|
60
|
-
private readonly geocodingApiUrl: string;
|
|
61
|
-
private readonly weatherApiUrl: string;
|
|
62
|
-
|
|
63
|
-
constructor(geocodingApiUrl: string = GEOCODING_API, weatherApiUrl: string = WEATHER_API) {
|
|
64
|
-
super();
|
|
65
|
-
this.geocodingApiUrl = geocodingApiUrl;
|
|
66
|
-
this.weatherApiUrl = weatherApiUrl;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Fetches weather forecast for a given location.
|
|
71
|
-
*
|
|
72
|
-
* @param location - The name of the location to get weather for
|
|
73
|
-
*/
|
|
74
|
-
async *generate(location: string): AsyncGenerator<any, void, unknown> {
|
|
75
|
-
// Step 1: Geocode the location name to get lat/lon
|
|
76
|
-
const geocodeUrl = `${this.geocodingApiUrl}?name=${encodeURIComponent(location)}`;
|
|
77
|
-
const geocodeResponse = await fetch(geocodeUrl);
|
|
78
|
-
|
|
79
|
-
if (!geocodeResponse.ok) {
|
|
80
|
-
throw new Error(`Failed to geocode location: ${geocodeResponse.statusText}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const geocodeData = await geocodeResponse.json();
|
|
84
|
-
|
|
85
|
-
if (!geocodeData.results || geocodeData.results.length === 0) {
|
|
86
|
-
throw new Error(`Location not found: ${location}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const firstResult = geocodeData.results[0];
|
|
90
|
-
const lat = firstResult.latitude;
|
|
91
|
-
const lon = firstResult.longitude;
|
|
92
|
-
|
|
93
|
-
// Step 2: Fetch weather forecast using lat/lon
|
|
94
|
-
const weatherUrl = `${this.weatherApiUrl}?lat=${lat}&lon=${lon}`;
|
|
95
|
-
const weatherResponse = await fetch(weatherUrl, {
|
|
96
|
-
headers: {
|
|
97
|
-
// MET Norway API requires a User-Agent header
|
|
98
|
-
"User-Agent": "FlowQuery-RAG/1.0",
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
if (!weatherResponse.ok) {
|
|
103
|
-
throw new Error(`Failed to fetch weather: ${weatherResponse.statusText}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const weatherData = await weatherResponse.json();
|
|
107
|
-
|
|
108
|
-
// Transform timeseries into simplified flat records and yield row by row
|
|
109
|
-
const locationName = firstResult.name;
|
|
110
|
-
const timeseries = weatherData.properties?.timeseries || [];
|
|
111
|
-
|
|
112
|
-
for (const entry of timeseries) {
|
|
113
|
-
const instant = entry.data?.instant?.details || {};
|
|
114
|
-
const next1h = entry.data?.next_1_hours || {};
|
|
115
|
-
const next6h = entry.data?.next_6_hours || {};
|
|
116
|
-
|
|
117
|
-
yield {
|
|
118
|
-
date: entry.time,
|
|
119
|
-
location: locationName,
|
|
120
|
-
lat,
|
|
121
|
-
lon,
|
|
122
|
-
temperature: instant.air_temperature,
|
|
123
|
-
humidity: instant.relative_humidity,
|
|
124
|
-
pressure: instant.air_pressure_at_sea_level,
|
|
125
|
-
cloud_cover: instant.cloud_area_fraction,
|
|
126
|
-
wind_speed: instant.wind_speed,
|
|
127
|
-
wind_direction: instant.wind_from_direction,
|
|
128
|
-
precipitation:
|
|
129
|
-
next1h.details?.precipitation_amount ??
|
|
130
|
-
next6h.details?.precipitation_amount ??
|
|
131
|
-
null,
|
|
132
|
-
symbol: next1h.summary?.symbol_code ?? next6h.summary?.symbol_code ?? null,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export default Weather;
|