node-red-contrib-ollama 0.5.3 → 0.6.1
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 +24 -0
- package/examples/Example.json +2 -2
- package/nodes/ollama-abort.js +4 -1
- package/nodes/ollama-chat.js +15 -4
- package/nodes/ollama-copy.js +4 -1
- package/nodes/ollama-create.html +60 -76
- package/nodes/ollama-create.js +48 -126
- package/nodes/ollama-delete.js +4 -1
- package/nodes/ollama-embed.js +4 -1
- package/nodes/ollama-generate.js +15 -4
- package/nodes/ollama-list.js +4 -1
- package/nodes/ollama-ps.js +4 -1
- package/nodes/ollama-pull.js +15 -4
- package/nodes/ollama-push.js +15 -4
- package/nodes/ollama-show.js +4 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ 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.1] - 2026-09-13
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `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).
|
|
12
|
+
|
|
13
|
+
## [0.6.0] - 2026-09-13
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `ollama-chat`, `ollama-generate`, `ollama-pull` and `ollama-push` now emit one output message per streamed chunk when `stream` is `true`, instead of a single message with an unusable raw iterator as `payload` ([#17](https://github.com/jakubburkiewicz/node-red-contrib-ollama/issues/17)). Non-streaming behavior (the default) is unchanged.
|
|
18
|
+
|
|
19
|
+
## [0.5.5] - 2026-09-13
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- The "Embeddings" node in the example flow using a stale node type (`ollama-embeddings` instead of `ollama-embed`) and a payload shaped for `ollama-generate` instead of `ollama-embed` ([#18](https://github.com/jakubburkiewicz/node-red-contrib-ollama/issues/18)).
|
|
24
|
+
|
|
25
|
+
## [0.5.4] - 2026-09-13
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- `msg.payload.host` being silently ignored on all nodes when the node's Server field is set to "none", instead of being used to reach the Ollama instance directly ([#28](https://github.com/jakubburkiewicz/node-red-contrib-ollama/issues/28), [#20](https://github.com/jakubburkiewicz/node-red-contrib-ollama/issues/20)).
|
|
30
|
+
|
|
7
31
|
## [0.5.3] - 2026-09-13
|
|
8
32
|
|
|
9
33
|
### Fixed
|
package/examples/Example.json
CHANGED
|
@@ -254,7 +254,7 @@
|
|
|
254
254
|
},
|
|
255
255
|
{
|
|
256
256
|
"id": "66e2fb897f54a093",
|
|
257
|
-
"type": "ollama-
|
|
257
|
+
"type": "ollama-embed",
|
|
258
258
|
"z": "3bccaf6e46d3dbf5",
|
|
259
259
|
"name": "Embeddings",
|
|
260
260
|
"x": 450,
|
|
@@ -280,7 +280,7 @@
|
|
|
280
280
|
"once": false,
|
|
281
281
|
"onceDelay": 0.1,
|
|
282
282
|
"topic": "",
|
|
283
|
-
"payload": "{\"model\":\"llama2\",\"
|
|
283
|
+
"payload": "{\"model\":\"llama2\",\"input\":\"Why is the sky blue?\"}",
|
|
284
284
|
"payloadType": "json",
|
|
285
285
|
"x": 270,
|
|
286
286
|
"y": 320,
|
package/nodes/ollama-abort.js
CHANGED
|
@@ -10,7 +10,7 @@ module.exports = function( RED ) {
|
|
|
10
10
|
|
|
11
11
|
// Construct host URL
|
|
12
12
|
let host = null
|
|
13
|
-
if (
|
|
13
|
+
if ( server ) {
|
|
14
14
|
if ( server.useCloud ) {
|
|
15
15
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
16
16
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -30,6 +30,9 @@ module.exports = function( RED ) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
} else {
|
|
34
|
+
// No server configured - allow msg.payload.host directly
|
|
35
|
+
host = msg?.payload?.host || null
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
// Ollama Cloud configuration
|
package/nodes/ollama-chat.js
CHANGED
|
@@ -15,7 +15,7 @@ module.exports = function( RED ) {
|
|
|
15
15
|
|
|
16
16
|
// Construct host URL
|
|
17
17
|
let host = null
|
|
18
|
-
if (
|
|
18
|
+
if ( server ) {
|
|
19
19
|
if ( server.useCloud ) {
|
|
20
20
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
21
21
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -35,6 +35,9 @@ module.exports = function( RED ) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
} else {
|
|
39
|
+
// No server configured - allow msg.payload.host directly
|
|
40
|
+
host = msg?.payload?.host || null
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
// Ollama Cloud configuration
|
|
@@ -114,9 +117,17 @@ module.exports = function( RED ) {
|
|
|
114
117
|
tools,
|
|
115
118
|
options
|
|
116
119
|
} )
|
|
117
|
-
.then( response => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
.then( async response => {
|
|
121
|
+
if ( stream ) {
|
|
122
|
+
for await ( const part of response ) {
|
|
123
|
+
const chunkMsg = RED.util.cloneMessage( msg )
|
|
124
|
+
chunkMsg.payload = part
|
|
125
|
+
node.send( chunkMsg )
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
msg.payload = response
|
|
129
|
+
node.send( msg )
|
|
130
|
+
}
|
|
120
131
|
} )
|
|
121
132
|
.catch( error => {
|
|
122
133
|
node.error( error )
|
package/nodes/ollama-copy.js
CHANGED
|
@@ -13,7 +13,7 @@ module.exports = function( RED ) {
|
|
|
13
13
|
|
|
14
14
|
// Construct host URL
|
|
15
15
|
let host = null
|
|
16
|
-
if (
|
|
16
|
+
if ( server ) {
|
|
17
17
|
if ( server.useCloud ) {
|
|
18
18
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
19
19
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -33,6 +33,9 @@ module.exports = function( RED ) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
} else {
|
|
37
|
+
// No server configured - allow msg.payload.host directly
|
|
38
|
+
host = msg?.payload?.host || null
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
// Ollama Cloud configuration
|
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,25 +4,15 @@ 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
|
|
|
23
13
|
// Construct host URL
|
|
24
14
|
let host = null
|
|
25
|
-
if (
|
|
15
|
+
if ( server ) {
|
|
26
16
|
if ( server.useCloud ) {
|
|
27
17
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
28
18
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -42,6 +32,9 @@ module.exports = function( RED ) {
|
|
|
42
32
|
}
|
|
43
33
|
}
|
|
44
34
|
}
|
|
35
|
+
} else {
|
|
36
|
+
// No server configured - allow msg.payload.host directly
|
|
37
|
+
host = msg?.payload?.host || null
|
|
45
38
|
}
|
|
46
39
|
|
|
47
40
|
// Ollama Cloud configuration
|
|
@@ -52,163 +45,92 @@ module.exports = function( RED ) {
|
|
|
52
45
|
}
|
|
53
46
|
}
|
|
54
47
|
|
|
55
|
-
const
|
|
48
|
+
const stream = (msg?.payload?.stream !== undefined) ? msg.payload.stream : cfg.stream
|
|
56
49
|
|
|
57
50
|
let model = null
|
|
58
51
|
if( msg?.payload?.model ) {
|
|
59
|
-
model = msg
|
|
60
|
-
} else
|
|
61
|
-
|
|
62
|
-
model = config.model
|
|
63
|
-
} else if( node.modelType === 'msg' ) {
|
|
64
|
-
model = msg[ config.model ]
|
|
65
|
-
} else if( node.modelType === 'flow' ) {
|
|
66
|
-
model = node.context().flow.get( config.model )
|
|
67
|
-
} else if( node.modelType === 'global' ) {
|
|
68
|
-
model = node.context().global.get( config.model )
|
|
69
|
-
}
|
|
52
|
+
model = msg.payload.model
|
|
53
|
+
} else {
|
|
54
|
+
model = RED.util.evaluateNodeProperty(cfg.model, cfg.modelType, node, msg)
|
|
70
55
|
}
|
|
71
56
|
|
|
72
57
|
let from = null
|
|
73
58
|
if( msg?.payload?.from ) {
|
|
74
|
-
from = msg
|
|
59
|
+
from = msg.payload.from
|
|
75
60
|
} else if( !!config.from ) {
|
|
76
|
-
|
|
77
|
-
from = config.from
|
|
78
|
-
} else if( node.fromType === 'msg' ) {
|
|
79
|
-
from = msg[ config.from ]
|
|
80
|
-
} else if( node.fromType === 'flow' ) {
|
|
81
|
-
from = node.context().flow.get( config.from )
|
|
82
|
-
} else if( node.fromType === 'global' ) {
|
|
83
|
-
from = node.context().global.get( config.from )
|
|
84
|
-
}
|
|
61
|
+
from = RED.util.evaluateNodeProperty(cfg.from, cfg.fromType, node, msg)
|
|
85
62
|
}
|
|
86
63
|
|
|
87
|
-
const stream = ( msg?.payload?.stream !== undefined ) ? msg?.payload?.stream : node.stream
|
|
88
|
-
|
|
89
64
|
let quantize = null
|
|
90
65
|
if( msg?.payload?.quantize ) {
|
|
91
|
-
quantize = msg
|
|
66
|
+
quantize = msg.payload.quantize
|
|
92
67
|
} else if( !!config.quantize ) {
|
|
93
|
-
|
|
94
|
-
quantize = config.quantize
|
|
95
|
-
} else if( node.quantize === 'msg' ) {
|
|
96
|
-
quantize = msg[ config.quantize ]
|
|
97
|
-
} else if( node.quantize === 'flow' ) {
|
|
98
|
-
quantize = node.context().flow.get( config.quantize )
|
|
99
|
-
} else if( node.quantize === 'global' ) {
|
|
100
|
-
quantize = node.context().global.get( config.quantize )
|
|
101
|
-
}
|
|
68
|
+
quantize = RED.util.evaluateNodeProperty(cfg.quantize, cfg.quantizeType, node, msg)
|
|
102
69
|
}
|
|
103
70
|
|
|
104
71
|
let template = null
|
|
105
72
|
if( msg?.payload?.template ) {
|
|
106
|
-
template = msg
|
|
73
|
+
template = msg.payload.template
|
|
107
74
|
} else if( !!config.template ) {
|
|
108
|
-
|
|
109
|
-
template = config.template
|
|
110
|
-
} else if( node.template === 'msg' ) {
|
|
111
|
-
template = msg[ config.template ]
|
|
112
|
-
} else if( node.template === 'flow' ) {
|
|
113
|
-
template = node.context().flow.get( config.template )
|
|
114
|
-
} else if( node.template === 'global' ) {
|
|
115
|
-
template = node.context().global.get( config.template )
|
|
116
|
-
}
|
|
75
|
+
template = RED.util.evaluateNodeProperty(cfg.template, cfg.templateType, node, msg)
|
|
117
76
|
}
|
|
118
77
|
|
|
119
78
|
let license = null
|
|
120
79
|
if( msg?.payload?.license ) {
|
|
121
|
-
license = msg
|
|
80
|
+
license = msg.payload.license
|
|
122
81
|
} else if( !!config.license ) {
|
|
123
|
-
|
|
124
|
-
license = config.license
|
|
125
|
-
} else if( node.license === 'msg' ) {
|
|
126
|
-
license = msg[ config.license ]
|
|
127
|
-
} else if( node.license === 'flow' ) {
|
|
128
|
-
license = node.context().flow.get( config.license )
|
|
129
|
-
} else if( node.license === 'global' ) {
|
|
130
|
-
license = node.context().global.get( config.license )
|
|
131
|
-
}
|
|
82
|
+
license = RED.util.evaluateNodeProperty(cfg.license, cfg.licenseType, node, msg)
|
|
132
83
|
}
|
|
133
84
|
|
|
134
85
|
let system = null
|
|
135
86
|
if( msg?.payload?.system ) {
|
|
136
|
-
system = msg
|
|
87
|
+
system = msg.payload.system
|
|
137
88
|
} else if( !!config.system ) {
|
|
138
|
-
|
|
139
|
-
system = config.system
|
|
140
|
-
} else if( node.system === 'msg' ) {
|
|
141
|
-
system = msg[ config.system ]
|
|
142
|
-
} else if( node.system === 'flow' ) {
|
|
143
|
-
system = node.context().flow.get( config.system )
|
|
144
|
-
} else if( node.system === 'global' ) {
|
|
145
|
-
system = node.context().global.get( config.system )
|
|
146
|
-
}
|
|
89
|
+
system = RED.util.evaluateNodeProperty(cfg.system, cfg.systemType, node, msg)
|
|
147
90
|
}
|
|
148
91
|
|
|
149
92
|
let parameters = null
|
|
150
93
|
if( msg?.payload?.parameters ) {
|
|
151
|
-
parameters = msg
|
|
94
|
+
parameters = msg.payload.parameters
|
|
152
95
|
} else if( !!config.parameters ) {
|
|
153
|
-
|
|
154
|
-
parameters = config.parameters
|
|
155
|
-
} else if( node.parameters === 'msg' ) {
|
|
156
|
-
parameters = msg[ config.parameters ]
|
|
157
|
-
} else if( node.parameters === 'flow' ) {
|
|
158
|
-
parameters = node.context().flow.get( config.parameters )
|
|
159
|
-
} else if( node.parameters === 'global' ) {
|
|
160
|
-
parameters = node.context().global.get( config.parameters )
|
|
161
|
-
}
|
|
96
|
+
parameters = RED.util.evaluateNodeProperty(cfg.parameters, cfg.parametersType, node, msg)
|
|
162
97
|
}
|
|
163
98
|
|
|
164
99
|
let messages = null
|
|
165
100
|
if( msg?.payload?.messages ) {
|
|
166
|
-
messages = msg
|
|
101
|
+
messages = msg.payload.messages
|
|
167
102
|
} else if( !!config.messages ) {
|
|
168
|
-
|
|
169
|
-
messages = config.messages
|
|
170
|
-
} else if( node.messages === 'msg' ) {
|
|
171
|
-
messages = msg[ config.messages ]
|
|
172
|
-
} else if( node.messages === 'flow' ) {
|
|
173
|
-
messages = node.context().flow.get( config.messages )
|
|
174
|
-
} else if( node.messages === 'global' ) {
|
|
175
|
-
messages = node.context().global.get( config.messages )
|
|
176
|
-
}
|
|
103
|
+
messages = RED.util.evaluateNodeProperty(cfg.messages, cfg.messagesType, node, msg)
|
|
177
104
|
}
|
|
178
105
|
|
|
179
106
|
let adapters = null
|
|
180
107
|
if( msg?.payload?.adapters ) {
|
|
181
|
-
adapters = msg
|
|
108
|
+
adapters = msg.payload.adapters
|
|
182
109
|
} else if( !!config.adapters ) {
|
|
183
|
-
|
|
184
|
-
adapters = config.adapters
|
|
185
|
-
} else if( node.adapters === 'msg' ) {
|
|
186
|
-
adapters = msg[ config.adapters ]
|
|
187
|
-
} else if( node.adapters === 'flow' ) {
|
|
188
|
-
adapters = node.context().flow.get( config.adapters )
|
|
189
|
-
} else if( node.adapters === 'global' ) {
|
|
190
|
-
adapters = node.context().global.get( config.adapters )
|
|
191
|
-
}
|
|
110
|
+
adapters = RED.util.evaluateNodeProperty(cfg.adapters, cfg.adaptersType, node, msg)
|
|
192
111
|
}
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
+
})
|
|
212
134
|
} )
|
|
213
135
|
}
|
|
214
136
|
|
package/nodes/ollama-delete.js
CHANGED
|
@@ -12,7 +12,7 @@ module.exports = function( RED ) {
|
|
|
12
12
|
|
|
13
13
|
// Construct host URL
|
|
14
14
|
let host = null
|
|
15
|
-
if (
|
|
15
|
+
if ( server ) {
|
|
16
16
|
if ( server.useCloud ) {
|
|
17
17
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
18
18
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -32,6 +32,9 @@ module.exports = function( RED ) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
} else {
|
|
36
|
+
// No server configured - allow msg.payload.host directly
|
|
37
|
+
host = msg?.payload?.host || null
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
// Ollama Cloud configuration
|
package/nodes/ollama-embed.js
CHANGED
|
@@ -15,7 +15,7 @@ module.exports = function( RED ) {
|
|
|
15
15
|
|
|
16
16
|
// Construct host URL
|
|
17
17
|
let host = null
|
|
18
|
-
if (
|
|
18
|
+
if ( server ) {
|
|
19
19
|
if ( server.useCloud ) {
|
|
20
20
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
21
21
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -35,6 +35,9 @@ module.exports = function( RED ) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
} else {
|
|
39
|
+
// No server configured - allow msg.payload.host directly
|
|
40
|
+
host = msg?.payload?.host || null
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
// Ollama Cloud configuration
|
package/nodes/ollama-generate.js
CHANGED
|
@@ -21,7 +21,7 @@ module.exports = function( RED ) {
|
|
|
21
21
|
|
|
22
22
|
// Construct host URL
|
|
23
23
|
let host = null
|
|
24
|
-
if (
|
|
24
|
+
if ( server ) {
|
|
25
25
|
if ( server.useCloud ) {
|
|
26
26
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
27
27
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -41,6 +41,9 @@ module.exports = function( RED ) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
} else {
|
|
45
|
+
// No server configured - allow msg.payload.host directly
|
|
46
|
+
host = msg?.payload?.host || null
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
// Ollama Cloud configuration
|
|
@@ -183,9 +186,17 @@ module.exports = function( RED ) {
|
|
|
183
186
|
keep_alive,
|
|
184
187
|
options
|
|
185
188
|
} )
|
|
186
|
-
.then( response => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
.then( async response => {
|
|
190
|
+
if ( stream ) {
|
|
191
|
+
for await ( const part of response ) {
|
|
192
|
+
const chunkMsg = RED.util.cloneMessage( msg )
|
|
193
|
+
chunkMsg.payload = part
|
|
194
|
+
node.send( chunkMsg )
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
msg.payload = response
|
|
198
|
+
node.send( msg )
|
|
199
|
+
}
|
|
189
200
|
} )
|
|
190
201
|
.catch( error => {
|
|
191
202
|
node.error( error )
|
package/nodes/ollama-list.js
CHANGED
|
@@ -10,7 +10,7 @@ module.exports = function( RED ) {
|
|
|
10
10
|
|
|
11
11
|
// Construct host URL
|
|
12
12
|
let host = null
|
|
13
|
-
if (
|
|
13
|
+
if ( server ) {
|
|
14
14
|
if ( server.useCloud ) {
|
|
15
15
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
16
16
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -30,6 +30,9 @@ module.exports = function( RED ) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
} else {
|
|
34
|
+
// No server configured - allow msg.payload.host directly
|
|
35
|
+
host = msg?.payload?.host || null
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
// Ollama Cloud configuration
|
package/nodes/ollama-ps.js
CHANGED
|
@@ -10,7 +10,7 @@ module.exports = function( RED ) {
|
|
|
10
10
|
|
|
11
11
|
// Construct host URL
|
|
12
12
|
let host = null
|
|
13
|
-
if (
|
|
13
|
+
if ( server ) {
|
|
14
14
|
if ( server.useCloud ) {
|
|
15
15
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
16
16
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -30,6 +30,9 @@ module.exports = function( RED ) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
} else {
|
|
34
|
+
// No server configured - allow msg.payload.host directly
|
|
35
|
+
host = msg?.payload?.host || null
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
// Ollama Cloud configuration
|
package/nodes/ollama-pull.js
CHANGED
|
@@ -14,7 +14,7 @@ module.exports = function( RED ) {
|
|
|
14
14
|
|
|
15
15
|
// Construct host URL
|
|
16
16
|
let host = null
|
|
17
|
-
if (
|
|
17
|
+
if ( server ) {
|
|
18
18
|
if ( server.useCloud ) {
|
|
19
19
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
20
20
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -34,6 +34,9 @@ module.exports = function( RED ) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
} else {
|
|
38
|
+
// No server configured - allow msg.payload.host directly
|
|
39
|
+
host = msg?.payload?.host || null
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
// Ollama Cloud configuration
|
|
@@ -70,9 +73,17 @@ module.exports = function( RED ) {
|
|
|
70
73
|
insecure,
|
|
71
74
|
stream
|
|
72
75
|
} )
|
|
73
|
-
.then( response => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
.then( async response => {
|
|
77
|
+
if ( stream ) {
|
|
78
|
+
for await ( const part of response ) {
|
|
79
|
+
const chunkMsg = RED.util.cloneMessage( msg )
|
|
80
|
+
chunkMsg.payload = part
|
|
81
|
+
node.send( chunkMsg )
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
msg.payload = response
|
|
85
|
+
node.send( msg )
|
|
86
|
+
}
|
|
76
87
|
} )
|
|
77
88
|
.catch( error => {
|
|
78
89
|
node.error( error )
|
package/nodes/ollama-push.js
CHANGED
|
@@ -14,7 +14,7 @@ module.exports = function( RED ) {
|
|
|
14
14
|
|
|
15
15
|
// Construct host URL
|
|
16
16
|
let host = null
|
|
17
|
-
if (
|
|
17
|
+
if ( server ) {
|
|
18
18
|
if ( server.useCloud ) {
|
|
19
19
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
20
20
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -34,6 +34,9 @@ module.exports = function( RED ) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
} else {
|
|
38
|
+
// No server configured - allow msg.payload.host directly
|
|
39
|
+
host = msg?.payload?.host || null
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
// Ollama Cloud configuration
|
|
@@ -70,9 +73,17 @@ module.exports = function( RED ) {
|
|
|
70
73
|
insecure,
|
|
71
74
|
stream
|
|
72
75
|
} )
|
|
73
|
-
.then( response => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
.then( async response => {
|
|
77
|
+
if ( stream ) {
|
|
78
|
+
for await ( const part of response ) {
|
|
79
|
+
const chunkMsg = RED.util.cloneMessage( msg )
|
|
80
|
+
chunkMsg.payload = part
|
|
81
|
+
node.send( chunkMsg )
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
msg.payload = response
|
|
85
|
+
node.send( msg )
|
|
86
|
+
}
|
|
76
87
|
} )
|
|
77
88
|
.catch( error => {
|
|
78
89
|
node.error( error )
|
package/nodes/ollama-show.js
CHANGED
|
@@ -14,7 +14,7 @@ module.exports = function( RED ) {
|
|
|
14
14
|
|
|
15
15
|
// Construct host URL
|
|
16
16
|
let host = null
|
|
17
|
-
if (
|
|
17
|
+
if ( server ) {
|
|
18
18
|
if ( server.useCloud ) {
|
|
19
19
|
// For Ollama Cloud, always use the configured host (https://ollama.com)
|
|
20
20
|
// NEVER allow msg.payload.host override when using API key authentication
|
|
@@ -34,6 +34,9 @@ module.exports = function( RED ) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
} else {
|
|
38
|
+
// No server configured - allow msg.payload.host directly
|
|
39
|
+
host = msg?.payload?.host || null
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
// Ollama Cloud configuration
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-ollama",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
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",
|