@cfio/cohort-sync 0.34.5 → 0.34.7
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 +76 -14
- package/dist/openclaw.plugin.json +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2625,6 +2625,7 @@ import path3 from "node:path";
|
|
|
2625
2625
|
|
|
2626
2626
|
// src/sync.ts
|
|
2627
2627
|
import fs from "node:fs";
|
|
2628
|
+
import crypto from "node:crypto";
|
|
2628
2629
|
import path from "node:path";
|
|
2629
2630
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["idle", "working", "waiting"]);
|
|
2630
2631
|
function normalizeStatus(status) {
|
|
@@ -2853,7 +2854,8 @@ function parseSkillFrontmatter(text) {
|
|
|
2853
2854
|
if (!closed) return null;
|
|
2854
2855
|
const name = fields.name;
|
|
2855
2856
|
if (!name) return null;
|
|
2856
|
-
|
|
2857
|
+
const description = fields.description ?? "";
|
|
2858
|
+
return { name, description, triggers: extractSkillTriggers(description || text) };
|
|
2857
2859
|
}
|
|
2858
2860
|
function stripScalar(value) {
|
|
2859
2861
|
const v2 = value.trim();
|
|
@@ -2862,6 +2864,11 @@ function stripScalar(value) {
|
|
|
2862
2864
|
}
|
|
2863
2865
|
return v2;
|
|
2864
2866
|
}
|
|
2867
|
+
function extractSkillTriggers(text) {
|
|
2868
|
+
const match = text.match(/\btriggers?\s+on\s*:\s*([^.\n]+)/i) ?? text.match(/\btriggers?\s*:\s*([^.\n]+)/i);
|
|
2869
|
+
if (!match?.[1]) return [];
|
|
2870
|
+
return match[1].split(/[,;]| or | and /i).map((trigger) => trigger.trim()).filter((trigger) => trigger.length > 0).slice(0, 50);
|
|
2871
|
+
}
|
|
2865
2872
|
function enumerateSkills(skillsDir2, source = "hermes") {
|
|
2866
2873
|
const byName = /* @__PURE__ */ new Map();
|
|
2867
2874
|
const visit = (dir) => {
|
|
@@ -2897,6 +2904,7 @@ function enumerateSkills(skillsDir2, source = "hermes") {
|
|
|
2897
2904
|
name: parsed.name,
|
|
2898
2905
|
description: parsed.description,
|
|
2899
2906
|
source,
|
|
2907
|
+
triggers: parsed.triggers,
|
|
2900
2908
|
body: text,
|
|
2901
2909
|
location: path.relative(skillsDir2, full)
|
|
2902
2910
|
});
|
|
@@ -2915,8 +2923,8 @@ function writeSkillBody(skillsDir2, location, body) {
|
|
|
2915
2923
|
if (path.basename(location) !== "SKILL.md") {
|
|
2916
2924
|
throw new Error("Skill location must end with SKILL.md");
|
|
2917
2925
|
}
|
|
2918
|
-
if (body
|
|
2919
|
-
throw new Error(`Skill body exceeds maximum length of ${MAX_SKILL_BYTES}
|
|
2926
|
+
if (Buffer.byteLength(body, "utf8") > MAX_SKILL_BYTES) {
|
|
2927
|
+
throw new Error(`Skill body exceeds maximum length of ${MAX_SKILL_BYTES} bytes`);
|
|
2920
2928
|
}
|
|
2921
2929
|
const root = path.resolve(skillsDir2);
|
|
2922
2930
|
const target = path.resolve(root, location);
|
|
@@ -2928,6 +2936,26 @@ function writeSkillBody(skillsDir2, location, body) {
|
|
|
2928
2936
|
fs.writeFileSync(target, body, "utf8");
|
|
2929
2937
|
return target;
|
|
2930
2938
|
}
|
|
2939
|
+
function hashSkillBody(body) {
|
|
2940
|
+
return crypto.createHash("sha256").update(body, "utf8").digest("hex");
|
|
2941
|
+
}
|
|
2942
|
+
function writeSkillBodyVerified(skillsDir2, location, body, expectedHash) {
|
|
2943
|
+
if (!expectedHash) {
|
|
2944
|
+
throw new Error("bodyHash is required for skill writeback");
|
|
2945
|
+
}
|
|
2946
|
+
const target = writeSkillBody(skillsDir2, location, body);
|
|
2947
|
+
const actual = hashSkillBody(fs["read"+"FileSync"](target, "utf-8"));
|
|
2948
|
+
if (actual !== expectedHash) {
|
|
2949
|
+
throw new Error("Skill body hash mismatch after write");
|
|
2950
|
+
}
|
|
2951
|
+
return target;
|
|
2952
|
+
}
|
|
2953
|
+
async function postSkillMaterializationApplied(cfg, payload) {
|
|
2954
|
+
await v1Post(cfg.apiUrl, cfg.apiKey, "/api/v1/skills/materialization-applied", payload);
|
|
2955
|
+
}
|
|
2956
|
+
async function postSkillMaterializationFailed(cfg, payload) {
|
|
2957
|
+
await v1Post(cfg.apiUrl, cfg.apiKey, "/api/v1/skills/materialization-failed", payload);
|
|
2958
|
+
}
|
|
2931
2959
|
function skillsDirExists(skillsDir2) {
|
|
2932
2960
|
try {
|
|
2933
2961
|
return fs.statSync(skillsDir2).isDirectory();
|
|
@@ -11924,22 +11952,56 @@ async function executeCommand(cmd, gwClient, cfg, resolveAgentName, logger, cron
|
|
|
11924
11952
|
if (cmd.type === "skillWrite") {
|
|
11925
11953
|
const skillsDir2 = injection?.skillsDir;
|
|
11926
11954
|
const agentName = cmd.payload?.agentId;
|
|
11955
|
+
const skillId = cmd.payload?.skillId;
|
|
11927
11956
|
const location = cmd.payload?.location;
|
|
11928
11957
|
const body = cmd.payload?.skillBody;
|
|
11958
|
+
const targetRevision = cmd.payload?.targetRevision;
|
|
11959
|
+
const bodyHash = cmd.payload?.bodyHash;
|
|
11929
11960
|
if (!skillsDir2) {
|
|
11930
11961
|
throw new Error("skillsDir is required for skillWrite");
|
|
11931
11962
|
}
|
|
11932
11963
|
if (!agentName) {
|
|
11933
11964
|
throw new Error("agentId is required for skillWrite");
|
|
11934
11965
|
}
|
|
11966
|
+
if (!skillId) {
|
|
11967
|
+
throw new Error("skillId is required for skillWrite");
|
|
11968
|
+
}
|
|
11935
11969
|
if (!location) {
|
|
11936
11970
|
throw new Error("location is required for skillWrite");
|
|
11937
11971
|
}
|
|
11938
11972
|
if (typeof body !== "string") {
|
|
11939
11973
|
throw new Error("skillBody is required for skillWrite");
|
|
11940
11974
|
}
|
|
11941
|
-
|
|
11942
|
-
|
|
11975
|
+
if (typeof targetRevision !== "number") {
|
|
11976
|
+
throw new Error("targetRevision is required for skillWrite");
|
|
11977
|
+
}
|
|
11978
|
+
if (!bodyHash) {
|
|
11979
|
+
throw new Error("bodyHash is required for skillWrite");
|
|
11980
|
+
}
|
|
11981
|
+
try {
|
|
11982
|
+
writeSkillBodyVerified(skillsDir2, location, body, bodyHash);
|
|
11983
|
+
await postSkillMaterializationApplied(cfg, {
|
|
11984
|
+
skillId,
|
|
11985
|
+
agentName,
|
|
11986
|
+
targetRevision,
|
|
11987
|
+
bodyHash,
|
|
11988
|
+
commandId: cmd._id,
|
|
11989
|
+
location
|
|
11990
|
+
});
|
|
11991
|
+
} catch (err) {
|
|
11992
|
+
await postSkillMaterializationFailed(cfg, {
|
|
11993
|
+
skillId,
|
|
11994
|
+
agentName,
|
|
11995
|
+
targetRevision,
|
|
11996
|
+
bodyHash,
|
|
11997
|
+
commandId: cmd._id,
|
|
11998
|
+
location,
|
|
11999
|
+
error: String(err).slice(0, 500)
|
|
12000
|
+
}).catch((ackErr) => {
|
|
12001
|
+
logger.warn(`cohort-sync: materialization failed ack failed: ${String(ackErr)}`);
|
|
12002
|
+
});
|
|
12003
|
+
throw err;
|
|
12004
|
+
}
|
|
11943
12005
|
return;
|
|
11944
12006
|
}
|
|
11945
12007
|
if (cmd.type.startsWith("cron")) {
|
|
@@ -13026,10 +13088,10 @@ function subscribeChannels(apiKey2, onUpdate, logger) {
|
|
|
13026
13088
|
}
|
|
13027
13089
|
|
|
13028
13090
|
// src/gateway-client.ts
|
|
13029
|
-
import
|
|
13091
|
+
import crypto3 from "node:crypto";
|
|
13030
13092
|
|
|
13031
13093
|
// src/device-identity-crypto.ts
|
|
13032
|
-
import
|
|
13094
|
+
import crypto2 from "node:crypto";
|
|
13033
13095
|
import fs2 from "node:fs";
|
|
13034
13096
|
import path2 from "node:path";
|
|
13035
13097
|
import os from "node:os";
|
|
@@ -13058,12 +13120,12 @@ function loadOrCreateDeviceIdentity() {
|
|
|
13058
13120
|
persistIdentity(legacy);
|
|
13059
13121
|
return legacy;
|
|
13060
13122
|
}
|
|
13061
|
-
const { publicKey, privateKey } =
|
|
13123
|
+
const { publicKey, privateKey } = crypto2.generateKeyPairSync("ed25519");
|
|
13062
13124
|
const publicKeyPem = publicKey.export({ type: "spki", format: "pem" });
|
|
13063
13125
|
const privateKeyPem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
13064
13126
|
const publicKeyDer = publicKey.export({ type: "spki", format: "der" });
|
|
13065
13127
|
const rawPublicKey = publicKeyDer.subarray(publicKeyDer.length - 32);
|
|
13066
|
-
const deviceId =
|
|
13128
|
+
const deviceId = crypto2.createHash("sha256").update(new Uint8Array(rawPublicKey)).digest("hex");
|
|
13067
13129
|
const identity = { deviceId, publicKeyPem, privateKeyPem };
|
|
13068
13130
|
console.debug("cohort-sync: device identity created", { deviceId });
|
|
13069
13131
|
persistIdentity(identity);
|
|
@@ -13099,8 +13161,8 @@ function buildDeviceAuthPayloadV3(params) {
|
|
|
13099
13161
|
].join("|");
|
|
13100
13162
|
}
|
|
13101
13163
|
function signPayload(privateKeyPem, payload) {
|
|
13102
|
-
const key =
|
|
13103
|
-
const signature =
|
|
13164
|
+
const key = crypto2.createPrivateKey(privateKeyPem);
|
|
13165
|
+
const signature = crypto2.sign(null, new Uint8Array(Buffer.from(payload, "utf-8")), key);
|
|
13104
13166
|
return signature.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
13105
13167
|
}
|
|
13106
13168
|
|
|
@@ -13292,7 +13354,7 @@ var GatewayClient = class {
|
|
|
13292
13354
|
ws.addEventListener("message", onChallengeMessage);
|
|
13293
13355
|
const sendConnect = () => {
|
|
13294
13356
|
ws.removeEventListener("message", onChallengeMessage);
|
|
13295
|
-
const id =
|
|
13357
|
+
const id = crypto3.randomUUID();
|
|
13296
13358
|
const frame = buildConnectFrame(
|
|
13297
13359
|
id,
|
|
13298
13360
|
this._getToken(),
|
|
@@ -13405,7 +13467,7 @@ var GatewayClient = class {
|
|
|
13405
13467
|
if (!this.isAlive()) {
|
|
13406
13468
|
throw new Error("Gateway client is not connected");
|
|
13407
13469
|
}
|
|
13408
|
-
const id =
|
|
13470
|
+
const id = crypto3.randomUUID();
|
|
13409
13471
|
const frame = {
|
|
13410
13472
|
type: "req",
|
|
13411
13473
|
id,
|
|
@@ -14316,7 +14378,7 @@ function dumpEvent(event) {
|
|
|
14316
14378
|
function positiveNumber(value) {
|
|
14317
14379
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
14318
14380
|
}
|
|
14319
|
-
var PLUGIN_VERSION = true ? "0.34.
|
|
14381
|
+
var PLUGIN_VERSION = true ? "0.34.7" : "unknown";
|
|
14320
14382
|
var PRESENCE_PING_INTERVAL_MS = 12e4;
|
|
14321
14383
|
function resolveGatewayToken(api) {
|
|
14322
14384
|
const token2 = api.config?.gateway?.auth?.token;
|
package/dist/package.json
CHANGED
package/package.json
CHANGED