@cfio/cohort-sync 0.15.0 → 0.17.0
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.js +145 -4
- package/dist/openclaw.plugin.json +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11826,7 +11826,13 @@ function createClient(convexUrl) {
|
|
|
11826
11826
|
}
|
|
11827
11827
|
savedConvexUrl = convexUrl;
|
|
11828
11828
|
authCircuitOpen = false;
|
|
11829
|
-
|
|
11829
|
+
const nativeWS = globalThis.WebSocket;
|
|
11830
|
+
delete globalThis.WebSocket;
|
|
11831
|
+
try {
|
|
11832
|
+
client = new ConvexClient(convexUrl);
|
|
11833
|
+
} finally {
|
|
11834
|
+
if (nativeWS) globalThis.WebSocket = nativeWS;
|
|
11835
|
+
}
|
|
11830
11836
|
return client;
|
|
11831
11837
|
}
|
|
11832
11838
|
function getClient() {
|
|
@@ -11855,7 +11861,10 @@ function closeBridge() {
|
|
|
11855
11861
|
}
|
|
11856
11862
|
var authCircuitOpen = false;
|
|
11857
11863
|
function isUnauthorizedError(err) {
|
|
11858
|
-
|
|
11864
|
+
if (!(err instanceof ConvexError)) return false;
|
|
11865
|
+
const data = err.data;
|
|
11866
|
+
if (!data || typeof data !== "object") return false;
|
|
11867
|
+
return data.code === "UNAUTHORIZED";
|
|
11859
11868
|
}
|
|
11860
11869
|
function tripAuthCircuit() {
|
|
11861
11870
|
if (authCircuitOpen) return;
|
|
@@ -11874,6 +11883,7 @@ var markDeliveredByPlugin = makeFunctionReference("notifications:markDeliveredBy
|
|
|
11874
11883
|
var getPendingCommandsForPlugin = makeFunctionReference("gatewayCommands:getPendingForPlugin");
|
|
11875
11884
|
var acknowledgeCommandRef = makeFunctionReference("gatewayCommands:acknowledgeCommand");
|
|
11876
11885
|
var failCommandRef = makeFunctionReference("gatewayCommands:failCommand");
|
|
11886
|
+
var getChannelsForPlugin = makeFunctionReference("cloudGatewayChannels:listForPlugin");
|
|
11877
11887
|
var addCommentFromPluginRef = makeFunctionReference("comments:addCommentFromPlugin");
|
|
11878
11888
|
async function pushTelemetry(apiKey2, data) {
|
|
11879
11889
|
if (authCircuitOpen) return;
|
|
@@ -12204,6 +12214,41 @@ function startCommandSubscription(cfg, logger, resolveAgentName, gwClient) {
|
|
|
12204
12214
|
logger.info("cohort-sync: command subscription active");
|
|
12205
12215
|
return unsubscribe;
|
|
12206
12216
|
}
|
|
12217
|
+
function subscribeChannels(apiKey2, onUpdate, logger) {
|
|
12218
|
+
const c = getClient();
|
|
12219
|
+
if (!c) {
|
|
12220
|
+
(logger ?? getLogger()).warn(
|
|
12221
|
+
"cohort-sync: no ConvexClient \u2014 channels subscription skipped"
|
|
12222
|
+
);
|
|
12223
|
+
return null;
|
|
12224
|
+
}
|
|
12225
|
+
const apiKeyHash = hashApiKey(apiKey2);
|
|
12226
|
+
const unsubscribe = c.onUpdate(
|
|
12227
|
+
getChannelsForPlugin,
|
|
12228
|
+
{ apiKeyHash },
|
|
12229
|
+
(rows) => {
|
|
12230
|
+
try {
|
|
12231
|
+
onUpdate(rows);
|
|
12232
|
+
} catch (err) {
|
|
12233
|
+
(logger ?? getLogger()).error(
|
|
12234
|
+
`cohort-sync: channels onUpdate handler threw: ${String(err)}`
|
|
12235
|
+
);
|
|
12236
|
+
}
|
|
12237
|
+
},
|
|
12238
|
+
(err) => {
|
|
12239
|
+
if (isUnauthorizedError(err)) {
|
|
12240
|
+
tripAuthCircuit();
|
|
12241
|
+
return;
|
|
12242
|
+
}
|
|
12243
|
+
(logger ?? getLogger()).error(
|
|
12244
|
+
`cohort-sync: channels subscription error: ${String(err)}`
|
|
12245
|
+
);
|
|
12246
|
+
}
|
|
12247
|
+
);
|
|
12248
|
+
unsubscribers.push(unsubscribe);
|
|
12249
|
+
(logger ?? getLogger()).info("cohort-sync: channels subscription active");
|
|
12250
|
+
return unsubscribe;
|
|
12251
|
+
}
|
|
12207
12252
|
|
|
12208
12253
|
// src/gateway-client.ts
|
|
12209
12254
|
import crypto2 from "node:crypto";
|
|
@@ -12299,7 +12344,13 @@ var ALLOWED_METHODS = /* @__PURE__ */ new Set([
|
|
|
12299
12344
|
"agent",
|
|
12300
12345
|
"snapshot",
|
|
12301
12346
|
"system.presence",
|
|
12302
|
-
"gateway.restart"
|
|
12347
|
+
"gateway.restart",
|
|
12348
|
+
// `secrets.reload` re-resolves SecretRefs and atomically swaps the runtime
|
|
12349
|
+
// snapshot. The plugin's `cohort-sync/secrets-reload` gateway-method wrapper
|
|
12350
|
+
// (see `gateway-methods.ts`) proxies inbound calls to this outbound RPC so
|
|
12351
|
+
// the Cohort web app (and #608 channel attach/detach flows) can trigger a
|
|
12352
|
+
// reload without minting an admin-scope key.
|
|
12353
|
+
"secrets.reload"
|
|
12303
12354
|
]);
|
|
12304
12355
|
function buildConnectFrame(id, token, pluginVersion, identity, nonce) {
|
|
12305
12356
|
const signedAtMs = Date.now();
|
|
@@ -13372,7 +13423,7 @@ function dumpCtx(ctx) {
|
|
|
13372
13423
|
function dumpEvent(event) {
|
|
13373
13424
|
return dumpCtx(event);
|
|
13374
13425
|
}
|
|
13375
|
-
var PLUGIN_VERSION = true ? "0.
|
|
13426
|
+
var PLUGIN_VERSION = true ? "0.17.0" : "unknown";
|
|
13376
13427
|
function resolveGatewayToken(api) {
|
|
13377
13428
|
const token = api.config?.gateway?.auth?.token;
|
|
13378
13429
|
return typeof token === "string" ? token : null;
|
|
@@ -13501,6 +13552,19 @@ function initGatewayClient(port, token, cfg, resolveAgentName, logger) {
|
|
|
13501
13552
|
});
|
|
13502
13553
|
return client2;
|
|
13503
13554
|
}
|
|
13555
|
+
function applyChannelRowsToBridge(rows, setChannel, resolveAgentName) {
|
|
13556
|
+
let count = 0;
|
|
13557
|
+
for (const row of rows) {
|
|
13558
|
+
const agentName = resolveAgentName(row.agentId);
|
|
13559
|
+
setChannel(row.kind, agentName);
|
|
13560
|
+
count++;
|
|
13561
|
+
if (row.accountId) {
|
|
13562
|
+
setChannel(`${row.kind}:${row.accountId}`, agentName);
|
|
13563
|
+
count++;
|
|
13564
|
+
}
|
|
13565
|
+
}
|
|
13566
|
+
return count;
|
|
13567
|
+
}
|
|
13504
13568
|
async function handleGatewayStart(event, state) {
|
|
13505
13569
|
if (!state) {
|
|
13506
13570
|
return;
|
|
@@ -13561,6 +13625,39 @@ async function handleGatewayStart(event, state) {
|
|
|
13561
13625
|
for (const agentId of allAgentIds) {
|
|
13562
13626
|
resolvedNameMap[agentId] = state.resolveAgentName(agentId);
|
|
13563
13627
|
}
|
|
13628
|
+
if (state.channelsUnsubscriber) {
|
|
13629
|
+
state.channelsUnsubscriber();
|
|
13630
|
+
state.channelsUnsubscriber = null;
|
|
13631
|
+
}
|
|
13632
|
+
try {
|
|
13633
|
+
const unsubChannels = subscribeChannels(
|
|
13634
|
+
cfg.apiKey,
|
|
13635
|
+
(rows) => {
|
|
13636
|
+
try {
|
|
13637
|
+
const count = applyChannelRowsToBridge(
|
|
13638
|
+
rows,
|
|
13639
|
+
setChannelAgent,
|
|
13640
|
+
state.resolveAgentName
|
|
13641
|
+
);
|
|
13642
|
+
logger.debug("cohort-sync: channels snapshot applied", {
|
|
13643
|
+
rowCount: rows.length,
|
|
13644
|
+
bridgeEntries: count,
|
|
13645
|
+
bridge: Object.fromEntries(getChannelAgentBridge())
|
|
13646
|
+
});
|
|
13647
|
+
} catch (err) {
|
|
13648
|
+
logger.warn(
|
|
13649
|
+
`cohort-sync: applyChannelRowsToBridge failed: ${String(err)}`
|
|
13650
|
+
);
|
|
13651
|
+
}
|
|
13652
|
+
},
|
|
13653
|
+
logger
|
|
13654
|
+
);
|
|
13655
|
+
if (unsubChannels) state.channelsUnsubscriber = unsubChannels;
|
|
13656
|
+
} catch (err) {
|
|
13657
|
+
logger.warn(
|
|
13658
|
+
`cohort-sync: channels subscription init failed: ${String(err)}`
|
|
13659
|
+
);
|
|
13660
|
+
}
|
|
13564
13661
|
await startNotificationSubscription(
|
|
13565
13662
|
event.port,
|
|
13566
13663
|
cfg,
|
|
@@ -14003,6 +14100,13 @@ function registerHookHandlers(api, logger, getState) {
|
|
|
14003
14100
|
clearInterval(state.keepaliveInterval);
|
|
14004
14101
|
state.keepaliveInterval = null;
|
|
14005
14102
|
}
|
|
14103
|
+
if (state.channelsUnsubscriber) {
|
|
14104
|
+
try {
|
|
14105
|
+
state.channelsUnsubscriber();
|
|
14106
|
+
} catch {
|
|
14107
|
+
}
|
|
14108
|
+
state.channelsUnsubscriber = null;
|
|
14109
|
+
}
|
|
14006
14110
|
state.activityBatch.drain();
|
|
14007
14111
|
if (!isRestart) {
|
|
14008
14112
|
const shutdownConfigIds = (config?.agents?.list ?? []).map((a) => a.id);
|
|
@@ -14150,11 +14254,47 @@ function initializeHookState(api, cfg) {
|
|
|
14150
14254
|
gwClientInitialized,
|
|
14151
14255
|
keepaliveInterval: null,
|
|
14152
14256
|
commandUnsubscriber: commandUnsub,
|
|
14257
|
+
channelsUnsubscriber: null,
|
|
14153
14258
|
api,
|
|
14154
14259
|
latestPluginVersion: null
|
|
14155
14260
|
};
|
|
14156
14261
|
}
|
|
14157
14262
|
|
|
14263
|
+
// src/gateway-methods.ts
|
|
14264
|
+
async function invokeSecretsReload(gwClient) {
|
|
14265
|
+
if (!gwClient || !gwClient.isAlive()) {
|
|
14266
|
+
return { ok: false, error: "gateway client not connected" };
|
|
14267
|
+
}
|
|
14268
|
+
try {
|
|
14269
|
+
const result = await gwClient.request(
|
|
14270
|
+
"secrets.reload",
|
|
14271
|
+
void 0,
|
|
14272
|
+
3e4
|
|
14273
|
+
// Channel restart can take a few seconds — give it headroom.
|
|
14274
|
+
);
|
|
14275
|
+
const warningCount = typeof result?.warningCount === "number" ? result.warningCount : 0;
|
|
14276
|
+
return { ok: true, warningCount };
|
|
14277
|
+
} catch (err) {
|
|
14278
|
+
return {
|
|
14279
|
+
ok: false,
|
|
14280
|
+
error: err instanceof Error ? err.message : String(err)
|
|
14281
|
+
};
|
|
14282
|
+
}
|
|
14283
|
+
}
|
|
14284
|
+
function registerGatewayMethods(api, getGatewayClient) {
|
|
14285
|
+
api.registerGatewayMethod(
|
|
14286
|
+
"cohort-sync/secrets-reload",
|
|
14287
|
+
async ({ respond }) => {
|
|
14288
|
+
const result = await invokeSecretsReload(getGatewayClient());
|
|
14289
|
+
respond(true, result);
|
|
14290
|
+
},
|
|
14291
|
+
// operator.write is the channel attach/detach surface — same scope used
|
|
14292
|
+
// for any write-side channels operation. Admins also pass (admin is a
|
|
14293
|
+
// superset).
|
|
14294
|
+
{ scope: "operator.write" }
|
|
14295
|
+
);
|
|
14296
|
+
}
|
|
14297
|
+
|
|
14158
14298
|
// src/pocket-guide.ts
|
|
14159
14299
|
var POCKET_GUIDE = `# Cohort Agent Guide (Pocket Version)
|
|
14160
14300
|
|
|
@@ -14230,6 +14370,7 @@ var plugin = {
|
|
|
14230
14370
|
return;
|
|
14231
14371
|
}
|
|
14232
14372
|
registerHookHandlers(api, api.logger, () => sharedHookState);
|
|
14373
|
+
registerGatewayMethods(api, () => sharedHookState?.persistentGwClient ?? null);
|
|
14233
14374
|
const gatewayPort = api.config?.gateway?.port ?? 18789;
|
|
14234
14375
|
api.registerHook(
|
|
14235
14376
|
"gateway:startup",
|
package/dist/package.json
CHANGED
package/package.json
CHANGED