@flowfuse/nr-assistant 0.4.1-91d3033-202508180852.0 → 0.5.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### 0.5.0
2
+ - Bump actions/checkout from 4.2.2 to 5.0.0 (#69)
3
+ - Bump flowfuse/github-actions-workflows from 0.40.0 to 0.42.0 (#68)
4
+ - Add tables codelens feature (#72) @Steve-Mcl
5
+
1
6
  ### 0.4.0
2
7
  - update package for 0.4.0 release
3
8
  - Bump flowfuse/github-actions-workflows from 0.39.0 to 0.40.0 (#60)
package/index.html CHANGED
@@ -24,6 +24,7 @@
24
24
  const modulesAllowed = RED.settings.functionExternalModules !== false
25
25
  const assistantOptions = {
26
26
  enabled: false,
27
+ tablesEnabled: false,
27
28
  requestTimeout: AI_TIMEOUT
28
29
  }
29
30
  let assistantInitialised = false
@@ -42,6 +43,7 @@
42
43
  if (topic === 'nr-assistant/initialise') {
43
44
  assistantOptions.enabled = !!msg?.enabled
44
45
  assistantOptions.requestTimeout = msg?.requestTimeout || AI_TIMEOUT
46
+ assistantOptions.tablesEnabled = msg?.tablesEnabled === true
45
47
  initAssistant(msg)
46
48
  RED.actions.add('flowfuse-nr-assistant:function-builder', showFunctionBuilderPrompt, { label: '@flowfuse/nr-assistant/flowfuse-nr-assistant:function-builder.action.label' })
47
49
  setMenuShortcutKey('ff-assistant-function-builder', 'red-ui-workspace', 'ctrl-alt-f', 'flowfuse-nr-assistant:function-builder')
@@ -69,7 +71,7 @@
69
71
  }
70
72
  RED.plugins.registerPlugin('flowfuse-nr-assistant', plugin)
71
73
 
72
- function initAssistant () {
74
+ function initAssistant (options) {
73
75
  if (assistantInitialised) {
74
76
  return
75
77
  }
@@ -88,6 +90,7 @@
88
90
  const jsonCommandId = 'nr-assistant-json-inline'
89
91
  const cssCommandId = 'nr-assistant-css-inline'
90
92
  const db2uiTemplateCommandId = 'nr-assistant-html-dashboard2-template-inline'
93
+ const ffTablesNodeCommandId = 'nr-assistant-ff-tables-node-inline'
91
94
 
92
95
  debug('registering code lens providers...')
93
96
 
@@ -264,6 +267,48 @@
264
267
  }
265
268
  })
266
269
 
270
+ assistantOptions.tablesEnabled && monaco.languages.registerCodeLensProvider('sql', {
271
+ provideCodeLenses: function (model, token) {
272
+ debug('SQL CodeLens provider called', model, token)
273
+ const thisEditor = getMonacoEditorForModel(model)
274
+ if (!thisEditor) {
275
+ return
276
+ }
277
+ const node = RED.view.selection()?.nodes?.[0]
278
+ // only support tables query nodes for now
279
+ if (!node || node.type !== 'tables-query' || node._def?.set?.id !== '@flowfuse/nr-tables-nodes/tables-query') {
280
+ return
281
+ }
282
+ return {
283
+ lenses: [
284
+ {
285
+ range: {
286
+ startLineNumber: 1,
287
+ startColumn: 1,
288
+ endLineNumber: 2,
289
+ endColumn: 1
290
+ },
291
+ id: ffTablesNodeCommandId
292
+ }
293
+ ],
294
+ dispose: () => { }
295
+ }
296
+ },
297
+ resolveCodeLens: function (model, codeLens, token) {
298
+ debug('SQL CodeLens resolve called', model, codeLens, token)
299
+ if (codeLens.id !== ffTablesNodeCommandId) {
300
+ return codeLens
301
+ }
302
+ codeLens.command = {
303
+ id: codeLens.id,
304
+ title: 'Ask the FlowFuse Assistant 🪄',
305
+ tooltip: 'Click to ask FlowFuse Assistant for help with PostgreSQL',
306
+ arguments: [model, codeLens, token]
307
+ }
308
+ return codeLens
309
+ }
310
+ })
311
+
267
312
  debug('registering commands...')
268
313
 
269
314
  monaco.editor.registerCommand(funcCommandId, function (accessor, model, codeLens, token) {
@@ -581,6 +626,69 @@
581
626
  }
582
627
  })
583
628
 
629
+ assistantOptions.tablesEnabled && monaco.editor.registerCommand(ffTablesNodeCommandId, function (accessor, model, codeLens, token) {
630
+ debug('running command', ffTablesNodeCommandId)
631
+ const node = RED.view.selection()?.nodes?.[0]
632
+ if (!node) {
633
+ console.warn('No node selected') // should not happen
634
+ return
635
+ }
636
+ if (!assistantOptions.enabled) {
637
+ RED.notify(plugin._('errors.assistant-not-enabled'), 'warning')
638
+ return
639
+ }
640
+ const thisEditor = getMonacoEditorForModel(model)
641
+ if (thisEditor) {
642
+ if (!document.body.contains(thisEditor.getDomNode())) {
643
+ console.warn('Editor is no longer in the DOM, cannot proceed.')
644
+ return
645
+ }
646
+
647
+ // FUTURE: for including selected text in the context for features like "fix my code", "refactor this", "what is this?" etc
648
+ // const userSelection = triggeredEditor.getSelection()
649
+ // const selectedText = model.getValueInRange(userSelection)
650
+ /** @type {PromptOptions} */
651
+ const promptOptions = {
652
+ method: 'flowfuse-tables-query',
653
+ lang: 'sql',
654
+ dialect: 'g',
655
+ type: node.type
656
+ // selectedText: model.getValueInRange(userSelection)
657
+ }
658
+ /** @type {PromptUIOptions} */
659
+ const uiOptions = {
660
+ title: 'FlowFuse Assistant : FlowFuse Query',
661
+ explanation: 'The FlowFuse Assistant can help you write SQL queries.',
662
+ description: 'Enter a short description of what you want it to do.'
663
+ }
664
+ doPrompt(node, thisEditor, promptOptions, uiOptions, (error, response) => {
665
+ if (error) {
666
+ console.warn('Error processing request', error)
667
+ return
668
+ }
669
+ debug('sql response', response)
670
+ const responseData = response?.data
671
+ if (responseData && responseData.sql) {
672
+ // ensure the editor is still present in the DOM
673
+ if (!document.body.contains(thisEditor.getDomNode())) {
674
+ console.warn('Editor is no longer in the DOM')
675
+ return
676
+ }
677
+ thisEditor.focus()
678
+ const currentSelection = thisEditor.getSelection()
679
+ thisEditor.executeEdits('', [
680
+ {
681
+ range: new monaco.Range(currentSelection.startLineNumber, currentSelection.startColumn, currentSelection.endLineNumber, currentSelection.endColumn),
682
+ text: responseData.sql
683
+ }
684
+ ])
685
+ }
686
+ })
687
+ } else {
688
+ console.warn('Could not find editor for model', model.uri.toString())
689
+ }
690
+ })
691
+
584
692
  const toolbarMenuButton = $('<li><a id="red-ui-header-button-ff-ai" class="button" href="#"></a></li>')
585
693
  const toolbarMenuButtonAnchor = toolbarMenuButton.find('a')
586
694
  const deployButtonLi = $('#red-ui-header-button-deploy').closest('li')
package/lib/assistant.js CHANGED
@@ -6,20 +6,12 @@ const { getLongestUpstreamPath } = require('./flowGraph')
6
6
  const { hasProperty } = require('./utils')
7
7
  const semver = require('semver')
8
8
 
9
- const FF_ASSISTANT_USER_AGENT = 'FlowFuse Assistant Plugin/' + require('../package.json').version
10
-
9
+ // import typedef AssistantSettings
11
10
  /**
12
- * @typedef {Object} AssistantSettings
13
- * @property {boolean} enabled - Whether the Assistant is enabled
14
- * @property {number} requestTimeout - The timeout for requests to the Assistant backend in milliseconds
15
- * @property {string} url - The URL of the Assistant server
16
- * @property {string} token - The authentication token for the Assistant server
17
- * @property {Object} [got] - The got instance to use for HTTP requests
18
- * @property {Object} completions - Settings for completions
19
- * @property {string} completions.modelUrl - The URL to the ML model
20
- * @property {string} completions.vocabularyUrl - The URL to the completions vocabulary lookup data
11
+ * @typedef {import('./settings.js').AssistantSettings} AssistantSettings
21
12
  */
22
13
 
14
+ const FF_ASSISTANT_USER_AGENT = 'FlowFuse Assistant Plugin/' + require('../package.json').version
23
15
  class Assistant {
24
16
  constructor () {
25
17
  // Main properties
@@ -70,7 +62,7 @@ class Assistant {
70
62
  await this.dispose() // Dispose of any existing instance before initializing a new one
71
63
  this.RED = RED
72
64
  this.options = options || {}
73
- this.got = this.options.got || require('got') // got can me passed in for testing purposes
65
+ this.got = this.options.got || require('got') // got can be passed in for testing purposes
74
66
 
75
67
  if (!this.options.enabled) {
76
68
  RED.log.info('FlowFuse Assistant Plugin is not enabled')
@@ -88,6 +80,7 @@ class Assistant {
88
80
 
89
81
  const clientSettings = {
90
82
  enabled: this.options.enabled !== false && !!this.options.url,
83
+ tablesEnabled: this.options.tables?.enabled === true,
91
84
  requestTimeout: this.options.requestTimeout || 60000
92
85
  }
93
86
  RED.comms.publish('nr-assistant/initialise', clientSettings, true /* retain */)
package/lib/settings.js CHANGED
@@ -1,4 +1,23 @@
1
+ /**
2
+ * @typedef {Object} AssistantSettings
3
+ * @property {boolean} enabled - Whether the Assistant is enabled
4
+ * @property {number} requestTimeout - The timeout for requests to the Assistant backend in milliseconds
5
+ * @property {string} url - The URL of the Assistant server
6
+ * @property {string} token - The authentication token for the Assistant server
7
+ * @property {Object} [got] - The got instance to use for HTTP requests
8
+ * @property {Object} completions - Settings for completions
9
+ * @property {string} completions.modelUrl - The URL to the ML model
10
+ * @property {string} completions.vocabularyUrl - The URL to the completions vocabulary lookup data
11
+ * @property {Object} tables - Settings for tables
12
+ * @property {Boolean} tables.enabled - Whether the tables feature is enabled
13
+ */
14
+
1
15
  module.exports = {
16
+ /**
17
+ * Get the Assistant settings from the RED instance.
18
+ * @param {Object} RED - The RED instance
19
+ * @returns {AssistantSettings} - The Assistant settings
20
+ */
2
21
  getSettings: (RED) => {
3
22
  const assistantSettings = (RED.settings.flowforge && RED.settings.flowforge.assistant) || {}
4
23
  if (assistantSettings.enabled !== true) {
@@ -13,6 +32,9 @@ module.exports = {
13
32
  modelUrl: null,
14
33
  vocabularyUrl: null
15
34
  }
35
+ assistantSettings.tables = {
36
+ enabled: !!(RED.settings.flowforge?.tables?.token) // for MVP, use the presence of a token is an indicator that tables are enabled
37
+ }
16
38
  return assistantSettings
17
39
  }
18
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowfuse/nr-assistant",
3
- "version": "0.4.1-91d3033-202508180852.0",
3
+ "version": "0.5.0",
4
4
  "description": "FlowFuse Node-RED assistant plugin",
5
5
  "main": "index.js",
6
6
  "scripts": {