@relayplane/proxy 1.8.10 → 1.8.12

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,207 @@
1
+ /**
2
+ * Adaptive Provider Recovery — Phase 2: Mesh Sharing
3
+ *
4
+ * Shares provider recovery/health patterns across proxy instances via the mesh layer.
5
+ * When one instance discovers a provider is down or degraded, other instances learn from it.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import type { RecoveryPattern, RecoveryPatternType, RecoveryPatternStore } from './recovery.js';
10
+ /**
11
+ * A recovery atom shared via the mesh.
12
+ * Contains only non-sensitive pattern data (no tokens, keys, prompts).
13
+ */
14
+ export interface RecoveryAtom {
15
+ /** Unique ID for this atom (deterministic from type+provider+trigger) */
16
+ id: string;
17
+ /** Atom type discriminator for the mesh */
18
+ atomType: 'recovery';
19
+ /** Recovery pattern type */
20
+ type: RecoveryPatternType;
21
+ /** Provider name (e.g., 'anthropic', 'openai') */
22
+ provider: string;
23
+ /** Trigger conditions for this pattern */
24
+ trigger: {
25
+ errorCode: number;
26
+ errorType?: string;
27
+ tokenPrefix?: string;
28
+ model?: string;
29
+ minTokens?: number;
30
+ };
31
+ /** Fix to apply when trigger matches */
32
+ fix: {
33
+ authHeader?: string;
34
+ model?: string;
35
+ timeoutMs?: number;
36
+ provider?: string;
37
+ };
38
+ /** Confidence score 0-1, aggregated across reports */
39
+ confidence: number;
40
+ /** Number of instances that reported this pattern */
41
+ reportCount: number;
42
+ /** Number of confirmed successful applications across instances */
43
+ confirmCount: number;
44
+ /** Number of confirmed failures across instances */
45
+ denyCount: number;
46
+ /** ISO timestamp of first discovery */
47
+ firstSeen: string;
48
+ /** ISO timestamp of last report/confirmation */
49
+ lastSeen: string;
50
+ /** ISO timestamp of last successful confirmation */
51
+ lastConfirmed?: string;
52
+ /** Instance hash that first discovered this pattern */
53
+ originInstance: string;
54
+ /** Version counter for conflict resolution (last-write-wins with merge) */
55
+ version: number;
56
+ }
57
+ /** Result of a mesh recovery sync operation */
58
+ export interface MeshRecoverySyncResult {
59
+ /** Number of patterns pushed to mesh */
60
+ pushed: number;
61
+ /** Number of patterns pulled from mesh */
62
+ pulled: number;
63
+ /** Number of patterns merged (conflict resolved) */
64
+ merged: number;
65
+ /** Number of patterns expired/removed */
66
+ expired: number;
67
+ /** Errors encountered */
68
+ errors: string[];
69
+ /** Timestamp of this sync */
70
+ timestamp: string;
71
+ }
72
+ /** Configuration for mesh recovery sharing */
73
+ export interface MeshRecoveryConfig {
74
+ /** URL of the mesh server */
75
+ meshUrl: string;
76
+ /** API key for mesh authentication */
77
+ apiKey?: string;
78
+ /** Unique hash identifying this proxy instance (anonymous) */
79
+ instanceHash: string;
80
+ /** Minimum local confidence before sharing to mesh (default: 0.7) */
81
+ minShareConfidence: number;
82
+ /** Minimum local success count before sharing (default: 3) */
83
+ minShareSuccessCount: number;
84
+ /** Minimum mesh report count for preemptive application (default: 2) */
85
+ minMeshReportCount: number;
86
+ /** Minimum mesh confidence for preemptive application (default: 0.6) */
87
+ minMeshConfidence: number;
88
+ /** Pattern expiry in days without confirmation (default: 30) */
89
+ expiryDays: number;
90
+ /** Maximum patterns to push per sync (default: 50) */
91
+ maxPushPerSync: number;
92
+ /** Rate limit: minimum seconds between syncs (default: 60) */
93
+ minSyncIntervalSec: number;
94
+ }
95
+ export declare const DEFAULT_MESH_RECOVERY_CONFIG: MeshRecoveryConfig;
96
+ /** Generate a deterministic atom ID from pattern properties using SHA-256 */
97
+ export declare function recoveryAtomId(type: RecoveryPatternType, provider: string, trigger: RecoveryAtom['trigger']): string;
98
+ /** Convert a local RecoveryPattern to a mesh RecoveryAtom */
99
+ export declare function patternToAtom(pattern: RecoveryPattern, instanceHash: string): RecoveryAtom;
100
+ /** Convert a mesh RecoveryAtom to a local RecoveryPattern */
101
+ export declare function atomToPattern(atom: RecoveryAtom): RecoveryPattern;
102
+ /**
103
+ * Merge two recovery atoms with conflict resolution.
104
+ *
105
+ * Strategy: "aggregate-and-recalculate"
106
+ * - Report/confirm/deny counts are summed
107
+ * - Confidence is recalculated from aggregated counts
108
+ * - Timestamps use earliest firstSeen, latest lastSeen
109
+ * - Version incremented
110
+ * - If fixes differ, the one with higher confirmCount wins
111
+ */
112
+ export declare function mergeRecoveryAtoms(local: RecoveryAtom, remote: RecoveryAtom): RecoveryAtom;
113
+ /**
114
+ * Stores recovery atoms for mesh sharing.
115
+ * Separate from the local RecoveryPatternStore to keep mesh vs local concerns clean.
116
+ */
117
+ export declare class MeshRecoveryAtomStore {
118
+ private atoms;
119
+ private readonly expiryDays;
120
+ constructor(expiryDays?: number);
121
+ /** Get all non-expired atoms */
122
+ getAll(): RecoveryAtom[];
123
+ /** Get a specific atom by ID */
124
+ get(id: string): RecoveryAtom | undefined;
125
+ /** Upsert with merge semantics */
126
+ upsert(atom: RecoveryAtom): RecoveryAtom;
127
+ /** Remove an atom */
128
+ remove(id: string): boolean;
129
+ /** Get atoms modified since a timestamp */
130
+ getSince(since: string): RecoveryAtom[];
131
+ /** Record a local confirmation of a mesh pattern */
132
+ recordConfirmation(id: string): void;
133
+ /** Record a local denial of a mesh pattern */
134
+ recordDenial(id: string): void;
135
+ /** Get stats */
136
+ stats(): {
137
+ total: number;
138
+ highConfidence: number;
139
+ avgConfidence: number;
140
+ totalReports: number;
141
+ };
142
+ /** Prune atoms that haven't been seen in expiryDays */
143
+ pruneExpired(): number;
144
+ /** Clear all atoms */
145
+ clear(): void;
146
+ /** Get count */
147
+ get size(): number;
148
+ }
149
+ /**
150
+ * Handles syncing recovery patterns between a local RecoveryPatternStore
151
+ * and the mesh via the mesh server's recovery endpoints.
152
+ */
153
+ export declare class MeshRecoverySync {
154
+ private readonly config;
155
+ private readonly meshStore;
156
+ private lastSyncTimestamp?;
157
+ private lastSyncAt;
158
+ constructor(config: Partial<MeshRecoveryConfig> & {
159
+ meshUrl: string;
160
+ instanceHash: string;
161
+ });
162
+ /** Get the mesh atom store (for testing/inspection) */
163
+ getMeshStore(): MeshRecoveryAtomStore;
164
+ /**
165
+ * Push eligible local patterns to the mesh.
166
+ * Only shares patterns that meet minimum confidence and success count.
167
+ */
168
+ pushPatterns(localStore: RecoveryPatternStore): Promise<{
169
+ pushed: number;
170
+ errors: string[];
171
+ }>;
172
+ /**
173
+ * Pull recovery patterns from the mesh and merge into local store.
174
+ * Applies conflict resolution when patterns overlap.
175
+ */
176
+ pullPatterns(localStore: RecoveryPatternStore): Promise<{
177
+ pulled: number;
178
+ merged: number;
179
+ errors: string[];
180
+ }>;
181
+ /**
182
+ * Full sync: push local patterns, then pull from mesh.
183
+ * Respects rate limiting.
184
+ */
185
+ sync(localStore: RecoveryPatternStore): Promise<MeshRecoverySyncResult>;
186
+ /**
187
+ * Report a local confirmation of a mesh-sourced pattern.
188
+ * Called when a pattern pulled from mesh works locally.
189
+ */
190
+ reportConfirmation(patternId: string): Promise<void>;
191
+ /**
192
+ * Report a local denial of a mesh-sourced pattern.
193
+ * Called when a pattern pulled from mesh fails locally.
194
+ */
195
+ reportDenial(patternId: string): Promise<void>;
196
+ /** Get sync status for dashboard */
197
+ getStatus(): {
198
+ meshStore: ReturnType<MeshRecoveryAtomStore['stats']>;
199
+ lastSync: string | undefined;
200
+ config: {
201
+ meshUrl: string;
202
+ minShareConfidence: number;
203
+ minMeshReportCount: number;
204
+ };
205
+ };
206
+ }
207
+ //# sourceMappingURL=recovery-mesh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-mesh.d.ts","sourceRoot":"","sources":["../src/recovery-mesh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,426 @@
1
+ "use strict";
2
+ /**
3
+ * Adaptive Provider Recovery — Phase 2: Mesh Sharing
4
+ *
5
+ * Shares provider recovery/health patterns across proxy instances via the mesh layer.
6
+ * When one instance discovers a provider is down or degraded, other instances learn from it.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.MeshRecoverySync = exports.MeshRecoveryAtomStore = exports.DEFAULT_MESH_RECOVERY_CONFIG = void 0;
12
+ exports.recoveryAtomId = recoveryAtomId;
13
+ exports.patternToAtom = patternToAtom;
14
+ exports.atomToPattern = atomToPattern;
15
+ exports.mergeRecoveryAtoms = mergeRecoveryAtoms;
16
+ const node_crypto_1 = require("node:crypto");
17
+ exports.DEFAULT_MESH_RECOVERY_CONFIG = {
18
+ meshUrl: '',
19
+ instanceHash: 'unknown',
20
+ minShareConfidence: 0.7,
21
+ minShareSuccessCount: 3,
22
+ minMeshReportCount: 2,
23
+ minMeshConfidence: 0.6,
24
+ expiryDays: 30,
25
+ maxPushPerSync: 50,
26
+ minSyncIntervalSec: 60,
27
+ };
28
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
29
+ /** Generate a deterministic atom ID from pattern properties using SHA-256 */
30
+ function recoveryAtomId(type, provider, trigger) {
31
+ const parts = [type, provider, trigger.errorCode];
32
+ if (trigger.tokenPrefix)
33
+ parts.push(trigger.tokenPrefix);
34
+ if (trigger.model)
35
+ parts.push(trigger.model);
36
+ if (trigger.errorType)
37
+ parts.push(trigger.errorType);
38
+ return `recovery:${(0, node_crypto_1.createHash)('sha256').update(JSON.stringify(parts)).digest('hex').slice(0, 16)}`;
39
+ }
40
+ /** Convert a local RecoveryPattern to a mesh RecoveryAtom */
41
+ function patternToAtom(pattern, instanceHash) {
42
+ return {
43
+ id: recoveryAtomId(pattern.type, pattern.provider, pattern.trigger),
44
+ atomType: 'recovery',
45
+ type: pattern.type,
46
+ provider: pattern.provider,
47
+ trigger: { ...pattern.trigger },
48
+ fix: { ...pattern.fix },
49
+ confidence: pattern.confidence,
50
+ reportCount: 1,
51
+ confirmCount: pattern.successCount,
52
+ denyCount: pattern.failureCount,
53
+ firstSeen: pattern.firstSeen,
54
+ lastSeen: pattern.lastSeen,
55
+ lastConfirmed: pattern.lastApplied,
56
+ originInstance: instanceHash,
57
+ version: 1,
58
+ };
59
+ }
60
+ /** Convert a mesh RecoveryAtom to a local RecoveryPattern */
61
+ function atomToPattern(atom) {
62
+ return {
63
+ id: atom.id,
64
+ type: atom.type,
65
+ provider: atom.provider,
66
+ trigger: { ...atom.trigger },
67
+ fix: { ...atom.fix },
68
+ confidence: atom.confidence,
69
+ successCount: atom.confirmCount,
70
+ failureCount: atom.denyCount,
71
+ firstSeen: atom.firstSeen,
72
+ lastSeen: atom.lastSeen,
73
+ lastApplied: atom.lastConfirmed,
74
+ };
75
+ }
76
+ // ─── Conflict Resolution ──────────────────────────────────────────────────────
77
+ /**
78
+ * Merge two recovery atoms with conflict resolution.
79
+ *
80
+ * Strategy: "aggregate-and-recalculate"
81
+ * - Report/confirm/deny counts are summed
82
+ * - Confidence is recalculated from aggregated counts
83
+ * - Timestamps use earliest firstSeen, latest lastSeen
84
+ * - Version incremented
85
+ * - If fixes differ, the one with higher confirmCount wins
86
+ */
87
+ function mergeRecoveryAtoms(local, remote) {
88
+ // If they're not the same atom, return remote (shouldn't happen but be safe)
89
+ if (local.id !== remote.id)
90
+ return remote;
91
+ // Aggregate counts — but avoid double-counting if this instance already contributed
92
+ // We use Math.max for report counts from the same origin, sum for different origins
93
+ const totalConfirm = Math.max(local.confirmCount, remote.confirmCount);
94
+ const totalDeny = Math.max(local.denyCount, remote.denyCount);
95
+ const totalReports = Math.max(local.reportCount, remote.reportCount);
96
+ // Recalculate confidence from aggregated data
97
+ const totalAttempts = totalConfirm + totalDeny;
98
+ const confidence = totalAttempts > 0 ? totalConfirm / totalAttempts : 0;
99
+ // Use the fix with more confirmations
100
+ const fix = local.confirmCount >= remote.confirmCount ? local.fix : remote.fix;
101
+ return {
102
+ id: local.id,
103
+ atomType: 'recovery',
104
+ type: local.type,
105
+ provider: local.provider,
106
+ trigger: local.trigger,
107
+ fix,
108
+ confidence,
109
+ reportCount: totalReports + (local.originInstance !== remote.originInstance ? 1 : 0),
110
+ confirmCount: totalConfirm,
111
+ denyCount: totalDeny,
112
+ firstSeen: local.firstSeen < remote.firstSeen ? local.firstSeen : remote.firstSeen,
113
+ lastSeen: local.lastSeen > remote.lastSeen ? local.lastSeen : remote.lastSeen,
114
+ lastConfirmed: newerTimestamp(local.lastConfirmed, remote.lastConfirmed),
115
+ originInstance: local.originInstance, // keep local origin
116
+ version: Math.max(local.version, remote.version) + 1,
117
+ };
118
+ }
119
+ function newerTimestamp(a, b) {
120
+ if (!a)
121
+ return b;
122
+ if (!b)
123
+ return a;
124
+ return a > b ? a : b;
125
+ }
126
+ // ─── Mesh Recovery Atom Store ─────────────────────────────────────────────────
127
+ /**
128
+ * Stores recovery atoms for mesh sharing.
129
+ * Separate from the local RecoveryPatternStore to keep mesh vs local concerns clean.
130
+ */
131
+ class MeshRecoveryAtomStore {
132
+ atoms = new Map();
133
+ expiryDays;
134
+ constructor(expiryDays = 30) {
135
+ this.expiryDays = expiryDays;
136
+ }
137
+ /** Get all non-expired atoms */
138
+ getAll() {
139
+ this.pruneExpired();
140
+ return Array.from(this.atoms.values());
141
+ }
142
+ /** Get a specific atom by ID */
143
+ get(id) {
144
+ this.pruneExpired();
145
+ return this.atoms.get(id);
146
+ }
147
+ /** Upsert with merge semantics */
148
+ upsert(atom) {
149
+ const existing = this.atoms.get(atom.id);
150
+ if (existing) {
151
+ const merged = mergeRecoveryAtoms(existing, atom);
152
+ this.atoms.set(atom.id, merged);
153
+ return merged;
154
+ }
155
+ this.atoms.set(atom.id, atom);
156
+ return atom;
157
+ }
158
+ /** Remove an atom */
159
+ remove(id) {
160
+ return this.atoms.delete(id);
161
+ }
162
+ /** Get atoms modified since a timestamp */
163
+ getSince(since) {
164
+ this.pruneExpired();
165
+ return Array.from(this.atoms.values()).filter(a => a.lastSeen > since);
166
+ }
167
+ /** Record a local confirmation of a mesh pattern */
168
+ recordConfirmation(id) {
169
+ const atom = this.atoms.get(id);
170
+ if (atom) {
171
+ atom.confirmCount++;
172
+ atom.confidence = atom.confirmCount / (atom.confirmCount + atom.denyCount);
173
+ atom.lastConfirmed = new Date().toISOString();
174
+ atom.lastSeen = new Date().toISOString();
175
+ atom.version++;
176
+ }
177
+ }
178
+ /** Record a local denial of a mesh pattern */
179
+ recordDenial(id) {
180
+ const atom = this.atoms.get(id);
181
+ if (atom) {
182
+ atom.denyCount++;
183
+ atom.confidence = atom.confirmCount / (atom.confirmCount + atom.denyCount);
184
+ atom.lastSeen = new Date().toISOString();
185
+ atom.version++;
186
+ }
187
+ }
188
+ /** Get stats */
189
+ stats() {
190
+ const all = this.getAll();
191
+ return {
192
+ total: all.length,
193
+ highConfidence: all.filter(a => a.confidence >= 0.8).length,
194
+ avgConfidence: all.length > 0
195
+ ? all.reduce((sum, a) => sum + a.confidence, 0) / all.length
196
+ : 0,
197
+ totalReports: all.reduce((sum, a) => sum + a.reportCount, 0),
198
+ };
199
+ }
200
+ /** Prune atoms that haven't been seen in expiryDays */
201
+ pruneExpired() {
202
+ const cutoff = Date.now() - this.expiryDays * 24 * 60 * 60 * 1000;
203
+ let pruned = 0;
204
+ for (const [key, atom] of this.atoms) {
205
+ const lastActivity = atom.lastConfirmed ?? atom.lastSeen;
206
+ if (new Date(lastActivity).getTime() < cutoff) {
207
+ this.atoms.delete(key);
208
+ pruned++;
209
+ }
210
+ }
211
+ return pruned;
212
+ }
213
+ /** Clear all atoms */
214
+ clear() {
215
+ this.atoms.clear();
216
+ }
217
+ /** Get count */
218
+ get size() {
219
+ return this.atoms.size;
220
+ }
221
+ }
222
+ exports.MeshRecoveryAtomStore = MeshRecoveryAtomStore;
223
+ // ─── Mesh Recovery Sync ───────────────────────────────────────────────────────
224
+ /**
225
+ * Handles syncing recovery patterns between a local RecoveryPatternStore
226
+ * and the mesh via the mesh server's recovery endpoints.
227
+ */
228
+ class MeshRecoverySync {
229
+ config;
230
+ meshStore;
231
+ lastSyncTimestamp;
232
+ lastSyncAt = 0; // unix ms — for rate limiting
233
+ constructor(config) {
234
+ this.config = { ...exports.DEFAULT_MESH_RECOVERY_CONFIG, ...config };
235
+ this.meshStore = new MeshRecoveryAtomStore(this.config.expiryDays);
236
+ }
237
+ /** Get the mesh atom store (for testing/inspection) */
238
+ getMeshStore() {
239
+ return this.meshStore;
240
+ }
241
+ /**
242
+ * Push eligible local patterns to the mesh.
243
+ * Only shares patterns that meet minimum confidence and success count.
244
+ */
245
+ async pushPatterns(localStore) {
246
+ const errors = [];
247
+ const eligible = localStore.getAll().filter(p => p.confidence >= this.config.minShareConfidence &&
248
+ p.successCount >= this.config.minShareSuccessCount);
249
+ if (eligible.length === 0) {
250
+ return { pushed: 0, errors: [] };
251
+ }
252
+ // Convert to atoms and limit
253
+ const atoms = eligible
254
+ .slice(0, this.config.maxPushPerSync)
255
+ .map(p => patternToAtom(p, this.config.instanceHash));
256
+ try {
257
+ const headers = { 'Content-Type': 'application/json' };
258
+ if (this.config.apiKey)
259
+ headers['Authorization'] = `Bearer ${this.config.apiKey}`;
260
+ const res = await fetch(`${this.config.meshUrl}/mesh/recovery/contribute`, {
261
+ method: 'POST',
262
+ headers,
263
+ body: JSON.stringify(atoms),
264
+ });
265
+ if (!res.ok) {
266
+ const errBody = await res.text();
267
+ errors.push(`Push failed: ${res.status} ${errBody}`);
268
+ return { pushed: 0, errors };
269
+ }
270
+ const body = await res.json();
271
+ // Update local mesh store with push results
272
+ for (const atom of atoms) {
273
+ this.meshStore.upsert(atom);
274
+ }
275
+ return { pushed: body.accepted, errors: [] };
276
+ }
277
+ catch (err) {
278
+ errors.push(`Push error: ${err.message}`);
279
+ return { pushed: 0, errors };
280
+ }
281
+ }
282
+ /**
283
+ * Pull recovery patterns from the mesh and merge into local store.
284
+ * Applies conflict resolution when patterns overlap.
285
+ */
286
+ async pullPatterns(localStore) {
287
+ const errors = [];
288
+ try {
289
+ const url = this.lastSyncTimestamp
290
+ ? `${this.config.meshUrl}/mesh/recovery/atoms?since=${encodeURIComponent(this.lastSyncTimestamp)}`
291
+ : `${this.config.meshUrl}/mesh/recovery/atoms`;
292
+ const headers = {};
293
+ if (this.config.apiKey)
294
+ headers['Authorization'] = `Bearer ${this.config.apiKey}`;
295
+ const res = await fetch(url, { headers });
296
+ if (!res.ok) {
297
+ const errBody = await res.text();
298
+ errors.push(`Pull failed: ${res.status} ${errBody}`);
299
+ return { pulled: 0, merged: 0, errors };
300
+ }
301
+ const remoteAtoms = await res.json();
302
+ let pulled = 0;
303
+ let merged = 0;
304
+ for (const remoteAtom of remoteAtoms) {
305
+ // Validate the atom has required fields
306
+ if (!remoteAtom.id || !remoteAtom.type || !remoteAtom.provider)
307
+ continue;
308
+ // Update mesh store (handles merge)
309
+ const existing = this.meshStore.get(remoteAtom.id);
310
+ this.meshStore.upsert(remoteAtom);
311
+ if (existing) {
312
+ merged++;
313
+ }
314
+ else {
315
+ pulled++;
316
+ }
317
+ // Apply to local pattern store if it meets our thresholds
318
+ if (remoteAtom.reportCount >= this.config.minMeshReportCount &&
319
+ remoteAtom.confidence >= this.config.minMeshConfidence) {
320
+ const localPattern = atomToPattern(remoteAtom);
321
+ localStore.upsert(localPattern);
322
+ }
323
+ }
324
+ this.lastSyncTimestamp = new Date().toISOString();
325
+ return { pulled, merged, errors: [] };
326
+ }
327
+ catch (err) {
328
+ errors.push(`Pull error: ${err.message}`);
329
+ return { pulled: 0, merged: 0, errors };
330
+ }
331
+ }
332
+ /**
333
+ * Full sync: push local patterns, then pull from mesh.
334
+ * Respects rate limiting.
335
+ */
336
+ async sync(localStore) {
337
+ const now = Date.now();
338
+ const minInterval = this.config.minSyncIntervalSec * 1000;
339
+ if (now - this.lastSyncAt < minInterval) {
340
+ return {
341
+ pushed: 0,
342
+ pulled: 0,
343
+ merged: 0,
344
+ expired: 0,
345
+ errors: ['Rate limited: sync too frequent'],
346
+ timestamp: new Date().toISOString(),
347
+ };
348
+ }
349
+ this.lastSyncAt = now;
350
+ const pushResult = await this.pushPatterns(localStore);
351
+ const pullResult = await this.pullPatterns(localStore);
352
+ // Prune expired patterns
353
+ const expired = this.meshStore.pruneExpired();
354
+ return {
355
+ pushed: pushResult.pushed,
356
+ pulled: pullResult.pulled,
357
+ merged: pullResult.merged,
358
+ expired,
359
+ errors: [...pushResult.errors, ...pullResult.errors],
360
+ timestamp: new Date().toISOString(),
361
+ };
362
+ }
363
+ /**
364
+ * Report a local confirmation of a mesh-sourced pattern.
365
+ * Called when a pattern pulled from mesh works locally.
366
+ */
367
+ async reportConfirmation(patternId) {
368
+ this.meshStore.recordConfirmation(patternId);
369
+ // Asynchronously report to mesh (best effort)
370
+ try {
371
+ const headers = { 'Content-Type': 'application/json' };
372
+ if (this.config.apiKey)
373
+ headers['Authorization'] = `Bearer ${this.config.apiKey}`;
374
+ await fetch(`${this.config.meshUrl}/mesh/recovery/confirm`, {
375
+ method: 'POST',
376
+ headers,
377
+ body: JSON.stringify({
378
+ patternId,
379
+ instanceHash: this.config.instanceHash,
380
+ success: true,
381
+ }),
382
+ });
383
+ }
384
+ catch {
385
+ // Best effort — don't fail on confirmation report
386
+ }
387
+ }
388
+ /**
389
+ * Report a local denial of a mesh-sourced pattern.
390
+ * Called when a pattern pulled from mesh fails locally.
391
+ */
392
+ async reportDenial(patternId) {
393
+ this.meshStore.recordDenial(patternId);
394
+ try {
395
+ const headers = { 'Content-Type': 'application/json' };
396
+ if (this.config.apiKey)
397
+ headers['Authorization'] = `Bearer ${this.config.apiKey}`;
398
+ await fetch(`${this.config.meshUrl}/mesh/recovery/confirm`, {
399
+ method: 'POST',
400
+ headers,
401
+ body: JSON.stringify({
402
+ patternId,
403
+ instanceHash: this.config.instanceHash,
404
+ success: false,
405
+ }),
406
+ });
407
+ }
408
+ catch {
409
+ // Best effort
410
+ }
411
+ }
412
+ /** Get sync status for dashboard */
413
+ getStatus() {
414
+ return {
415
+ meshStore: this.meshStore.stats(),
416
+ lastSync: this.lastSyncTimestamp,
417
+ config: {
418
+ meshUrl: this.config.meshUrl,
419
+ minShareConfidence: this.config.minShareConfidence,
420
+ minMeshReportCount: this.config.minMeshReportCount,
421
+ },
422
+ };
423
+ }
424
+ }
425
+ exports.MeshRecoverySync = MeshRecoverySync;
426
+ //# sourceMappingURL=recovery-mesh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-mesh.js","sourceRoot":"","sources":["../src/recovery-mesh.ts"],"names":[],"mappings":"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"}