@leg3ndy/otto-bridge 0.5.3 → 0.5.4
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/dist/config.js +3 -0
- package/dist/runtime.js +72 -0
- package/dist/types.js +1 -1
- package/package.json +1 -1
package/dist/config.js
CHANGED
|
@@ -67,6 +67,9 @@ export async function loadBridgeConfig() {
|
|
|
67
67
|
...parsed,
|
|
68
68
|
apiBaseUrl: sanitizeApiBaseUrl(parsed.apiBaseUrl),
|
|
69
69
|
wsUrl: buildWebSocketUrl(parsed.apiBaseUrl),
|
|
70
|
+
// Older pairings may have persisted an outdated bridgeVersion in config.json.
|
|
71
|
+
// The runtime must always report the currently installed package version.
|
|
72
|
+
bridgeVersion: BRIDGE_VERSION,
|
|
70
73
|
executor: resolveExecutorConfig(undefined, migrateLegacyExecutor(parsed.executor)),
|
|
71
74
|
};
|
|
72
75
|
}
|
package/dist/runtime.js
CHANGED
|
@@ -6,6 +6,52 @@ import { JobCancelledError } from "./executors/shared.js";
|
|
|
6
6
|
function delay(ms) {
|
|
7
7
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
8
8
|
}
|
|
9
|
+
function parseSemverTuple(value) {
|
|
10
|
+
const text = String(value || "").trim().replace(/^[vV]/, "");
|
|
11
|
+
if (!text) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const parts = text.split(".");
|
|
15
|
+
const parsed = [];
|
|
16
|
+
for (const part of parts) {
|
|
17
|
+
const match = part.match(/^(\d+)/);
|
|
18
|
+
if (!match) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
parsed.push(Number(match[1]));
|
|
22
|
+
}
|
|
23
|
+
return parsed.length > 0 ? parsed : null;
|
|
24
|
+
}
|
|
25
|
+
function compareSemver(left, right) {
|
|
26
|
+
const a = parseSemverTuple(left);
|
|
27
|
+
const b = parseSemverTuple(right);
|
|
28
|
+
if (!a && !b)
|
|
29
|
+
return 0;
|
|
30
|
+
if (!a)
|
|
31
|
+
return -1;
|
|
32
|
+
if (!b)
|
|
33
|
+
return 1;
|
|
34
|
+
const maxLength = Math.max(a.length, b.length);
|
|
35
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
36
|
+
const leftPart = a[index] ?? 0;
|
|
37
|
+
const rightPart = b[index] ?? 0;
|
|
38
|
+
if (leftPart < rightPart)
|
|
39
|
+
return -1;
|
|
40
|
+
if (leftPart > rightPart)
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
function bridgeReleaseFromMessage(message) {
|
|
46
|
+
const nested = message.bridge_release;
|
|
47
|
+
if (nested && typeof nested === "object") {
|
|
48
|
+
return nested;
|
|
49
|
+
}
|
|
50
|
+
if (message.latest_version || message.min_supported_version || message.update_command) {
|
|
51
|
+
return message;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
9
55
|
async function parseSocketMessage(data) {
|
|
10
56
|
if (typeof data === "string") {
|
|
11
57
|
return JSON.parse(data);
|
|
@@ -25,6 +71,7 @@ export class BridgeRuntime {
|
|
|
25
71
|
config;
|
|
26
72
|
reconnectDelayMs = DEFAULT_RECONNECT_BASE_DELAY_MS;
|
|
27
73
|
executor;
|
|
74
|
+
lastBridgeReleaseNoticeKey = null;
|
|
28
75
|
pendingConfirmations = new Map();
|
|
29
76
|
activeCancels = new Map();
|
|
30
77
|
constructor(config, executor) {
|
|
@@ -116,9 +163,11 @@ export class BridgeRuntime {
|
|
|
116
163
|
const type = String(message.type || "");
|
|
117
164
|
switch (type) {
|
|
118
165
|
case "device.hello":
|
|
166
|
+
this.maybeLogBridgeReleaseNotice(message);
|
|
119
167
|
console.log(`[otto-bridge] server hello device=${String(message.device_id || "")}`);
|
|
120
168
|
return;
|
|
121
169
|
case "device.hello_ack":
|
|
170
|
+
this.maybeLogBridgeReleaseNotice(message);
|
|
122
171
|
case "device.heartbeat_ack":
|
|
123
172
|
return;
|
|
124
173
|
case "device.job.start":
|
|
@@ -145,6 +194,29 @@ export class BridgeRuntime {
|
|
|
145
194
|
console.log(`[otto-bridge] event=${type || "unknown"} payload=${JSON.stringify(message)}`);
|
|
146
195
|
}
|
|
147
196
|
}
|
|
197
|
+
maybeLogBridgeReleaseNotice(message) {
|
|
198
|
+
const release = bridgeReleaseFromMessage(message);
|
|
199
|
+
if (!release) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const latestVersion = String(release.latest_version || "").trim();
|
|
203
|
+
const minSupportedVersion = String(release.min_supported_version || "").trim();
|
|
204
|
+
const updateCommand = String(release.update_command || "otto-bridge update").trim() || "otto-bridge update";
|
|
205
|
+
const updateRequired = release.update_required === true || (minSupportedVersion ? compareSemver(this.config.bridgeVersion, minSupportedVersion) < 0 : false);
|
|
206
|
+
const updateAvailable = release.update_available === true || (latestVersion ? compareSemver(this.config.bridgeVersion, latestVersion) < 0 : false);
|
|
207
|
+
const noticeKey = [latestVersion, minSupportedVersion, updateRequired ? "req" : "ok", updateAvailable ? "avail" : "cur"].join("|");
|
|
208
|
+
if (!noticeKey.trim() || this.lastBridgeReleaseNoticeKey === noticeKey) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
this.lastBridgeReleaseNoticeKey = noticeKey;
|
|
212
|
+
if (updateRequired) {
|
|
213
|
+
console.warn(`[otto-bridge] update required current=${this.config.bridgeVersion} min_supported=${minSupportedVersion || "unknown"} latest=${latestVersion || "unknown"} command="${updateCommand}"`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (updateAvailable) {
|
|
217
|
+
console.log(`[otto-bridge] update available current=${this.config.bridgeVersion} latest=${latestVersion || "unknown"} command="${updateCommand}"`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
148
220
|
resolveConfirmation(message) {
|
|
149
221
|
const jobId = String(message.job_id || "");
|
|
150
222
|
const action = String(message.action || "").trim().toLowerCase();
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const BRIDGE_CONFIG_VERSION = 1;
|
|
2
|
-
export const BRIDGE_VERSION = "0.5.
|
|
2
|
+
export const BRIDGE_VERSION = "0.5.4";
|
|
3
3
|
export const BRIDGE_PACKAGE_NAME = "@leg3ndy/otto-bridge";
|
|
4
4
|
export const DEFAULT_API_BASE_URL = "http://localhost:8000";
|
|
5
5
|
export const DEFAULT_POLL_INTERVAL_MS = 3000;
|