aap-agent-client 2.6.0 → 2.7.0
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/index.js +3 -0
- package/package.json +3 -2
- package/websocket.js +162 -0
package/index.js
CHANGED
|
@@ -208,4 +208,7 @@ export function createClient(options) {
|
|
|
208
208
|
// Re-export Prover
|
|
209
209
|
export { Prover };
|
|
210
210
|
|
|
211
|
+
// WebSocket client (v2.7+)
|
|
212
|
+
export { AAPWebSocketClient, createSolver, verifyWithWebSocket } from './websocket.js';
|
|
213
|
+
|
|
211
214
|
export default { AAPClient, createClient, Prover };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aap-agent-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "Client library for Agent Attestation Protocol - prove your AI agent identity",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/ira-hash/agent-attestation-protocol#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"aap-agent-core": "^2.6.0"
|
|
23
|
+
"aap-agent-core": "^2.6.0",
|
|
24
|
+
"ws": "^8.16.0"
|
|
24
25
|
},
|
|
25
26
|
"engines": {
|
|
26
27
|
"node": ">=18.0.0"
|
package/websocket.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AAP WebSocket Client v2.7
|
|
3
|
+
*
|
|
4
|
+
* Connects to AAP WebSocket server, receives sequential challenges,
|
|
5
|
+
* and responds in real-time.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import WebSocket from 'ws';
|
|
9
|
+
import { Identity } from 'aap-agent-core';
|
|
10
|
+
|
|
11
|
+
const PROTOCOL_VERSION = '2.7.0';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* AAP WebSocket Client
|
|
15
|
+
*/
|
|
16
|
+
export class AAPWebSocketClient {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.serverUrl = options.serverUrl || 'ws://localhost:3000/aap';
|
|
19
|
+
this.identity = options.identity || new Identity(options);
|
|
20
|
+
this.llmCallback = options.llmCallback || null;
|
|
21
|
+
this.autoSolve = options.autoSolve !== false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get public identity info
|
|
26
|
+
*/
|
|
27
|
+
getIdentity() {
|
|
28
|
+
return this.identity.getPublic();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Connect and verify
|
|
33
|
+
* @param {Function} [llmCallback] - async (challengeString) => solutionObject
|
|
34
|
+
* @returns {Promise<Object>} Verification result
|
|
35
|
+
*/
|
|
36
|
+
async verify(llmCallback) {
|
|
37
|
+
const solver = llmCallback || this.llmCallback;
|
|
38
|
+
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
const ws = new WebSocket(this.serverUrl);
|
|
41
|
+
let sessionId = null;
|
|
42
|
+
let result = null;
|
|
43
|
+
|
|
44
|
+
ws.on('open', () => {
|
|
45
|
+
// Wait for handshake
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
ws.on('message', async (data) => {
|
|
49
|
+
try {
|
|
50
|
+
const msg = JSON.parse(data.toString());
|
|
51
|
+
|
|
52
|
+
switch (msg.type) {
|
|
53
|
+
case 'handshake':
|
|
54
|
+
sessionId = msg.sessionId;
|
|
55
|
+
// Send ready with identity
|
|
56
|
+
const identity = this.identity.getPublic();
|
|
57
|
+
ws.send(JSON.stringify({
|
|
58
|
+
type: 'ready',
|
|
59
|
+
publicKey: identity.publicKey,
|
|
60
|
+
publicId: identity.publicId
|
|
61
|
+
}));
|
|
62
|
+
break;
|
|
63
|
+
|
|
64
|
+
case 'challenge':
|
|
65
|
+
// Solve challenge
|
|
66
|
+
if (!solver) {
|
|
67
|
+
ws.send(JSON.stringify({
|
|
68
|
+
type: 'answer',
|
|
69
|
+
answer: {} // Empty - will fail
|
|
70
|
+
}));
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const answer = await solver(msg.challenge, msg.id);
|
|
76
|
+
ws.send(JSON.stringify({
|
|
77
|
+
type: 'answer',
|
|
78
|
+
answer
|
|
79
|
+
}));
|
|
80
|
+
} catch (e) {
|
|
81
|
+
ws.send(JSON.stringify({
|
|
82
|
+
type: 'answer',
|
|
83
|
+
answer: { error: e.message }
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
|
|
88
|
+
case 'ack':
|
|
89
|
+
// Challenge acknowledged, wait for next
|
|
90
|
+
break;
|
|
91
|
+
|
|
92
|
+
case 'timeout':
|
|
93
|
+
// Too slow
|
|
94
|
+
break;
|
|
95
|
+
|
|
96
|
+
case 'result':
|
|
97
|
+
result = msg;
|
|
98
|
+
ws.close();
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
case 'error':
|
|
102
|
+
reject(new Error(msg.message));
|
|
103
|
+
ws.close();
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
} catch (e) {
|
|
107
|
+
reject(e);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
ws.on('close', () => {
|
|
112
|
+
if (result) {
|
|
113
|
+
resolve(result);
|
|
114
|
+
} else {
|
|
115
|
+
reject(new Error('Connection closed without result'));
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
ws.on('error', (err) => {
|
|
120
|
+
reject(err);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Create solver function from LLM
|
|
128
|
+
* @param {Function} llm - async (prompt) => response string
|
|
129
|
+
* @returns {Function} Solver function
|
|
130
|
+
*/
|
|
131
|
+
export function createSolver(llm) {
|
|
132
|
+
return async (challengeString, challengeId) => {
|
|
133
|
+
const prompt = `Solve this challenge and respond with ONLY valid JSON (no markdown, no explanation):
|
|
134
|
+
|
|
135
|
+
${challengeString}
|
|
136
|
+
|
|
137
|
+
Important:
|
|
138
|
+
- Include the exact salt from the challenge
|
|
139
|
+
- Follow the response format exactly
|
|
140
|
+
- Return ONLY the JSON object`;
|
|
141
|
+
|
|
142
|
+
const response = await llm(prompt);
|
|
143
|
+
|
|
144
|
+
// Parse JSON from response
|
|
145
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
146
|
+
if (!jsonMatch) {
|
|
147
|
+
throw new Error('No JSON found in response');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return JSON.parse(jsonMatch[0]);
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Quick verify helper
|
|
156
|
+
*/
|
|
157
|
+
export async function verifyWithWebSocket(serverUrl, llmCallback) {
|
|
158
|
+
const client = new AAPWebSocketClient({ serverUrl, llmCallback });
|
|
159
|
+
return client.verify();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export default AAPWebSocketClient;
|