@perkos/perkos-a2a 0.12.64 → 0.12.66

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.
@@ -0,0 +1,9 @@
1
+ import type { A2APluginConfig } from "./types.js";
2
+ export type PlatformControlPlane = {
3
+ apiBaseUrl: string;
4
+ agentId: string;
5
+ relayApiKey: string;
6
+ };
7
+ /** Resolve the same platform identity whether installers persisted it in config or service env. */
8
+ export declare function resolvePlatformControlPlane(config: A2APluginConfig, env?: Record<string, string | undefined>): PlatformControlPlane | null;
9
+ //# sourceMappingURL=platform-control-plane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-control-plane.d.ts","sourceRoot":"","sources":["../src/platform-control-plane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,mGAAmG;AACnG,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,eAAe,EACvB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,oBAAoB,GAAG,IAAI,CAgB7B"}
@@ -0,0 +1,25 @@
1
+ /** Resolve the same platform identity whether installers persisted it in config or service env. */
2
+ export function resolvePlatformControlPlane(config, env = process.env) {
3
+ const heartbeat = config.platform?.heartbeatUrl?.trim() || env.PERKOS_HEARTBEAT_URL?.trim();
4
+ const relayApiKey = config.relay?.apiKey?.trim()
5
+ || config.chat?.apiKey?.trim()
6
+ || env.A2A_RELAY_API_KEY?.trim()
7
+ || env.A2A_CHAT_API_KEY?.trim();
8
+ if (!heartbeat || !relayApiKey)
9
+ return null;
10
+ let url;
11
+ try {
12
+ url = new URL(heartbeat);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ const match = url.pathname.match(/^(.*)\/agents\/([^/]+)\/heartbeat\/?$/u);
18
+ const agentId = config.platform?.agentId?.trim()
19
+ || (match ? decodeURIComponent(match[2]) : "")
20
+ || env.PERKOS_AGENT_ID?.trim();
21
+ if (!match || !agentId)
22
+ return null;
23
+ return { apiBaseUrl: `${url.origin}${match[1]}`, agentId, relayApiKey };
24
+ }
25
+ //# sourceMappingURL=platform-control-plane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-control-plane.js","sourceRoot":"","sources":["../src/platform-control-plane.ts"],"names":[],"mappings":"AAQA,mGAAmG;AACnG,MAAM,UAAU,2BAA2B,CACzC,MAAuB,EACvB,MAA0C,OAAO,CAAC,GAAG;IAErD,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC;IAC5F,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;WAC3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;WAC3B,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE;WAC7B,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE5C,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACxD,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;WAC3C,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;WAC5C,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IACjC,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=platform-control-plane.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-control-plane.test.d.ts","sourceRoot":"","sources":["../src/platform-control-plane.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { resolvePlatformControlPlane } from "./platform-control-plane.js";
3
+ const baseConfig = {
4
+ agentName: "Athena",
5
+ port: 5050,
6
+ skills: [],
7
+ peers: {},
8
+ runtime: { kind: "hermes-api" },
9
+ };
10
+ describe("resolvePlatformControlPlane", () => {
11
+ it("uses plugin config when the complete identity is persisted there", () => {
12
+ expect(resolvePlatformControlPlane({
13
+ ...baseConfig,
14
+ relay: { enabled: true, url: "wss://dev.transport.perkos.xyz/a2a", apiKey: "rk_config" },
15
+ platform: { agentId: "athena", heartbeatUrl: "https://dev.api.perkos.xyz/agents/athena/heartbeat" },
16
+ }, {})).toEqual({ apiBaseUrl: "https://dev.api.perkos.xyz", agentId: "athena", relayApiKey: "rk_config" });
17
+ });
18
+ it("uses service env when update-hermes keeps runtime identity outside plugin JSON", () => {
19
+ expect(resolvePlatformControlPlane(baseConfig, {
20
+ PERKOS_HEARTBEAT_URL: "https://dev.api.perkos.xyz/agents/athena/heartbeat",
21
+ A2A_RELAY_API_KEY: "rk_env",
22
+ })).toEqual({ apiBaseUrl: "https://dev.api.perkos.xyz", agentId: "athena", relayApiKey: "rk_env" });
23
+ });
24
+ it("fails closed without a complete validated heartbeat identity", () => {
25
+ expect(resolvePlatformControlPlane(baseConfig, { A2A_RELAY_API_KEY: "rk_env" })).toBeNull();
26
+ expect(resolvePlatformControlPlane(baseConfig, {
27
+ PERKOS_HEARTBEAT_URL: "not-a-url",
28
+ A2A_RELAY_API_KEY: "rk_env",
29
+ })).toBeNull();
30
+ });
31
+ });
32
+ //# sourceMappingURL=platform-control-plane.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-control-plane.test.js","sourceRoot":"","sources":["../src/platform-control-plane.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAG1E,MAAM,UAAU,GAAoB;IAClC,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;CAChC,CAAC;AAEF,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,2BAA2B,CAAC;YACjC,GAAG,UAAU;YACb,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,oCAAoC,EAAE,MAAM,EAAE,WAAW,EAAE;YACxF,QAAQ,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,oDAAoD,EAAE;SACpG,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,CAAC,2BAA2B,CAAC,UAAU,EAAE;YAC7C,oBAAoB,EAAE,oDAAoD;YAC1E,iBAAiB,EAAE,QAAQ;SAC5B,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,4BAA4B,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,2BAA2B,CAAC,UAAU,EAAE,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5F,MAAM,CAAC,2BAA2B,CAAC,UAAU,EAAE;YAC7C,oBAAoB,EAAE,WAAW;YACjC,iBAAiB,EAAE,QAAQ;SAC5B,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"voice-capability.d.ts","sourceRoot":"","sources":["../src/voice-capability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,yBAAyB,EAAG,oBAA6B,CAAC;AACvE,eAAO,MAAM,0BAA0B,EAAG,qBAA8B,CAAC;AAEzE,KAAK,WAAW,GAAG;IACjB,oBAAoB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpG,2BAA2B,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxG,CAAC;AAEF,KAAK,iBAAiB,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;AAsCpD;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,EACvB,SAAS,GAAE,iBAAiC,GAC3C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBxB"}
1
+ {"version":3,"file":"voice-capability.d.ts","sourceRoot":"","sources":["../src/voice-capability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AAG/D,eAAO,MAAM,yBAAyB,EAAG,oBAA6B,CAAC;AACvE,eAAO,MAAM,0BAA0B,EAAG,qBAA8B,CAAC;AAEzE,KAAK,WAAW,GAAG;IACjB,oBAAoB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpG,2BAA2B,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxG,CAAC;AAEF,KAAK,iBAAiB,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;AA0BpD;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,EACvB,SAAS,GAAE,iBAAiC,GAC3C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBxB"}
@@ -1,3 +1,4 @@
1
+ import { resolvePlatformControlPlane } from "./platform-control-plane.js";
1
2
  export const PERKOS_VOICE_PROBE_MARKER = "PERKOS_VOICE_PROBE";
2
3
  export const PERKOS_VOICE_ENROLL_MARKER = "PERKOS_VOICE_ENROLL";
3
4
  function runtime(runtimeKind) {
@@ -9,28 +10,10 @@ function runtime(runtimeKind) {
9
10
  return "zeroclaw";
10
11
  return null;
11
12
  }
12
- function controlPlane(config) {
13
- const heartbeat = config.platform?.heartbeatUrl;
14
- const relayApiKey = config.relay?.apiKey || config.chat?.apiKey;
15
- if (!heartbeat || !relayApiKey)
16
- return null;
17
- let url;
18
- try {
19
- url = new URL(heartbeat);
20
- }
21
- catch {
22
- return null;
23
- }
24
- const match = url.pathname.match(/^(.*)\/agents\/([^/]+)\/heartbeat\/?$/u);
25
- const agentId = config.platform?.agentId || (match ? decodeURIComponent(match[2]) : "");
26
- if (!match || !agentId)
27
- return null;
28
- return { apiBaseUrl: `${url.origin}${match[1]}`, agentId, relayApiKey };
29
- }
30
13
  async function reportPluginMissing(message, config) {
31
14
  if (message !== PERKOS_VOICE_PROBE_MARKER)
32
15
  return "PERKOS_VOICE_FAILED:voice_plugin_missing";
33
- const target = controlPlane(config);
16
+ const target = resolvePlatformControlPlane(config);
34
17
  if (!target)
35
18
  return "PERKOS_VOICE_FAILED:a2a_identity_unavailable";
36
19
  const response = await fetch(`${target.apiBaseUrl}/agents/${encodeURIComponent(target.agentId)}/voice-credential/capability-report`, {
@@ -53,7 +36,7 @@ export async function tryHandleInstalledVoiceMarker(message, config, loadVoice =
53
36
  const marker = message.trim();
54
37
  if (marker !== PERKOS_VOICE_PROBE_MARKER && marker !== PERKOS_VOICE_ENROLL_MARKER)
55
38
  return null;
56
- const target = controlPlane(config);
39
+ const target = resolvePlatformControlPlane(config);
57
40
  if (!target)
58
41
  return "PERKOS_VOICE_FAILED:a2a_identity_unavailable";
59
42
  const runtimeKind = runtime(config.runtime?.kind);
@@ -1 +1 @@
1
- {"version":3,"file":"voice-capability.js","sourceRoot":"","sources":["../src/voice-capability.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"voice-capability.js","sourceRoot":"","sources":["../src/voice-capability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAE1E,MAAM,CAAC,MAAM,yBAAyB,GAAG,oBAA6B,CAAC;AACvE,MAAM,CAAC,MAAM,0BAA0B,GAAG,qBAA8B,CAAC;AASzE,SAAS,OAAO,CAAC,WAAoC;IACnD,IAAI,WAAW,KAAK,QAAQ,IAAI,WAAW,KAAK,YAAY;QAAE,OAAO,QAAQ,CAAC;IAC9E,IAAI,WAAW,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAClD,IAAI,WAAW,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAClD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,OAAe,EAAE,MAAuB;IACzE,IAAI,OAAO,KAAK,yBAAyB;QAAE,OAAO,0CAA0C,CAAC;IAC7F,MAAM,MAAM,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM;QAAE,OAAO,8CAA8C,CAAC;IACnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,UAAU,WAAW,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,qCAAqC,EAAE;QACnI,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC9F,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,sBAAsB,EAAE,CAAC;KACnF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,+CAA+C,CAAC,CAAC,CAAC,+CAA+C,CAAC;AAC1H,CAAC;AAED,KAAK,UAAU,aAAa;IAC1B,MAAM,SAAS,GAAG,0BAA0B,CAAC;IAC7C,OAAO,MAAM,CAAC,SAAS,CAAyB,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAe,EACf,MAAuB,EACvB,YAA+B,aAAa;IAE5C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,MAAM,KAAK,yBAAyB,IAAI,MAAM,KAAK,0BAA0B;QAAE,OAAO,IAAI,CAAC;IAC/F,MAAM,MAAM,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM;QAAE,OAAO,8CAA8C,CAAC;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAClD,IAAI,CAAC,WAAW;QAAE,OAAO,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7D,IAAI,KAAkB,CAAC;IACvB,IAAI,CAAC;QAAC,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IACxF,IAAI,OAAO,KAAK,CAAC,oBAAoB,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,2BAA2B,KAAK,UAAU,EAAE,CAAC;QAChH,OAAO,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE;QACxC,GAAG,MAAM;QACT,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,KAAK,CAAC,2BAA2B;KAC7C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ # Identidad del control plane desde config o entorno
2
+
3
+ ## Hallazgo
4
+
5
+ El bridge Hermes instalado por `update-hermes` puede conservar `PERKOS_HEARTBEAT_URL` y `A2A_RELAY_API_KEY` en el entorno del servicio. Heartbeat ya lee ambos orígenes, pero los handlers de mantenimiento y Voice sólo consultaban el JSON del plugin. Así, una instancia podía anunciar una capability Chat-bound válida y responder `a2a_identity_unavailable` al recibir el marcador.
6
+
7
+ ## Decisión
8
+
9
+ Un resolvedor compartido aplica una precedencia única: configuración explícita del plugin y luego variables del servicio. Valida una URL de heartbeat con la ruta exacta `/agents/<id>/heartbeat`, deriva el API base y nunca registra ni devuelve la credencial fuera del proceso. Mantenimiento y Voice consumen el mismo resolvedor para impedir nuevas divergencias.
10
+
11
+ ## Seguridad y verificación
12
+
13
+ La ausencia de URL o credencial continúa fallando cerrado. La capability sigue ligada a la conexión Chat y a `bridgeInstanceId`; este cambio sólo hace accesible al handler la misma identidad que ya usa heartbeat. Las pruebas cubren identidad completa en config, fallback completo por entorno y rechazo de identidad incompleta o URL inválida.
14
+
15
+ > Relacionado: [[PerkOS-Projects/README]] · [[PerkOS-A2A]] · [[PerkOS-API]] · [[PerkOS]] · [[PerkOS-Voice]]
@@ -0,0 +1,20 @@
1
+ # Resolución opcional de PerkOS Voice 0.1.1
2
+
3
+ > Relacionado: `docs/plans/2026-09-01-optional-voice-package-resolution-design.md`
4
+
5
+ ## Objetivo
6
+
7
+ Distribuir la reducción de polling incluida en `@perkos/perkos-voice@0.1.1` a los agentes que declaren soporte de voz, sin convertir Voice en un requisito para todos los runtimes.
8
+
9
+ ## Diseño
10
+
11
+ `@perkos/perkos-a2a` conserva Voice en `optionalDependencies` y actualiza el rango mínimo a `^0.1.1`. El lockfile fija exactamente el artefacto público `0.1.1` y su integridad. La carga continúa siendo dinámica mediante el adaptador A2A existente: si Voice está disponible se atienden los marcadores de capacidad y enrolamiento; si no está disponible se reporta `voice_plugin_missing` sin interrumpir chat, tareas ni A2A.
12
+
13
+ La versión de A2A avanza a `0.12.66` para producir un artefacto nuevo y reproducible. Los agentes instalados no deben compartir credenciales entre Production, Dev y QA. Cada despliegue recibe su propio control plane, identidad y servicio local; la activación ocurre únicamente después de la comprobación de capacidad.
14
+
15
+ ## Verificación
16
+
17
+ - manifests de A2A con la misma versión;
18
+ - lockfile resolviendo Voice `0.1.1` con el hash publicado;
19
+ - lint, pruebas y build completos;
20
+ - `npm pack --dry-run` confirmando que los adaptadores y scripts requeridos estén incluidos.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "perkos-a2a",
3
3
  "name": "PerkOS A2A",
4
- "version": "0.12.64",
4
+ "version": "0.12.66",
5
5
  "description": "Agent-to-Agent (A2A) protocol communication for OpenClaw agents",
6
6
  "author": "PerkOS",
7
7
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perkos/perkos-a2a",
3
- "version": "0.12.64",
3
+ "version": "0.12.66",
4
4
  "description": "A2A Protocol communication plugin for OpenClaw — Agent-to-Agent protocol implementation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -79,7 +79,7 @@
79
79
  "ws": "^8.20.1"
80
80
  },
81
81
  "optionalDependencies": {
82
- "@perkos/perkos-voice": "^0.1.0"
82
+ "@perkos/perkos-voice": "^0.1.1"
83
83
  },
84
84
  "overrides": {
85
85
  "qs": "^6.15.2"