@alfe.ai/openclaw-sync 0.3.13 → 0.3.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/dist/index.d.cts +64 -29
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +64 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.cjs +7 -1
- package/dist/plugin.d.cts +9 -1
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.ts +9 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -2
- package/dist/plugin2.cjs +84 -2
- package/dist/plugin2.js +73 -3
- package/dist/plugin2.js.map +1 -1
- package/package.json +2 -2
package/dist/plugin.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":";;AAkEA;AAuCA;AAaC;AA8CqB;;;;;AAWA;;;;;;;;AAW2B,iBAxHjC,mBAAA,CAwHiC,KAAA,EAAA;EAAO,MAAA,EAAA,MAAA;EA0BvC,aAAA,CAAA,EAAA,MAAgB;EA6jB3B,cAuWL,CAAA,EAAA,MAAA;EAAA,WAAA,EAAA,OAAA;UAhWe;;AA+QiB,iBA97BjB,wBAAA,CA87BiB,OAAA,EAAA,MAAA,CAAA,EAAA,OAAA;UAn4BvB,YAAA,CA26Ba;MAAmB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;MAAgB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAA,KAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;;UAp6BhD,oBAAA;UACA;;;UAGA;;UAGA,SAAA;UACA;;WAEC;wDAC6C;;;iBAGvC,gCAAgC;iBAChC,gCAAgC;;;UA0BhC,gBAAA;;;;;;;;;;;;cA6jBX;;;;;gBAOU;kBA+QQ,YAAS;iBAwCV,mBAAmB,mBAAgB"}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
*
|
|
17
17
|
* Registers gateway RPC methods: `sync.now`, `sync.status`.
|
|
18
18
|
*/
|
|
19
|
+
declare function resolveSyncRelayUrl(input: {
|
|
20
|
+
apiUrl: string;
|
|
21
|
+
configuredUrl?: string;
|
|
22
|
+
environmentUrl?: string;
|
|
23
|
+
privateMode: boolean;
|
|
24
|
+
}): string;
|
|
25
|
+
/** Only RFC1918 IPv4 and unique-local IPv6 addresses are valid VPC relay targets. */
|
|
26
|
+
declare function isVpcPrivateRelayAddress(address: string): boolean;
|
|
19
27
|
interface PluginLogger {
|
|
20
28
|
info(msg: string): void;
|
|
21
29
|
warn(msg: string): void;
|
|
@@ -61,5 +69,5 @@ declare const plugin: {
|
|
|
61
69
|
configure(api: PluginApi, config: SyncPluginConfig): Promise<void>;
|
|
62
70
|
};
|
|
63
71
|
//#endregion
|
|
64
|
-
export { SyncPluginConfig, plugin as default };
|
|
72
|
+
export { SyncPluginConfig, plugin as default, isVpcPrivateRelayAddress, resolveSyncRelayUrl };
|
|
65
73
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;AAkEA;AAuCA;AAaC;AA8CqB;;;;;AAWA;;;;;;;;AAW2B,iBAxHjC,mBAAA,CAwHiC,KAAA,EAAA;EAAO,MAAA,EAAA,MAAA;EA0BvC,aAAA,CAAA,EAAA,MAAgB;EA6jB3B,cAuWL,CAAA,EAAA,MAAA;EAAA,WAAA,EAAA,OAAA;UAhWe;;AA+QiB,iBA97BjB,wBAAA,CA87BiB,OAAA,EAAA,MAAA,CAAA,EAAA,OAAA;UAn4BvB,YAAA,CA26Ba;MAAmB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;MAAgB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAA,KAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;;UAp6BhD,oBAAA;UACA;;;UAGA;;UAGA,SAAA;UACA;;WAEC;wDAC6C;;;iBAGvC,gCAAgC;iBAChC,gCAAgC;;;UA0BhC,gBAAA;;;;;;;;;;;;cA6jBX;;;;;gBAOU;kBA+QQ,YAAS;iBAwCV,mBAAmB,mBAAgB"}
|
package/dist/plugin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { plugin as default };
|
|
1
|
+
import { n as plugin, r as resolveSyncRelayUrl, t as isVpcPrivateRelayAddress } from "./plugin2.js";
|
|
2
|
+
export { plugin as default, isVpcPrivateRelayAddress, resolveSyncRelayUrl };
|
package/dist/plugin2.cjs
CHANGED
|
@@ -8,6 +8,8 @@ let node_module = require("node:module");
|
|
|
8
8
|
let _alfe_ai_config = require("@alfe.ai/config");
|
|
9
9
|
let _alfe_ai_openclaw_plugin_kit = require("@alfe.ai/openclaw-plugin-kit");
|
|
10
10
|
let _alfe_ai_agent_api_client = require("@alfe.ai/agent-api-client");
|
|
11
|
+
let node_dns = require("node:dns");
|
|
12
|
+
let node_net = require("node:net");
|
|
11
13
|
//#region src/watcher.ts
|
|
12
14
|
/**
|
|
13
15
|
* AlfeSync watcher — recursive file watcher with debounce and ignore support.
|
|
@@ -447,6 +449,64 @@ const SYNC_RELAY_DEBOUNCE_MS = 500;
|
|
|
447
449
|
const SYNC_RELAY_MAX_MESSAGE_BYTES = 64 * 1024;
|
|
448
450
|
const SYNC_RELAY_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
449
451
|
const REMOTE_DELETE_SUPPRESSION_MS = 3e4;
|
|
452
|
+
function resolveSyncRelayUrl(input) {
|
|
453
|
+
if (input.privateMode) {
|
|
454
|
+
const regionalUrl = input.environmentUrl?.trim();
|
|
455
|
+
if (!regionalUrl) throw new Error("ALFE_SYNC_RELAY_WS_URL is required in AWS-private mode");
|
|
456
|
+
let parsed;
|
|
457
|
+
try {
|
|
458
|
+
parsed = new URL(regionalUrl);
|
|
459
|
+
} catch {
|
|
460
|
+
throw new Error("AWS-private sync relay URL must be valid");
|
|
461
|
+
}
|
|
462
|
+
if (parsed.protocol !== "ws:" || !parsed.hostname.endsWith(".local") && !parsed.hostname.endsWith(".sst") || parsed.pathname !== "/ws" || parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "") throw new Error("AWS-private sync relay URL must be a canonical VPC-local service URL");
|
|
463
|
+
return parsed.toString();
|
|
464
|
+
}
|
|
465
|
+
const configuredUrl = input.configuredUrl?.trim();
|
|
466
|
+
const environmentUrl = input.environmentUrl?.trim();
|
|
467
|
+
if (configuredUrl && configuredUrl.length > 0) return configuredUrl;
|
|
468
|
+
if (environmentUrl && environmentUrl.length > 0) return environmentUrl;
|
|
469
|
+
return (0, _alfe_ai_config.deriveServiceWsUrl)(input.apiUrl, "sync");
|
|
470
|
+
}
|
|
471
|
+
/** Only RFC1918 IPv4 and unique-local IPv6 addresses are valid VPC relay targets. */
|
|
472
|
+
function isVpcPrivateRelayAddress(address) {
|
|
473
|
+
const family = (0, node_net.isIP)(address);
|
|
474
|
+
if (family === 4) {
|
|
475
|
+
const [first, second] = address.split(".").map(Number);
|
|
476
|
+
return first === 10 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 168;
|
|
477
|
+
}
|
|
478
|
+
if (family === 6) {
|
|
479
|
+
const firstHextet = Number.parseInt(address.split(":", 1)[0] ?? "", 16);
|
|
480
|
+
return Number.isFinite(firstHextet) && (firstHextet & 65024) === 64512;
|
|
481
|
+
}
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
const vpcPrivateRelayLookup = (hostname, options, callback) => {
|
|
485
|
+
(0, node_dns.lookup)(hostname, {
|
|
486
|
+
all: true,
|
|
487
|
+
verbatim: true
|
|
488
|
+
}, (error, addresses) => {
|
|
489
|
+
if (error) {
|
|
490
|
+
callback(error, "", 4);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (addresses.length === 0 || addresses.some(({ address }) => !isVpcPrivateRelayAddress(address))) {
|
|
494
|
+
callback(Object.assign(/* @__PURE__ */ new Error("private sync relay resolved outside the VPC address space"), { code: "EACCES" }), "", 4);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
const family = typeof options.family === "number" ? options.family : 0;
|
|
498
|
+
const selected = family === 0 ? addresses[0] : addresses.find((candidate) => candidate.family === family);
|
|
499
|
+
if (!selected) {
|
|
500
|
+
callback(Object.assign(/* @__PURE__ */ new Error("private sync relay has no address in the requested family"), { code: "EADDRNOTAVAIL" }), "", family || 4);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (options.all) {
|
|
504
|
+
callback(null, addresses);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
callback(null, selected.address, selected.family);
|
|
508
|
+
});
|
|
509
|
+
};
|
|
450
510
|
let client = null;
|
|
451
511
|
let agentId = null;
|
|
452
512
|
let syncEngine = null;
|
|
@@ -679,10 +739,13 @@ async function connectToSyncRelay(relayUrl, token, agentIdForSubscribe, log, gen
|
|
|
679
739
|
try {
|
|
680
740
|
const { default: WebSocket } = await import("ws");
|
|
681
741
|
if (!syncRelayActive || generation !== syncRelayGeneration) return null;
|
|
742
|
+
const relayHost = new URL(relayUrl).hostname;
|
|
743
|
+
const privateRelay = relayHost.endsWith(".local") || relayHost.endsWith(".sst");
|
|
682
744
|
const ws = new WebSocket(relayUrl, {
|
|
683
745
|
headers: { Authorization: `Bearer ${token}` },
|
|
684
746
|
handshakeTimeout: SYNC_RELAY_HANDSHAKE_TIMEOUT_MS,
|
|
685
|
-
maxPayload: SYNC_RELAY_MAX_MESSAGE_BYTES
|
|
747
|
+
maxPayload: SYNC_RELAY_MAX_MESSAGE_BYTES,
|
|
748
|
+
...privateRelay ? { lookup: vpcPrivateRelayLookup } : {}
|
|
686
749
|
});
|
|
687
750
|
ws.on("open", () => {
|
|
688
751
|
if (!syncRelayActive || generation !== syncRelayGeneration) {
|
|
@@ -897,7 +960,14 @@ const plugin = {
|
|
|
897
960
|
log.debug(`Shared sync engine skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
898
961
|
}
|
|
899
962
|
try {
|
|
900
|
-
const
|
|
963
|
+
const configuredRelayUrl = pluginConfig.syncRelayUrl?.trim();
|
|
964
|
+
const environmentRelayUrl = process.env.ALFE_SYNC_RELAY_WS_URL?.trim();
|
|
965
|
+
const relayUrl = resolveSyncRelayUrl({
|
|
966
|
+
apiUrl: syncCfg.apiUrl,
|
|
967
|
+
configuredUrl: configuredRelayUrl,
|
|
968
|
+
environmentUrl: environmentRelayUrl,
|
|
969
|
+
privateMode: process.env.ALFE_PRIVATE_DATA_PLANE === "true"
|
|
970
|
+
});
|
|
901
971
|
syncRelayActive = true;
|
|
902
972
|
const relayGeneration = ++syncRelayGeneration;
|
|
903
973
|
syncRelayWs = await connectToSyncRelay(relayUrl, syncCfg.apiKey, registered.agentId, log, relayGeneration);
|
|
@@ -1061,12 +1131,24 @@ Object.defineProperty(exports, "createSharedSyncEngine", {
|
|
|
1061
1131
|
return createSharedSyncEngine;
|
|
1062
1132
|
}
|
|
1063
1133
|
});
|
|
1134
|
+
Object.defineProperty(exports, "isVpcPrivateRelayAddress", {
|
|
1135
|
+
enumerable: true,
|
|
1136
|
+
get: function() {
|
|
1137
|
+
return isVpcPrivateRelayAddress;
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1064
1140
|
Object.defineProperty(exports, "plugin", {
|
|
1065
1141
|
enumerable: true,
|
|
1066
1142
|
get: function() {
|
|
1067
1143
|
return plugin;
|
|
1068
1144
|
}
|
|
1069
1145
|
});
|
|
1146
|
+
Object.defineProperty(exports, "resolveSyncRelayUrl", {
|
|
1147
|
+
enumerable: true,
|
|
1148
|
+
get: function() {
|
|
1149
|
+
return resolveSyncRelayUrl;
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
1070
1152
|
Object.defineProperty(exports, "startWatcher", {
|
|
1071
1153
|
enumerable: true,
|
|
1072
1154
|
get: function() {
|
package/dist/plugin2.js
CHANGED
|
@@ -8,6 +8,8 @@ import { watch } from "chokidar";
|
|
|
8
8
|
import { DEFAULT_SOCKET_PATH, DEFAULT_WORKSPACE_PATH, configExists, deriveServiceWsUrl, resolveConfig } from "@alfe.ai/config";
|
|
9
9
|
import { connectToDaemon, getActivationKey, guardedStart, resetActivation } from "@alfe.ai/openclaw-plugin-kit";
|
|
10
10
|
import { AgentApiClient } from "@alfe.ai/agent-api-client";
|
|
11
|
+
import { lookup } from "node:dns";
|
|
12
|
+
import { isIP } from "node:net";
|
|
11
13
|
//#region src/watcher.ts
|
|
12
14
|
/**
|
|
13
15
|
* AlfeSync watcher — recursive file watcher with debounce and ignore support.
|
|
@@ -447,6 +449,64 @@ const SYNC_RELAY_DEBOUNCE_MS = 500;
|
|
|
447
449
|
const SYNC_RELAY_MAX_MESSAGE_BYTES = 64 * 1024;
|
|
448
450
|
const SYNC_RELAY_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
449
451
|
const REMOTE_DELETE_SUPPRESSION_MS = 3e4;
|
|
452
|
+
function resolveSyncRelayUrl(input) {
|
|
453
|
+
if (input.privateMode) {
|
|
454
|
+
const regionalUrl = input.environmentUrl?.trim();
|
|
455
|
+
if (!regionalUrl) throw new Error("ALFE_SYNC_RELAY_WS_URL is required in AWS-private mode");
|
|
456
|
+
let parsed;
|
|
457
|
+
try {
|
|
458
|
+
parsed = new URL(regionalUrl);
|
|
459
|
+
} catch {
|
|
460
|
+
throw new Error("AWS-private sync relay URL must be valid");
|
|
461
|
+
}
|
|
462
|
+
if (parsed.protocol !== "ws:" || !parsed.hostname.endsWith(".local") && !parsed.hostname.endsWith(".sst") || parsed.pathname !== "/ws" || parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "") throw new Error("AWS-private sync relay URL must be a canonical VPC-local service URL");
|
|
463
|
+
return parsed.toString();
|
|
464
|
+
}
|
|
465
|
+
const configuredUrl = input.configuredUrl?.trim();
|
|
466
|
+
const environmentUrl = input.environmentUrl?.trim();
|
|
467
|
+
if (configuredUrl && configuredUrl.length > 0) return configuredUrl;
|
|
468
|
+
if (environmentUrl && environmentUrl.length > 0) return environmentUrl;
|
|
469
|
+
return deriveServiceWsUrl(input.apiUrl, "sync");
|
|
470
|
+
}
|
|
471
|
+
/** Only RFC1918 IPv4 and unique-local IPv6 addresses are valid VPC relay targets. */
|
|
472
|
+
function isVpcPrivateRelayAddress(address) {
|
|
473
|
+
const family = isIP(address);
|
|
474
|
+
if (family === 4) {
|
|
475
|
+
const [first, second] = address.split(".").map(Number);
|
|
476
|
+
return first === 10 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 168;
|
|
477
|
+
}
|
|
478
|
+
if (family === 6) {
|
|
479
|
+
const firstHextet = Number.parseInt(address.split(":", 1)[0] ?? "", 16);
|
|
480
|
+
return Number.isFinite(firstHextet) && (firstHextet & 65024) === 64512;
|
|
481
|
+
}
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
const vpcPrivateRelayLookup = (hostname, options, callback) => {
|
|
485
|
+
lookup(hostname, {
|
|
486
|
+
all: true,
|
|
487
|
+
verbatim: true
|
|
488
|
+
}, (error, addresses) => {
|
|
489
|
+
if (error) {
|
|
490
|
+
callback(error, "", 4);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (addresses.length === 0 || addresses.some(({ address }) => !isVpcPrivateRelayAddress(address))) {
|
|
494
|
+
callback(Object.assign(/* @__PURE__ */ new Error("private sync relay resolved outside the VPC address space"), { code: "EACCES" }), "", 4);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
const family = typeof options.family === "number" ? options.family : 0;
|
|
498
|
+
const selected = family === 0 ? addresses[0] : addresses.find((candidate) => candidate.family === family);
|
|
499
|
+
if (!selected) {
|
|
500
|
+
callback(Object.assign(/* @__PURE__ */ new Error("private sync relay has no address in the requested family"), { code: "EADDRNOTAVAIL" }), "", family || 4);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (options.all) {
|
|
504
|
+
callback(null, addresses);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
callback(null, selected.address, selected.family);
|
|
508
|
+
});
|
|
509
|
+
};
|
|
450
510
|
let client = null;
|
|
451
511
|
let agentId = null;
|
|
452
512
|
let syncEngine = null;
|
|
@@ -679,10 +739,13 @@ async function connectToSyncRelay(relayUrl, token, agentIdForSubscribe, log, gen
|
|
|
679
739
|
try {
|
|
680
740
|
const { default: WebSocket } = await import("ws");
|
|
681
741
|
if (!syncRelayActive || generation !== syncRelayGeneration) return null;
|
|
742
|
+
const relayHost = new URL(relayUrl).hostname;
|
|
743
|
+
const privateRelay = relayHost.endsWith(".local") || relayHost.endsWith(".sst");
|
|
682
744
|
const ws = new WebSocket(relayUrl, {
|
|
683
745
|
headers: { Authorization: `Bearer ${token}` },
|
|
684
746
|
handshakeTimeout: SYNC_RELAY_HANDSHAKE_TIMEOUT_MS,
|
|
685
|
-
maxPayload: SYNC_RELAY_MAX_MESSAGE_BYTES
|
|
747
|
+
maxPayload: SYNC_RELAY_MAX_MESSAGE_BYTES,
|
|
748
|
+
...privateRelay ? { lookup: vpcPrivateRelayLookup } : {}
|
|
686
749
|
});
|
|
687
750
|
ws.on("open", () => {
|
|
688
751
|
if (!syncRelayActive || generation !== syncRelayGeneration) {
|
|
@@ -897,7 +960,14 @@ const plugin = {
|
|
|
897
960
|
log.debug(`Shared sync engine skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
898
961
|
}
|
|
899
962
|
try {
|
|
900
|
-
const
|
|
963
|
+
const configuredRelayUrl = pluginConfig.syncRelayUrl?.trim();
|
|
964
|
+
const environmentRelayUrl = process.env.ALFE_SYNC_RELAY_WS_URL?.trim();
|
|
965
|
+
const relayUrl = resolveSyncRelayUrl({
|
|
966
|
+
apiUrl: syncCfg.apiUrl,
|
|
967
|
+
configuredUrl: configuredRelayUrl,
|
|
968
|
+
environmentUrl: environmentRelayUrl,
|
|
969
|
+
privateMode: process.env.ALFE_PRIVATE_DATA_PLANE === "true"
|
|
970
|
+
});
|
|
901
971
|
syncRelayActive = true;
|
|
902
972
|
const relayGeneration = ++syncRelayGeneration;
|
|
903
973
|
syncRelayWs = await connectToSyncRelay(relayUrl, syncCfg.apiKey, registered.agentId, log, relayGeneration);
|
|
@@ -1055,6 +1125,6 @@ const plugin = {
|
|
|
1055
1125
|
}
|
|
1056
1126
|
};
|
|
1057
1127
|
//#endregion
|
|
1058
|
-
export { createSharedSyncEngine as n,
|
|
1128
|
+
export { startWatcher as a, createSharedSyncEngine as i, plugin as n, resolveSyncRelayUrl as r, isVpcPrivateRelayAddress as t };
|
|
1059
1129
|
|
|
1060
1130
|
//# sourceMappingURL=plugin2.js.map
|