clinch-core 0.6.0 → 0.6.1

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.
Files changed (2) hide show
  1. package/README.md +120 -107
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,110 +1,121 @@
1
1
  # Clinch Core (`clinch-core`)
2
2
 
3
- > **Autonomous Agent Negotiation Mediation Protocol — Edge Client & Seller SDK**
3
+ > **Agent Negotiation Protocol (ANP) — Edge Client & Seller SDK**
4
4
 
5
- Clinch is a modular, edge-first protocol designed to mediate autonomous negotiations between a buyer AI agent and a seller AI agent. It allows agents to negotiate price and terms to a mutual, mathematically converged agreement without a human in the loop, and without the seller ever seeing the buyer's full profile.
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
- ## 🎯 Project Aim & Philosophy
9
+ ## 1. Protocol Architecture & Mechanics
12
10
 
13
- In the modern web, purchasing, SaaS licensing, transport, and commodity procurement involve endless manual comparisons, form-filling, and back-and-forth communication. Clinch replaces this overhead by allowing buyers to delegate constraints to a local agent that negotiates autonomously with the seller's hosted agent.
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
- * **Buyer Anonymity First**: The seller receives a simplified constraint vector (e.g., budget bracket, target category) rather than the buyer’s identity, private data, or raw history. All counter-offers are routed through the Registry proxy, guaranteeing 100% IP anonymity for the buyer.
16
- * **Edge-First Execution**: The buyer agent runs locally on-device. This SDK supports dynamically importing and running optimized 1.5B 4-bit quantized models in under **1.3 GB of RAM**, making it compatible with consumer hardware.
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
- ## 📦 Installation
18
+ *Example:* `ANP/C.amazon.anp`
23
19
 
24
- To use `clinch-core` as a raw network client (Bring Your Own LLM or Seller Node):
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
- If you wish to use the **out-of-the-box local Sandbox engine** (Buyer Edge Mode), install the required peer dependency:
30
- ```bash
31
- npm install node-llama-cpp
32
- ```
33
- *(Note: `node-llama-cpp` is dynamically imported. Web/React Native builds will not fail if this is missing, provided `.sandbox()` is not called).*
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
- ## 🚦 Core State Machine & Event Architecture
31
+ ## 2. State Machine & Event Architecture
38
32
 
39
- `clinch-core` is driven by a strict network and negotiation state machine. You can subscribe to state transitions and real-time transaction logging to build clean, reactive user interfaces.
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`: Resolving registry configuration and performing Proof-of-Work auth.
44
- * `IDLE`: Connected and authenticated. Waiting for handshakes or callbacks.
45
- * `RECONNECTING`: Socket connection lost; executing exponential backoff.
46
- * `NEGOTIATING`: Active turn-based negotiation sequence in progress.
47
- * `CONVERGED`: Mathematical agreement reached successfully.
48
- * `STALEMATE`: Negotiation terminated; max turns reached without convergence.
49
- * `ERROR`: Internal network, cryptographic, or compilation failure.
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(`State transitioned to: ${status}`);
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(`Negotiation initiated with ${sellerId} (Session: ${sessionId})`);
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} closed. Outcome: ${outcome} at $${finalPrice}`);
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
- // Fired when the seller routes a callback counter-offer via the Registry WS
63
+ console.log(`[Callback] Re-engagement for session ${sessionId} received`);
67
64
  });
68
65
  ```
69
66
 
70
67
  ---
71
68
 
72
- ## Quickstart: Out-of-the-Box Sandbox (Buyer)
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
- The Sandbox automatically downloads an optimized **Qwen 2.5 1.5B Q4_K_M** model (~1.1GB), loads it securely into local RAM, and automatically wires up the WebSocket listeners to negotiate autonomously on incoming network events.
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 startLocalAgent() {
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 }) => console.log(`Deal secured at $${finalPrice}!`));
96
+ core.on('session_closed', ({ finalPrice }) => {
97
+ console.log(`✓ Negotiation completed at $${finalPrice}`);
98
+ });
84
99
 
85
- // 1. Initialize Sandbox: Handles network auth, downloads GGUF, & registers auto-listeners
100
+ // 1. Initialize local LLM, solve PoW, and connect WebSocket
86
101
  await core.sandbox({ downloadLLM: true });
87
102
 
88
- // 2. Initiate Negotiation: Session automatically transitions to 'NEGOTIATING'
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 // Strictly enforced constraint
108
+ max_budget: 85.00
95
109
  });
96
110
 
97
- console.log(`🤖 Auto-agent listening on Session ${sessionId}`);
111
+ console.log(`Session active: ${sessionId}`);
98
112
  }
99
113
 
100
- startLocalAgent();
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 and save state to DB
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
- // --- LATER, ON A DIFFERENT SERVER OR WEBHOOK --- //
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(savedState);
143
+ webhookCore.importSessionState(exportedState);
131
144
 
132
145
  webhookCore.on('callback_received', async (event) => {
133
- // 2. Let the Core build the perfect state-aware protocol prompt
146
+ // 3. Generate system prompt using rehydrated session data
134
147
  const systemPrompt = webhookCore.buildAgentPrompt(event.sessionId, event.payload.message);
135
148
 
136
- // 3. Feed it to Claude/OpenAI
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: "Determine our next protocol move." }]
154
+ messages: [{ role: "user", content: "Calculate next move." }]
142
155
  });
143
156
 
144
- const aiDecision = JSON.parse(msg.content[0].text);
157
+ const decision = JSON.parse(msg.content[0].text);
145
158
 
146
- // 4. Act on the deterministic JSON response
147
- if (aiDecision.action === 'accept') {
148
- console.log("Deal reached!");
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, aiDecision.price, aiDecision.message);
151
- // Reserialize and update DB after turn to maintain state sync
152
- await db.update(event.sessionId, webhookCore.exportSessionState(event.sessionId));
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
- ## 🏪 Quickstart: Building a Seller Node
172
+ ## 5. Integration Guide: Seller Nodes
160
173
 
161
- `clinch-core` exports the `ClinchSeller` class to make building a native seller server seamless.
174
+ Sellers use the `ClinchSeller` class to build compliant, automated endpoints.
162
175
 
163
- **Architecture Note:** Seller Nodes do not use JWTs. You generate a permanent Ed25519 Keypair in the Clinch Dashboard, claim your domain, and pass the private key to your Node. The node securely self-publishes its endpoint and capabilities on boot.
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 your permanent Dashboard-generated Private Key
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 your routing endpoint to the network on boot
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
- // Create your counter-offer route
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
- // Verify the payload actually came from the buyer who holds the session key
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).send("Invalid signature");
213
+ if (!isValid) return res.status(401).json({ error: "Invalid signature" });
199
214
 
200
- // Process logic and return standard counter JSON...
201
- res.json({ msg_type: 'counter', price: 95.00, reason: "Best I can do is $95." });
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
- ## 📖 API Reference
224
+ ## 6. API Reference
210
225
 
211
- ### Buyer Client (`ClinchCore`)
226
+ ### 6.1 `ClinchCore` (Buyer Client)
212
227
 
213
228
  #### `new ClinchCore(config)`
214
- * `config.registryUrl` *(string)*: Override default dynamic configuration resolution for local testing.
215
- * `config.timeoutMs` *(number)*: Connection timeout limit (Default: `5000`ms).
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
- Authenticates the node on the network, completes Identity-Bound PoW, and connects the WebSocket.
219
- * `cachedToken` *(string)*: Optional. Re-use an existing network token to bypass PoW calculations on restart.
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
- Launches a cryptographic session handshake. Returns `sessionId`.
223
- * `address` *(string)*: Target seller address. Must include the protocol mode prefix (e.g., `ANP/C.amazon.anp`).
224
- * `constraints` *(ConstraintVector)*: Must include `max_budget` (number) and `item` (string).
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 the active sessionincluding the ephemeral cryptographic keys, current turn, and LLM context parameters—to a JSON string. Used to scale instances horizontally, survive pod restarts, or pick up negotiations across async callback windows.
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
- Returns a highly-optimized, state-aware string to pass to an external LLM as a System Prompt. Ensures the LLM outputs strict JSON matching the protocol rules.
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 via the Registry proxy.
248
+ Signs and dispatches a standard counter-offer to the seller endpoint.
234
249
 
235
250
  #### `async exitSession(sessionId)`
236
- Closes the active connection and generates a single-use re-engagement Callback token.
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
- ### Seller Client (`ClinchSeller`)
255
+ ### 6.2 `ClinchSeller` (Seller Client)
244
256
 
245
257
  #### `new ClinchSeller(config)`
246
- * `config.privateKeyHex` *(string)*: The Ed25519 private key generated from the Clinch Dashboard. Used to cryptographically authenticate endpoint updates.
247
- * `config.registryUrl` *(string)*: Optional. Overrides Registry configuration resolution for local testing.
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
- Publishes the seller's DNS-style record to the Registry so buyers can discover and route to it. Signed locally via the Ed25519 identity key.
262
+ Locally signs and publishes dynamic endpoint mappings and categories to the discovery registry.
251
263
 
252
- #### `verifyBuyerSignature(payload, signatureHex, pubKeyHex)`
253
- Returns `boolean`. Cryptographically verifies that incoming counter-offers were signed by the exact ephemeral session key generated by the buyer during the handshake.
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
- ## 🔏 Cryptographic Guarantees
258
- Clinch operates on a strictly zero-trust model.
259
- 1. **Identity-Bound PoW**: Buyer challenge hashes include the client's `pubKey`, making outsourcing/bot-farming mathematically impossible.
260
- 2. **Ed25519 Seller Authority**: Seller endpoints and capabilities are updated via Ed25519 signatures, completely decoupling the control plane (Dashboard) from the data plane (Server).
261
- 3. **Ephemeral Sessions**: `negotiate()` generates an ephemeral Session Key. This key signs every individual message. If a session key is compromised, your global identity remains secure, and historical session logs remain completely un-linkable.
262
- 4. **Anonymity Proxy**: Counter-offers are routed strictly through the Registry. The seller never logs the buyer's IP address.
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.0",
3
+ "version": "0.6.1",
4
4
 
5
5
  "description": "Clinch Protocol Edge Client",
6
6
  "main": "dist/index.js",