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.
Files changed (268) hide show
  1. package/README.md +182 -0
  2. package/dist/compute/runner.d.ts +81 -0
  3. package/dist/compute/runner.d.ts.map +1 -0
  4. package/dist/extensibility.d.ts +9 -0
  5. package/dist/extensibility.d.ts.map +1 -0
  6. package/dist/extensibility.js +25 -0
  7. package/dist/extensibility.js.map +1 -0
  8. package/dist/flowquery.min.js +1 -1
  9. package/dist/index.browser.d.ts +10 -0
  10. package/dist/index.browser.d.ts.map +1 -0
  11. package/dist/index.d.ts +9 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.node.d.ts +14 -0
  14. package/dist/index.node.d.ts.map +1 -0
  15. package/dist/io/command_line.d.ts +28 -0
  16. package/dist/io/command_line.d.ts.map +1 -0
  17. package/dist/parsing/alias.d.ts +10 -0
  18. package/dist/parsing/alias.d.ts.map +1 -0
  19. package/dist/parsing/alias_option.d.ts +6 -0
  20. package/dist/parsing/alias_option.d.ts.map +1 -0
  21. package/dist/parsing/ast_node.d.ts +100 -0
  22. package/dist/parsing/ast_node.d.ts.map +1 -0
  23. package/dist/parsing/base_parser.d.ts +49 -0
  24. package/dist/parsing/base_parser.d.ts.map +1 -0
  25. package/dist/parsing/components/csv.d.ts +6 -0
  26. package/dist/parsing/components/csv.d.ts.map +1 -0
  27. package/dist/parsing/components/from.d.ts +7 -0
  28. package/dist/parsing/components/from.d.ts.map +1 -0
  29. package/dist/parsing/components/headers.d.ts +7 -0
  30. package/dist/parsing/components/headers.d.ts.map +1 -0
  31. package/dist/parsing/components/json.d.ts +6 -0
  32. package/dist/parsing/components/json.d.ts.map +1 -0
  33. package/dist/parsing/components/null.d.ts +6 -0
  34. package/dist/parsing/components/null.d.ts.map +1 -0
  35. package/dist/parsing/components/post.d.ts +6 -0
  36. package/dist/parsing/components/post.d.ts.map +1 -0
  37. package/dist/parsing/components/text.d.ts +6 -0
  38. package/dist/parsing/components/text.d.ts.map +1 -0
  39. package/dist/parsing/context.d.ts +38 -0
  40. package/dist/parsing/context.d.ts.map +1 -0
  41. package/dist/parsing/data_structures/associative_array.d.ts +28 -0
  42. package/dist/parsing/data_structures/associative_array.d.ts.map +1 -0
  43. package/dist/parsing/data_structures/json_array.d.ts +26 -0
  44. package/dist/parsing/data_structures/json_array.d.ts.map +1 -0
  45. package/dist/parsing/data_structures/key_value_pair.d.ts +25 -0
  46. package/dist/parsing/data_structures/key_value_pair.d.ts.map +1 -0
  47. package/dist/parsing/data_structures/lookup.d.ts +25 -0
  48. package/dist/parsing/data_structures/lookup.d.ts.map +1 -0
  49. package/dist/parsing/data_structures/range_lookup.d.ts +14 -0
  50. package/dist/parsing/data_structures/range_lookup.d.ts.map +1 -0
  51. package/dist/parsing/expressions/expression.d.ts +53 -0
  52. package/dist/parsing/expressions/expression.d.ts.map +1 -0
  53. package/dist/parsing/expressions/f_string.d.ts +21 -0
  54. package/dist/parsing/expressions/f_string.d.ts.map +1 -0
  55. package/dist/parsing/expressions/identifier.d.ts +17 -0
  56. package/dist/parsing/expressions/identifier.d.ts.map +1 -0
  57. package/dist/parsing/expressions/number.d.ts +25 -0
  58. package/dist/parsing/expressions/number.d.ts.map +1 -0
  59. package/dist/parsing/expressions/operator.d.ts +79 -0
  60. package/dist/parsing/expressions/operator.d.ts.map +1 -0
  61. package/dist/parsing/expressions/reference.d.ts +29 -0
  62. package/dist/parsing/expressions/reference.d.ts.map +1 -0
  63. package/dist/parsing/expressions/string.d.ts +23 -0
  64. package/dist/parsing/expressions/string.d.ts.map +1 -0
  65. package/dist/parsing/functions/aggregate_function.d.ts +42 -0
  66. package/dist/parsing/functions/aggregate_function.d.ts.map +1 -0
  67. package/dist/parsing/functions/async_function.d.ts +52 -0
  68. package/dist/parsing/functions/async_function.d.ts.map +1 -0
  69. package/dist/parsing/functions/avg.d.ts +15 -0
  70. package/dist/parsing/functions/avg.d.ts.map +1 -0
  71. package/dist/parsing/functions/avg.js +20 -2
  72. package/dist/parsing/functions/avg.js.map +1 -1
  73. package/dist/parsing/functions/collect.d.ts +21 -0
  74. package/dist/parsing/functions/collect.d.ts.map +1 -0
  75. package/dist/parsing/functions/collect.js +20 -2
  76. package/dist/parsing/functions/collect.js.map +1 -1
  77. package/dist/parsing/functions/extensibility/index.d.ts +37 -0
  78. package/dist/parsing/functions/extensibility/index.d.ts.map +1 -0
  79. package/dist/parsing/functions/extensibility/index.js +50 -0
  80. package/dist/parsing/functions/extensibility/index.js.map +1 -0
  81. package/dist/parsing/functions/function.d.ts +36 -0
  82. package/dist/parsing/functions/function.d.ts.map +1 -0
  83. package/dist/parsing/functions/function_factory.d.ts +174 -0
  84. package/dist/parsing/functions/function_factory.d.ts.map +1 -0
  85. package/dist/parsing/functions/function_factory.js +44 -47
  86. package/dist/parsing/functions/function_factory.js.map +1 -1
  87. package/dist/parsing/functions/function_metadata.d.ts +134 -0
  88. package/dist/parsing/functions/function_metadata.d.ts.map +1 -0
  89. package/dist/parsing/functions/function_metadata.js +103 -153
  90. package/dist/parsing/functions/function_metadata.js.map +1 -1
  91. package/dist/parsing/functions/functions.d.ts +21 -0
  92. package/dist/parsing/functions/functions.d.ts.map +1 -0
  93. package/dist/parsing/functions/functions.js +37 -2
  94. package/dist/parsing/functions/functions.js.map +1 -1
  95. package/dist/parsing/functions/join.d.ts +9 -0
  96. package/dist/parsing/functions/join.d.ts.map +1 -0
  97. package/dist/parsing/functions/join.js +21 -2
  98. package/dist/parsing/functions/join.js.map +1 -1
  99. package/dist/parsing/functions/predicate_function.d.ts +19 -0
  100. package/dist/parsing/functions/predicate_function.d.ts.map +1 -0
  101. package/dist/parsing/functions/predicate_function.js +3 -0
  102. package/dist/parsing/functions/predicate_function.js.map +1 -1
  103. package/dist/parsing/functions/predicate_sum.d.ts +7 -0
  104. package/dist/parsing/functions/predicate_sum.d.ts.map +1 -0
  105. package/dist/parsing/functions/predicate_sum.js +23 -2
  106. package/dist/parsing/functions/predicate_sum.js.map +1 -1
  107. package/dist/parsing/functions/rand.d.ts +7 -0
  108. package/dist/parsing/functions/rand.d.ts.map +1 -0
  109. package/dist/parsing/functions/rand.js +18 -2
  110. package/dist/parsing/functions/rand.js.map +1 -1
  111. package/dist/parsing/functions/range.d.ts +7 -0
  112. package/dist/parsing/functions/range.d.ts.map +1 -0
  113. package/dist/parsing/functions/range.js +21 -2
  114. package/dist/parsing/functions/range.js.map +1 -1
  115. package/dist/parsing/functions/reducer_element.d.ts +6 -0
  116. package/dist/parsing/functions/reducer_element.d.ts.map +1 -0
  117. package/dist/parsing/functions/replace.d.ts +7 -0
  118. package/dist/parsing/functions/replace.d.ts.map +1 -0
  119. package/dist/parsing/functions/replace.js +22 -2
  120. package/dist/parsing/functions/replace.js.map +1 -1
  121. package/dist/parsing/functions/round.d.ts +7 -0
  122. package/dist/parsing/functions/round.d.ts.map +1 -0
  123. package/dist/parsing/functions/round.js +20 -2
  124. package/dist/parsing/functions/round.js.map +1 -1
  125. package/dist/parsing/functions/size.d.ts +7 -0
  126. package/dist/parsing/functions/size.d.ts.map +1 -0
  127. package/dist/parsing/functions/size.js +20 -2
  128. package/dist/parsing/functions/size.js.map +1 -1
  129. package/dist/parsing/functions/split.d.ts +9 -0
  130. package/dist/parsing/functions/split.d.ts.map +1 -0
  131. package/dist/parsing/functions/split.js +21 -2
  132. package/dist/parsing/functions/split.js.map +1 -1
  133. package/dist/parsing/functions/stringify.d.ts +9 -0
  134. package/dist/parsing/functions/stringify.d.ts.map +1 -0
  135. package/dist/parsing/functions/stringify.js +20 -2
  136. package/dist/parsing/functions/stringify.js.map +1 -1
  137. package/dist/parsing/functions/sum.d.ts +14 -0
  138. package/dist/parsing/functions/sum.d.ts.map +1 -0
  139. package/dist/parsing/functions/sum.js +20 -2
  140. package/dist/parsing/functions/sum.js.map +1 -1
  141. package/dist/parsing/functions/to_json.d.ts +7 -0
  142. package/dist/parsing/functions/to_json.d.ts.map +1 -0
  143. package/dist/parsing/functions/to_json.js +20 -2
  144. package/dist/parsing/functions/to_json.js.map +1 -1
  145. package/dist/parsing/functions/value_holder.d.ts +8 -0
  146. package/dist/parsing/functions/value_holder.d.ts.map +1 -0
  147. package/dist/parsing/logic/case.d.ts +7 -0
  148. package/dist/parsing/logic/case.d.ts.map +1 -0
  149. package/dist/parsing/logic/else.d.ts +7 -0
  150. package/dist/parsing/logic/else.d.ts.map +1 -0
  151. package/dist/parsing/logic/end.d.ts +6 -0
  152. package/dist/parsing/logic/end.d.ts.map +1 -0
  153. package/dist/parsing/logic/then.d.ts +7 -0
  154. package/dist/parsing/logic/then.d.ts.map +1 -0
  155. package/dist/parsing/logic/when.d.ts +7 -0
  156. package/dist/parsing/logic/when.d.ts.map +1 -0
  157. package/dist/parsing/operations/aggregated_return.d.ts +8 -0
  158. package/dist/parsing/operations/aggregated_return.d.ts.map +1 -0
  159. package/dist/parsing/operations/aggregated_with.d.ts +8 -0
  160. package/dist/parsing/operations/aggregated_with.d.ts.map +1 -0
  161. package/dist/parsing/operations/group_by.d.ts +35 -0
  162. package/dist/parsing/operations/group_by.d.ts.map +1 -0
  163. package/dist/parsing/operations/limit.d.ts +10 -0
  164. package/dist/parsing/operations/limit.d.ts.map +1 -0
  165. package/dist/parsing/operations/load.d.ts +48 -0
  166. package/dist/parsing/operations/load.d.ts.map +1 -0
  167. package/dist/parsing/operations/operation.d.ts +39 -0
  168. package/dist/parsing/operations/operation.d.ts.map +1 -0
  169. package/dist/parsing/operations/projection.d.ts +8 -0
  170. package/dist/parsing/operations/projection.d.ts.map +1 -0
  171. package/dist/parsing/operations/return.d.ts +23 -0
  172. package/dist/parsing/operations/return.d.ts.map +1 -0
  173. package/dist/parsing/operations/unwind.d.ts +12 -0
  174. package/dist/parsing/operations/unwind.d.ts.map +1 -0
  175. package/dist/parsing/operations/where.d.ts +26 -0
  176. package/dist/parsing/operations/where.d.ts.map +1 -0
  177. package/dist/parsing/operations/with.d.ts +17 -0
  178. package/dist/parsing/operations/with.d.ts.map +1 -0
  179. package/dist/parsing/parser.d.ts +66 -0
  180. package/dist/parsing/parser.d.ts.map +1 -0
  181. package/dist/parsing/parser.js +2 -3
  182. package/dist/parsing/parser.js.map +1 -1
  183. package/dist/parsing/token_to_node.d.ts +7 -0
  184. package/dist/parsing/token_to_node.d.ts.map +1 -0
  185. package/dist/tokenization/keyword.d.ts +43 -0
  186. package/dist/tokenization/keyword.d.ts.map +1 -0
  187. package/dist/tokenization/operator.d.ts +22 -0
  188. package/dist/tokenization/operator.d.ts.map +1 -0
  189. package/dist/tokenization/string_walker.d.ts +55 -0
  190. package/dist/tokenization/string_walker.d.ts.map +1 -0
  191. package/dist/tokenization/symbol.d.ts +15 -0
  192. package/dist/tokenization/symbol.d.ts.map +1 -0
  193. package/dist/tokenization/token.d.ts +176 -0
  194. package/dist/tokenization/token.d.ts.map +1 -0
  195. package/dist/tokenization/token_mapper.d.ts +40 -0
  196. package/dist/tokenization/token_mapper.d.ts.map +1 -0
  197. package/dist/tokenization/token_type.d.ts +16 -0
  198. package/dist/tokenization/token_type.d.ts.map +1 -0
  199. package/dist/tokenization/tokenizer.d.ts +45 -0
  200. package/dist/tokenization/tokenizer.d.ts.map +1 -0
  201. package/dist/tokenization/trie.d.ts +41 -0
  202. package/dist/tokenization/trie.d.ts.map +1 -0
  203. package/dist/utils/object_utils.d.ts +15 -0
  204. package/dist/utils/object_utils.d.ts.map +1 -0
  205. package/dist/utils/string_utils.d.ts +51 -0
  206. package/dist/utils/string_utils.d.ts.map +1 -0
  207. package/docs/flowquery.min.js +1 -1
  208. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  209. package/misc/apps/RAG/.env.example +14 -0
  210. package/misc/apps/RAG/README.md +0 -7
  211. package/misc/apps/RAG/package.json +16 -7
  212. package/misc/apps/RAG/public/index.html +18 -0
  213. package/misc/apps/RAG/src/App.css +42 -0
  214. package/misc/apps/RAG/src/App.tsx +50 -0
  215. package/misc/apps/RAG/src/components/ApiKeySettings.tsx +245 -0
  216. package/misc/apps/RAG/src/components/ChatContainer.css +67 -0
  217. package/misc/apps/RAG/src/components/ChatContainer.tsx +239 -0
  218. package/misc/apps/RAG/src/components/ChatInput.css +23 -0
  219. package/misc/apps/RAG/src/components/ChatInput.tsx +62 -0
  220. package/misc/apps/RAG/src/components/ChatMessage.css +136 -0
  221. package/misc/apps/RAG/src/components/ChatMessage.tsx +152 -0
  222. package/misc/apps/RAG/src/components/FlowQueryAgent.ts +390 -0
  223. package/misc/apps/RAG/src/components/FlowQueryRunner.css +104 -0
  224. package/misc/apps/RAG/src/components/FlowQueryRunner.tsx +332 -0
  225. package/misc/apps/RAG/src/components/index.ts +15 -0
  226. package/misc/apps/RAG/src/index.tsx +17 -0
  227. package/misc/apps/RAG/src/plugins/PluginRegistry.ts +136 -0
  228. package/misc/apps/RAG/src/plugins/README.md +139 -0
  229. package/misc/apps/RAG/src/plugins/index.ts +72 -0
  230. package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +79 -0
  231. package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +71 -0
  232. package/misc/apps/RAG/src/plugins/loaders/Llm.ts +441 -0
  233. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +161 -0
  234. package/misc/apps/RAG/src/plugins/types.ts +52 -0
  235. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +385 -0
  236. package/misc/apps/RAG/src/prompts/index.ts +10 -0
  237. package/misc/apps/RAG/src/utils/FlowQueryExecutor.ts +131 -0
  238. package/misc/apps/RAG/src/utils/FlowQueryExtractor.ts +203 -0
  239. package/misc/apps/RAG/src/utils/index.ts +9 -0
  240. package/misc/apps/RAG/tsconfig.json +4 -2
  241. package/misc/apps/RAG/webpack.config.js +23 -12
  242. package/package.json +7 -1
  243. package/src/extensibility.ts +9 -0
  244. package/src/parsing/functions/avg.ts +10 -0
  245. package/src/parsing/functions/collect.ts +10 -0
  246. package/src/parsing/functions/extensibility/index.ts +54 -0
  247. package/src/parsing/functions/function_factory.ts +51 -48
  248. package/src/parsing/functions/function_metadata.ts +132 -156
  249. package/src/parsing/functions/functions.ts +27 -0
  250. package/src/parsing/functions/join.ts +11 -0
  251. package/src/parsing/functions/predicate_function.ts +4 -0
  252. package/src/parsing/functions/predicate_sum.ts +13 -0
  253. package/src/parsing/functions/rand.ts +8 -0
  254. package/src/parsing/functions/range.ts +11 -0
  255. package/src/parsing/functions/replace.ts +12 -0
  256. package/src/parsing/functions/round.ts +10 -0
  257. package/src/parsing/functions/size.ts +10 -0
  258. package/src/parsing/functions/split.ts +11 -0
  259. package/src/parsing/functions/stringify.ts +10 -0
  260. package/src/parsing/functions/sum.ts +10 -0
  261. package/src/parsing/functions/to_json.ts +10 -0
  262. package/src/parsing/parser.ts +2 -3
  263. package/tests/parsing/function_plugins.test.ts +11 -11
  264. package/tsconfig.json +4 -1
  265. package/dist/parsing/functions/predicate_function_factory.js +0 -19
  266. package/dist/parsing/functions/predicate_function_factory.js.map +0 -1
  267. package/misc/apps/RAG/src/index.ts +0 -20
  268. 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;