beeos-claw 0.6.42 → 0.6.43
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": "beeos-claw",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.43",
|
|
4
4
|
"description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "BeeOS <dev@beeos.ai>",
|
|
@@ -16,3 +16,38 @@ export function bindRuntimeBlackboxLease(input) {
|
|
|
16
16
|
journalGeneration: input.journalGeneration,
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Construct the black-box Worker through the same one-client Message SDK
|
|
22
|
+
* composition used by the production plugin. Returning the direct HTTP
|
|
23
|
+
* channel here is not equivalent: the runtime consumer is owned by
|
|
24
|
+
* MessageClient.methods and requires the SDK runtime-delivery port.
|
|
25
|
+
*/
|
|
26
|
+
export function createRuntimeBlackboxMessageComposition(input) {
|
|
27
|
+
const options = {
|
|
28
|
+
identityId: input.identityId,
|
|
29
|
+
serviceUrl: input.serviceUrl,
|
|
30
|
+
tokenProvider: async (requestedIdentityId) => {
|
|
31
|
+
if (requestedIdentityId !== input.identityId) {
|
|
32
|
+
throw new Error("runtime black-box MessageClient identity changed");
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
token: input.token,
|
|
36
|
+
centrifugoUrl: input.centrifugoUrl,
|
|
37
|
+
serviceUrl: input.serviceUrl,
|
|
38
|
+
identityId: input.identityId,
|
|
39
|
+
expiresAt: input.expiresAt,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
runtimeDelivery: {
|
|
43
|
+
scopedDeliveryKey: input.scopedDeliveryKey,
|
|
44
|
+
authority: { currentLease: input.currentLease },
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const composition = input.compose(options);
|
|
48
|
+
if (typeof composition?.client?.methods?.consume !== "function" ||
|
|
49
|
+
typeof composition?.nodeTransport?.fetchRuntimeChannel !== "function") {
|
|
50
|
+
throw new Error("runtime black-box MessageClient composition is incomplete");
|
|
51
|
+
}
|
|
52
|
+
return composition;
|
|
53
|
+
}
|
|
@@ -10,10 +10,9 @@ import { FileRuntimeLeasePort } from "../dist/runtime/runtime-operation-lease.js
|
|
|
10
10
|
import { FileRuntimeCommandJournal } from "../dist/runtime/runtime-command-journal.js";
|
|
11
11
|
import { FileRuntimePoisonDeliveryJournal } from
|
|
12
12
|
"../dist/runtime/runtime-poison-delivery-journal.js";
|
|
13
|
-
import { MessageServiceRuntimeAuthenticatedFetch } from
|
|
14
|
-
"../dist/runtime/message-service-runtime-authenticated-fetch.js";
|
|
15
13
|
import { MessageServiceRuntimeMessageChannel } from
|
|
16
14
|
"../dist/runtime/message-service-runtime-message-channel.js";
|
|
15
|
+
import { composeMessageClient } from "../dist/message-client-composition.js";
|
|
17
16
|
import { AgentGatewayGrantJwksReadinessAdapter, RuntimeServiceTransportReadinessAdapter,
|
|
18
17
|
createRuntimeServiceProductionCandidate } from
|
|
19
18
|
"../dist/runtime/runtime-service-production-candidate.js";
|
|
@@ -21,7 +20,8 @@ import { createRuntimeBlackboxReceipt } from "./runtime-security.mjs";
|
|
|
21
20
|
import { runRuntimePoisonBlackbox } from "./runtime-poison-blackbox-lib.mjs";
|
|
22
21
|
import { closeRuntimeResources, createRuntimeBlackboxCompletionGate, selectRuntimeError, startGatewayWithinDeadline, withinDeadline } from
|
|
23
22
|
"./runtime-blackbox-worker-lifecycle.mjs";
|
|
24
|
-
import { bindRuntimeBlackboxLease } from
|
|
23
|
+
import { bindRuntimeBlackboxLease, createRuntimeBlackboxMessageComposition } from
|
|
24
|
+
"./runtime-blackbox-worker-lease.mjs";
|
|
25
25
|
|
|
26
26
|
export async function main() {
|
|
27
27
|
const contractPath = requiredEnvironment("RUNTIME_BLACKBOX_CONTRACT_FILE");
|
|
@@ -61,6 +61,17 @@ export async function main() {
|
|
|
61
61
|
const journalStoreId = nonempty(leaseClaims.journalStoreId, "runtime lease journalStoreId");
|
|
62
62
|
const journalGeneration = decimal(leaseClaims.journalGeneration, "runtime lease journalGeneration");
|
|
63
63
|
const messageServiceUrl = strictBaseUrl(requiredEnvironment("MESSAGE_SERVICE_URL"), "MESSAGE_SERVICE_URL");
|
|
64
|
+
const messageServiceOrigin = new URL(messageServiceUrl).origin;
|
|
65
|
+
const messageIdentityId = nonempty(authority.handlerIdentity, "authority.handlerIdentity");
|
|
66
|
+
const scopedDeliveryKey = requiredEnvironment("MESSAGE_RUNTIME_DELIVERY_KEY");
|
|
67
|
+
const runtimeLease = () => bindRuntimeBlackboxLease({
|
|
68
|
+
instanceId, leaseId: nonempty(authority.leaseId, "authority.leaseId"),
|
|
69
|
+
handlerIdentity: messageIdentityId,
|
|
70
|
+
runtimeEpoch: decimal(authority.runtimeEpoch, "authority.runtimeEpoch"),
|
|
71
|
+
runtimeLeaseCredential: nonempty(authority.runtimeLeaseCredential, "authority.runtimeLeaseCredential"),
|
|
72
|
+
leaseExpiresAt: new Date(Number(leaseClaims.exp) * 1_000).toISOString(),
|
|
73
|
+
journalStoreId, journalGeneration,
|
|
74
|
+
});
|
|
64
75
|
const agentGatewayUrl = strictBaseUrl(requiredEnvironment(
|
|
65
76
|
nonempty(contract.authorization?.http?.baseUrlEnvironment,
|
|
66
77
|
"contract.authorization.http.baseUrlEnvironment")), "Agent Gateway base URL");
|
|
@@ -72,17 +83,23 @@ export async function main() {
|
|
|
72
83
|
|
|
73
84
|
let httpRequests = 0;
|
|
74
85
|
let terminalEvent;
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
const processFetch = globalThis.fetch;
|
|
87
|
+
globalThis.fetch = async (url, init = {}) => {
|
|
88
|
+
const requested = new URL(url instanceof Request ? url.url : url);
|
|
89
|
+
if (requested.origin === messageServiceOrigin) httpRequests += 1;
|
|
90
|
+
return await processFetch(url, init);
|
|
78
91
|
};
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
const messageComposition = createRuntimeBlackboxMessageComposition({
|
|
93
|
+
compose: composeMessageClient,
|
|
94
|
+
identityId: messageIdentityId,
|
|
95
|
+
serviceUrl: messageServiceUrl,
|
|
96
|
+
token: requiredEnvironment("MESSAGE_API_KEY"),
|
|
97
|
+
centrifugoUrl: strictWebSocketUrl(requiredEnvironment("CENTRIFUGO_WS_URL"), "CENTRIFUGO_WS_URL"),
|
|
98
|
+
expiresAt: Math.floor(deadline / 1_000) + 60,
|
|
99
|
+
scopedDeliveryKey,
|
|
100
|
+
currentLease: runtimeLease,
|
|
85
101
|
});
|
|
102
|
+
const messageFetch = messageComposition.nodeTransport;
|
|
86
103
|
const boundAgentFetch = async (url, init = {}) => {
|
|
87
104
|
const headers = new Headers(init.headers);
|
|
88
105
|
headers.set("X-Instance-ID", instanceId);
|
|
@@ -99,7 +116,6 @@ export async function main() {
|
|
|
99
116
|
// candidate.status=unavailable (message_channel_transport) — the
|
|
100
117
|
// 0.6.20–0.6.22 worker false red that blocks backend#842 even when the
|
|
101
118
|
// harness fixture is correct. Reused later for the post-ack renew proof.
|
|
102
|
-
const scopedDeliveryKey = requiredEnvironment("MESSAGE_RUNTIME_DELIVERY_KEY");
|
|
103
119
|
const authorityChannel = new MessageServiceRuntimeMessageChannel({
|
|
104
120
|
serviceUrl: messageServiceUrl,
|
|
105
121
|
transport: messageFetch,
|
|
@@ -109,7 +125,7 @@ export async function main() {
|
|
|
109
125
|
authorizationAdapter: new AgentGatewayGrantJwksReadinessAdapter({ agentGatewayUrl }),
|
|
110
126
|
transportAdapter: new RuntimeServiceTransportReadinessAdapter({ agentGatewayUrl,
|
|
111
127
|
messageService: messageFetch, boundAgentFetch,
|
|
112
|
-
messageClient:
|
|
128
|
+
messageClient: messageComposition.client,
|
|
113
129
|
configuredServiceUrl: messageServiceUrl,
|
|
114
130
|
scopedDeliveryKey }),
|
|
115
131
|
commandJournal,
|
|
@@ -130,14 +146,6 @@ export async function main() {
|
|
|
130
146
|
let consumer;
|
|
131
147
|
let primaryError;
|
|
132
148
|
let releaseGatewayTransportObserver;
|
|
133
|
-
const runtimeLease = () => bindRuntimeBlackboxLease({
|
|
134
|
-
instanceId, leaseId: nonempty(authority.leaseId, "authority.leaseId"),
|
|
135
|
-
handlerIdentity: nonempty(authority.handlerIdentity, "authority.handlerIdentity"),
|
|
136
|
-
runtimeEpoch: decimal(authority.runtimeEpoch, "authority.runtimeEpoch"),
|
|
137
|
-
runtimeLeaseCredential: nonempty(authority.runtimeLeaseCredential, "authority.runtimeLeaseCredential"),
|
|
138
|
-
leaseExpiresAt: new Date(Number(leaseClaims.exp) * 1_000).toISOString(),
|
|
139
|
-
journalStoreId, journalGeneration,
|
|
140
|
-
});
|
|
141
149
|
try {
|
|
142
150
|
releaseGatewayTransportObserver = await startGatewayWithinDeadline(gateway, deadline);
|
|
143
151
|
const identities = new FileRuntimeAgentIdentityRegistry(`${statePrefix}-identities.json`);
|
|
@@ -168,6 +176,7 @@ export async function main() {
|
|
|
168
176
|
} finally {
|
|
169
177
|
primaryError = selectRuntimeError(primaryError,
|
|
170
178
|
await closeRuntimeResources({ consumer, gateway, releaseGatewayTransportObserver }));
|
|
179
|
+
globalThis.fetch = processFetch;
|
|
171
180
|
try { completionGate.assertNoFailure(); }
|
|
172
181
|
catch (error) { primaryError ??= error; }
|
|
173
182
|
}
|
|
@@ -213,13 +222,6 @@ function decodeRuntimeLease(token) {
|
|
|
213
222
|
}
|
|
214
223
|
return claims;
|
|
215
224
|
}
|
|
216
|
-
async function fetchWithDeadline(url, init, deadline) {
|
|
217
|
-
const requested = new URL(url);
|
|
218
|
-
const response = await withinDeadline((signal) =>
|
|
219
|
-
fetch(requested, { ...init, redirect: "error", signal }), deadline);
|
|
220
|
-
if (response.url && new URL(response.url).origin !== requested.origin) throw new Error("HTTP origin changed");
|
|
221
|
-
return response;
|
|
222
|
-
}
|
|
223
225
|
function requiredEnvironment(name) {
|
|
224
226
|
const value = process.env[name]?.trim();
|
|
225
227
|
if (!value) throw new Error(`${name} is required`);
|
|
@@ -232,6 +234,13 @@ function strictBaseUrl(value, label) {
|
|
|
232
234
|
}
|
|
233
235
|
return url.toString();
|
|
234
236
|
}
|
|
237
|
+
function strictWebSocketUrl(value, label) {
|
|
238
|
+
const url = new URL(value);
|
|
239
|
+
if (!/^wss?:$/.test(url.protocol) || url.username || url.password || url.search || url.hash) {
|
|
240
|
+
throw new Error(`${label} must be an absolute query-free WebSocket URL`);
|
|
241
|
+
}
|
|
242
|
+
return url.toString();
|
|
243
|
+
}
|
|
235
244
|
function parseObject(raw, label) {
|
|
236
245
|
const value = JSON.parse(raw);
|
|
237
246
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
|