@perkos/perkos-a2a 0.12.35 → 0.12.36

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 CHANGED
@@ -248,7 +248,7 @@ routing.
248
248
 
249
249
  ```bash
250
250
  A2A_RELAY_API_KEY='<credential-from-invitation>' \
251
- npx --yes @perkos/perkos-a2a@0.12.35 connect \
251
+ npx --yes @perkos/perkos-a2a@0.12.36 connect \
252
252
  --artifact ./perkos-a2a.tgz \
253
253
  --sha256 '<sha256-from-the-official-invitation>' \
254
254
  --agent-name '<agent-name>' \
package/dist/index.d.ts CHANGED
@@ -53,5 +53,12 @@ export declare function runOpenClawChatTurn(api: any, config: A2APluginConfig, s
53
53
  export declare function formatRecentChatContext(messages: ChatMessage[], currentMessageId: string): string;
54
54
  /** The identity the relay treats as exclusive; names are display metadata. */
55
55
  export declare function a2aLifecycleKey(config: A2APluginConfig): string;
56
+ /**
57
+ * OpenClaw may briefly call register while a plugin entry is being rewritten.
58
+ * Treat partial/empty config as an inert, valid shape instead of crashing the
59
+ * whole service on string operations. The repair CLI restores the complete
60
+ * identity atomically before the service is enabled.
61
+ */
62
+ export declare function normalizeOpenClawPluginConfig(value: unknown): A2APluginConfig;
56
63
  export default function register(api: any): void;
57
64
  //# sourceMappingURL=index.d.ts.map
@@ -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;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QAuzBxC"}
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,QAozBxC"}
package/dist/index.js CHANGED
@@ -28530,17 +28530,42 @@ var OpenClawSupervisorClient = class {
28530
28530
  const oldHealth = this.health;
28531
28531
  this.closeSocket(new Error("SUPERVISOR_ROLLOVER"));
28532
28532
  await this.waitForSupervisorStop(oldHealth, 1e4);
28533
- await this.connectOrSpawn();
28534
- const target = await this.claimCurrentSupervisor();
28535
- if (!this.healthMatchesTarget(target.health)) {
28536
- throw new Error(`SUPERVISOR_ROLLOVER_TARGET_MISMATCH:${reason}`);
28537
- }
28533
+ const target = await this.claimTargetAfterRollover(reason);
28538
28534
  this.logger.info(`[perkos-a2a] Supervisor rollover complete targetVersion=${this.config.version}`);
28539
28535
  return target;
28540
28536
  } finally {
28541
28537
  releaseLock();
28542
28538
  }
28543
28539
  }
28540
+ /**
28541
+ * OpenClaw can register two adjacent hot-reload generations while its config
28542
+ * file is settling. The first generation may successfully bootstrap the
28543
+ * target supervisor just as its client socket is replaced. Reconnect to that
28544
+ * single fenced supervisor instead of abandoning the agent offline.
28545
+ */
28546
+ async claimTargetAfterRollover(reason) {
28547
+ let lastError;
28548
+ for (let attempt = 1; attempt <= 3; attempt += 1) {
28549
+ try {
28550
+ await this.connectOrSpawn();
28551
+ const target = await this.claimCurrentSupervisor();
28552
+ if (!this.healthMatchesTarget(target.health)) {
28553
+ throw new Error(`SUPERVISOR_ROLLOVER_TARGET_MISMATCH:${reason}`);
28554
+ }
28555
+ return target;
28556
+ } catch (error) {
28557
+ lastError = error;
28558
+ this.closeSocket(new Error("SUPERVISOR_ROLLOVER_TARGET_RETRY"));
28559
+ this.logger.error(
28560
+ `[perkos-a2a] Supervisor target claim retry ${attempt}/3: ${error instanceof Error ? error.message : String(error)}`
28561
+ );
28562
+ if (attempt < 3) await new Promise((resolveWait) => setTimeout(resolveWait, 250));
28563
+ }
28564
+ }
28565
+ throw new Error(
28566
+ `SUPERVISOR_ROLLOVER_TARGET_START_FAILED:${lastError instanceof Error ? lastError.message : String(lastError)}`
28567
+ );
28568
+ }
28544
28569
  async acquireRolloverLock(timeoutMs = 15e3) {
28545
28570
  const path = supervisorRolloverLockPath(this.stateDir, this.ownerHash);
28546
28571
  mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
@@ -29607,16 +29632,29 @@ function a2aLifecycleKey(config) {
29607
29632
  }
29608
29633
  const heartbeatUrl = config.platform?.heartbeatUrl || "";
29609
29634
  const idFromHeartbeat = heartbeatUrl.match(/\/agents\/([^/]+)\/heartbeat(?:\?|$)/u)?.[1];
29610
- const agentId = config.platform?.agentId || idFromHeartbeat || config.agentName.trim().toLowerCase();
29635
+ const agentId = config.platform?.agentId || idFromHeartbeat || safeAgentName(config.agentName).toLowerCase();
29611
29636
  return `${relayUrl}|${agentId}`;
29612
29637
  }
29613
- function register(api) {
29614
- const pluginConfig = api.config?.plugins?.entries?.["perkos-a2a"]?.config || {
29615
- agentName: "agent",
29616
- port: 5050,
29617
- skills: [],
29618
- peers: {}
29638
+ function safeAgentName(value) {
29639
+ return typeof value === "string" && value.trim() ? value.trim() : "agent";
29640
+ }
29641
+ function normalizeOpenClawPluginConfig(value) {
29642
+ const raw = value && typeof value === "object" && !Array.isArray(value) ? value : {};
29643
+ const platform = raw.platform && typeof raw.platform === "object" ? raw.platform : void 0;
29644
+ const heartbeatAgentId = platform?.heartbeatUrl?.match(/\/agents\/([^/]+)\/heartbeat/u)?.[1];
29645
+ const agentName = safeAgentName(raw.agentName || platform?.agentId || heartbeatAgentId);
29646
+ return {
29647
+ ...raw,
29648
+ agentName,
29649
+ port: typeof raw.port === "number" ? raw.port : 5050,
29650
+ skills: Array.isArray(raw.skills) ? raw.skills : [],
29651
+ peers: raw.peers && typeof raw.peers === "object" ? raw.peers : {}
29619
29652
  };
29653
+ }
29654
+ function register(api) {
29655
+ const pluginConfig = normalizeOpenClawPluginConfig(
29656
+ api.config?.plugins?.entries?.["perkos-a2a"]?.config
29657
+ );
29620
29658
  const logger = api.logger || console;
29621
29659
  const pluginVersion = loadedPluginVersion();
29622
29660
  const pluginRoot = resolve3(dirname3(fileURLToPath2(import.meta.url)), "..");
@@ -29880,7 +29918,7 @@ function register(api) {
29880
29918
  if (pluginConfig.chat?.enabled && !chatApiKey) {
29881
29919
  logger.error("[perkos-chat] chat.enabled=true but no apiKey (set chat.apiKey or fall back from relay.apiKey)");
29882
29920
  }
29883
- const platformAgentId = pluginConfig.platform?.agentId || pluginConfig.platform?.heartbeatUrl?.match(/\/agents\/([^/]+)\/heartbeat/u)?.[1] || pluginConfig.agentName.trim().toLowerCase();
29921
+ const platformAgentId = pluginConfig.platform?.agentId || pluginConfig.platform?.heartbeatUrl?.match(/\/agents\/([^/]+)\/heartbeat/u)?.[1] || safeAgentName(pluginConfig.agentName).toLowerCase();
29884
29922
  supervisorClient = new OpenClawSupervisorClient({
29885
29923
  ownerHash: supervisorOwnerHash(lifecycleKey),
29886
29924
  generation: Date.now(),
@@ -30325,6 +30363,7 @@ export {
30325
30363
  extractOpenClawChatReply,
30326
30364
  formatRecentChatContext,
30327
30365
  isWebhookEvent,
30366
+ normalizeOpenClawPluginConfig,
30328
30367
  omitUnavailableAgentHarness,
30329
30368
  openclawChatSessionKey,
30330
30369
  runOpenClawChatTurn