@kya-os/mcp-i 1.4.0 → 1.5.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.
- package/dist/runtime/auth-handshake.d.ts +144 -0
- package/dist/runtime/auth-handshake.js +254 -0
- package/dist/runtime/delegation-verifier-agentshield.d.ts +64 -0
- package/dist/runtime/delegation-verifier-agentshield.js +301 -0
- package/dist/runtime/delegation-verifier-kv.d.ts +51 -0
- package/dist/runtime/delegation-verifier-kv.js +280 -0
- package/dist/runtime/delegation-verifier-memory.d.ts +50 -0
- package/dist/runtime/delegation-verifier-memory.js +128 -0
- package/dist/runtime/delegation-verifier.d.ts +133 -0
- package/dist/runtime/delegation-verifier.js +107 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.js +24 -1
- package/dist/runtime/mcpi-runtime.d.ts +31 -1
- package/dist/runtime/mcpi-runtime.js +46 -1
- package/dist/runtime/proof-batch-queue.d.ts +117 -0
- package/dist/runtime/proof-batch-queue.js +257 -0
- package/package.json +1 -1
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Proof Batch Queue
|
|
4
|
+
*
|
|
5
|
+
* Collects proofs in memory and submits them in batches to KTA and AgentShield.
|
|
6
|
+
* This prevents blocking tool execution while ensuring proofs are eventually submitted.
|
|
7
|
+
*
|
|
8
|
+
* Performance:
|
|
9
|
+
* - Batch size: 10 proofs (configurable)
|
|
10
|
+
* - Flush interval: 5 seconds (configurable)
|
|
11
|
+
* - Fire-and-forget submission (doesn't block tool execution)
|
|
12
|
+
*
|
|
13
|
+
* Retry Strategy:
|
|
14
|
+
* - Exponential backoff: 1s, 2s, 4s, 8s, 16s
|
|
15
|
+
* - Max retries: 5
|
|
16
|
+
* - Failed proofs logged and dropped after max retries
|
|
17
|
+
*
|
|
18
|
+
* Related: PHASE_1_XMCP_I_SERVER.md Epic 3 (Proof Batching)
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.ProofBatchQueue = exports.AgentShieldProofDestination = exports.KTAProofDestination = void 0;
|
|
22
|
+
exports.createProofBatchQueue = createProofBatchQueue;
|
|
23
|
+
/**
|
|
24
|
+
* KTA proof submission destination
|
|
25
|
+
*/
|
|
26
|
+
class KTAProofDestination {
|
|
27
|
+
name = 'KTA';
|
|
28
|
+
apiUrl;
|
|
29
|
+
apiKey;
|
|
30
|
+
constructor(apiUrl, apiKey) {
|
|
31
|
+
this.apiUrl = apiUrl.replace(/\/$/, '');
|
|
32
|
+
this.apiKey = apiKey;
|
|
33
|
+
}
|
|
34
|
+
async submit(proofs) {
|
|
35
|
+
const headers = {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
};
|
|
38
|
+
if (this.apiKey) {
|
|
39
|
+
headers['X-API-Key'] = this.apiKey;
|
|
40
|
+
}
|
|
41
|
+
const response = await fetch(`${this.apiUrl}/api/v1/proofs/batch`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers,
|
|
44
|
+
body: JSON.stringify({ proofs }),
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error(`KTA proof submission failed: ${response.status} ${response.statusText}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.KTAProofDestination = KTAProofDestination;
|
|
52
|
+
/**
|
|
53
|
+
* AgentShield proof submission destination
|
|
54
|
+
*/
|
|
55
|
+
class AgentShieldProofDestination {
|
|
56
|
+
name = 'AgentShield';
|
|
57
|
+
apiUrl;
|
|
58
|
+
apiKey;
|
|
59
|
+
constructor(apiUrl, apiKey) {
|
|
60
|
+
this.apiUrl = apiUrl.replace(/\/$/, '');
|
|
61
|
+
this.apiKey = apiKey;
|
|
62
|
+
}
|
|
63
|
+
async submit(proofs) {
|
|
64
|
+
const response = await fetch(`${this.apiUrl}/api/v1/proofs/batch`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
'X-API-Key': this.apiKey,
|
|
69
|
+
},
|
|
70
|
+
body: JSON.stringify({ proofs }),
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(`AgentShield proof submission failed: ${response.status} ${response.statusText}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.AgentShieldProofDestination = AgentShieldProofDestination;
|
|
78
|
+
/**
|
|
79
|
+
* Proof Batch Queue
|
|
80
|
+
*
|
|
81
|
+
* Collects proofs and submits them in batches to multiple destinations
|
|
82
|
+
*/
|
|
83
|
+
class ProofBatchQueue {
|
|
84
|
+
queue = [];
|
|
85
|
+
pendingBatches = [];
|
|
86
|
+
config;
|
|
87
|
+
flushTimer;
|
|
88
|
+
retryTimer;
|
|
89
|
+
closed = false;
|
|
90
|
+
// Stats
|
|
91
|
+
stats = {
|
|
92
|
+
queued: 0,
|
|
93
|
+
submitted: 0,
|
|
94
|
+
failed: 0,
|
|
95
|
+
batchesSubmitted: 0,
|
|
96
|
+
};
|
|
97
|
+
constructor(config) {
|
|
98
|
+
this.config = {
|
|
99
|
+
destinations: config.destinations,
|
|
100
|
+
maxBatchSize: config.maxBatchSize || 10,
|
|
101
|
+
flushIntervalMs: config.flushIntervalMs || 5000,
|
|
102
|
+
maxRetries: config.maxRetries || 5,
|
|
103
|
+
debug: config.debug || false,
|
|
104
|
+
};
|
|
105
|
+
// Start flush timer
|
|
106
|
+
this.startFlushTimer();
|
|
107
|
+
// Start retry timer (check every second)
|
|
108
|
+
this.startRetryTimer();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Add proof to queue
|
|
112
|
+
*/
|
|
113
|
+
enqueue(proof) {
|
|
114
|
+
if (this.closed) {
|
|
115
|
+
console.warn('[ProofBatchQueue] Queue is closed, dropping proof');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.queue.push(proof);
|
|
119
|
+
this.stats.queued++;
|
|
120
|
+
if (this.config.debug) {
|
|
121
|
+
console.log(`[ProofBatchQueue] Enqueued proof (queue size: ${this.queue.length})`);
|
|
122
|
+
}
|
|
123
|
+
// Flush immediately if batch size reached
|
|
124
|
+
if (this.queue.length >= this.config.maxBatchSize) {
|
|
125
|
+
this.flush();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Flush queue immediately (submit all queued proofs)
|
|
130
|
+
*/
|
|
131
|
+
async flush() {
|
|
132
|
+
if (this.queue.length === 0) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const proofs = this.queue.splice(0, this.config.maxBatchSize);
|
|
136
|
+
if (this.config.debug) {
|
|
137
|
+
console.log(`[ProofBatchQueue] Flushing ${proofs.length} proofs to ${this.config.destinations.length} destinations`);
|
|
138
|
+
}
|
|
139
|
+
// Submit to each destination (fire-and-forget)
|
|
140
|
+
for (const destination of this.config.destinations) {
|
|
141
|
+
const batch = {
|
|
142
|
+
proofs,
|
|
143
|
+
destination,
|
|
144
|
+
retryCount: 0,
|
|
145
|
+
};
|
|
146
|
+
this.submitBatch(batch); // Fire-and-forget
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Submit batch to destination (with retries)
|
|
151
|
+
*/
|
|
152
|
+
async submitBatch(batch) {
|
|
153
|
+
try {
|
|
154
|
+
await batch.destination.submit(batch.proofs);
|
|
155
|
+
this.stats.submitted += batch.proofs.length;
|
|
156
|
+
this.stats.batchesSubmitted++;
|
|
157
|
+
if (this.config.debug) {
|
|
158
|
+
console.log(`[ProofBatchQueue] Successfully submitted ${batch.proofs.length} proofs to ${batch.destination.name}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error(`[ProofBatchQueue] Failed to submit to ${batch.destination.name}:`, error);
|
|
163
|
+
// Retry with exponential backoff
|
|
164
|
+
if (batch.retryCount < this.config.maxRetries) {
|
|
165
|
+
batch.retryCount++;
|
|
166
|
+
const backoffMs = Math.min(1000 * Math.pow(2, batch.retryCount - 1), 16000);
|
|
167
|
+
batch.nextRetryAt = Date.now() + backoffMs;
|
|
168
|
+
this.pendingBatches.push(batch);
|
|
169
|
+
if (this.config.debug) {
|
|
170
|
+
console.log(`[ProofBatchQueue] Scheduling retry ${batch.retryCount}/${this.config.maxRetries} in ${backoffMs}ms`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Max retries exceeded, drop batch
|
|
175
|
+
this.stats.failed += batch.proofs.length;
|
|
176
|
+
console.error(`[ProofBatchQueue] Max retries exceeded for ${batch.destination.name}, dropping ${batch.proofs.length} proofs`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Start flush timer
|
|
182
|
+
*/
|
|
183
|
+
startFlushTimer() {
|
|
184
|
+
this.flushTimer = setInterval(() => {
|
|
185
|
+
if (this.queue.length > 0) {
|
|
186
|
+
this.flush();
|
|
187
|
+
}
|
|
188
|
+
}, this.config.flushIntervalMs);
|
|
189
|
+
// Prevent timer from keeping process alive
|
|
190
|
+
if (typeof this.flushTimer.unref === 'function') {
|
|
191
|
+
this.flushTimer.unref();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Start retry timer
|
|
196
|
+
*/
|
|
197
|
+
startRetryTimer() {
|
|
198
|
+
this.retryTimer = setInterval(() => {
|
|
199
|
+
const now = Date.now();
|
|
200
|
+
// Find batches ready for retry
|
|
201
|
+
const retryBatches = this.pendingBatches.filter((batch) => batch.nextRetryAt && batch.nextRetryAt <= now);
|
|
202
|
+
if (retryBatches.length > 0) {
|
|
203
|
+
// Remove from pending
|
|
204
|
+
this.pendingBatches = this.pendingBatches.filter((batch) => !retryBatches.includes(batch));
|
|
205
|
+
// Retry each batch
|
|
206
|
+
for (const batch of retryBatches) {
|
|
207
|
+
this.submitBatch(batch); // Fire-and-forget
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}, 1000);
|
|
211
|
+
// Prevent timer from keeping process alive
|
|
212
|
+
if (typeof this.retryTimer.unref === 'function') {
|
|
213
|
+
this.retryTimer.unref();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Close queue and flush remaining proofs
|
|
218
|
+
*/
|
|
219
|
+
async close() {
|
|
220
|
+
this.closed = true;
|
|
221
|
+
// Clear timers
|
|
222
|
+
if (this.flushTimer) {
|
|
223
|
+
clearInterval(this.flushTimer);
|
|
224
|
+
}
|
|
225
|
+
if (this.retryTimer) {
|
|
226
|
+
clearInterval(this.retryTimer);
|
|
227
|
+
}
|
|
228
|
+
// Flush remaining proofs
|
|
229
|
+
await this.flush();
|
|
230
|
+
// Wait for pending retries (with timeout)
|
|
231
|
+
const maxWaitMs = 30000; // 30 seconds
|
|
232
|
+
const startTime = Date.now();
|
|
233
|
+
while (this.pendingBatches.length > 0 && Date.now() - startTime < maxWaitMs) {
|
|
234
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
235
|
+
}
|
|
236
|
+
if (this.pendingBatches.length > 0) {
|
|
237
|
+
console.warn(`[ProofBatchQueue] Closing with ${this.pendingBatches.length} pending batches (timed out)`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get queue statistics
|
|
242
|
+
*/
|
|
243
|
+
getStats() {
|
|
244
|
+
return {
|
|
245
|
+
...this.stats,
|
|
246
|
+
queueSize: this.queue.length,
|
|
247
|
+
pendingBatches: this.pendingBatches.length,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.ProofBatchQueue = ProofBatchQueue;
|
|
252
|
+
/**
|
|
253
|
+
* Create proof batch queue from config
|
|
254
|
+
*/
|
|
255
|
+
function createProofBatchQueue(config) {
|
|
256
|
+
return new ProofBatchQueue(config);
|
|
257
|
+
}
|