@perkos/perkos-a2a 0.12.36 → 0.12.38
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/README.md +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -16
- package/dist/index.js.map +3 -3
- package/dist/openclaw-supervisor-client.js +1 -1
- package/dist/openclaw-supervisor-client.js.map +1 -1
- package/dist/openclaw-supervisor.d.ts.map +1 -1
- package/dist/openclaw-supervisor.js +8 -1
- package/dist/openclaw-supervisor.js.map +1 -1
- package/dist/repair.d.ts +30 -1
- package/dist/repair.d.ts.map +1 -1
- package/dist/repair.js +106 -23
- package/dist/repair.js.map +1 -1
- package/dist/runtime-evidence.d.ts +26 -2
- package/dist/runtime-evidence.d.ts.map +1 -1
- package/dist/runtime-evidence.js +130 -6
- package/dist/runtime-evidence.js.map +1 -1
- package/dist/supervisor-protocol.d.ts +8 -1
- package/dist/supervisor-protocol.d.ts.map +1 -1
- package/dist/supervisor-protocol.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -241,14 +241,24 @@ generation. Before accepting a newer generation, the supervisor waits for
|
|
|
241
241
|
confirmed transport shutdown; a timeout fails closed with
|
|
242
242
|
`OWNER_STOP_TIMEOUT`. A private TTL rollover lock serializes concurrent upgrades,
|
|
243
243
|
and health certifies the supervisor package version and real install root. Lease
|
|
244
|
-
and health evidence are owner-only files and never
|
|
245
|
-
|
|
244
|
+
and health evidence are owner-only files and never contain relay or chat
|
|
245
|
+
credentials. From 0.12.37, supervisor health is HMAC-bound to the active repair
|
|
246
|
+
attempt and is authoritative after a real restart; runtime load status is
|
|
247
|
+
written only by the claimed owner service. Incidental validation/doctor plugin
|
|
248
|
+
loads are diagnostic and cannot invalidate signed owner health. This ownership boundary applies to OpenClaw;
|
|
246
249
|
Hermes/custom runtimes keep their existing runtime-owned model and transport
|
|
247
250
|
routing.
|
|
248
251
|
|
|
252
|
+
From 0.12.38, runtime verification has its own post-install budget. The
|
|
253
|
+
continuous stability clock begins when signed supervisor health reports one
|
|
254
|
+
healthy relay client plus authenticated chat; fresh heartbeat count continues
|
|
255
|
+
to accumulate during that same window and is enforced at completion. Package
|
|
256
|
+
download, config migration, and gateway reload time therefore cannot consume
|
|
257
|
+
the three-minute transport acceptance window.
|
|
258
|
+
|
|
249
259
|
```bash
|
|
250
260
|
A2A_RELAY_API_KEY='<credential-from-invitation>' \
|
|
251
|
-
npx --yes @perkos/perkos-a2a@0.12.
|
|
261
|
+
npx --yes @perkos/perkos-a2a@0.12.38 connect \
|
|
252
262
|
--artifact ./perkos-a2a.tgz \
|
|
253
263
|
--sha256 '<sha256-from-the-official-invitation>' \
|
|
254
264
|
--agent-name '<agent-name>' \
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAGV,WAAW,EAEZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,cAAc,YAAY,CAAC;AA0C3B,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAItF;AAED,KAAK,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AASpD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CA2BT;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,oBAAoB,EAC3B,eAAe,CAAC,EAAE,MAAM,GACvB,oBAAoB,CA+BtB;AAiED,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC,CAAC;IACH,IAAI,CAAC,EAAE;QACL,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAYrF;AAQD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,GAClF,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuFxB;AAYD,oFAAoF;AACpF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,WAAW,EAAE,EACvB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAWR;AA4CD,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAe/D;AAMD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAc7E;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAGV,WAAW,EAEZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,cAAc,YAAY,CAAC;AA0C3B,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAItF;AAED,KAAK,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AASpD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CA2BT;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,oBAAoB,EAC3B,eAAe,CAAC,EAAE,MAAM,GACvB,oBAAoB,CA+BtB;AAiED,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC,CAAC;IACH,IAAI,CAAC,EAAE;QACL,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAYrF;AAQD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,GAClF,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuFxB;AAYD,oFAAoF;AACpF,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,WAAW,EAAE,EACvB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAWR;AA4CD,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAe/D;AAMD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAc7E;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QAszBxC"}
|
package/dist/index.js
CHANGED
|
@@ -24817,7 +24817,7 @@ var require_websocket = __commonJS({
|
|
|
24817
24817
|
var http = __require("http");
|
|
24818
24818
|
var net2 = __require("net");
|
|
24819
24819
|
var tls = __require("tls");
|
|
24820
|
-
var { randomBytes, createHash:
|
|
24820
|
+
var { randomBytes, createHash: createHash4 } = __require("crypto");
|
|
24821
24821
|
var { Duplex, Readable } = __require("stream");
|
|
24822
24822
|
var { URL: URL2 } = __require("url");
|
|
24823
24823
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -25477,7 +25477,7 @@ var require_websocket = __commonJS({
|
|
|
25477
25477
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
25478
25478
|
return;
|
|
25479
25479
|
}
|
|
25480
|
-
const digest =
|
|
25480
|
+
const digest = createHash4("sha1").update(key + GUID).digest("base64");
|
|
25481
25481
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
25482
25482
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
25483
25483
|
return;
|
|
@@ -25844,7 +25844,7 @@ var require_websocket_server = __commonJS({
|
|
|
25844
25844
|
var EventEmitter = __require("events");
|
|
25845
25845
|
var http = __require("http");
|
|
25846
25846
|
var { Duplex } = __require("stream");
|
|
25847
|
-
var { createHash:
|
|
25847
|
+
var { createHash: createHash4 } = __require("crypto");
|
|
25848
25848
|
var extension2 = require_extension();
|
|
25849
25849
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
25850
25850
|
var subprotocol2 = require_subprotocol();
|
|
@@ -26145,7 +26145,7 @@ var require_websocket_server = __commonJS({
|
|
|
26145
26145
|
);
|
|
26146
26146
|
}
|
|
26147
26147
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
26148
|
-
const digest =
|
|
26148
|
+
const digest = createHash4("sha1").update(key + GUID).digest("base64");
|
|
26149
26149
|
const headers = [
|
|
26150
26150
|
"HTTP/1.1 101 Switching Protocols",
|
|
26151
26151
|
"Upgrade: websocket",
|
|
@@ -28469,7 +28469,7 @@ var OpenClawSupervisorClient = class {
|
|
|
28469
28469
|
claim = await this.rolloverSupervisor("legacy-health-missing-target");
|
|
28470
28470
|
}
|
|
28471
28471
|
const health = claim?.health;
|
|
28472
|
-
if (claim?.state !== "READY" || health?.schemaVersion !== 2 || health.authority !== "process-external-supervisor" || health.state !== "running" || health.ownerKey !== this.ownerHash || health.instanceId !== this.lease.instanceId || health.generation !== this.lease.generation || !this.healthMatchesTarget(health) || health.relayClientCount !== (this.config.relay?.enabled && this.config.relay.url ? 1 : 0) || !health.claimedAt) {
|
|
28472
|
+
if (claim?.state !== "READY" || health?.schemaVersion !== 2 && health?.schemaVersion !== 3 || health.authority !== "process-external-supervisor" || health.state !== "running" || health.ownerKey !== this.ownerHash || health.instanceId !== this.lease.instanceId || health.generation !== this.lease.generation || !this.healthMatchesTarget(health) || health.relayClientCount !== (this.config.relay?.enabled && this.config.relay.url ? 1 : 0) || !health.claimedAt) {
|
|
28473
28473
|
throw new Error("OWNERSHIP_PRIMITIVE_UNAVAILABLE:supervisor claim did not return certified READY/CLAIMED health");
|
|
28474
28474
|
}
|
|
28475
28475
|
this.health = health;
|
|
@@ -28855,7 +28855,7 @@ var OpenClawSupervisorClient = class {
|
|
|
28855
28855
|
};
|
|
28856
28856
|
|
|
28857
28857
|
// src/runtime-evidence.ts
|
|
28858
|
-
import { createHmac } from "node:crypto";
|
|
28858
|
+
import { createHash as createHash3, createHmac, timingSafeEqual } from "node:crypto";
|
|
28859
28859
|
import {
|
|
28860
28860
|
chmodSync as chmodSync2,
|
|
28861
28861
|
mkdirSync as mkdirSync3,
|
|
@@ -28865,7 +28865,8 @@ import {
|
|
|
28865
28865
|
} from "node:fs";
|
|
28866
28866
|
import { homedir as homedir4 } from "node:os";
|
|
28867
28867
|
import { join as join3, resolve as resolve2 } from "node:path";
|
|
28868
|
-
var
|
|
28868
|
+
var RUNTIME_ATTEMPT_SCHEMA_VERSION = 2;
|
|
28869
|
+
var RUNTIME_STATUS_SCHEMA_VERSION = 3;
|
|
28869
28870
|
function canonicalize(value) {
|
|
28870
28871
|
if (Array.isArray(value)) return value.map(canonicalize);
|
|
28871
28872
|
if (!value || typeof value !== "object") return value;
|
|
@@ -28873,8 +28874,52 @@ function canonicalize(value) {
|
|
|
28873
28874
|
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, canonicalize(child)])
|
|
28874
28875
|
);
|
|
28875
28876
|
}
|
|
28877
|
+
function objectValue(value) {
|
|
28878
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
28879
|
+
}
|
|
28880
|
+
function normalizedServiceUrl(value) {
|
|
28881
|
+
if (typeof value !== "string" || !value.trim()) return void 0;
|
|
28882
|
+
try {
|
|
28883
|
+
const url = new URL(value);
|
|
28884
|
+
url.username = "";
|
|
28885
|
+
url.password = "";
|
|
28886
|
+
url.search = "";
|
|
28887
|
+
url.hash = "";
|
|
28888
|
+
return url.toString().replace(/\/+$/u, "");
|
|
28889
|
+
} catch {
|
|
28890
|
+
return value.trim().replace(/\/+$/u, "");
|
|
28891
|
+
}
|
|
28892
|
+
}
|
|
28893
|
+
function configEvidenceProjection(config) {
|
|
28894
|
+
const root = objectValue(config);
|
|
28895
|
+
const relay = objectValue(root.relay);
|
|
28896
|
+
const chat = objectValue(root.chat);
|
|
28897
|
+
const platform = objectValue(root.platform);
|
|
28898
|
+
const heartbeatUrl = typeof platform.heartbeatUrl === "string" ? platform.heartbeatUrl : "";
|
|
28899
|
+
const heartbeatAgentId = heartbeatUrl.match(/\/agents\/([^/]+)\/heartbeat(?:\?|$)/u)?.[1];
|
|
28900
|
+
const agentId = typeof root.agentId === "string" ? root.agentId : typeof platform.agentId === "string" ? platform.agentId : heartbeatAgentId;
|
|
28901
|
+
return {
|
|
28902
|
+
agentName: typeof root.agentName === "string" ? root.agentName.trim() : "",
|
|
28903
|
+
agentId: agentId ?? "unknown",
|
|
28904
|
+
relay: {
|
|
28905
|
+
enabled: relay.enabled === true,
|
|
28906
|
+
url: normalizedServiceUrl(relay.url) ?? ""
|
|
28907
|
+
},
|
|
28908
|
+
chat: {
|
|
28909
|
+
enabled: chat.enabled === true,
|
|
28910
|
+
url: normalizedServiceUrl(chat.url) ?? (chat.enabled === true ? "wss://chat.perkos.xyz/chat" : "")
|
|
28911
|
+
},
|
|
28912
|
+
platform: {
|
|
28913
|
+
heartbeatAgentId: heartbeatAgentId ?? agentId ?? "unknown",
|
|
28914
|
+
heartbeatIntervalMs: typeof platform.heartbeatIntervalMs === "number" ? platform.heartbeatIntervalMs : null
|
|
28915
|
+
}
|
|
28916
|
+
};
|
|
28917
|
+
}
|
|
28876
28918
|
function canonicalConfigJson(config) {
|
|
28877
|
-
return JSON.stringify({ schemaVersion:
|
|
28919
|
+
return JSON.stringify({ schemaVersion: RUNTIME_STATUS_SCHEMA_VERSION, config: canonicalize(configEvidenceProjection(config)) });
|
|
28920
|
+
}
|
|
28921
|
+
function configDigest(config) {
|
|
28922
|
+
return createHash3("sha256").update(canonicalConfigJson(config)).digest("hex");
|
|
28878
28923
|
}
|
|
28879
28924
|
function configFingerprint(config, hmacKeyHex) {
|
|
28880
28925
|
if (!/^[a-f0-9]{64}$/u.test(hmacKeyHex)) throw new Error("runtime evidence HMAC key is invalid");
|
|
@@ -28904,17 +28949,22 @@ function recordRuntimeLoadEvidence(input) {
|
|
|
28904
28949
|
return null;
|
|
28905
28950
|
}
|
|
28906
28951
|
const agentId = configAgentId(input.config);
|
|
28907
|
-
if (attempt.schemaVersion !==
|
|
28952
|
+
if (attempt.schemaVersion !== RUNTIME_ATTEMPT_SCHEMA_VERSION || attempt.targetVersion !== input.version || attempt.expectedAgentId !== agentId) {
|
|
28908
28953
|
input.logger.warn?.("[perkos-a2a] runtime evidence attempt does not match the loaded plugin identity");
|
|
28909
28954
|
return null;
|
|
28910
28955
|
}
|
|
28956
|
+
const digest = configDigest(input.config);
|
|
28911
28957
|
const status = {
|
|
28912
|
-
schemaVersion:
|
|
28958
|
+
schemaVersion: RUNTIME_STATUS_SCHEMA_VERSION,
|
|
28913
28959
|
loadedAt: (input.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
28914
28960
|
version: input.version,
|
|
28915
28961
|
agentId,
|
|
28916
28962
|
fingerprint: configFingerprint(input.config, attempt.hmacKeyHex),
|
|
28963
|
+
configDigest: digest,
|
|
28964
|
+
configRevision: `${input.generation}:${digest}`,
|
|
28917
28965
|
attemptId: attempt.attemptId,
|
|
28966
|
+
writerKind: "owner-plugin",
|
|
28967
|
+
generation: input.generation,
|
|
28918
28968
|
pid: process.pid,
|
|
28919
28969
|
processStartTime: processStartIdentity(),
|
|
28920
28970
|
bootId: currentBootId(),
|
|
@@ -29658,12 +29708,6 @@ function register(api) {
|
|
|
29658
29708
|
const logger = api.logger || console;
|
|
29659
29709
|
const pluginVersion = loadedPluginVersion();
|
|
29660
29710
|
const pluginRoot = resolve3(dirname3(fileURLToPath2(import.meta.url)), "..");
|
|
29661
|
-
recordRuntimeLoadEvidence({
|
|
29662
|
-
config: pluginConfig,
|
|
29663
|
-
version: pluginVersion,
|
|
29664
|
-
pluginRoot,
|
|
29665
|
-
logger
|
|
29666
|
-
});
|
|
29667
29711
|
const server = new A2AServer(pluginConfig, logger, { relayOwnership: "external-required" });
|
|
29668
29712
|
const lifecycleKey = a2aLifecycleKey(pluginConfig);
|
|
29669
29713
|
const lifecycleInstanceId = randomUUID7();
|
|
@@ -29960,6 +30004,14 @@ function register(api) {
|
|
|
29960
30004
|
start: async () => {
|
|
29961
30005
|
try {
|
|
29962
30006
|
await supervisorClient.start();
|
|
30007
|
+
const ownerHealth = supervisorClient.currentHealth();
|
|
30008
|
+
recordRuntimeLoadEvidence({
|
|
30009
|
+
config: pluginConfig,
|
|
30010
|
+
version: pluginVersion,
|
|
30011
|
+
pluginRoot,
|
|
30012
|
+
generation: ownerHealth?.generation ?? 0,
|
|
30013
|
+
logger
|
|
30014
|
+
});
|
|
29963
30015
|
await server.start();
|
|
29964
30016
|
logger.info(`[perkos-a2a] A2A server started for ${pluginConfig.agentName}`);
|
|
29965
30017
|
} catch (error) {
|