ultravisor 1.0.10 → 1.0.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultravisor",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "Cyclic process execution with ai integration.",
5
5
  "main": "source/Ultravisor.cjs",
6
6
  "bin": {
@@ -33,7 +33,7 @@
33
33
  "pict": "^1.0.359",
34
34
  "pict-service-commandlineutility": "^1.0.19",
35
35
  "pict-serviceproviderbase": "^1.0.4",
36
- "ultravisor-beacon": "^0.0.4",
36
+ "ultravisor-beacon": "^0.0.7",
37
37
  "ws": "^8.20.0"
38
38
  },
39
39
  "devDependencies": {
@@ -20,7 +20,6 @@ module.exports = (
20
20
  {
21
21
  ReadFile: require('./services/tasks/file-system/Ultravisor-TaskType-ReadFile.cjs'),
22
22
  WriteFile: require('./services/tasks/file-system/Ultravisor-TaskType-WriteFile.cjs'),
23
- SetValues: require('./services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs'),
24
23
  ReplaceString: require('./services/tasks/data-transform/Ultravisor-TaskType-ReplaceString.cjs'),
25
24
  StringAppender: require('./services/tasks/data-transform/Ultravisor-TaskType-StringAppender.cjs'),
26
25
  IfConditional: require('./services/tasks/flow-control/Ultravisor-TaskType-IfConditional.cjs'),
@@ -77,6 +77,34 @@ module.exports =
77
77
  ProxyURL: ''
78
78
  };
79
79
 
80
+ // Helper: build a full URL from a beacon's bind address + context path + resource path
81
+ let _buildDirectURL = function (pDirectBaseURL)
82
+ {
83
+ let tmpContextDef = tmpCoordinator.getBeacon(tmpResolved.BeaconID);
84
+ let tmpCtx = tmpContextDef && tmpContextDef.Contexts ? tmpContextDef.Contexts[tmpResolved.Context] : null;
85
+ let tmpContextPath = tmpCtx && tmpCtx.BaseURL ? tmpCtx.BaseURL : '/';
86
+ if (!tmpContextPath.endsWith('/'))
87
+ {
88
+ tmpContextPath = tmpContextPath + '/';
89
+ }
90
+ // Strip protocol+host from BaseURL if it's absolute, keep just the path
91
+ try
92
+ {
93
+ let tmpParsed = new URL(tmpContextPath);
94
+ tmpContextPath = tmpParsed.pathname;
95
+ if (!tmpContextPath.endsWith('/'))
96
+ {
97
+ tmpContextPath = tmpContextPath + '/';
98
+ }
99
+ }
100
+ catch (pParseError)
101
+ {
102
+ // Already a relative path — use as-is
103
+ }
104
+ let tmpEncodedPath = tmpResolved.Path.split('/').map(encodeURIComponent).join('/');
105
+ return pDirectBaseURL.replace(/\/$/, '') + tmpContextPath + tmpEncodedPath;
106
+ };
107
+
80
108
  // Resolve transfer strategy when a requesting beacon is specified
81
109
  let tmpRequestingBeaconID = pResolvedSettings.RequestingBeaconID;
82
110
  if (tmpRequestingBeaconID)
@@ -89,30 +117,7 @@ module.exports =
89
117
 
90
118
  if (tmpStrategyResult.Strategy === 'direct' && tmpStrategyResult.DirectURL)
91
119
  {
92
- // Build full direct URL using bind address + context path
93
- let tmpContextDef = tmpCoordinator.getBeacon(tmpResolved.BeaconID);
94
- let tmpCtx = tmpContextDef && tmpContextDef.Contexts ? tmpContextDef.Contexts[tmpResolved.Context] : null;
95
- let tmpContextPath = tmpCtx && tmpCtx.BaseURL ? tmpCtx.BaseURL : '/';
96
- if (!tmpContextPath.endsWith('/'))
97
- {
98
- tmpContextPath = tmpContextPath + '/';
99
- }
100
- // Strip protocol+host from BaseURL if it's absolute, keep just the path
101
- try
102
- {
103
- let tmpParsed = new URL(tmpContextPath);
104
- tmpContextPath = tmpParsed.pathname;
105
- if (!tmpContextPath.endsWith('/'))
106
- {
107
- tmpContextPath = tmpContextPath + '/';
108
- }
109
- }
110
- catch (pParseError)
111
- {
112
- // Already a relative path — use as-is
113
- }
114
- let tmpEncodedPath = tmpResolved.Path.split('/').map(encodeURIComponent).join('/');
115
- tmpOutputs.DirectURL = tmpStrategyResult.DirectURL.replace(/\/$/, '') + tmpContextPath + tmpEncodedPath;
120
+ tmpOutputs.DirectURL = _buildDirectURL(tmpStrategyResult.DirectURL);
116
121
  tmpOutputs.URL = tmpOutputs.DirectURL;
117
122
  }
118
123
  else if (tmpStrategyResult.Strategy === 'proxy')
@@ -125,6 +130,28 @@ module.exports =
125
130
  }
126
131
  }
127
132
 
133
+ // If the URL is still relative (no protocol), use the beacon's first
134
+ // bind address to make it absolute so file-transfer can fetch it.
135
+ if (tmpOutputs.URL && !tmpOutputs.URL.startsWith('http'))
136
+ {
137
+ let tmpBeaconDef = tmpCoordinator.getBeacon(tmpResolved.BeaconID);
138
+ pTask.log.info(`Resolve Address: URL is relative, looking up BindAddresses for beacon ${tmpResolved.BeaconID}. getBeacon returned: ${tmpBeaconDef ? 'found' : 'null'}, BindAddresses: ${JSON.stringify(tmpBeaconDef && tmpBeaconDef.BindAddresses)}`);
139
+ let tmpBindAddresses = tmpBeaconDef && tmpBeaconDef.BindAddresses ? tmpBeaconDef.BindAddresses : [];
140
+ // Prefer non-loopback addresses
141
+ let tmpBind = tmpBindAddresses.find(function (pB) { return pB.IP !== '127.0.0.1' && pB.IP !== '::1'; }) || tmpBindAddresses[0];
142
+ if (tmpBind)
143
+ {
144
+ let tmpBaseURL = (tmpBind.Protocol || 'http') + '://' + tmpBind.IP + ':' + tmpBind.Port;
145
+ pTask.log.info(`Resolve Address: using bind address ${tmpBaseURL}`);
146
+ tmpOutputs.DirectURL = _buildDirectURL(tmpBaseURL);
147
+ tmpOutputs.URL = tmpOutputs.DirectURL;
148
+ }
149
+ else
150
+ {
151
+ pTask.log.warn(`Resolve Address: no BindAddresses available for beacon ${tmpResolved.BeaconID} — URL will remain relative`);
152
+ }
153
+ }
154
+
128
155
  let tmpStateWrites = {};
129
156
  if (pResolvedSettings.Destination)
130
157
  {
@@ -190,6 +217,16 @@ module.exports =
190
217
 
191
218
  pTask.log.info(`File Transfer: downloading ${tmpSourceURL} → ${tmpFilename}`);
192
219
 
220
+ // Validate URL before attempting request
221
+ if (!tmpSourceURL.startsWith('http://') && !tmpSourceURL.startsWith('https://'))
222
+ {
223
+ return fCallback(null, {
224
+ EventToFire: 'Error',
225
+ Outputs: { LocalPath: '', BytesTransferred: 0, DurationMs: 0 },
226
+ Log: [`File Transfer: invalid URL (no protocol): ${tmpSourceURL}`]
227
+ });
228
+ }
229
+
193
230
  let tmpLib = tmpSourceURL.startsWith('https') ? libHTTPS : libHTTP;
194
231
  let tmpRequest = tmpLib.get(tmpSourceURL, function (pResponse)
195
232
  {
@@ -2062,7 +2062,8 @@ class UltravisorAPIServer extends libPictService
2062
2062
  Operations: pData.Operations,
2063
2063
  MaxConcurrent: pData.MaxConcurrent,
2064
2064
  Tags: pData.Tags,
2065
- Contexts: pData.Contexts
2065
+ Contexts: pData.Contexts,
2066
+ BindAddresses: pData.BindAddresses
2066
2067
  });
2067
2068
 
2068
2069
  pWebSocket._BeaconID = tmpBeacon.BeaconID;
@@ -6,7 +6,7 @@
6
6
  "scripts": {
7
7
  "start": "node source/Pict-Application-Ultravisor.js",
8
8
  "prebuild": "node ./node_modules/pict-section-flow/scripts/generate-card-help.js ./docs/card-help ./source/card-help-content.js",
9
- "build": "npx quack build && npx quack copy"
9
+ "build": "npx quack build && node build/build-codemirror-bundle.js && npx quack copy"
10
10
  },
11
11
  "author": "steven velozo <steven@velozo.com>",
12
12
  "license": "MIT",