node-red-contrib-ollama 0.6.0 → 0.6.2
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/deploy-site.yml +38 -0
- package/CHANGELOG.md +12 -0
- package/CLAUDE.md +18 -0
- package/examples/Example.json +76 -0
- package/nodes/ollama-create.html +60 -76
- package/nodes/ollama-create.js +44 -125
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Deploy site
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "site/**"
|
|
8
|
+
- ".github/workflows/deploy-site.yml"
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
pages: write
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: pages
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: withastro/action@v3
|
|
26
|
+
with:
|
|
27
|
+
path: site
|
|
28
|
+
node-version: 22
|
|
29
|
+
deploy:
|
|
30
|
+
needs: build
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
environment:
|
|
33
|
+
name: github-pages
|
|
34
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
35
|
+
steps:
|
|
36
|
+
- name: Deploy to GitHub Pages
|
|
37
|
+
id: deployment
|
|
38
|
+
uses: actions/deploy-pages@v4
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [0.6.2] - 2026-09-15
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Added `ollama-ps` and `ollama-abort` to the bundled example flow (`examples/Example.json`) — they were the only two action nodes not demonstrated in any example, which the Node-RED flow library scorecard flags as missing example coverage.
|
|
12
|
+
|
|
13
|
+
## [0.6.1] - 2026-09-13
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `ollama-create` node configuration fields (model, from, quantize, template, license, system, parameters, messages, adapters) were never actually used — only `msg.payload` overrides worked. Switched to `RED.util.evaluateNodeProperty` and fixed the node's `typedInput` setup. Also removed dead `this.editor` references that threw on every save/cancel, made `parameters` a proper JSON field, and made `quantize` optional ([#32](https://github.com/jakubburkiewicz/node-red-contrib-ollama/pull/32), thanks @gorenje).
|
|
18
|
+
|
|
7
19
|
## [0.6.0] - 2026-09-13
|
|
8
20
|
|
|
9
21
|
### Added
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Code notes for this repo
|
|
2
|
+
|
|
3
|
+
Node-RED plugin wrapping the `ollama` JS client library as configurable nodes. Each node type is declared in `package.json` (`node-red.nodes`) as an `.html` + `.js` pair under `nodes/`.
|
|
4
|
+
|
|
5
|
+
## Node categories
|
|
6
|
+
|
|
7
|
+
- **Config nodes** (no direct output, referenced by action nodes via `config.server`/etc.): `ollama-config-server` (host/port, or Ollama Cloud + API key credential), `ollama-config-options`, `ollama-config-format`, `ollama-config-tools`.
|
|
8
|
+
- **Action nodes** (12): `ollama-chat`, `ollama-generate`, `ollama-embed`, `ollama-list`, `ollama-show`, `ollama-ps`, `ollama-pull`, `ollama-push`, `ollama-create`, `ollama-copy`, `ollama-delete`, `ollama-abort` — each wraps one `ollama.js` client method.
|
|
9
|
+
|
|
10
|
+
## Shared patterns (present in every action node — keep them in sync when touching one)
|
|
11
|
+
|
|
12
|
+
- **Host resolution**: with a local server configured, `msg.payload.host` may override the configured host. With Ollama Cloud (`server.useCloud`), the configured host is always used and `msg.payload.host` is **never** allowed to override it — an override would let the configured API key leak to an arbitrary host. See `ollama-chat.js` for the canonical implementation.
|
|
13
|
+
- **Param resolution**: `model` and other per-call params read from `msg.payload.<field>` first, falling back to the node's own config value — respecting the field's configured type (`str` literal vs `msg` property lookup).
|
|
14
|
+
- **Streaming** (`stream: true`): the node consumes the response with `for await` and emits one cloned `msg` per chunk on `payload` — never pass a raw `AbortableAsyncIterator` out to `msg.payload`.
|
|
15
|
+
|
|
16
|
+
## Style
|
|
17
|
+
|
|
18
|
+
- 4-space indentation, a space inside parens in declarations/conditions (`function( RED )`, `if( config.model )`) — match this in new code, even though it's an unusual style choice.
|
package/examples/Example.json
CHANGED
|
@@ -403,5 +403,81 @@
|
|
|
403
403
|
"c74ec4ac9b76d0f4"
|
|
404
404
|
]
|
|
405
405
|
]
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"id": "f1a2b3c4d5e6f708",
|
|
409
|
+
"type": "ollama-ps",
|
|
410
|
+
"z": "3bccaf6e46d3dbf5",
|
|
411
|
+
"name": "Running models",
|
|
412
|
+
"x": 450,
|
|
413
|
+
"y": 700,
|
|
414
|
+
"wires": [
|
|
415
|
+
[
|
|
416
|
+
"03ee0eeb510c4079"
|
|
417
|
+
]
|
|
418
|
+
]
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"id": "a1b2c3d4e5f60718",
|
|
422
|
+
"type": "inject",
|
|
423
|
+
"z": "3bccaf6e46d3dbf5",
|
|
424
|
+
"name": "Trigger",
|
|
425
|
+
"props": [
|
|
426
|
+
{
|
|
427
|
+
"p": "payload"
|
|
428
|
+
}
|
|
429
|
+
],
|
|
430
|
+
"repeat": "",
|
|
431
|
+
"crontab": "",
|
|
432
|
+
"once": false,
|
|
433
|
+
"onceDelay": 0.1,
|
|
434
|
+
"topic": "",
|
|
435
|
+
"payload": "",
|
|
436
|
+
"payloadType": "date",
|
|
437
|
+
"x": 270,
|
|
438
|
+
"y": 700,
|
|
439
|
+
"wires": [
|
|
440
|
+
[
|
|
441
|
+
"f1a2b3c4d5e6f708"
|
|
442
|
+
]
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"id": "b2c3d4e5f6071829",
|
|
447
|
+
"type": "ollama-abort",
|
|
448
|
+
"z": "3bccaf6e46d3dbf5",
|
|
449
|
+
"name": "Abort",
|
|
450
|
+
"x": 430,
|
|
451
|
+
"y": 760,
|
|
452
|
+
"wires": [
|
|
453
|
+
[
|
|
454
|
+
"03ee0eeb510c4079"
|
|
455
|
+
]
|
|
456
|
+
]
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
"id": "c3d4e5f607182930",
|
|
460
|
+
"type": "inject",
|
|
461
|
+
"z": "3bccaf6e46d3dbf5",
|
|
462
|
+
"name": "Trigger",
|
|
463
|
+
"props": [
|
|
464
|
+
{
|
|
465
|
+
"p": "payload"
|
|
466
|
+
}
|
|
467
|
+
],
|
|
468
|
+
"repeat": "",
|
|
469
|
+
"crontab": "",
|
|
470
|
+
"once": false,
|
|
471
|
+
"onceDelay": 0.1,
|
|
472
|
+
"topic": "",
|
|
473
|
+
"payload": "",
|
|
474
|
+
"payloadType": "date",
|
|
475
|
+
"x": 270,
|
|
476
|
+
"y": 760,
|
|
477
|
+
"wires": [
|
|
478
|
+
[
|
|
479
|
+
"b2c3d4e5f6071829"
|
|
480
|
+
]
|
|
481
|
+
]
|
|
406
482
|
}
|
|
407
483
|
]
|
package/nodes/ollama-create.html
CHANGED
|
@@ -3,92 +3,76 @@
|
|
|
3
3
|
category: 'AI',
|
|
4
4
|
color: 'rgb(186 230 253)',
|
|
5
5
|
defaults: {
|
|
6
|
-
name: { value: '
|
|
6
|
+
name: { value: '' },
|
|
7
7
|
server: { value: '', type: 'ollama-config-server', required: false },
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
stream: { value: false, required: false },
|
|
9
|
+
|
|
10
|
+
model: { value: '', required: true },
|
|
11
|
+
modelType: { value: "str" },
|
|
12
|
+
|
|
13
|
+
from: { value: '', required: true },
|
|
14
|
+
fromType: { value: "str" },
|
|
15
|
+
|
|
16
|
+
quantize: { value: '', required: false },
|
|
17
|
+
quantizeType: { value: "str" },
|
|
18
|
+
|
|
19
|
+
template: { value: '', required: false },
|
|
20
|
+
templateType: { value: "str" },
|
|
21
|
+
|
|
22
|
+
license: { value: '', required: false },
|
|
23
|
+
licenseType: { value: "str" },
|
|
24
|
+
|
|
25
|
+
system: { value: '', required: false },
|
|
26
|
+
systemType: { value: "str" },
|
|
27
|
+
|
|
28
|
+
parameters: { value: '{}', required: false },
|
|
29
|
+
parametersType: { value: "json" },
|
|
30
|
+
|
|
31
|
+
messages: { value: '', required: false },
|
|
32
|
+
messagesType: { value: "str" },
|
|
33
|
+
|
|
34
|
+
adapters: { value: '', required: false },
|
|
35
|
+
adaptersType: { value: "str" }
|
|
18
36
|
},
|
|
19
37
|
inputs: 1,
|
|
20
38
|
outputs: 1,
|
|
21
39
|
icon: 'ollama.png',
|
|
22
40
|
label: function() {
|
|
23
|
-
return this.name || 'ollama-create';
|
|
41
|
+
return this.name || (this.modelType === 'str' && this.model) || 'ollama-create';
|
|
24
42
|
},
|
|
43
|
+
|
|
25
44
|
oneditprepare: function() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
typeField: '#node-input-templateType'
|
|
52
|
-
} )
|
|
53
|
-
|
|
54
|
-
$( '#node-input-license' ).typedInput( {
|
|
55
|
-
type: 'str',
|
|
56
|
-
types: [ 'str', 'msg', 'flow', 'global' ],
|
|
57
|
-
typeField: '#node-input-licenseType'
|
|
58
|
-
} )
|
|
59
|
-
|
|
60
|
-
$( '#node-input-system' ).typedInput( {
|
|
61
|
-
type: 'str',
|
|
62
|
-
types: [ 'str', 'msg', 'flow', 'global' ],
|
|
63
|
-
typeField: '#node-input-systemType'
|
|
64
|
-
} )
|
|
65
|
-
|
|
66
|
-
$( '#node-input-parameters' ).typedInput( {
|
|
67
|
-
type: 'str',
|
|
68
|
-
types: [ 'str', 'msg', 'flow', 'global' ],
|
|
69
|
-
typeField: '#node-input-parametersType'
|
|
70
|
-
} )
|
|
71
|
-
|
|
72
|
-
$( '#node-input-messages' ).typedInput( {
|
|
73
|
-
type: 'str',
|
|
74
|
-
types: [ 'str', 'msg', 'flow', 'global' ],
|
|
75
|
-
typeField: '#node-input-messagesType'
|
|
76
|
-
} )
|
|
77
|
-
|
|
78
|
-
$( '#node-input-adapters' ).typedInput( {
|
|
79
|
-
type: 'str',
|
|
80
|
-
types: [ 'str', 'msg', 'flow', 'global' ],
|
|
81
|
-
typeField: '#node-input-adaptersType'
|
|
82
|
-
} )
|
|
45
|
+
[
|
|
46
|
+
"model",
|
|
47
|
+
"from",
|
|
48
|
+
"quantize",
|
|
49
|
+
"template",
|
|
50
|
+
"license",
|
|
51
|
+
"system",
|
|
52
|
+
"messages",
|
|
53
|
+
"adapters"
|
|
54
|
+
].forEach( parameter => {
|
|
55
|
+
$( `#node-input-${parameter}` ).typedInput( {
|
|
56
|
+
types: [ 'str', 'msg', 'flow', 'global' ],
|
|
57
|
+
typeField: `#node-input-${parameter}Type`
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// not 'str' but 'json'
|
|
62
|
+
[
|
|
63
|
+
"parameters"
|
|
64
|
+
].forEach( parameter => {
|
|
65
|
+
$( `#node-input-${parameter}` ).typedInput( {
|
|
66
|
+
types: [ 'json', 'msg', 'flow', 'global' ],
|
|
67
|
+
typeField: `#node-input-${parameter}Type`
|
|
68
|
+
})
|
|
69
|
+
});
|
|
83
70
|
},
|
|
71
|
+
|
|
84
72
|
oneditsave: function() {
|
|
85
|
-
this.modelfile = this.editor.getValue()
|
|
86
|
-
this.editor.destroy()
|
|
87
|
-
delete this.editor
|
|
88
73
|
},
|
|
74
|
+
|
|
89
75
|
oneditcancel: function() {
|
|
90
|
-
this.editor.destroy()
|
|
91
|
-
delete this.editor
|
|
92
76
|
}
|
|
93
77
|
} )
|
|
94
78
|
</script>
|
|
@@ -117,7 +101,7 @@
|
|
|
117
101
|
</div>
|
|
118
102
|
|
|
119
103
|
<div class="form-row">
|
|
120
|
-
<label for="node-input-stream"><i class="fa fa-
|
|
104
|
+
<label for="node-input-stream"><i class="fa fa-umbrella"></i> Stream</label>
|
|
121
105
|
<input type="checkbox" id="node-input-stream" />
|
|
122
106
|
</div>
|
|
123
107
|
|
|
@@ -128,7 +112,7 @@
|
|
|
128
112
|
</div>
|
|
129
113
|
|
|
130
114
|
<div class="form-row">
|
|
131
|
-
<label for="node-input-template"><i class="fa fa-file-code"></i> Template</label>
|
|
115
|
+
<label for="node-input-template"><i class="fa fa-file-code-o"></i> Template</label>
|
|
132
116
|
<input type="text" id="node-input-template" />
|
|
133
117
|
<input type="hidden" id="node-input-templateType" />
|
|
134
118
|
</div>
|
package/nodes/ollama-create.js
CHANGED
|
@@ -4,19 +4,9 @@ module.exports = function( RED ) {
|
|
|
4
4
|
function OllamaCreateNode( config ) {
|
|
5
5
|
RED.nodes.createNode( this, config )
|
|
6
6
|
|
|
7
|
-
this.modelType = config.modelType || 'str'
|
|
8
|
-
this.fromType = config.from || 'str'
|
|
9
|
-
this.stream = config.stream || false
|
|
10
|
-
this.quantize = config.quantize || 'str'
|
|
11
|
-
this.template = config.template || null
|
|
12
|
-
this.license = config.license || null
|
|
13
|
-
this.system = config.system || null
|
|
14
|
-
this.parameters = config.parameters || 'str'
|
|
15
|
-
this.messages = config.messages || 'str'
|
|
16
|
-
this.adapters = config.adapters || 'str'
|
|
17
|
-
this.pathType = config.pathType || 'str'
|
|
18
|
-
|
|
19
7
|
const node = this
|
|
8
|
+
const cfg = config
|
|
9
|
+
|
|
20
10
|
node.on( 'input', async function( msg ) {
|
|
21
11
|
const server = RED.nodes.getNode( config.server )
|
|
22
12
|
|
|
@@ -55,163 +45,92 @@ module.exports = function( RED ) {
|
|
|
55
45
|
}
|
|
56
46
|
}
|
|
57
47
|
|
|
58
|
-
const
|
|
48
|
+
const stream = (msg?.payload?.stream !== undefined) ? msg.payload.stream : cfg.stream
|
|
59
49
|
|
|
60
50
|
let model = null
|
|
61
51
|
if( msg?.payload?.model ) {
|
|
62
|
-
model = msg
|
|
63
|
-
} else
|
|
64
|
-
|
|
65
|
-
model = config.model
|
|
66
|
-
} else if( node.modelType === 'msg' ) {
|
|
67
|
-
model = msg[ config.model ]
|
|
68
|
-
} else if( node.modelType === 'flow' ) {
|
|
69
|
-
model = node.context().flow.get( config.model )
|
|
70
|
-
} else if( node.modelType === 'global' ) {
|
|
71
|
-
model = node.context().global.get( config.model )
|
|
72
|
-
}
|
|
52
|
+
model = msg.payload.model
|
|
53
|
+
} else {
|
|
54
|
+
model = RED.util.evaluateNodeProperty(cfg.model, cfg.modelType, node, msg)
|
|
73
55
|
}
|
|
74
56
|
|
|
75
57
|
let from = null
|
|
76
58
|
if( msg?.payload?.from ) {
|
|
77
|
-
from = msg
|
|
59
|
+
from = msg.payload.from
|
|
78
60
|
} else if( !!config.from ) {
|
|
79
|
-
|
|
80
|
-
from = config.from
|
|
81
|
-
} else if( node.fromType === 'msg' ) {
|
|
82
|
-
from = msg[ config.from ]
|
|
83
|
-
} else if( node.fromType === 'flow' ) {
|
|
84
|
-
from = node.context().flow.get( config.from )
|
|
85
|
-
} else if( node.fromType === 'global' ) {
|
|
86
|
-
from = node.context().global.get( config.from )
|
|
87
|
-
}
|
|
61
|
+
from = RED.util.evaluateNodeProperty(cfg.from, cfg.fromType, node, msg)
|
|
88
62
|
}
|
|
89
63
|
|
|
90
|
-
const stream = ( msg?.payload?.stream !== undefined ) ? msg?.payload?.stream : node.stream
|
|
91
|
-
|
|
92
64
|
let quantize = null
|
|
93
65
|
if( msg?.payload?.quantize ) {
|
|
94
|
-
quantize = msg
|
|
66
|
+
quantize = msg.payload.quantize
|
|
95
67
|
} else if( !!config.quantize ) {
|
|
96
|
-
|
|
97
|
-
quantize = config.quantize
|
|
98
|
-
} else if( node.quantize === 'msg' ) {
|
|
99
|
-
quantize = msg[ config.quantize ]
|
|
100
|
-
} else if( node.quantize === 'flow' ) {
|
|
101
|
-
quantize = node.context().flow.get( config.quantize )
|
|
102
|
-
} else if( node.quantize === 'global' ) {
|
|
103
|
-
quantize = node.context().global.get( config.quantize )
|
|
104
|
-
}
|
|
68
|
+
quantize = RED.util.evaluateNodeProperty(cfg.quantize, cfg.quantizeType, node, msg)
|
|
105
69
|
}
|
|
106
70
|
|
|
107
71
|
let template = null
|
|
108
72
|
if( msg?.payload?.template ) {
|
|
109
|
-
template = msg
|
|
73
|
+
template = msg.payload.template
|
|
110
74
|
} else if( !!config.template ) {
|
|
111
|
-
|
|
112
|
-
template = config.template
|
|
113
|
-
} else if( node.template === 'msg' ) {
|
|
114
|
-
template = msg[ config.template ]
|
|
115
|
-
} else if( node.template === 'flow' ) {
|
|
116
|
-
template = node.context().flow.get( config.template )
|
|
117
|
-
} else if( node.template === 'global' ) {
|
|
118
|
-
template = node.context().global.get( config.template )
|
|
119
|
-
}
|
|
75
|
+
template = RED.util.evaluateNodeProperty(cfg.template, cfg.templateType, node, msg)
|
|
120
76
|
}
|
|
121
77
|
|
|
122
78
|
let license = null
|
|
123
79
|
if( msg?.payload?.license ) {
|
|
124
|
-
license = msg
|
|
80
|
+
license = msg.payload.license
|
|
125
81
|
} else if( !!config.license ) {
|
|
126
|
-
|
|
127
|
-
license = config.license
|
|
128
|
-
} else if( node.license === 'msg' ) {
|
|
129
|
-
license = msg[ config.license ]
|
|
130
|
-
} else if( node.license === 'flow' ) {
|
|
131
|
-
license = node.context().flow.get( config.license )
|
|
132
|
-
} else if( node.license === 'global' ) {
|
|
133
|
-
license = node.context().global.get( config.license )
|
|
134
|
-
}
|
|
82
|
+
license = RED.util.evaluateNodeProperty(cfg.license, cfg.licenseType, node, msg)
|
|
135
83
|
}
|
|
136
84
|
|
|
137
85
|
let system = null
|
|
138
86
|
if( msg?.payload?.system ) {
|
|
139
|
-
system = msg
|
|
87
|
+
system = msg.payload.system
|
|
140
88
|
} else if( !!config.system ) {
|
|
141
|
-
|
|
142
|
-
system = config.system
|
|
143
|
-
} else if( node.system === 'msg' ) {
|
|
144
|
-
system = msg[ config.system ]
|
|
145
|
-
} else if( node.system === 'flow' ) {
|
|
146
|
-
system = node.context().flow.get( config.system )
|
|
147
|
-
} else if( node.system === 'global' ) {
|
|
148
|
-
system = node.context().global.get( config.system )
|
|
149
|
-
}
|
|
89
|
+
system = RED.util.evaluateNodeProperty(cfg.system, cfg.systemType, node, msg)
|
|
150
90
|
}
|
|
151
91
|
|
|
152
92
|
let parameters = null
|
|
153
93
|
if( msg?.payload?.parameters ) {
|
|
154
|
-
parameters = msg
|
|
94
|
+
parameters = msg.payload.parameters
|
|
155
95
|
} else if( !!config.parameters ) {
|
|
156
|
-
|
|
157
|
-
parameters = config.parameters
|
|
158
|
-
} else if( node.parameters === 'msg' ) {
|
|
159
|
-
parameters = msg[ config.parameters ]
|
|
160
|
-
} else if( node.parameters === 'flow' ) {
|
|
161
|
-
parameters = node.context().flow.get( config.parameters )
|
|
162
|
-
} else if( node.parameters === 'global' ) {
|
|
163
|
-
parameters = node.context().global.get( config.parameters )
|
|
164
|
-
}
|
|
96
|
+
parameters = RED.util.evaluateNodeProperty(cfg.parameters, cfg.parametersType, node, msg)
|
|
165
97
|
}
|
|
166
98
|
|
|
167
99
|
let messages = null
|
|
168
100
|
if( msg?.payload?.messages ) {
|
|
169
|
-
messages = msg
|
|
101
|
+
messages = msg.payload.messages
|
|
170
102
|
} else if( !!config.messages ) {
|
|
171
|
-
|
|
172
|
-
messages = config.messages
|
|
173
|
-
} else if( node.messages === 'msg' ) {
|
|
174
|
-
messages = msg[ config.messages ]
|
|
175
|
-
} else if( node.messages === 'flow' ) {
|
|
176
|
-
messages = node.context().flow.get( config.messages )
|
|
177
|
-
} else if( node.messages === 'global' ) {
|
|
178
|
-
messages = node.context().global.get( config.messages )
|
|
179
|
-
}
|
|
103
|
+
messages = RED.util.evaluateNodeProperty(cfg.messages, cfg.messagesType, node, msg)
|
|
180
104
|
}
|
|
181
105
|
|
|
182
106
|
let adapters = null
|
|
183
107
|
if( msg?.payload?.adapters ) {
|
|
184
|
-
adapters = msg
|
|
108
|
+
adapters = msg.payload.adapters
|
|
185
109
|
} else if( !!config.adapters ) {
|
|
186
|
-
|
|
187
|
-
adapters = config.adapters
|
|
188
|
-
} else if( node.adapters === 'msg' ) {
|
|
189
|
-
adapters = msg[ config.adapters ]
|
|
190
|
-
} else if( node.adapters === 'flow' ) {
|
|
191
|
-
adapters = node.context().flow.get( config.adapters )
|
|
192
|
-
} else if( node.adapters === 'global' ) {
|
|
193
|
-
adapters = node.context().global.get( config.adapters )
|
|
194
|
-
}
|
|
110
|
+
adapters = RED.util.evaluateNodeProperty(cfg.adapters, cfg.adaptersType, node, msg)
|
|
195
111
|
}
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
112
|
+
|
|
113
|
+
const ollama = new Ollama(ollamaConfig)
|
|
114
|
+
|
|
115
|
+
ollama.create( {
|
|
116
|
+
model,
|
|
117
|
+
from,
|
|
118
|
+
stream,
|
|
119
|
+
quantize,
|
|
120
|
+
template,
|
|
121
|
+
license,
|
|
122
|
+
system,
|
|
123
|
+
parameters,
|
|
124
|
+
messages,
|
|
125
|
+
adapters
|
|
126
|
+
})
|
|
127
|
+
.then( response => {
|
|
128
|
+
msg.payload = response
|
|
129
|
+
node.send(msg)
|
|
130
|
+
})
|
|
131
|
+
.catch( error => {
|
|
132
|
+
node.error( error )
|
|
133
|
+
})
|
|
215
134
|
} )
|
|
216
135
|
}
|
|
217
136
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-ollama",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Add AI functionality to your flows! This module includes a set of nodes that enable easy communication with Ollama, enriching your projects with intelligent solutions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|