flowquery 1.0.3 → 1.0.6
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 +182 -0
- package/dist/compute/runner.d.ts +81 -0
- package/dist/compute/runner.d.ts.map +1 -0
- package/dist/extensibility.d.ts +9 -0
- package/dist/extensibility.d.ts.map +1 -0
- package/dist/extensibility.js +25 -0
- package/dist/extensibility.js.map +1 -0
- package/dist/flowquery.min.js +1 -1
- package/dist/index.browser.d.ts +10 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.node.d.ts +14 -0
- package/dist/index.node.d.ts.map +1 -0
- package/dist/io/command_line.d.ts +28 -0
- package/dist/io/command_line.d.ts.map +1 -0
- package/dist/parsing/alias.d.ts +10 -0
- package/dist/parsing/alias.d.ts.map +1 -0
- package/dist/parsing/alias_option.d.ts +6 -0
- package/dist/parsing/alias_option.d.ts.map +1 -0
- package/dist/parsing/ast_node.d.ts +100 -0
- package/dist/parsing/ast_node.d.ts.map +1 -0
- package/dist/parsing/base_parser.d.ts +49 -0
- package/dist/parsing/base_parser.d.ts.map +1 -0
- package/dist/parsing/components/csv.d.ts +6 -0
- package/dist/parsing/components/csv.d.ts.map +1 -0
- package/dist/parsing/components/from.d.ts +7 -0
- package/dist/parsing/components/from.d.ts.map +1 -0
- package/dist/parsing/components/headers.d.ts +7 -0
- package/dist/parsing/components/headers.d.ts.map +1 -0
- package/dist/parsing/components/json.d.ts +6 -0
- package/dist/parsing/components/json.d.ts.map +1 -0
- package/dist/parsing/components/null.d.ts +6 -0
- package/dist/parsing/components/null.d.ts.map +1 -0
- package/dist/parsing/components/post.d.ts +6 -0
- package/dist/parsing/components/post.d.ts.map +1 -0
- package/dist/parsing/components/text.d.ts +6 -0
- package/dist/parsing/components/text.d.ts.map +1 -0
- package/dist/parsing/context.d.ts +38 -0
- package/dist/parsing/context.d.ts.map +1 -0
- package/dist/parsing/data_structures/associative_array.d.ts +28 -0
- package/dist/parsing/data_structures/associative_array.d.ts.map +1 -0
- package/dist/parsing/data_structures/json_array.d.ts +26 -0
- package/dist/parsing/data_structures/json_array.d.ts.map +1 -0
- package/dist/parsing/data_structures/key_value_pair.d.ts +25 -0
- package/dist/parsing/data_structures/key_value_pair.d.ts.map +1 -0
- package/dist/parsing/data_structures/lookup.d.ts +25 -0
- package/dist/parsing/data_structures/lookup.d.ts.map +1 -0
- package/dist/parsing/data_structures/range_lookup.d.ts +14 -0
- package/dist/parsing/data_structures/range_lookup.d.ts.map +1 -0
- package/dist/parsing/expressions/expression.d.ts +53 -0
- package/dist/parsing/expressions/expression.d.ts.map +1 -0
- package/dist/parsing/expressions/f_string.d.ts +21 -0
- package/dist/parsing/expressions/f_string.d.ts.map +1 -0
- package/dist/parsing/expressions/identifier.d.ts +17 -0
- package/dist/parsing/expressions/identifier.d.ts.map +1 -0
- package/dist/parsing/expressions/number.d.ts +25 -0
- package/dist/parsing/expressions/number.d.ts.map +1 -0
- package/dist/parsing/expressions/operator.d.ts +79 -0
- package/dist/parsing/expressions/operator.d.ts.map +1 -0
- package/dist/parsing/expressions/reference.d.ts +29 -0
- package/dist/parsing/expressions/reference.d.ts.map +1 -0
- package/dist/parsing/expressions/string.d.ts +23 -0
- package/dist/parsing/expressions/string.d.ts.map +1 -0
- package/dist/parsing/functions/aggregate_function.d.ts +42 -0
- package/dist/parsing/functions/aggregate_function.d.ts.map +1 -0
- package/dist/parsing/functions/async_function.d.ts +52 -0
- package/dist/parsing/functions/async_function.d.ts.map +1 -0
- package/dist/parsing/functions/avg.d.ts +15 -0
- package/dist/parsing/functions/avg.d.ts.map +1 -0
- package/dist/parsing/functions/avg.js +20 -2
- package/dist/parsing/functions/avg.js.map +1 -1
- package/dist/parsing/functions/collect.d.ts +21 -0
- package/dist/parsing/functions/collect.d.ts.map +1 -0
- package/dist/parsing/functions/collect.js +20 -2
- package/dist/parsing/functions/collect.js.map +1 -1
- package/dist/parsing/functions/extensibility/index.d.ts +37 -0
- package/dist/parsing/functions/extensibility/index.d.ts.map +1 -0
- package/dist/parsing/functions/extensibility/index.js +50 -0
- package/dist/parsing/functions/extensibility/index.js.map +1 -0
- package/dist/parsing/functions/function.d.ts +36 -0
- package/dist/parsing/functions/function.d.ts.map +1 -0
- package/dist/parsing/functions/function_factory.d.ts +174 -0
- package/dist/parsing/functions/function_factory.d.ts.map +1 -0
- package/dist/parsing/functions/function_factory.js +44 -47
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/functions/function_metadata.d.ts +134 -0
- package/dist/parsing/functions/function_metadata.d.ts.map +1 -0
- package/dist/parsing/functions/function_metadata.js +103 -153
- package/dist/parsing/functions/function_metadata.js.map +1 -1
- package/dist/parsing/functions/functions.d.ts +21 -0
- package/dist/parsing/functions/functions.d.ts.map +1 -0
- package/dist/parsing/functions/functions.js +37 -2
- package/dist/parsing/functions/functions.js.map +1 -1
- package/dist/parsing/functions/join.d.ts +9 -0
- package/dist/parsing/functions/join.d.ts.map +1 -0
- package/dist/parsing/functions/join.js +21 -2
- package/dist/parsing/functions/join.js.map +1 -1
- package/dist/parsing/functions/predicate_function.d.ts +19 -0
- package/dist/parsing/functions/predicate_function.d.ts.map +1 -0
- package/dist/parsing/functions/predicate_function.js +3 -0
- package/dist/parsing/functions/predicate_function.js.map +1 -1
- package/dist/parsing/functions/predicate_sum.d.ts +7 -0
- package/dist/parsing/functions/predicate_sum.d.ts.map +1 -0
- package/dist/parsing/functions/predicate_sum.js +23 -2
- package/dist/parsing/functions/predicate_sum.js.map +1 -1
- package/dist/parsing/functions/rand.d.ts +7 -0
- package/dist/parsing/functions/rand.d.ts.map +1 -0
- package/dist/parsing/functions/rand.js +18 -2
- package/dist/parsing/functions/rand.js.map +1 -1
- package/dist/parsing/functions/range.d.ts +7 -0
- package/dist/parsing/functions/range.d.ts.map +1 -0
- package/dist/parsing/functions/range.js +21 -2
- package/dist/parsing/functions/range.js.map +1 -1
- package/dist/parsing/functions/reducer_element.d.ts +6 -0
- package/dist/parsing/functions/reducer_element.d.ts.map +1 -0
- package/dist/parsing/functions/replace.d.ts +7 -0
- package/dist/parsing/functions/replace.d.ts.map +1 -0
- package/dist/parsing/functions/replace.js +22 -2
- package/dist/parsing/functions/replace.js.map +1 -1
- package/dist/parsing/functions/round.d.ts +7 -0
- package/dist/parsing/functions/round.d.ts.map +1 -0
- package/dist/parsing/functions/round.js +20 -2
- package/dist/parsing/functions/round.js.map +1 -1
- package/dist/parsing/functions/size.d.ts +7 -0
- package/dist/parsing/functions/size.d.ts.map +1 -0
- package/dist/parsing/functions/size.js +20 -2
- package/dist/parsing/functions/size.js.map +1 -1
- package/dist/parsing/functions/split.d.ts +9 -0
- package/dist/parsing/functions/split.d.ts.map +1 -0
- package/dist/parsing/functions/split.js +21 -2
- package/dist/parsing/functions/split.js.map +1 -1
- package/dist/parsing/functions/stringify.d.ts +9 -0
- package/dist/parsing/functions/stringify.d.ts.map +1 -0
- package/dist/parsing/functions/stringify.js +20 -2
- package/dist/parsing/functions/stringify.js.map +1 -1
- package/dist/parsing/functions/sum.d.ts +14 -0
- package/dist/parsing/functions/sum.d.ts.map +1 -0
- package/dist/parsing/functions/sum.js +20 -2
- package/dist/parsing/functions/sum.js.map +1 -1
- package/dist/parsing/functions/to_json.d.ts +7 -0
- package/dist/parsing/functions/to_json.d.ts.map +1 -0
- package/dist/parsing/functions/to_json.js +20 -2
- package/dist/parsing/functions/to_json.js.map +1 -1
- package/dist/parsing/functions/value_holder.d.ts +8 -0
- package/dist/parsing/functions/value_holder.d.ts.map +1 -0
- package/dist/parsing/logic/case.d.ts +7 -0
- package/dist/parsing/logic/case.d.ts.map +1 -0
- package/dist/parsing/logic/else.d.ts +7 -0
- package/dist/parsing/logic/else.d.ts.map +1 -0
- package/dist/parsing/logic/end.d.ts +6 -0
- package/dist/parsing/logic/end.d.ts.map +1 -0
- package/dist/parsing/logic/then.d.ts +7 -0
- package/dist/parsing/logic/then.d.ts.map +1 -0
- package/dist/parsing/logic/when.d.ts +7 -0
- package/dist/parsing/logic/when.d.ts.map +1 -0
- package/dist/parsing/operations/aggregated_return.d.ts +8 -0
- package/dist/parsing/operations/aggregated_return.d.ts.map +1 -0
- package/dist/parsing/operations/aggregated_with.d.ts +8 -0
- package/dist/parsing/operations/aggregated_with.d.ts.map +1 -0
- package/dist/parsing/operations/group_by.d.ts +35 -0
- package/dist/parsing/operations/group_by.d.ts.map +1 -0
- package/dist/parsing/operations/limit.d.ts +10 -0
- package/dist/parsing/operations/limit.d.ts.map +1 -0
- package/dist/parsing/operations/load.d.ts +48 -0
- package/dist/parsing/operations/load.d.ts.map +1 -0
- package/dist/parsing/operations/operation.d.ts +39 -0
- package/dist/parsing/operations/operation.d.ts.map +1 -0
- package/dist/parsing/operations/projection.d.ts +8 -0
- package/dist/parsing/operations/projection.d.ts.map +1 -0
- package/dist/parsing/operations/return.d.ts +23 -0
- package/dist/parsing/operations/return.d.ts.map +1 -0
- package/dist/parsing/operations/unwind.d.ts +12 -0
- package/dist/parsing/operations/unwind.d.ts.map +1 -0
- package/dist/parsing/operations/where.d.ts +26 -0
- package/dist/parsing/operations/where.d.ts.map +1 -0
- package/dist/parsing/operations/with.d.ts +17 -0
- package/dist/parsing/operations/with.d.ts.map +1 -0
- package/dist/parsing/parser.d.ts +66 -0
- package/dist/parsing/parser.d.ts.map +1 -0
- package/dist/parsing/parser.js +2 -3
- package/dist/parsing/parser.js.map +1 -1
- package/dist/parsing/token_to_node.d.ts +7 -0
- package/dist/parsing/token_to_node.d.ts.map +1 -0
- package/dist/tokenization/keyword.d.ts +43 -0
- package/dist/tokenization/keyword.d.ts.map +1 -0
- package/dist/tokenization/operator.d.ts +22 -0
- package/dist/tokenization/operator.d.ts.map +1 -0
- package/dist/tokenization/string_walker.d.ts +55 -0
- package/dist/tokenization/string_walker.d.ts.map +1 -0
- package/dist/tokenization/symbol.d.ts +15 -0
- package/dist/tokenization/symbol.d.ts.map +1 -0
- package/dist/tokenization/token.d.ts +176 -0
- package/dist/tokenization/token.d.ts.map +1 -0
- package/dist/tokenization/token_mapper.d.ts +40 -0
- package/dist/tokenization/token_mapper.d.ts.map +1 -0
- package/dist/tokenization/token_type.d.ts +16 -0
- package/dist/tokenization/token_type.d.ts.map +1 -0
- package/dist/tokenization/tokenizer.d.ts +45 -0
- package/dist/tokenization/tokenizer.d.ts.map +1 -0
- package/dist/tokenization/trie.d.ts +41 -0
- package/dist/tokenization/trie.d.ts.map +1 -0
- package/dist/utils/object_utils.d.ts +15 -0
- package/dist/utils/object_utils.d.ts.map +1 -0
- package/dist/utils/string_utils.d.ts +51 -0
- package/dist/utils/string_utils.d.ts.map +1 -0
- package/docs/flowquery.min.js +1 -1
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/misc/apps/RAG/.env.example +14 -0
- package/misc/apps/RAG/README.md +0 -7
- package/misc/apps/RAG/package.json +16 -7
- package/misc/apps/RAG/public/index.html +18 -0
- package/misc/apps/RAG/src/App.css +42 -0
- package/misc/apps/RAG/src/App.tsx +50 -0
- package/misc/apps/RAG/src/components/ApiKeySettings.tsx +245 -0
- package/misc/apps/RAG/src/components/ChatContainer.css +67 -0
- package/misc/apps/RAG/src/components/ChatContainer.tsx +239 -0
- package/misc/apps/RAG/src/components/ChatInput.css +23 -0
- package/misc/apps/RAG/src/components/ChatInput.tsx +62 -0
- package/misc/apps/RAG/src/components/ChatMessage.css +136 -0
- package/misc/apps/RAG/src/components/ChatMessage.tsx +152 -0
- package/misc/apps/RAG/src/components/FlowQueryAgent.ts +390 -0
- package/misc/apps/RAG/src/components/FlowQueryRunner.css +104 -0
- package/misc/apps/RAG/src/components/FlowQueryRunner.tsx +332 -0
- package/misc/apps/RAG/src/components/index.ts +15 -0
- package/misc/apps/RAG/src/index.tsx +17 -0
- package/misc/apps/RAG/src/plugins/PluginRegistry.ts +136 -0
- package/misc/apps/RAG/src/plugins/README.md +139 -0
- package/misc/apps/RAG/src/plugins/index.ts +72 -0
- package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +79 -0
- package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +71 -0
- package/misc/apps/RAG/src/plugins/loaders/Llm.ts +441 -0
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +161 -0
- package/misc/apps/RAG/src/plugins/types.ts +52 -0
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +385 -0
- package/misc/apps/RAG/src/prompts/index.ts +10 -0
- package/misc/apps/RAG/src/utils/FlowQueryExecutor.ts +131 -0
- package/misc/apps/RAG/src/utils/FlowQueryExtractor.ts +203 -0
- package/misc/apps/RAG/src/utils/index.ts +9 -0
- package/misc/apps/RAG/tsconfig.json +4 -2
- package/misc/apps/RAG/webpack.config.js +23 -12
- package/package.json +7 -1
- package/src/extensibility.ts +9 -0
- package/src/parsing/functions/avg.ts +10 -0
- package/src/parsing/functions/collect.ts +10 -0
- package/src/parsing/functions/extensibility/index.ts +54 -0
- package/src/parsing/functions/function_factory.ts +51 -48
- package/src/parsing/functions/function_metadata.ts +132 -156
- package/src/parsing/functions/functions.ts +27 -0
- package/src/parsing/functions/join.ts +11 -0
- package/src/parsing/functions/predicate_function.ts +4 -0
- package/src/parsing/functions/predicate_sum.ts +13 -0
- package/src/parsing/functions/rand.ts +8 -0
- package/src/parsing/functions/range.ts +11 -0
- package/src/parsing/functions/replace.ts +12 -0
- package/src/parsing/functions/round.ts +10 -0
- package/src/parsing/functions/size.ts +10 -0
- package/src/parsing/functions/split.ts +11 -0
- package/src/parsing/functions/stringify.ts +10 -0
- package/src/parsing/functions/sum.ts +10 -0
- package/src/parsing/functions/to_json.ts +10 -0
- package/src/parsing/parser.ts +2 -3
- package/tests/parsing/function_plugins.test.ts +11 -11
- package/tsconfig.json +4 -1
- package/dist/parsing/functions/predicate_function_factory.js +0 -19
- package/dist/parsing/functions/predicate_function_factory.js.map +0 -1
- package/misc/apps/RAG/src/index.ts +0 -20
- package/src/parsing/functions/predicate_function_factory.ts +0 -15
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
.flowquery-runner-surface {
|
|
2
|
+
max-width: 800px;
|
|
3
|
+
width: 90vw;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.flowquery-runner-content {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: 16px;
|
|
10
|
+
padding-top: 16px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.flowquery-input-container {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: 8px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.flowquery-textarea {
|
|
20
|
+
width: 100%;
|
|
21
|
+
min-height: 120px;
|
|
22
|
+
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
23
|
+
font-size: 13px;
|
|
24
|
+
resize: vertical;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.flowquery-actions {
|
|
28
|
+
display: flex;
|
|
29
|
+
gap: 8px;
|
|
30
|
+
align-items: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.flowquery-execution-time {
|
|
34
|
+
margin-left: auto;
|
|
35
|
+
font-size: 12px;
|
|
36
|
+
color: #666;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.flowquery-results-container {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: 8px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.flowquery-results-header {
|
|
46
|
+
display: flex;
|
|
47
|
+
justify-content: space-between;
|
|
48
|
+
align-items: center;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.flowquery-results-count {
|
|
52
|
+
font-size: 12px;
|
|
53
|
+
color: #666;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.flowquery-results {
|
|
57
|
+
max-height: 300px;
|
|
58
|
+
overflow: auto;
|
|
59
|
+
border: 1px solid #e0e0e0;
|
|
60
|
+
border-radius: 4px;
|
|
61
|
+
background-color: #f8f8f8;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.flowquery-results-content {
|
|
65
|
+
padding: 12px;
|
|
66
|
+
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
white-space: pre-wrap;
|
|
69
|
+
word-break: break-word;
|
|
70
|
+
margin: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.flowquery-error {
|
|
74
|
+
color: #c50f1f;
|
|
75
|
+
padding: 12px;
|
|
76
|
+
margin: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.flowquery-no-results {
|
|
80
|
+
color: #666;
|
|
81
|
+
font-style: italic;
|
|
82
|
+
padding: 12px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.flowquery-loading {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 8px;
|
|
89
|
+
padding: 12px;
|
|
90
|
+
color: #666;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.flowquery-examples-list {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
gap: 4px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.flowquery-example-button {
|
|
100
|
+
text-align: left;
|
|
101
|
+
justify-content: flex-start;
|
|
102
|
+
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
103
|
+
font-size: 12px;
|
|
104
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowQuery Runner Component
|
|
3
|
+
*
|
|
4
|
+
* A popup dialog that allows users to run FlowQuery statements directly
|
|
5
|
+
* and see the results in the dialog.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { Component } from 'react';
|
|
9
|
+
import {
|
|
10
|
+
Dialog,
|
|
11
|
+
DialogTrigger,
|
|
12
|
+
DialogSurface,
|
|
13
|
+
DialogTitle,
|
|
14
|
+
DialogBody,
|
|
15
|
+
DialogActions,
|
|
16
|
+
DialogContent,
|
|
17
|
+
Button,
|
|
18
|
+
Textarea,
|
|
19
|
+
Label,
|
|
20
|
+
Field,
|
|
21
|
+
Spinner,
|
|
22
|
+
Tooltip,
|
|
23
|
+
} from '@fluentui/react-components';
|
|
24
|
+
import {
|
|
25
|
+
Play24Regular,
|
|
26
|
+
Code24Regular,
|
|
27
|
+
Dismiss24Regular,
|
|
28
|
+
Copy24Regular,
|
|
29
|
+
ArrowClockwise24Regular,
|
|
30
|
+
Checkmark24Regular,
|
|
31
|
+
} from '@fluentui/react-icons';
|
|
32
|
+
import { FlowQueryExecutor, FlowQueryExecutionResult } from '../utils/FlowQueryExecutor';
|
|
33
|
+
import './FlowQueryRunner.css';
|
|
34
|
+
|
|
35
|
+
const flowQueryExecutor = new FlowQueryExecutor();
|
|
36
|
+
|
|
37
|
+
interface FlowQueryRunnerProps {
|
|
38
|
+
/** Initial query to pre-populate the input */
|
|
39
|
+
initialQuery?: string;
|
|
40
|
+
/** Controlled open state - if provided, the component becomes controlled */
|
|
41
|
+
open?: boolean;
|
|
42
|
+
/** Callback when open state changes (for controlled mode) */
|
|
43
|
+
onOpenChange?: (open: boolean) => void;
|
|
44
|
+
/** Callback when the dialog is closed (deprecated, use onOpenChange) */
|
|
45
|
+
onClose?: () => void;
|
|
46
|
+
/** Custom trigger element. If not provided, a default button is shown. Not used in controlled mode. */
|
|
47
|
+
trigger?: React.ReactElement;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface FlowQueryRunnerState {
|
|
51
|
+
open: boolean;
|
|
52
|
+
query: string;
|
|
53
|
+
isExecuting: boolean;
|
|
54
|
+
result: FlowQueryExecutionResult | null;
|
|
55
|
+
copied: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class FlowQueryRunner extends Component<FlowQueryRunnerProps, FlowQueryRunnerState> {
|
|
59
|
+
constructor(props: FlowQueryRunnerProps) {
|
|
60
|
+
super(props);
|
|
61
|
+
this.state = {
|
|
62
|
+
open: props.open ?? false,
|
|
63
|
+
query: props.initialQuery || '',
|
|
64
|
+
isExecuting: false,
|
|
65
|
+
result: null,
|
|
66
|
+
copied: false,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
componentDidUpdate(prevProps: FlowQueryRunnerProps): void {
|
|
71
|
+
// Handle controlled mode: sync open state from props
|
|
72
|
+
if (this.props.open !== undefined && this.props.open !== prevProps.open) {
|
|
73
|
+
this.setState({ open: this.props.open });
|
|
74
|
+
// If opening with a new initial query, update the query
|
|
75
|
+
if (this.props.open && this.props.initialQuery !== prevProps.initialQuery) {
|
|
76
|
+
this.setState({ query: this.props.initialQuery || '', result: null });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Handle initialQuery changes when opening
|
|
80
|
+
if (this.props.initialQuery !== prevProps.initialQuery && this.props.open) {
|
|
81
|
+
this.setState({ query: this.props.initialQuery || '', result: null });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if the component is in controlled mode
|
|
87
|
+
*/
|
|
88
|
+
isControlled = (): boolean => {
|
|
89
|
+
return this.props.open !== undefined;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
handleOpenChange = (_: unknown, data: { open: boolean }): void => {
|
|
93
|
+
if (this.isControlled()) {
|
|
94
|
+
// In controlled mode, notify parent
|
|
95
|
+
this.props.onOpenChange?.(data.open);
|
|
96
|
+
} else {
|
|
97
|
+
// In uncontrolled mode, manage state internally
|
|
98
|
+
this.setState({ open: data.open });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!data.open && this.props.onClose) {
|
|
102
|
+
this.props.onClose();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
handleClose = (): void => {
|
|
107
|
+
if (this.isControlled()) {
|
|
108
|
+
this.props.onOpenChange?.(false);
|
|
109
|
+
} else {
|
|
110
|
+
this.setState({ open: false });
|
|
111
|
+
}
|
|
112
|
+
this.props.onClose?.();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
handleQueryChange = (_: unknown, data: { value: string }): void => {
|
|
116
|
+
this.setState({ query: data.value });
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
handleExecute = async (): Promise<void> => {
|
|
120
|
+
const { query } = this.state;
|
|
121
|
+
|
|
122
|
+
if (!query.trim()) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.setState({ isExecuting: true, result: null });
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const result = await flowQueryExecutor.execute(query);
|
|
130
|
+
this.setState({ result, isExecuting: false });
|
|
131
|
+
} catch (error) {
|
|
132
|
+
this.setState({
|
|
133
|
+
result: {
|
|
134
|
+
success: false,
|
|
135
|
+
query,
|
|
136
|
+
error: error instanceof Error ? error.message : String(error),
|
|
137
|
+
executionTime: 0,
|
|
138
|
+
},
|
|
139
|
+
isExecuting: false,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
handleClear = (): void => {
|
|
145
|
+
this.setState({ query: '', result: null });
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
handleCopyResults = (): void => {
|
|
149
|
+
const { result } = this.state;
|
|
150
|
+
if (result?.success && result.results) {
|
|
151
|
+
navigator.clipboard.writeText(JSON.stringify(result.results, null, 2));
|
|
152
|
+
this.setState({ copied: true });
|
|
153
|
+
setTimeout(() => this.setState({ copied: false }), 2000);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
handleKeyDown = (event: React.KeyboardEvent): void => {
|
|
158
|
+
// Execute on Ctrl+Enter or Cmd+Enter
|
|
159
|
+
if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') {
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
this.handleExecute();
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
renderResults(): React.ReactNode {
|
|
166
|
+
const { result, isExecuting, copied } = this.state;
|
|
167
|
+
|
|
168
|
+
if (isExecuting) {
|
|
169
|
+
return (
|
|
170
|
+
<div className="flowquery-loading">
|
|
171
|
+
<Spinner size="tiny" />
|
|
172
|
+
<span>Executing query...</span>
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!result) {
|
|
178
|
+
return (
|
|
179
|
+
<div className="flowquery-no-results">
|
|
180
|
+
Enter a FlowQuery statement and click Run to see results.
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!result.success) {
|
|
186
|
+
return (
|
|
187
|
+
<pre className="flowquery-error">
|
|
188
|
+
Error: {result.error}
|
|
189
|
+
</pre>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const resultCount = result.results?.length || 0;
|
|
194
|
+
const resultsJson = JSON.stringify(result.results, null, 2);
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<div className="flowquery-results-container">
|
|
198
|
+
<div className="flowquery-results-header">
|
|
199
|
+
<span className="flowquery-results-count">
|
|
200
|
+
{resultCount} result{resultCount !== 1 ? 's' : ''}
|
|
201
|
+
{' • '}
|
|
202
|
+
{result.executionTime.toFixed(2)}ms
|
|
203
|
+
</span>
|
|
204
|
+
<Tooltip
|
|
205
|
+
content={copied ? "Copied!" : "Copy results"}
|
|
206
|
+
relationship="label"
|
|
207
|
+
>
|
|
208
|
+
<Button
|
|
209
|
+
appearance="subtle"
|
|
210
|
+
icon={copied ? <Checkmark24Regular /> : <Copy24Regular />}
|
|
211
|
+
size="small"
|
|
212
|
+
onClick={this.handleCopyResults}
|
|
213
|
+
disabled={!result.results?.length}
|
|
214
|
+
/>
|
|
215
|
+
</Tooltip>
|
|
216
|
+
</div>
|
|
217
|
+
<div className="flowquery-results">
|
|
218
|
+
<pre className="flowquery-results-content">
|
|
219
|
+
{resultsJson}
|
|
220
|
+
</pre>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
renderDialogSurface(): React.JSX.Element {
|
|
227
|
+
const { query, isExecuting } = this.state;
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<DialogSurface className="flowquery-runner-surface">
|
|
231
|
+
<DialogBody>
|
|
232
|
+
<DialogTitle
|
|
233
|
+
action={
|
|
234
|
+
<Button
|
|
235
|
+
appearance="subtle"
|
|
236
|
+
icon={<Dismiss24Regular />}
|
|
237
|
+
onClick={this.handleClose}
|
|
238
|
+
/>
|
|
239
|
+
}
|
|
240
|
+
>
|
|
241
|
+
FlowQuery Runner
|
|
242
|
+
</DialogTitle>
|
|
243
|
+
<DialogContent className="flowquery-runner-content">
|
|
244
|
+
<div className="flowquery-input-container">
|
|
245
|
+
<Field label="FlowQuery Statement">
|
|
246
|
+
<Textarea
|
|
247
|
+
value={query}
|
|
248
|
+
onChange={this.handleQueryChange}
|
|
249
|
+
onKeyDown={this.handleKeyDown}
|
|
250
|
+
placeholder="Enter your FlowQuery statement here..."
|
|
251
|
+
className="flowquery-textarea"
|
|
252
|
+
resize="vertical"
|
|
253
|
+
/>
|
|
254
|
+
</Field>
|
|
255
|
+
<div className="flowquery-actions">
|
|
256
|
+
<Tooltip content="Run query (Ctrl+Enter)" relationship="label">
|
|
257
|
+
<Button
|
|
258
|
+
appearance="primary"
|
|
259
|
+
icon={<Play24Regular />}
|
|
260
|
+
onClick={this.handleExecute}
|
|
261
|
+
disabled={isExecuting || !query.trim()}
|
|
262
|
+
>
|
|
263
|
+
Run
|
|
264
|
+
</Button>
|
|
265
|
+
</Tooltip>
|
|
266
|
+
<Tooltip content="Clear query and results" relationship="label">
|
|
267
|
+
<Button
|
|
268
|
+
appearance="subtle"
|
|
269
|
+
icon={<ArrowClockwise24Regular />}
|
|
270
|
+
onClick={this.handleClear}
|
|
271
|
+
disabled={isExecuting}
|
|
272
|
+
>
|
|
273
|
+
Clear
|
|
274
|
+
</Button>
|
|
275
|
+
</Tooltip>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<Field label="Results">
|
|
280
|
+
<div className="flowquery-results">
|
|
281
|
+
{this.renderResults()}
|
|
282
|
+
</div>
|
|
283
|
+
</Field>
|
|
284
|
+
</DialogContent>
|
|
285
|
+
<DialogActions>
|
|
286
|
+
<Button
|
|
287
|
+
appearance="secondary"
|
|
288
|
+
onClick={this.handleClose}
|
|
289
|
+
>
|
|
290
|
+
Close
|
|
291
|
+
</Button>
|
|
292
|
+
</DialogActions>
|
|
293
|
+
</DialogBody>
|
|
294
|
+
</DialogSurface>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
render(): React.ReactNode {
|
|
299
|
+
const { open } = this.state;
|
|
300
|
+
const { trigger } = this.props;
|
|
301
|
+
const isControlled = this.isControlled();
|
|
302
|
+
|
|
303
|
+
// In controlled mode, render dialog without trigger
|
|
304
|
+
if (isControlled) {
|
|
305
|
+
return (
|
|
306
|
+
<Dialog open={open} onOpenChange={this.handleOpenChange}>
|
|
307
|
+
{this.renderDialogSurface()}
|
|
308
|
+
</Dialog>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// In uncontrolled mode, render with trigger
|
|
313
|
+
return (
|
|
314
|
+
<Dialog open={open} onOpenChange={this.handleOpenChange}>
|
|
315
|
+
<DialogTrigger disableButtonEnhancement>
|
|
316
|
+
{trigger || (
|
|
317
|
+
<Button
|
|
318
|
+
appearance="subtle"
|
|
319
|
+
icon={<Code24Regular />}
|
|
320
|
+
title="FlowQuery Runner"
|
|
321
|
+
>
|
|
322
|
+
FlowQuery
|
|
323
|
+
</Button>
|
|
324
|
+
)}
|
|
325
|
+
</DialogTrigger>
|
|
326
|
+
{this.renderDialogSurface()}
|
|
327
|
+
</Dialog>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export default FlowQueryRunner;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Chat components exports
|
|
2
|
+
export { ChatContainer } from './ChatContainer';
|
|
3
|
+
export { ChatMessage } from './ChatMessage';
|
|
4
|
+
export { ChatInput } from './ChatInput';
|
|
5
|
+
export { ApiKeySettings } from './ApiKeySettings';
|
|
6
|
+
|
|
7
|
+
// FlowQuery Runner
|
|
8
|
+
export { FlowQueryRunner } from './FlowQueryRunner';
|
|
9
|
+
|
|
10
|
+
// FlowQuery Agent
|
|
11
|
+
export { processQuery, processQueryStream } from './FlowQueryAgent';
|
|
12
|
+
export type { AgentStep, AgentResult, FlowQueryAgentOptions, AgentStreamCallback } from './FlowQueryAgent';
|
|
13
|
+
|
|
14
|
+
// Types
|
|
15
|
+
export type { Message } from './ChatMessage';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import App from './App';
|
|
4
|
+
import { initializePlugins } from './plugins';
|
|
5
|
+
|
|
6
|
+
// Initialize FlowQuery plugins before rendering
|
|
7
|
+
initializePlugins();
|
|
8
|
+
|
|
9
|
+
const container = document.getElementById('root');
|
|
10
|
+
if (container) {
|
|
11
|
+
const root = createRoot(container);
|
|
12
|
+
root.render(
|
|
13
|
+
<React.StrictMode>
|
|
14
|
+
<App />
|
|
15
|
+
</React.StrictMode>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin registry for loading and managing FlowQuery async data loader plugins.
|
|
3
|
+
*
|
|
4
|
+
* This registry uses FlowQuery's built-in function introspection via the functions()
|
|
5
|
+
* function as the single source of truth for available loaders and their metadata.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import FlowQuery from 'flowquery';
|
|
9
|
+
import { AsyncLoaderPlugin, PluginMetadata, PluginModule } from './types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Registry for managing FlowQuery plugins.
|
|
13
|
+
*
|
|
14
|
+
* Uses FlowQuery's `functions()` introspection as the source of truth,
|
|
15
|
+
* eliminating duplicate tracking of registered plugins.
|
|
16
|
+
*/
|
|
17
|
+
class PluginRegistry {
|
|
18
|
+
/**
|
|
19
|
+
* Register a single plugin with FlowQuery.
|
|
20
|
+
*
|
|
21
|
+
* @param plugin - The plugin to register
|
|
22
|
+
*/
|
|
23
|
+
public register(plugin: AsyncLoaderPlugin): void {
|
|
24
|
+
// Register with FlowQuery - it becomes the source of truth
|
|
25
|
+
if (plugin.metadata) {
|
|
26
|
+
FlowQuery.registerAsyncProvider(plugin.name, {
|
|
27
|
+
provider: plugin.provider,
|
|
28
|
+
metadata: {
|
|
29
|
+
name: plugin.name,
|
|
30
|
+
...plugin.metadata
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
FlowQuery.registerAsyncProvider(plugin.name, plugin.provider);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log(`Registered plugin: ${plugin.name}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Register multiple plugins at once.
|
|
42
|
+
*
|
|
43
|
+
* @param plugins - Array of plugins to register
|
|
44
|
+
*/
|
|
45
|
+
public registerAll(plugins: AsyncLoaderPlugin[]): void {
|
|
46
|
+
for (const plugin of plugins) {
|
|
47
|
+
this.register(plugin);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Load plugins from a plugin module.
|
|
53
|
+
*
|
|
54
|
+
* @param module - The plugin module to load
|
|
55
|
+
*/
|
|
56
|
+
public loadModule(module: PluginModule): void {
|
|
57
|
+
this.registerAll(module.plugins);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Unregister a plugin by name.
|
|
62
|
+
*
|
|
63
|
+
* @param name - The plugin name to unregister
|
|
64
|
+
*/
|
|
65
|
+
public unregister(name: string): void {
|
|
66
|
+
FlowQuery.unregisterAsyncProvider(name);
|
|
67
|
+
console.log(`Unregistered plugin: ${name}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get all loaded async provider names by querying FlowQuery directly.
|
|
72
|
+
*
|
|
73
|
+
* @returns Array of registered async provider names
|
|
74
|
+
*/
|
|
75
|
+
public getLoadedPlugins(): string[] {
|
|
76
|
+
// Use FlowQuery's FunctionFactory to get async provider names
|
|
77
|
+
const allFunctions = FlowQuery.listFunctions({ asyncOnly: true });
|
|
78
|
+
return allFunctions.map(f => f.name);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Check if a plugin is registered by querying FlowQuery.
|
|
83
|
+
*
|
|
84
|
+
* @param name - The plugin name to check
|
|
85
|
+
* @returns True if the plugin is registered
|
|
86
|
+
*/
|
|
87
|
+
public isRegistered(name: string): boolean {
|
|
88
|
+
const plugins = this.getLoadedPlugins();
|
|
89
|
+
return plugins.some(p => p.toLowerCase() === name.toLowerCase());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get all plugin metadata for registered async providers.
|
|
94
|
+
* Uses FlowQuery's functions() introspection as the single source of truth.
|
|
95
|
+
*
|
|
96
|
+
* @returns Array of plugin metadata objects
|
|
97
|
+
*/
|
|
98
|
+
public getAllPluginMetadata(): PluginMetadata[] {
|
|
99
|
+
// Query FlowQuery directly for all async providers with their metadata
|
|
100
|
+
const asyncFunctions = FlowQuery.listFunctions({ asyncOnly: true });
|
|
101
|
+
|
|
102
|
+
return asyncFunctions.map(f => ({
|
|
103
|
+
name: f.name,
|
|
104
|
+
description: f.description,
|
|
105
|
+
category: f.category,
|
|
106
|
+
parameters: f.parameters || [],
|
|
107
|
+
output: f.output || { description: 'Data items', type: 'object' },
|
|
108
|
+
examples: f.examples,
|
|
109
|
+
notes: f.notes
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get all plugin metadata asynchronously using a FlowQuery statement.
|
|
115
|
+
* This demonstrates the functions() approach for dynamic discovery.
|
|
116
|
+
*
|
|
117
|
+
* @returns Promise resolving to array of plugin metadata
|
|
118
|
+
*/
|
|
119
|
+
public async getAvailableLoadersAsync(): Promise<PluginMetadata[]> {
|
|
120
|
+
const runner = new FlowQuery(`
|
|
121
|
+
WITH functions() AS funcs
|
|
122
|
+
UNWIND funcs AS f
|
|
123
|
+
WHERE f.isAsyncProvider = true
|
|
124
|
+
RETURN f
|
|
125
|
+
`);
|
|
126
|
+
await runner.run();
|
|
127
|
+
return runner.results.map((r: any) => r.expr0 as PluginMetadata);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Global plugin registry instance.
|
|
133
|
+
*/
|
|
134
|
+
export const pluginRegistry = new PluginRegistry();
|
|
135
|
+
|
|
136
|
+
export default pluginRegistry;
|