@perkos/perkos-a2a 0.12.59 → 0.12.61
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 +6 -0
- package/dist/bridge-agent.js +8 -0
- package/dist/bridge-agent.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -274
- package/dist/index.js.map +4 -4
- package/dist/voice-capability.d.ts +19 -0
- package/dist/voice-capability.d.ts.map +1 -0
- package/dist/voice-capability.js +78 -0
- package/dist/voice-capability.js.map +1 -0
- package/dist/voice-capability.test.d.ts +2 -0
- package/dist/voice-capability.test.d.ts.map +1 -0
- package/dist/voice-capability.test.js +32 -0
- package/dist/voice-capability.test.js.map +1 -0
- package/docs/plans/2026-09-01-optional-voice-package-resolution-design.md +24 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { A2APluginConfig } from "./types.js";
|
|
2
|
+
export declare const PERKOS_VOICE_PROBE_MARKER: "PERKOS_VOICE_PROBE";
|
|
3
|
+
export declare const PERKOS_VOICE_ENROLL_MARKER: "PERKOS_VOICE_ENROLL";
|
|
4
|
+
type VoiceModule = {
|
|
5
|
+
handleA2AVoiceMarker: (message: string, options: Record<string, unknown>) => Promise<string | null>;
|
|
6
|
+
configureA2AVoiceEnrollment: (enrollment: unknown) => Promise<{
|
|
7
|
+
ready: boolean;
|
|
8
|
+
actionCode?: string;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
type VoiceModuleLoader = () => Promise<VoiceModule>;
|
|
12
|
+
/**
|
|
13
|
+
* Optional bridge: exact Voice markers are consumed before the model sees
|
|
14
|
+
* them. A2A supplies identity/transport only; the separately installed Voice
|
|
15
|
+
* package owns support detection, credential storage and runtime activation.
|
|
16
|
+
*/
|
|
17
|
+
export declare function tryHandleInstalledVoiceMarker(message: string, config: A2APluginConfig, loadVoice?: VoiceModuleLoader): Promise<string | null>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=voice-capability.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export const PERKOS_VOICE_PROBE_MARKER = "PERKOS_VOICE_PROBE";
|
|
2
|
+
export const PERKOS_VOICE_ENROLL_MARKER = "PERKOS_VOICE_ENROLL";
|
|
3
|
+
function runtime(runtimeKind) {
|
|
4
|
+
if (runtimeKind === "hermes" || runtimeKind === "hermes-api")
|
|
5
|
+
return "hermes";
|
|
6
|
+
if (runtimeKind === "openclaw")
|
|
7
|
+
return "openclaw";
|
|
8
|
+
if (runtimeKind === "zeroclaw")
|
|
9
|
+
return "zeroclaw";
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
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
|
+
async function reportPluginMissing(message, config) {
|
|
31
|
+
if (message !== PERKOS_VOICE_PROBE_MARKER)
|
|
32
|
+
return "PERKOS_VOICE_FAILED:voice_plugin_missing";
|
|
33
|
+
const target = controlPlane(config);
|
|
34
|
+
if (!target)
|
|
35
|
+
return "PERKOS_VOICE_FAILED:a2a_identity_unavailable";
|
|
36
|
+
const response = await fetch(`${target.apiBaseUrl}/agents/${encodeURIComponent(target.agentId)}/voice-credential/capability-report`, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: { authorization: `Bearer ${target.relayApiKey}`, "content-type": "application/json" },
|
|
39
|
+
body: JSON.stringify({ state: "unsupported", reasonCode: "voice_plugin_missing" }),
|
|
40
|
+
}).catch(() => null);
|
|
41
|
+
return response?.ok ? "PERKOS_VOICE_UNSUPPORTED:voice_plugin_missing" : "PERKOS_VOICE_FAILED:control_plane_unavailable";
|
|
42
|
+
}
|
|
43
|
+
async function defaultLoader() {
|
|
44
|
+
const specifier = "@perkos/perkos-voice/a2a";
|
|
45
|
+
return import(specifier);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Optional bridge: exact Voice markers are consumed before the model sees
|
|
49
|
+
* them. A2A supplies identity/transport only; the separately installed Voice
|
|
50
|
+
* package owns support detection, credential storage and runtime activation.
|
|
51
|
+
*/
|
|
52
|
+
export async function tryHandleInstalledVoiceMarker(message, config, loadVoice = defaultLoader) {
|
|
53
|
+
const marker = message.trim();
|
|
54
|
+
if (marker !== PERKOS_VOICE_PROBE_MARKER && marker !== PERKOS_VOICE_ENROLL_MARKER)
|
|
55
|
+
return null;
|
|
56
|
+
const target = controlPlane(config);
|
|
57
|
+
if (!target)
|
|
58
|
+
return "PERKOS_VOICE_FAILED:a2a_identity_unavailable";
|
|
59
|
+
const runtimeKind = runtime(config.runtime?.kind);
|
|
60
|
+
if (!runtimeKind)
|
|
61
|
+
return reportPluginMissing(marker, config);
|
|
62
|
+
let voice;
|
|
63
|
+
try {
|
|
64
|
+
voice = await loadVoice();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return reportPluginMissing(marker, config);
|
|
68
|
+
}
|
|
69
|
+
if (typeof voice.handleA2AVoiceMarker !== "function" || typeof voice.configureA2AVoiceEnrollment !== "function") {
|
|
70
|
+
return reportPluginMissing(marker, config);
|
|
71
|
+
}
|
|
72
|
+
return voice.handleA2AVoiceMarker(marker, {
|
|
73
|
+
...target,
|
|
74
|
+
runtime: runtimeKind,
|
|
75
|
+
configure: voice.configureA2AVoiceEnrollment,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=voice-capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-capability.js","sourceRoot":"","sources":["../src/voice-capability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-capability.test.d.ts","sourceRoot":"","sources":["../src/voice-capability.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { tryHandleInstalledVoiceMarker } from "./voice-capability.js";
|
|
3
|
+
const config = {
|
|
4
|
+
agentName: "Athena", port: 5060, skills: [], peers: {},
|
|
5
|
+
runtime: { kind: "hermes-api" },
|
|
6
|
+
relay: { url: "wss://transport.perkos.xyz/a2a", apiKey: "rk_private", enabled: true },
|
|
7
|
+
platform: { agentId: "athena-id", heartbeatUrl: "https://dev.api.perkos.xyz/agents/athena-id/heartbeat" },
|
|
8
|
+
};
|
|
9
|
+
describe("optional Voice capability bridge", () => {
|
|
10
|
+
it("delegates exact Voice markers with the existing scoped identity", async () => {
|
|
11
|
+
let options;
|
|
12
|
+
const result = await tryHandleInstalledVoiceMarker("PERKOS_VOICE_ENROLL", config, async () => ({
|
|
13
|
+
handleA2AVoiceMarker: async (_message, value) => { options = value; return "PERKOS_VOICE_READY"; },
|
|
14
|
+
configureA2AVoiceEnrollment: async () => ({ ready: true }),
|
|
15
|
+
}));
|
|
16
|
+
expect(result).toBe("PERKOS_VOICE_READY");
|
|
17
|
+
expect(options?.apiBaseUrl).toBe("https://dev.api.perkos.xyz");
|
|
18
|
+
expect(options?.agentId).toBe("athena-id");
|
|
19
|
+
expect(options?.relayApiKey).toBe("rk_private");
|
|
20
|
+
expect(options?.runtime).toBe("hermes");
|
|
21
|
+
});
|
|
22
|
+
it("ignores natural language and keeps Voice parallel", async () => {
|
|
23
|
+
let loaded = false;
|
|
24
|
+
const result = await tryHandleInstalledVoiceMarker("please enable calls", config, async () => {
|
|
25
|
+
loaded = true;
|
|
26
|
+
throw new Error("not used");
|
|
27
|
+
});
|
|
28
|
+
expect(result).toBeNull();
|
|
29
|
+
expect(loaded).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=voice-capability.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-capability.test.js","sourceRoot":"","sources":["../src/voice-capability.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAGtE,MAAM,MAAM,GAAoB;IAC9B,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE;IACtD,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;IAC/B,KAAK,EAAE,EAAE,GAAG,EAAE,gCAAgC,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE;IACrF,QAAQ,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,uDAAuD,EAAE;CAC1G,CAAC;AAEF,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,IAAI,OAA4C,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,6BAA6B,CAAC,qBAAqB,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAC7F,oBAAoB,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC;YAClG,2BAA2B,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SAC3D,CAAC,CAAC,CAAC;QACJ,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,MAAM,MAAM,GAAG,MAAM,6BAA6B,CAAC,qBAAqB,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;YAC3F,MAAM,GAAG,IAAI,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Optional Voice package resolution
|
|
2
|
+
|
|
3
|
+
## Decision
|
|
4
|
+
|
|
5
|
+
PerkOS Voice remains a capability parallel to A2A, but A2A declares
|
|
6
|
+
`@perkos/perkos-voice` as an `optionalDependency`. This places the package next
|
|
7
|
+
to A2A in npm-managed private runtime installations, where the existing dynamic
|
|
8
|
+
`import("@perkos/perkos-voice/a2a")` can resolve it normally. Unsupported
|
|
9
|
+
runtimes still report their runtime/model limitation and never enable calls.
|
|
10
|
+
|
|
11
|
+
The alternatives were an optional peer dependency, which would require every
|
|
12
|
+
runtime installer to perform a second correctly scoped install, or resolving a
|
|
13
|
+
global package path, which is host-specific and bypasses normal Node package
|
|
14
|
+
resolution. The optional dependency is preferred because npm may omit or fail
|
|
15
|
+
it without making A2A installation fail, while a successful installation is
|
|
16
|
+
discoverable without secrets, custom paths, or model involvement.
|
|
17
|
+
|
|
18
|
+
## Verification
|
|
19
|
+
|
|
20
|
+
Release validation must prove manifest and lockfile agreement, the existing
|
|
21
|
+
missing-package fallback, successful dynamic delegation, the full A2A suite,
|
|
22
|
+
and a clean external install that imports both package subpaths. The package
|
|
23
|
+
remains absent from A2A responses and no Voice credential crosses the A2A
|
|
24
|
+
boundary.
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perkos/perkos-a2a",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.61",
|
|
4
4
|
"description": "A2A Protocol communication plugin for OpenClaw — Agent-to-Agent protocol implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -78,6 +78,9 @@
|
|
|
78
78
|
"express": "^4.22.2",
|
|
79
79
|
"ws": "^8.20.1"
|
|
80
80
|
},
|
|
81
|
+
"optionalDependencies": {
|
|
82
|
+
"@perkos/perkos-voice": "^0.1.0"
|
|
83
|
+
},
|
|
81
84
|
"overrides": {
|
|
82
85
|
"qs": "^6.15.2"
|
|
83
86
|
},
|