clinch-core 0.6.0 → 0.6.2
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 +120 -107
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,110 +1,121 @@
|
|
|
1
1
|
# Clinch Core (`clinch-core`)
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Agent Negotiation Protocol (ANP) — Edge Client & Seller SDK**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Once an agreement is reached, Clinch issues a **cryptographically co-signed deal artifact** held by both parties. This SDK provides the complete network client, state-isolated session management, cryptographic signing engines, an optional out-of-the-box local LLM bargaining sandbox, and the server-side Seller SDK.
|
|
5
|
+
`clinch-core` is the programmatic engine of the Clinch Protocol. It provides the state machine, cryptographic signing interfaces, local LLM sandbox adapters, and server-side utilities required to implement both buyer and seller agents conforming to the **Agent Negotiation Protocol (ANP)**.
|
|
8
6
|
|
|
9
7
|
---
|
|
10
8
|
|
|
11
|
-
##
|
|
9
|
+
## 1. Protocol Architecture & Mechanics
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
The Agent Negotiation Protocol (ANP) governs how two autonomous software agents establish identity, declare capabilities, and reach a cryptographically verifiable agreement on price and terms.
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* **Enterprise Concurrency**: Complete session isolation allows scaling horizontally. You can run hundreds of concurrent negotiations on a single server, serialize state, and resume negotiations across pod restarts or delayed webhooks.
|
|
18
|
-
* **Cryptographic Accountability**: Identity is proven via Ed25519 keys and Proof-of-Work (PoW). The final co-signed deal artifact is self-verifying against the Registry's daily rotating key chain. Zero-trust machine-to-machine updates are enforced without centralized JWT expirations.
|
|
13
|
+
### 1.1 Address Formatting & Routing
|
|
14
|
+
All destination routing in Clinch relies on strict, structured addressing:
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
$$\text{PROTOCOL\_MODE} \mathbin{.} \text{domain} \mathbin{.} \text{TLD}$$
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
*Example:* `ANP/C.amazon.anp`
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
npm install clinch-core
|
|
27
|
-
```
|
|
20
|
+
The SDK parses the address to extract the negotiated **Protocol Mode** and target namespace domain before dispatching the initialization request.
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*
|
|
22
|
+
### 1.2 Protocol Modes
|
|
23
|
+
Sellers declare which execution profiles they support. The SDK maps these mode flags to session parameters during handshake:
|
|
24
|
+
|
|
25
|
+
* **`ANP/A`**: Standard native execution. Both buyer and seller agents run the local Clinch edge model. Best suited for high-volume, low-friction commodity exchanges.
|
|
26
|
+
* **`ANP/B`**: Mixed execution. One side uses the native edge model, while the other runs a custom model or external API adapter.
|
|
27
|
+
* **`ANP/C`**: Custom integration. Both agents run custom decision engines (e.g., GPT-4o, Claude 3.5, or proprietary heuristics).
|
|
34
28
|
|
|
35
29
|
---
|
|
36
30
|
|
|
37
|
-
##
|
|
31
|
+
## 2. State Machine & Event Architecture
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
The SDK maintains an isolated, turn-based state machine for each active session.
|
|
40
34
|
|
|
41
35
|
### Core Statuses (`CoreStatus`)
|
|
42
|
-
* `OFFLINE`: Client is disconnected.
|
|
43
|
-
* `CONNECTING`:
|
|
44
|
-
* `IDLE`: Connected and authenticated.
|
|
45
|
-
* `
|
|
46
|
-
* `
|
|
47
|
-
* `
|
|
48
|
-
* `
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
### Event Emitters
|
|
36
|
+
* `OFFLINE`: Client is completely disconnected.
|
|
37
|
+
* `CONNECTING`: Authenticating identity and performing local Proof-of-Work (PoW) verification.
|
|
38
|
+
* `IDLE`: Connected and authenticated. Ready to initialize new sessions.
|
|
39
|
+
* `NEGOTIATING`: Active, turn-based bargaining sequence in progress.
|
|
40
|
+
* `CONVERGED`: Mathematical convergence reached; agreement co-signed.
|
|
41
|
+
* `STALEMATE`: Handshake or negotiation sequence aborted or timed out.
|
|
42
|
+
* `ERROR`: Internal network, compilation, or cryptographic validation failure.
|
|
43
|
+
|
|
44
|
+
### Developer Event Subscriptions
|
|
52
45
|
```typescript
|
|
46
|
+
// Track the operational status of the client
|
|
53
47
|
core.on('status_changed', (status: CoreStatus) => {
|
|
54
|
-
console.log(`
|
|
48
|
+
console.log(`[Status] Client changed to: ${status}`);
|
|
55
49
|
});
|
|
56
50
|
|
|
51
|
+
// Fired when a new negotiation handshake is completed
|
|
57
52
|
core.on('session_started', ({ sessionId, sellerId }) => {
|
|
58
|
-
console.log(`
|
|
53
|
+
console.log(`[Session Started] Active ID: ${sessionId} targeting ${sellerId}`);
|
|
59
54
|
});
|
|
60
55
|
|
|
56
|
+
// Fired when a session reaches terminal state (deal converged or stalemate)
|
|
61
57
|
core.on('session_closed', ({ sessionId, outcome, finalPrice }) => {
|
|
62
|
-
console.log(`Session ${sessionId}
|
|
58
|
+
console.log(`[Session Closed] ID: ${sessionId} | Outcome: ${outcome} | Price: $${finalPrice}`);
|
|
63
59
|
});
|
|
64
60
|
|
|
61
|
+
// Fired when an out-of-band message is received via the WS callback channel
|
|
65
62
|
core.on('callback_received', ({ sessionId, payload }) => {
|
|
66
|
-
|
|
63
|
+
console.log(`[Callback] Re-engagement for session ${sessionId} received`);
|
|
67
64
|
});
|
|
68
65
|
```
|
|
69
66
|
|
|
70
67
|
---
|
|
71
68
|
|
|
72
|
-
##
|
|
69
|
+
## 3. Installation
|
|
70
|
+
|
|
71
|
+
Install the library using your package manager:
|
|
72
|
+
```bash
|
|
73
|
+
npm install clinch-core
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To run the local autonomous **Sandbox engine**, install the required peer dependency:
|
|
77
|
+
```bash
|
|
78
|
+
npm install node-llama-cpp
|
|
79
|
+
```
|
|
80
|
+
*(Note: `node-llama-cpp` is dynamically imported at runtime. Web builds or headless environments will not fail if this dependency is omitted, provided `.sandbox()` is not invoked).*
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 4. Integration Guide: Buyer Agents
|
|
73
85
|
|
|
74
|
-
|
|
86
|
+
### 4.1 Running the On-Device Sandbox
|
|
87
|
+
The local Sandbox runs an optimized **Qwen 2.5 1.5B Q4_K_M** model on local hardware resources. It automatically handles handshake math and turn-based counter-offers based on your strict constraints.
|
|
75
88
|
|
|
76
89
|
```javascript
|
|
77
90
|
const { ClinchCore } = require('clinch-core');
|
|
78
91
|
|
|
79
|
-
async function
|
|
92
|
+
async function runAutonomousSession() {
|
|
80
93
|
const core = new ClinchCore();
|
|
81
94
|
|
|
82
95
|
core.on('log', (msg) => console.log(msg));
|
|
83
|
-
core.on('session_closed', ({ finalPrice }) =>
|
|
96
|
+
core.on('session_closed', ({ finalPrice }) => {
|
|
97
|
+
console.log(`✓ Negotiation completed at $${finalPrice}`);
|
|
98
|
+
});
|
|
84
99
|
|
|
85
|
-
// 1. Initialize
|
|
100
|
+
// 1. Initialize local LLM, solve PoW, and connect WebSocket
|
|
86
101
|
await core.sandbox({ downloadLLM: true });
|
|
87
102
|
|
|
88
|
-
// 2.
|
|
89
|
-
// Format: PROTOCOL_MODE.domain.anp (e.g., ANP/C.amazon.anp)
|
|
103
|
+
// 2. Begin autonomous negotiation
|
|
90
104
|
const sessionId = await core.negotiate('ANP/C.amazon.anp', {
|
|
91
105
|
intent: 'purchase',
|
|
92
106
|
category: 'electronics',
|
|
93
107
|
item: 'Ninja Blender',
|
|
94
|
-
max_budget: 85.00
|
|
108
|
+
max_budget: 85.00
|
|
95
109
|
});
|
|
96
110
|
|
|
97
|
-
console.log(
|
|
111
|
+
console.log(`Session active: ${sessionId}`);
|
|
98
112
|
}
|
|
99
113
|
|
|
100
|
-
|
|
114
|
+
runAutonomousSession();
|
|
101
115
|
```
|
|
102
116
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
## 🔌 Quickstart: Bring Your Own AI & Webhook Persistence
|
|
106
|
-
|
|
107
|
-
If you are running in a cloud environment (e.g., handling webhooks) and want to leverage high-end hosted APIs (e.g. Claude 3.5 Sonnet or OpenAI GPT-4o), bypass the sandbox. The Core provides **State Serialization** to survive server restarts.
|
|
117
|
+
### 4.2 Cloud Webhook & Horizontal Scale Pattern
|
|
118
|
+
For enterprise cloud environments where processes must remain stateless or scale horizontally across server pods, you must serialize and rehydrate active sessions dynamically. This ensures that when an asynchronous callback arrives, any pod can load the session state and use the matching ephemeral key to sign the next turn.
|
|
108
119
|
|
|
109
120
|
```javascript
|
|
110
121
|
import { ClinchCore } from 'clinch-core';
|
|
@@ -113,54 +124,59 @@ import Anthropic from '@anthropic-ai/sdk';
|
|
|
113
124
|
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
114
125
|
const core = new ClinchCore();
|
|
115
126
|
|
|
116
|
-
await core.initialize();
|
|
127
|
+
await core.initialize();
|
|
117
128
|
|
|
118
|
-
// 1. Start session
|
|
129
|
+
// 1. Start session
|
|
119
130
|
const sessionId = await core.negotiate('ANP/C.amazon.anp', {
|
|
120
131
|
intent: 'purchase',
|
|
121
132
|
item: 'Ninja Blender',
|
|
122
133
|
max_budget: 85.00
|
|
123
134
|
});
|
|
124
|
-
const savedState = core.exportSessionState(sessionId);
|
|
125
|
-
await db.save(sessionId, savedState);
|
|
126
135
|
|
|
127
|
-
//
|
|
136
|
+
// 2. Serialize and persist the state to your DB (Redis, Postgres, etc.)
|
|
137
|
+
const exportedState = core.exportSessionState(sessionId);
|
|
138
|
+
await db.saveSession(sessionId, exportedState);
|
|
139
|
+
|
|
140
|
+
// --- LATER, ON A DIFFERENT POD OR ASYNCHRONOUS WEBHOOK TRIGGER --- //
|
|
128
141
|
|
|
129
142
|
const webhookCore = new ClinchCore();
|
|
130
|
-
webhookCore.importSessionState(
|
|
143
|
+
webhookCore.importSessionState(exportedState);
|
|
131
144
|
|
|
132
145
|
webhookCore.on('callback_received', async (event) => {
|
|
133
|
-
//
|
|
146
|
+
// 3. Generate system prompt using rehydrated session data
|
|
134
147
|
const systemPrompt = webhookCore.buildAgentPrompt(event.sessionId, event.payload.message);
|
|
135
148
|
|
|
136
|
-
//
|
|
149
|
+
// 4. Evaluate with hosted LLM
|
|
137
150
|
const msg = await anthropic.messages.create({
|
|
138
151
|
model: "claude-3-5-sonnet-20241022",
|
|
139
152
|
maxTokens: 150,
|
|
140
153
|
system: systemPrompt,
|
|
141
|
-
messages: [{ role: "user", content: "
|
|
154
|
+
messages: [{ role: "user", content: "Calculate next move." }]
|
|
142
155
|
});
|
|
143
156
|
|
|
144
|
-
const
|
|
157
|
+
const decision = JSON.parse(msg.content[0].text);
|
|
145
158
|
|
|
146
|
-
//
|
|
147
|
-
if (
|
|
148
|
-
console.log("
|
|
159
|
+
// 5. Submit cryptographic counter-offer
|
|
160
|
+
if (decision.action === 'accept') {
|
|
161
|
+
console.log("Agreement reached!");
|
|
149
162
|
} else {
|
|
150
|
-
await webhookCore.sendCounter(event.sessionId,
|
|
151
|
-
//
|
|
152
|
-
await db.
|
|
163
|
+
await webhookCore.sendCounter(event.sessionId, decision.price, decision.message);
|
|
164
|
+
// 6. Update DB with new turn state and counters
|
|
165
|
+
await db.updateSession(event.sessionId, webhookCore.exportSessionState(event.sessionId));
|
|
153
166
|
}
|
|
154
167
|
});
|
|
155
168
|
```
|
|
156
169
|
|
|
157
170
|
---
|
|
158
171
|
|
|
159
|
-
##
|
|
172
|
+
## 5. Integration Guide: Seller Nodes
|
|
160
173
|
|
|
161
|
-
|
|
174
|
+
Sellers use the `ClinchSeller` class to build compliant, automated endpoints.
|
|
162
175
|
|
|
163
|
-
|
|
176
|
+
### 5.1 Decoupled Routing Architecture
|
|
177
|
+
To prevent centralized token expiration failures, Clinch separates ownership from routing:
|
|
178
|
+
1. **The Control Plane**: The merchant claims their domain name (e.g., `amazon.anp`) and binds their permanent public key to it once using the dashboard.
|
|
179
|
+
2. **The Data Plane**: The actual seller server is initialized with the matching permanent private key. On boot, the machine signs its dynamic endpoint configuration locally and publishes it to the registry. No JWTs are used on-wire for machine routing.
|
|
164
180
|
|
|
165
181
|
```javascript
|
|
166
182
|
import { ClinchSeller } from 'clinch-core';
|
|
@@ -169,13 +185,12 @@ import express from 'express';
|
|
|
169
185
|
const app = express();
|
|
170
186
|
app.use(express.json());
|
|
171
187
|
|
|
172
|
-
// Initialize with
|
|
188
|
+
// 1. Initialize seller with the permanent cryptographic key
|
|
173
189
|
const seller = new ClinchSeller({
|
|
174
190
|
privateKeyHex: process.env.SELLER_PRIVATE_KEY
|
|
175
|
-
// registryUrl: 'http://localhost:7860' // Optional: Override for local dev
|
|
176
191
|
});
|
|
177
192
|
|
|
178
|
-
// Publish
|
|
193
|
+
// 2. Publish endpoint to the registry on boot (Self-Signing)
|
|
179
194
|
await seller.registerEndpoint({
|
|
180
195
|
agent_id: 'amazon.anp',
|
|
181
196
|
endpoint: 'https://your-seller-api.com/anp/v1',
|
|
@@ -184,21 +199,21 @@ await seller.registerEndpoint({
|
|
|
184
199
|
capabilities: ['price_flex']
|
|
185
200
|
});
|
|
186
201
|
|
|
187
|
-
//
|
|
202
|
+
// 3. Implement the standard ANP counter-offer endpoint
|
|
188
203
|
app.post('/anp/v1/counter', (req, res) => {
|
|
189
204
|
const { session_id, turn, price, reason, buyer_sig } = req.body;
|
|
190
205
|
|
|
191
|
-
//
|
|
206
|
+
// Cryptographically verify the buyer's ephemeral signature
|
|
192
207
|
const isValid = seller.verifyBuyerSignature(
|
|
193
208
|
{ session_id, turn, price, reason },
|
|
194
209
|
buyer_sig,
|
|
195
210
|
req.headers['x-buyer-pubkey']
|
|
196
211
|
);
|
|
197
212
|
|
|
198
|
-
if (!isValid) return res.status(401).
|
|
213
|
+
if (!isValid) return res.status(401).json({ error: "Invalid signature" });
|
|
199
214
|
|
|
200
|
-
//
|
|
201
|
-
res.json({ msg_type: 'counter', price: 95.00, reason: "Best
|
|
215
|
+
// Execute bargaining logic and respond
|
|
216
|
+
res.json({ msg_type: 'counter', price: 95.00, reason: "Best we can offer is $95." });
|
|
202
217
|
});
|
|
203
218
|
|
|
204
219
|
app.listen(8080);
|
|
@@ -206,57 +221,55 @@ app.listen(8080);
|
|
|
206
221
|
|
|
207
222
|
---
|
|
208
223
|
|
|
209
|
-
##
|
|
224
|
+
## 6. API Reference
|
|
210
225
|
|
|
211
|
-
###
|
|
226
|
+
### 6.1 `ClinchCore` (Buyer Client)
|
|
212
227
|
|
|
213
228
|
#### `new ClinchCore(config)`
|
|
214
|
-
* `config.registryUrl` *(string)*:
|
|
215
|
-
* `config.timeoutMs` *(number)*:
|
|
229
|
+
* `config.registryUrl` *(string)*: Optional. Direct override pointing to a local development registry.
|
|
230
|
+
* `config.timeoutMs` *(number)*: Network connection timeout limit (Default: `5000`ms).
|
|
216
231
|
|
|
217
232
|
#### `async initialize(cachedToken?)`
|
|
218
|
-
|
|
219
|
-
* `cachedToken` *(string)*: Optional.
|
|
233
|
+
Resolves network configurations, computes Proof-of-Work proof, and opens active WebSocket channels.
|
|
234
|
+
* `cachedToken` *(string)*: Optional. Pastes a previous registry authorization token to skip PoW calculations on startup.
|
|
220
235
|
|
|
221
236
|
#### `async negotiate(address, constraints)`
|
|
222
|
-
|
|
223
|
-
* `address` *(string)*: Target
|
|
224
|
-
* `constraints` *(ConstraintVector)*:
|
|
237
|
+
Initializes the cryptographic handshake with a seller. Returns `sessionId`.
|
|
238
|
+
* `address` *(string)*: Target address formatted strictly as `PROTOCOL_MODE.domain` (e.g., `ANP/C.amazon.anp`).
|
|
239
|
+
* `constraints` *(ConstraintVector)*: Schema requiring `max_budget` (number) and `item` (string).
|
|
225
240
|
|
|
226
241
|
#### `exportSessionState(sessionId)` / `importSessionState(serializedData)`
|
|
227
|
-
Serializes
|
|
242
|
+
Serializes or de-serializes all in-flight state for a given session, including ephemeral Ed25519 keys, state metrics, and local sandbox parameters, into an exchangeable JSON string.
|
|
228
243
|
|
|
229
244
|
#### `buildAgentPrompt(sessionId, incomingMessage)`
|
|
230
|
-
|
|
245
|
+
Assembles a contextual, structure-compliant system prompt for external LLMs to ensure compliant JSON execution.
|
|
231
246
|
|
|
232
247
|
#### `async sendCounter(sessionId, price, reason)`
|
|
233
|
-
Signs and dispatches a counter-offer to the seller
|
|
248
|
+
Signs and dispatches a standard counter-offer to the seller endpoint.
|
|
234
249
|
|
|
235
250
|
#### `async exitSession(sessionId)`
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
#### `async sandbox(config)`
|
|
239
|
-
Initializes the edge-AI execution context, downloads the GGUF, and auto-listens.
|
|
251
|
+
Stops the live execution channel and requests a callback token.
|
|
240
252
|
|
|
241
253
|
---
|
|
242
254
|
|
|
243
|
-
###
|
|
255
|
+
### 6.2 `ClinchSeller` (Seller Client)
|
|
244
256
|
|
|
245
257
|
#### `new ClinchSeller(config)`
|
|
246
|
-
* `config.privateKeyHex` *(string)*: The Ed25519 private key generated
|
|
247
|
-
* `config.registryUrl` *(string)*: Optional.
|
|
258
|
+
* `config.privateKeyHex` *(string)*: The permanent Ed25519 private key generated via the registration interface.
|
|
259
|
+
* `config.registryUrl` *(string)*: Optional. Point to a dev registry for local testing.
|
|
248
260
|
|
|
249
261
|
#### `async registerEndpoint(record)`
|
|
250
|
-
|
|
262
|
+
Locally signs and publishes dynamic endpoint mappings and categories to the discovery registry.
|
|
251
263
|
|
|
252
|
-
#### `verifyBuyerSignature(payload, signatureHex,
|
|
253
|
-
|
|
264
|
+
#### `verifyBuyerSignature(payload, signatureHex, buyerPubKeyHex)`
|
|
265
|
+
Verifies that the provided turn payload matches the cryptographic signature produced by the session's ephemeral public key.
|
|
254
266
|
|
|
255
267
|
---
|
|
256
268
|
|
|
257
|
-
##
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
269
|
+
## 7. Cryptographic Properties
|
|
270
|
+
|
|
271
|
+
Clinch relies entirely on zero-trust cryptography to maintain buyer privacy and seller authenticity:
|
|
272
|
+
|
|
273
|
+
1. **Proof-of-Work Binding**: The PoW challenge solution includes the client's public key hash, ensuring challenges cannot be pre-computed or farmed.
|
|
274
|
+
2. **Ephemeral Session Keypairs**: Calling `negotiate()` generates a single-use keypair (`nacl.sign.keyPair()`). This ephemeral key signs every message sent within the session context. In the event of a key compromise, your permanent global identity remains secure, and historical session logs are completely unlinkable.
|
|
275
|
+
3. **Decoupled Verification**: Agreement artifacts are sequentially co-signed by the buyer's session key, the seller's verified identity key, and countersigned by the active registry key. This provides independent verification offline using only the registry's public key chain.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clinch-core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
|
|
5
5
|
"description": "Clinch Protocol Edge Client",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,9 +20,8 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"js-sha256": "^0.11.1",
|
|
22
22
|
"tweetnacl": "^1.0.3",
|
|
23
|
-
"ws": "^8.20.1"
|
|
24
|
-
},
|
|
25
|
-
"peerDependencies":{
|
|
23
|
+
"ws": "^8.20.1",
|
|
26
24
|
"node-llama-cpp": "^3.18.1"
|
|
27
25
|
}
|
|
26
|
+
|
|
28
27
|
}
|