clinch-core 0.1.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.
@@ -0,0 +1,29 @@
1
+ name: Publish Clinch Core to NPM
2
+
3
+ on:
4
+ workflow_dispatch: # Allows you to trigger this manually from the GitHub UI
5
+
6
+ jobs:
7
+ build-and-publish:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - name: Checkout Source Code
11
+ uses: actions/checkout@v4
12
+
13
+ - name: Setup Node.js
14
+ uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20.x'
17
+ registry-url: 'https://registry.npmjs.org'
18
+
19
+ - name: Install Dependencies
20
+ # Ubuntu has all C++ compilers, so node-llama-cpp will install perfectly here
21
+ run: npm install
22
+
23
+ - name: Build TypeScript
24
+ run: npm run build
25
+
26
+ - name: Publish to NPM
27
+ run: npm publish
28
+ env:
29
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 publicstringapps
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,245 @@
1
+ # Clinch Core (`clinch-core`)
2
+
3
+ > **Autonomous Agent Negotiation Mediation Protocol β€” Edge Client & Seller SDK**
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 machine, cryptographic signing engine, an optional out-of-the-box local LLM bargaining sandbox, and the server-side Seller SDK.
8
+
9
+ ---
10
+
11
+ ## 🎯 Project Aim & Philosophy
12
+
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.
14
+
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
+ * **Cryptographic Accountability**: Identity is proven via an Ed25519 identity key and Proof-of-Work (PoW). Every session uses throwaway, ephemeral session keys. The final co-signed deal artifact is self-verifying against the Registry's daily rotating key chain.
18
+ * **Deterministic Hybrid Architecture**: The SDK decouples conversational language from protocol math. The LLM strictly generates persuasive copy while the core SDK evaluates numerical convergence, preventing AI hallucination or rule-bypassing.
19
+
20
+ ---
21
+
22
+ ## πŸ“¦ Installation
23
+
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
+ ```
28
+
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).*
34
+
35
+ ---
36
+
37
+ ## 🚦 Core State Machine & Event Architecture
38
+
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.
40
+
41
+ ### Core Statuses (`CoreStatus`)
42
+ * `OFFLINE`: Client is disconnected.
43
+ * `CONNECTING`: Resolving registry DNS 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
52
+ ```typescript
53
+ core.on('status_changed', (status: CoreStatus) => {
54
+ console.log(`State transitioned to: ${status}`);
55
+ });
56
+
57
+ core.on('log', (message: string) => {
58
+ console.log(`[LOG] ${message}`);
59
+ });
60
+
61
+ core.on('callback_received', (data: { sessionId: string, payload: any }) => {
62
+ // Fired when the seller routes a callback counter-offer via the Registry WS
63
+ });
64
+
65
+ core.on('token_issued', (data: { token: string }) => {
66
+ // Fired when PoW completes. Save this JWT to disk to skip PoW on next boot!
67
+ });
68
+ ```
69
+
70
+ ---
71
+
72
+ ## ⚑ Quickstart: Out-of-the-Box Sandbox (Buyer)
73
+
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.
75
+
76
+ ```javascript
77
+ const { ClinchCore } = require('clinch-core');
78
+
79
+ async function startLocalAgent() {
80
+ const core = new ClinchCore();
81
+
82
+ core.on('log', (msg) => console.log(msg));
83
+ core.on('status_changed', (status) => console.log(`πŸ‘‰ State: ${status}`));
84
+
85
+ // 1. Initialize Sandbox: Handles network auth, downloads GGUF, & registers auto-listeners
86
+ await core.sandbox({ downloadLLM: true });
87
+
88
+ // 2. Initiate Negotiation: Session automatically transitions to 'NEGOTIATING'
89
+ const sessionId = await core.negotiate('ANP/A.amazon.anp', {
90
+ intent: 'purchase',
91
+ category: 'electronics',
92
+ item: 'Ninja Blender',
93
+ max_budget: 85.00 // Strictly enforced constraint
94
+ });
95
+
96
+ console.log(`πŸ€– Auto-agent listening on Session ${sessionId}`);
97
+ }
98
+
99
+ startLocalAgent();
100
+ ```
101
+
102
+ ---
103
+
104
+ ## πŸ”Œ Quickstart: Bring Your Own AI (Universal Prompt Builder)
105
+
106
+ If you are running in a cloud environment and want to leverage high-end hosted APIs (e.g. Claude 3.5 Sonnet or OpenAI GPT-4o), bypass the sandbox.
107
+
108
+ `clinch-core` includes a **Universal Prompt Builder** (`buildAgentPrompt`) that automatically injects the current negotiation state, budget gaps, and strict JSON output schemas into a perfect system prompt for any LLM.
109
+
110
+ ```javascript
111
+ import { ClinchCore } from 'clinch-core';
112
+ import Anthropic from '@anthropic-ai/sdk';
113
+
114
+ const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
115
+ const core = new ClinchCore();
116
+
117
+ await core.initialize(); // Completes PoW and connects to WS
118
+
119
+ const sessionId = await core.negotiate('ANP/C.amazon.anp', {
120
+ intent: 'purchase',
121
+ item: 'Ninja Blender',
122
+ max_budget: 85.00
123
+ });
124
+
125
+ core.on('callback_received', async (event) => {
126
+ const sellerCounter = event.payload;
127
+
128
+ // 1. Let the Core build the perfect state-aware protocol prompt
129
+ const systemPrompt = core.buildAgentPrompt(sessionId, sellerCounter.message);
130
+
131
+ // 2. Feed it to Claude/OpenAI
132
+ const msg = await anthropic.messages.create({
133
+ model: "claude-3-5-sonnet-20241022",
134
+ max_tokens: 150,
135
+ system: systemPrompt,
136
+ messages: [{ role: "user", content: "Determine our next protocol move." }]
137
+ });
138
+
139
+ const aiDecision = JSON.parse(msg.content[0].text);
140
+
141
+ // 3. Act on the deterministic JSON response
142
+ if (aiDecision.action === 'accept') {
143
+ console.log("Deal reached!");
144
+ // Proceed to /commit
145
+ } else {
146
+ await core.sendCounter(sessionId, aiDecision.price, aiDecision.message);
147
+ }
148
+ });
149
+ ```
150
+
151
+ ---
152
+
153
+ ## πŸͺ Quickstart: Building a Seller Node
154
+
155
+ `clinch-core` exports the `ClinchSeller` class to make building an Adapter Node or native seller server seamless. It handles dashboard authentication, endpoint registration, and cryptographic signature verification of buyer requests.
156
+
157
+ ```javascript
158
+ import { ClinchSeller } from 'clinch-core';
159
+ import express from 'express';
160
+
161
+ const app = express();
162
+ app.use(express.json());
163
+
164
+ const seller = new ClinchSeller();
165
+
166
+ // Authenticate with your dashboard token and register your endpoint
167
+ await seller.authenticate('your-supabase-seller-jwt');
168
+ await seller.registerEndpoint({
169
+ agent_id: 'amazon.anp',
170
+ display_name: 'Amazon Adapter',
171
+ endpoint: 'https://your-seller-api.com/anp',
172
+ supported_modes: ['ANP/A', 'ANP/C'],
173
+ categories: ['electronics'],
174
+ capabilities: ['price_flex']
175
+ });
176
+
177
+ // Create your counter-offer route
178
+ app.post('/anp/counter', (req, res) => {
179
+ const { session_id, turn, price, reason, buyer_sig } = req.body;
180
+
181
+ // Verify the payload actually came from the buyer who holds the session key
182
+ const isValid = seller.verifyBuyerSignature(
183
+ { session_id, turn, price, reason },
184
+ buyer_sig,
185
+ req.headers['x-buyer-pubkey']
186
+ );
187
+
188
+ if (!isValid) return res.status(401).send("Invalid signature");
189
+
190
+ // Process logic and return standard counter JSON...
191
+ res.json({ action: 'counter', price: 95.00, message: "Best I can do is $95." });
192
+ });
193
+ ```
194
+
195
+ ---
196
+
197
+ ## πŸ“– API Reference
198
+
199
+ ### Buyer Client (`ClinchCore`)
200
+
201
+ #### `new ClinchCore(config)`
202
+ * `config.registryUrl` *(string)*: Override Firebase dynamic routing.
203
+ * `config.timeoutMs` *(number)*: Connection timeout limit (Default: `5000`ms).
204
+
205
+ #### `async initialize(cachedToken?)`
206
+ Authenticates the node, completes Identity-Bound PoW, and connects the WebSocket.
207
+ * `cachedToken` *(string)*: Saved JWT to skip PoW and restore connectivity instantly.
208
+
209
+ #### `async negotiate(address, constraints)`
210
+ Launches a cryptographic session handshake. Returns `sessionId`.
211
+ * `address` *(string)*: e.g. `ANP/A.cloudflare.anp`.
212
+ * `constraints` *(ConstraintVector)*: Must include `max_budget` (number).
213
+
214
+ #### `buildAgentPrompt(sessionId, incomingMessage)`
215
+ 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.
216
+
217
+ #### `async sendCounter(sessionId, price, reason)`
218
+ Signs and dispatches a counter-offer to the seller via the Registry proxy.
219
+
220
+ #### `async exitSession(sessionId)`
221
+ Closes the active connection and generates a single-use re-engagement Callback token.
222
+
223
+ #### `async sandbox(config)`
224
+ Initializes the edge-AI execution context, downloads the GGUF, and auto-listens.
225
+ * `config.downloadLLM` *(boolean)*: Default `true`.
226
+ * `config.maxTurns` *(number)*: Turn limit threshold. Default `6`.
227
+
228
+ ### Seller Client (`ClinchSeller`)
229
+
230
+ #### `async authenticate(authToken)`
231
+ Logs the seller node into the registry using a Dashboard JWT.
232
+
233
+ #### `async registerEndpoint(record)`
234
+ Publishes the seller's DNS-style record to the Registry so buyers can discover and route to it.
235
+
236
+ #### `verifyBuyerSignature(payload, signatureHex, pubKeyHex)`
237
+ Returns `boolean`. Cryptographically verifies that incoming counter-offers were signed by the exact ephemeral session key generated by the buyer during the handshake.
238
+
239
+ ---
240
+
241
+ ## πŸ” Cryptographic Guarantees
242
+ Clinch operates on a strictly zero-trust model.
243
+ 1. **Identity-Bound PoW**: Challenge hashes include the client's `pubKey`, making outsourcing/bot-farming mathematically impossible.
244
+ 2. **Ephemeral Sessions**: `negotiate()` generates an ephemeral Session Key (`nacl.sign.keyPair()`). 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.
245
+ 3. **Anonymity Proxy**: Counter-offers are routed strictly through the Registry. The seller never logs the buyer's IP address.
@@ -0,0 +1,101 @@
1
+ import { EventEmitter } from 'events';
2
+ import nacl from 'tweetnacl';
3
+ export type CoreStatus = 'OFFLINE' | 'CONNECTING' | 'IDLE' | 'RECONNECTING' | 'ERROR' | 'NEGOTIATING' | 'CONVERGED' | 'STALEMATE';
4
+ export interface ParsedAddress {
5
+ mode: string;
6
+ domain: string;
7
+ route: string;
8
+ }
9
+ export interface ClinchConfig {
10
+ registryUrl?: string;
11
+ timeoutMs?: number;
12
+ }
13
+ export interface ConstraintVector {
14
+ intent: string;
15
+ category?: string;
16
+ max_budget: number;
17
+ [key: string]: any;
18
+ }
19
+ export interface SessionState {
20
+ sessionId: string;
21
+ sellerId: string;
22
+ keyPair: nacl.SignKeyPair;
23
+ status: 'ACTIVE' | 'EXITED' | 'CLOSED';
24
+ exitTokenHash?: string;
25
+ constraints: ConstraintVector;
26
+ }
27
+ export interface SandboxConfig {
28
+ downloadLLM?: boolean;
29
+ modelUrl?: string;
30
+ modelPath?: string;
31
+ maxTurns?: number;
32
+ }
33
+ export interface AgentAdapter {
34
+ evaluateOffer(sessionState: any, constraints: any): Promise<any>;
35
+ }
36
+ export declare class ClinchCore extends EventEmitter {
37
+ private config;
38
+ private cachedRegistryUrl;
39
+ status: CoreStatus;
40
+ private reconnectAttempts;
41
+ private maxReconnectDelay;
42
+ jwtToken: string | null;
43
+ private identityPrivKey;
44
+ identityPubKey: string;
45
+ private activeSessions;
46
+ private ws;
47
+ private isSandboxMode;
48
+ private sandboxContext;
49
+ private sandboxSequence;
50
+ private sandboxSession;
51
+ private sandboxMaxTurns;
52
+ currentTurn: number;
53
+ lastKnownPrice: number;
54
+ activeNegotiationId: string | null;
55
+ constructor(config?: ClinchConfig);
56
+ private setStatus;
57
+ initialize(cachedToken?: string): Promise<void>;
58
+ private getRegistryUrl;
59
+ private networkRequest;
60
+ private registerNode;
61
+ private connectWebSocket;
62
+ private handleReconnect;
63
+ disconnect(): void;
64
+ /**
65
+ * Generates a universally formatted System Prompt for external LLMs (Claude, OpenAI, Gemini).
66
+ * Developers can pass this string directly to their AI to ensure protocol-compliant negotiation.
67
+ */
68
+ buildAgentPrompt(sessionId: string, incomingMessage: string): string;
69
+ search(query: string, mode?: string): Promise<any>;
70
+ negotiate(address: string, constraints: ConstraintVector): Promise<string>;
71
+ sendCounter(sessionId: string, price: number, reason: string): Promise<void>;
72
+ exitSession(sessionId: string): Promise<string>;
73
+ sandbox(config?: SandboxConfig): Promise<void>;
74
+ private setupSandbox;
75
+ private handleAutomaticSandboxTurn;
76
+ private sandboxEvaluate;
77
+ private extractPrice;
78
+ parseAddress(address: string): ParsedAddress;
79
+ private solvePoW;
80
+ private hasLeadingZeroBits;
81
+ }
82
+ export interface SellerRecord {
83
+ agent_id: string;
84
+ display_name: string;
85
+ endpoint: string;
86
+ supported_modes: string[];
87
+ categories: string[];
88
+ capabilities: string[];
89
+ }
90
+ export declare class ClinchSeller extends EventEmitter {
91
+ private config;
92
+ private cachedRegistryUrl;
93
+ sellerAuthToken: string | null;
94
+ private identityPrivKey;
95
+ identityPubKey: string;
96
+ constructor(config?: ClinchConfig);
97
+ authenticate(authToken: string): Promise<void>;
98
+ registerEndpoint(record: SellerRecord): Promise<any>;
99
+ verifyBuyerSignature(payload: any, signatureHex: string, buyerSessionPubKeyHex: string): boolean;
100
+ private signData;
101
+ }