ultravisor 1.0.13 → 1.0.15

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.13",
3
+ "version": "1.0.15",
4
4
  "description": "Cyclic process execution with ai integration.",
5
5
  "main": "source/Ultravisor.cjs",
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
  "test": "npx quack test",
12
12
  "tests": "npx mocha -u tdd --exit -R spec --grep",
13
13
  "coverage": "npx quack coverage",
14
+ "postinstall": "cd webinterface && npm install && npm run build && cd ..",
14
15
  "build": "npx quack build && cd webinterface && npm install && npm run build && cd ..",
15
16
  "docs": "npx quack prepare-docs ./docs -d ./modules",
16
17
  "docs-serve": "npx quack docs-serve ./docs"
@@ -33,7 +34,7 @@
33
34
  "pict": "^1.0.359",
34
35
  "pict-service-commandlineutility": "^1.0.19",
35
36
  "pict-serviceproviderbase": "^1.0.4",
36
- "ultravisor-beacon": "^0.0.7",
37
+ "ultravisor-beacon": "^0.0.8",
37
38
  "ws": "^8.20.0"
38
39
  },
39
40
  "devDependencies": {
@@ -40,6 +40,9 @@ class UltravisorBeaconClient
40
40
  this._ActiveWorkItems = 0;
41
41
  this._SessionCookie = null;
42
42
  this._Authenticating = false;
43
+ this._ReconnectPending = false;
44
+ this._ReconnectAttempts = 0;
45
+ this._MaxReconnectDelayMs = 300000; // Cap at 5 minutes
43
46
 
44
47
  this._Executor = new libBeaconExecutor({
45
48
  StagingPath: this._Config.StagingPath
@@ -433,10 +436,32 @@ class UltravisorBeaconClient
433
436
  if (tmpOutputs.ExitCode && tmpOutputs.ExitCode !== 0)
434
437
  {
435
438
  console.warn(`[Beacon] Work item [${pWorkItem.WorkItemHash}] completed with exit code ${tmpOutputs.ExitCode}`);
439
+ this._reportComplete(pWorkItem.WorkItemHash, tmpOutputs, pResult.Log || []);
440
+ return;
436
441
  }
437
- else
442
+
443
+ console.log(`[Beacon] Work item [${pWorkItem.WorkItemHash}] completed successfully.`);
444
+
445
+ // If the result contains a file, upload it to the coordinator before reporting completion
446
+ if (tmpOutputs.Result && tmpOutputs.OutputSize > 0)
438
447
  {
439
- console.log(`[Beacon] Work item [${pWorkItem.WorkItemHash}] completed successfully.`);
448
+ let tmpResultPath = tmpOutputs.Result;
449
+ let tmpOutputFile = pWorkItem.Settings && pWorkItem.Settings.OutputFile;
450
+ let tmpFilename = tmpOutputFile || require('path').basename(tmpResultPath);
451
+
452
+ this._uploadResultFile(pWorkItem.WorkItemHash, tmpResultPath, tmpFilename, (pUploadError) =>
453
+ {
454
+ if (pUploadError)
455
+ {
456
+ console.warn(`[Beacon] File upload failed for [${pWorkItem.WorkItemHash}]: ${pUploadError.message} — reporting completion without file`);
457
+ }
458
+ else
459
+ {
460
+ console.log(`[Beacon] Uploaded result file [${tmpFilename}] for [${pWorkItem.WorkItemHash}]`);
461
+ }
462
+ this._reportComplete(pWorkItem.WorkItemHash, tmpOutputs, pResult.Log || []);
463
+ });
464
+ return;
440
465
  }
441
466
 
442
467
  this._reportComplete(pWorkItem.WorkItemHash, tmpOutputs, pResult.Log || []);
@@ -447,6 +472,58 @@ class UltravisorBeaconClient
447
472
  // Reporting
448
473
  // ================================================================
449
474
 
475
+ _uploadResultFile(pWorkItemHash, pFilePath, pFilename, fCallback)
476
+ {
477
+ let tmpFS = require('fs');
478
+
479
+ if (!tmpFS.existsSync(pFilePath))
480
+ {
481
+ return fCallback(new Error(`File not found: ${pFilePath}`));
482
+ }
483
+
484
+ let tmpFileBuffer = tmpFS.readFileSync(pFilePath);
485
+ let tmpParsedURL = new URL(this._Config.ServerURL);
486
+
487
+ let tmpOptions = {
488
+ hostname: tmpParsedURL.hostname,
489
+ port: tmpParsedURL.port || 80,
490
+ path: `/Beacon/Work/${pWorkItemHash}/Upload`,
491
+ method: 'POST',
492
+ headers: {
493
+ 'Content-Type': 'application/octet-stream',
494
+ 'Content-Length': tmpFileBuffer.length,
495
+ 'X-Output-Filename': pFilename
496
+ }
497
+ };
498
+
499
+ if (this._SessionCookie)
500
+ {
501
+ tmpOptions.headers['Cookie'] = this._SessionCookie;
502
+ }
503
+
504
+ let tmpReq = libHTTP.request(tmpOptions, (pResponse) =>
505
+ {
506
+ let tmpData = '';
507
+ pResponse.on('data', (pChunk) => { tmpData += pChunk; });
508
+ pResponse.on('end', () =>
509
+ {
510
+ if (pResponse.statusCode >= 400)
511
+ {
512
+ return fCallback(new Error(`Upload failed: HTTP ${pResponse.statusCode}`));
513
+ }
514
+ return fCallback(null);
515
+ });
516
+ });
517
+
518
+ tmpReq.on('error', (pError) =>
519
+ {
520
+ return fCallback(pError);
521
+ });
522
+
523
+ tmpReq.write(tmpFileBuffer);
524
+ tmpReq.end();
525
+ }
526
+
450
527
  _reportComplete(pWorkItemHash, pOutputs, pLog)
451
528
  {
452
529
  this._httpRequest('POST', `/Beacon/Work/${pWorkItemHash}/Complete`,
@@ -36,6 +36,10 @@
36
36
  "whenFileExists": "overwrite"
37
37
  },
38
38
  "copyFiles": [
39
+ {
40
+ "from": "./ultravisor-webinterface*",
41
+ "to": "./dist/"
42
+ },
39
43
  {
40
44
  "from": "./html/*",
41
45
  "to": "./dist/"