@prismer/sdk 1.7.1 → 1.7.3

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/index.mjs CHANGED
@@ -196,10 +196,11 @@ var RealtimeWSClient = class extends TypedEmitter {
196
196
  joinConversation(conversationId) {
197
197
  this.sendRaw({ type: "conversation.join", payload: { conversationId } });
198
198
  }
199
- sendMessage(conversationId, content, type = "text") {
199
+ sendMessage(conversationId, content, options) {
200
+ const opts = typeof options === "string" ? { type: options } : options;
200
201
  this.sendRaw({
201
202
  type: "message.send",
202
- payload: { conversationId, content, type },
203
+ payload: { conversationId, content, type: opts?.type ?? "text", ...opts?.metadata ? { metadata: opts.metadata } : {}, ...opts?.parentId ? { parentId: opts.parentId } : {} },
203
204
  requestId: `msg-${++this.pingCounter}`
204
205
  });
205
206
  }
@@ -2267,6 +2268,548 @@ function base64ToArrayBuffer(base64) {
2267
2268
  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
2268
2269
  }
2269
2270
 
2271
+ // src/encryption-pipeline.ts
2272
+ async function encryptForSend(e2e, conversationId, content, metadata) {
2273
+ if (!e2e.hasSessionKey(conversationId)) {
2274
+ return { content, metadata: metadata ?? {} };
2275
+ }
2276
+ const ciphertext = await e2e.encrypt(conversationId, content);
2277
+ return {
2278
+ content: ciphertext,
2279
+ metadata: { ...metadata, encrypted: true, encKeyId: `conv-${conversationId}` }
2280
+ };
2281
+ }
2282
+ async function decryptOnReceive(e2e, conversationId, content, metadata) {
2283
+ if (!metadata?.encrypted) {
2284
+ return { content, decrypted: false };
2285
+ }
2286
+ if (!e2e.hasSessionKey(conversationId)) {
2287
+ return { content, decrypted: false, error: "no_session_key" };
2288
+ }
2289
+ try {
2290
+ const plain = await e2e.decrypt(conversationId, content);
2291
+ return { content: plain, decrypted: true };
2292
+ } catch (err) {
2293
+ const message = err instanceof Error ? err.message : String(err);
2294
+ return { content, decrypted: false, error: message };
2295
+ }
2296
+ }
2297
+ async function encryptFile(e2e, conversationId, data) {
2298
+ if (!e2e.hasSessionKey(conversationId)) return null;
2299
+ const b64 = typeof Buffer !== "undefined" ? Buffer.from(data).toString("base64") : uint8ArrayToBase64(data);
2300
+ const ciphertext = await e2e.encrypt(conversationId, b64);
2301
+ return {
2302
+ data: ciphertext,
2303
+ metadata: { encrypted: true, encKeyId: `conv-${conversationId}` }
2304
+ };
2305
+ }
2306
+ async function decryptFile(e2e, conversationId, ciphertext) {
2307
+ if (!e2e.hasSessionKey(conversationId)) return null;
2308
+ try {
2309
+ const b64 = await e2e.decrypt(conversationId, ciphertext);
2310
+ if (typeof Buffer !== "undefined") {
2311
+ return new Uint8Array(Buffer.from(b64, "base64"));
2312
+ }
2313
+ return base64ToUint8Array(b64);
2314
+ } catch {
2315
+ return null;
2316
+ }
2317
+ }
2318
+ async function encryptContext(e2e, content, contextId = "context-cache") {
2319
+ if (!e2e.hasSessionKey(contextId)) return null;
2320
+ const ciphertext = await e2e.encrypt(contextId, content);
2321
+ return { content: ciphertext, encrypted: true };
2322
+ }
2323
+ async function decryptContext(e2e, ciphertext, contextId = "context-cache") {
2324
+ if (!e2e.hasSessionKey(contextId)) return null;
2325
+ try {
2326
+ return await e2e.decrypt(contextId, ciphertext);
2327
+ } catch {
2328
+ return null;
2329
+ }
2330
+ }
2331
+ async function decryptMessages(e2e, messages, conversationId) {
2332
+ let decryptedCount = 0;
2333
+ const errors = [];
2334
+ for (let i = 0; i < messages.length; i++) {
2335
+ const msg = messages[i];
2336
+ const convId = conversationId ?? msg.conversationId;
2337
+ if (!convId) continue;
2338
+ const result = await decryptOnReceive(e2e, convId, msg.content, msg.metadata);
2339
+ if (result.decrypted) {
2340
+ msg.content = result.content;
2341
+ if (msg.metadata) {
2342
+ msg.metadata._decrypted = true;
2343
+ }
2344
+ decryptedCount++;
2345
+ } else if (result.error) {
2346
+ errors.push({ index: i, error: result.error });
2347
+ }
2348
+ }
2349
+ return { decryptedCount, errors };
2350
+ }
2351
+ function uint8ArrayToBase64(bytes) {
2352
+ let binary = "";
2353
+ for (let i = 0; i < bytes.length; i++) {
2354
+ binary += String.fromCharCode(bytes[i]);
2355
+ }
2356
+ return btoa(binary);
2357
+ }
2358
+ function base64ToUint8Array(b64) {
2359
+ const binary = atob(b64);
2360
+ const bytes = new Uint8Array(binary.length);
2361
+ for (let i = 0; i < binary.length; i++) {
2362
+ bytes[i] = binary.charCodeAt(i);
2363
+ }
2364
+ return bytes;
2365
+ }
2366
+
2367
+ // src/evolution-cache.ts
2368
+ var EvolutionCache = class {
2369
+ constructor() {
2370
+ this._genes = /* @__PURE__ */ new Map();
2371
+ this._edges = /* @__PURE__ */ new Map();
2372
+ // key = signal_key
2373
+ this._globalPrior = /* @__PURE__ */ new Map();
2374
+ this._cursor = 0;
2375
+ }
2376
+ get cursor() {
2377
+ return this._cursor;
2378
+ }
2379
+ get geneCount() {
2380
+ return this._genes.size;
2381
+ }
2382
+ /** Load from a full snapshot */
2383
+ loadSnapshot(snapshot) {
2384
+ this._genes.clear();
2385
+ this._edges.clear();
2386
+ this._globalPrior.clear();
2387
+ for (const gene of snapshot.genes) {
2388
+ this._genes.set(gene.id, gene);
2389
+ }
2390
+ for (const edge of snapshot.edges) {
2391
+ const list = this._edges.get(edge.signal_key) ?? [];
2392
+ list.push(edge);
2393
+ this._edges.set(edge.signal_key, list);
2394
+ }
2395
+ for (const [key, val] of Object.entries(snapshot.globalPrior)) {
2396
+ this._globalPrior.set(key, val);
2397
+ }
2398
+ this._cursor = snapshot.cursor;
2399
+ }
2400
+ /** Apply incremental delta (alias: loadDelta) */
2401
+ applyDelta(delta) {
2402
+ const pulled = delta.pulled;
2403
+ for (const gene of pulled.genes) {
2404
+ this._genes.set(gene.id, gene);
2405
+ }
2406
+ for (const id of pulled.quarantines) {
2407
+ this._genes.delete(id);
2408
+ }
2409
+ for (const edge of pulled.edges) {
2410
+ const list = this._edges.get(edge.signal_key) ?? [];
2411
+ const idx = list.findIndex((e) => e.gene_id === edge.gene_id);
2412
+ if (idx >= 0) list[idx] = edge;
2413
+ else list.push(edge);
2414
+ this._edges.set(edge.signal_key, list);
2415
+ }
2416
+ for (const [key, val] of Object.entries(pulled.globalPrior)) {
2417
+ this._globalPrior.set(key, val);
2418
+ }
2419
+ this._cursor = pulled.cursor;
2420
+ }
2421
+ /** Apply incremental delta (alias for applyDelta) */
2422
+ loadDelta(delta) {
2423
+ this.applyDelta(delta);
2424
+ }
2425
+ /** Select best gene locally using Thompson Sampling — pure CPU, <1ms */
2426
+ selectGene(signals) {
2427
+ if (this._genes.size === 0) {
2428
+ return { action: "none", confidence: 0, reason: "no genes in cache", fromCache: true };
2429
+ }
2430
+ const signalKeys = signals.map((s) => s.type);
2431
+ const candidates = [];
2432
+ for (const gene of this._genes.values()) {
2433
+ if (gene.visibility === "quarantined") continue;
2434
+ const geneSignalTypes = (gene.signals_match || []).map(
2435
+ (s) => typeof s === "string" ? s : s.type
2436
+ );
2437
+ if (geneSignalTypes.length === 0) continue;
2438
+ const matchCount = signalKeys.filter((k) => geneSignalTypes.includes(k)).length;
2439
+ const coverageScore = matchCount / geneSignalTypes.length;
2440
+ if (coverageScore === 0) continue;
2441
+ let alpha = gene.success_count + 1;
2442
+ let beta = gene.failure_count + 1;
2443
+ for (const key of signalKeys) {
2444
+ const prior = this._globalPrior.get(key);
2445
+ if (prior) {
2446
+ alpha += 0.3 * prior.alpha;
2447
+ beta += 0.3 * prior.beta;
2448
+ }
2449
+ }
2450
+ const sampledScore = alpha / (alpha + beta);
2451
+ const totalObs = gene.success_count + gene.failure_count;
2452
+ if (totalObs >= 10 && gene.success_count / totalObs < 0.18) continue;
2453
+ const rankScore = coverageScore * 0.4 + sampledScore * 0.6;
2454
+ candidates.push({ gene, rankScore, coverageScore, sampledScore });
2455
+ }
2456
+ if (candidates.length === 0) {
2457
+ return {
2458
+ action: "create_suggested",
2459
+ confidence: 0,
2460
+ reason: "no matching genes for signals",
2461
+ fromCache: true
2462
+ };
2463
+ }
2464
+ candidates.sort((a, b) => b.rankScore - a.rankScore);
2465
+ const best = candidates[0];
2466
+ const alternatives = candidates.slice(1, 4).map((c) => ({
2467
+ gene_id: c.gene.id,
2468
+ confidence: Math.round(c.rankScore * 100) / 100,
2469
+ title: c.gene.title
2470
+ }));
2471
+ return {
2472
+ action: "apply_gene",
2473
+ gene_id: best.gene.id,
2474
+ gene: best.gene,
2475
+ strategy: best.gene.strategy,
2476
+ confidence: Math.round(best.rankScore * 100) / 100,
2477
+ coverageScore: Math.round(best.coverageScore * 100) / 100,
2478
+ alternatives,
2479
+ reason: `local cache selection (${this._genes.size} genes)`,
2480
+ fromCache: true
2481
+ };
2482
+ }
2483
+ };
2484
+
2485
+ // src/signal-enrichment.ts
2486
+ var ERROR_PATTERNS = [
2487
+ { pattern: /timeout|timed?\s*out|deadline\s*exceeded|context\s*deadline/i, type: "timeout" },
2488
+ { pattern: /econnrefused|connection\s*refused/i, type: "connection_refused" },
2489
+ { pattern: /enotfound|dns|getaddrinfo|resolve/i, type: "dns_error" },
2490
+ { pattern: /rate\s*limit|too\s*many\s*requests|429/i, type: "rate_limit" },
2491
+ { pattern: /401|unauthorized|unauthenticated|auth.*fail/i, type: "auth_error" },
2492
+ { pattern: /403|forbidden|access\s*denied|permission/i, type: "permission_error" },
2493
+ { pattern: /404|not\s*found/i, type: "not_found" },
2494
+ { pattern: /5\d{2}|internal\s*server|server\s*error|502|503|504/i, type: "server_error" },
2495
+ { pattern: /type\s*error|typeerror/i, type: "type_error" },
2496
+ { pattern: /syntax\s*error|syntaxerror|unexpected\s*token/i, type: "syntax_error" },
2497
+ { pattern: /reference\s*error|referenceerror|is\s*not\s*defined/i, type: "reference_error" },
2498
+ { pattern: /out\s*of\s*memory|oom|heap|allocation\s*failed/i, type: "oom" },
2499
+ { pattern: /crash|panic|segfault|sigsegv|sigabrt/i, type: "crash" },
2500
+ { pattern: /quota|limit\s*exceeded|insufficient/i, type: "quota_exceeded" },
2501
+ { pattern: /tls|ssl|certificate|cert\s*verify/i, type: "tls_error" },
2502
+ { pattern: /deadlock|lock\s*timeout|lock\s*wait/i, type: "deadlock" }
2503
+ ];
2504
+ function extractSignals(ctx) {
2505
+ const tags = [];
2506
+ if (ctx.error) {
2507
+ let matched = false;
2508
+ for (const { pattern, type } of ERROR_PATTERNS) {
2509
+ if (pattern.test(ctx.error)) {
2510
+ const tag = { type: `error:${type}` };
2511
+ if (ctx.provider) tag.provider = ctx.provider;
2512
+ if (ctx.stage) tag.stage = ctx.stage;
2513
+ if (ctx.severity) tag.severity = ctx.severity;
2514
+ tags.push(tag);
2515
+ matched = true;
2516
+ break;
2517
+ }
2518
+ }
2519
+ if (!matched) {
2520
+ const normalized = ctx.error.slice(0, 50).toLowerCase().replace(/[^a-z0-9_]/g, "_");
2521
+ const tag = { type: `error:${normalized}` };
2522
+ if (ctx.provider) tag.provider = ctx.provider;
2523
+ if (ctx.stage) tag.stage = ctx.stage;
2524
+ tags.push(tag);
2525
+ }
2526
+ }
2527
+ if (ctx.taskStatus === "failed") tags.push({ type: "task.failed" });
2528
+ if (ctx.taskStatus === "completed") tags.push({ type: "task.completed" });
2529
+ if (ctx.taskCapability) {
2530
+ tags.push({ type: `capability:${ctx.taskCapability}` });
2531
+ }
2532
+ if (ctx.tags) {
2533
+ for (const tag of ctx.tags) {
2534
+ tags.push({ type: tag });
2535
+ }
2536
+ }
2537
+ return tags;
2538
+ }
2539
+ function createEnrichedExtractor(config) {
2540
+ if (config.mode === "rules") {
2541
+ return async (ctx) => extractSignals(ctx);
2542
+ }
2543
+ const { llmExtract, timeoutMs = 3e3 } = config;
2544
+ if (!llmExtract) return async (ctx) => extractSignals(ctx);
2545
+ return async (ctx) => {
2546
+ try {
2547
+ const result = await Promise.race([
2548
+ llmExtract(ctx),
2549
+ new Promise(
2550
+ (_, reject) => setTimeout(() => reject(new Error("llm_timeout")), timeoutMs)
2551
+ )
2552
+ ]);
2553
+ return result;
2554
+ } catch {
2555
+ return extractSignals(ctx);
2556
+ }
2557
+ };
2558
+ }
2559
+
2560
+ // src/evolution-runtime.ts
2561
+ var EvolutionRuntime = class {
2562
+ constructor(client, config) {
2563
+ this.client = client;
2564
+ this.outbox = [];
2565
+ this.started = false;
2566
+ // Session tracking
2567
+ this._sessions = [];
2568
+ this._sessionCounter = 0;
2569
+ this.config = {
2570
+ syncIntervalMs: config?.syncIntervalMs ?? 6e4,
2571
+ enrichment: config?.enrichment ?? { mode: "rules" },
2572
+ scope: config?.scope ?? "global",
2573
+ outboxMaxSize: config?.outboxMaxSize ?? 50,
2574
+ outboxFlushMs: config?.outboxFlushMs ?? 5e3
2575
+ };
2576
+ this.scope = this.config.scope;
2577
+ this.cache = new EvolutionCache();
2578
+ this.enricher = config?.enrichment ? createEnrichedExtractor(config.enrichment) : async (ctx) => extractSignals(ctx);
2579
+ }
2580
+ // ─── Lifecycle ──────────────────────────────────────
2581
+ /** Initialize: load snapshot + start sync + start outbox flush */
2582
+ async start() {
2583
+ if (this.started) return;
2584
+ this.started = true;
2585
+ try {
2586
+ const snapshot = await this.client.getSyncSnapshot(0);
2587
+ if (snapshot.data) {
2588
+ this.cache.loadSnapshot(snapshot.data);
2589
+ }
2590
+ } catch {
2591
+ }
2592
+ if (this.config.syncIntervalMs > 0) {
2593
+ this.syncTimer = setInterval(() => this.sync(), this.config.syncIntervalMs);
2594
+ }
2595
+ this.flushTimer = setInterval(() => this.flush(), this.config.outboxFlushMs);
2596
+ }
2597
+ /** Stop: clear timers + flush remaining outbox */
2598
+ async stop() {
2599
+ if (this.syncTimer) clearInterval(this.syncTimer);
2600
+ if (this.flushTimer) clearInterval(this.flushTimer);
2601
+ await this.flush();
2602
+ this.started = false;
2603
+ }
2604
+ // ─── High-Level API ─────────────────────────────────
2605
+ /**
2606
+ * Get a strategy recommendation for an error/context.
2607
+ *
2608
+ * Flow: extract signals → try local cache (<1ms) → fallback to server (~30ms)
2609
+ *
2610
+ * @param error - Error message or Error object
2611
+ * @param context - Optional additional context (provider, stage, etc.)
2612
+ */
2613
+ async suggest(error, context) {
2614
+ const errorStr = error instanceof Error ? error.message : error;
2615
+ const ctx = {
2616
+ error: errorStr,
2617
+ ...context
2618
+ };
2619
+ const signals = await this.enricher(ctx);
2620
+ if (signals.length === 0) {
2621
+ return {
2622
+ action: "none",
2623
+ confidence: 0,
2624
+ signals: [],
2625
+ fromCache: false,
2626
+ reason: "no signals extracted from error"
2627
+ };
2628
+ }
2629
+ const buildSuggestion = (action, geneId, gene, strategy, confidence, fromCache, reason, alternatives) => {
2630
+ this.lastSuggestedGeneId = geneId;
2631
+ this._activeSession = {
2632
+ id: `ses_${++this._sessionCounter}_${Date.now()}`,
2633
+ suggestedAt: Date.now(),
2634
+ suggestedGeneId: geneId,
2635
+ signals,
2636
+ adopted: false,
2637
+ confidence,
2638
+ fromCache
2639
+ };
2640
+ return {
2641
+ action,
2642
+ geneId,
2643
+ gene,
2644
+ strategy,
2645
+ confidence,
2646
+ signals,
2647
+ fromCache,
2648
+ reason,
2649
+ alternatives
2650
+ };
2651
+ };
2652
+ if (this.cache.geneCount > 0) {
2653
+ const local = this.cache.selectGene(signals);
2654
+ if (local.action === "apply_gene" && local.confidence > 0.3) {
2655
+ return buildSuggestion(
2656
+ local.action,
2657
+ local.gene_id,
2658
+ local.gene,
2659
+ local.strategy,
2660
+ local.confidence,
2661
+ true,
2662
+ local.reason,
2663
+ local.alternatives
2664
+ );
2665
+ }
2666
+ }
2667
+ try {
2668
+ const result = await this.client.analyze({
2669
+ signals,
2670
+ scope: this.scope
2671
+ });
2672
+ if (result.data) {
2673
+ return buildSuggestion(
2674
+ result.data.action,
2675
+ result.data.gene_id,
2676
+ result.data.gene,
2677
+ result.data.strategy,
2678
+ result.data.confidence ?? 0,
2679
+ false,
2680
+ result.data.reason,
2681
+ result.data.alternatives
2682
+ );
2683
+ }
2684
+ } catch {
2685
+ const local = this.cache.selectGene(signals);
2686
+ return buildSuggestion(
2687
+ local.action,
2688
+ local.gene_id,
2689
+ local.gene,
2690
+ local.strategy,
2691
+ local.confidence,
2692
+ true,
2693
+ "server unreachable, using cache fallback",
2694
+ local.alternatives
2695
+ );
2696
+ }
2697
+ return {
2698
+ action: "none",
2699
+ confidence: 0,
2700
+ signals,
2701
+ fromCache: false,
2702
+ reason: "no recommendation from server"
2703
+ };
2704
+ }
2705
+ /**
2706
+ * Record an outcome. Fire-and-forget — never blocks, never throws.
2707
+ *
2708
+ * @param error - The error that was encountered
2709
+ * @param outcome - 'success' or 'failed'
2710
+ * @param summary - One-line summary of what happened
2711
+ * @param geneId - Gene that was used (auto-detected from last suggest() if omitted)
2712
+ */
2713
+ learned(error, outcome, summary, geneId, metadata) {
2714
+ const errorStr = error instanceof Error ? error.message : error;
2715
+ const ctx = { error: errorStr };
2716
+ const signals = extractSignals(ctx);
2717
+ const resolvedGeneId = geneId || this.lastSuggestedGeneId;
2718
+ if (!resolvedGeneId) return;
2719
+ if (this._activeSession) {
2720
+ const session = this._activeSession;
2721
+ session.usedGeneId = resolvedGeneId;
2722
+ session.adopted = resolvedGeneId === session.suggestedGeneId;
2723
+ session.completedAt = Date.now();
2724
+ session.outcome = outcome;
2725
+ session.durationMs = session.completedAt - session.suggestedAt;
2726
+ this._sessions.push(session);
2727
+ this._activeSession = void 0;
2728
+ }
2729
+ this.outbox.push({
2730
+ geneId: resolvedGeneId,
2731
+ signals,
2732
+ outcome,
2733
+ summary,
2734
+ metadata,
2735
+ timestamp: Date.now(),
2736
+ sessionId: this._sessions[this._sessions.length - 1]?.id
2737
+ });
2738
+ if (this.outbox.length >= this.config.outboxMaxSize) {
2739
+ this.flush().catch(() => {
2740
+ });
2741
+ }
2742
+ }
2743
+ // ─── Session Metrics ────────────────────────────────
2744
+ /** Get all completed sessions. */
2745
+ get sessions() {
2746
+ return this._sessions;
2747
+ }
2748
+ /** Get aggregate metrics for benchmarking. */
2749
+ getMetrics() {
2750
+ const sessions = this._sessions;
2751
+ const totalSuggestions = sessions.length;
2752
+ const suggestionsWithGene = sessions.filter((s) => s.suggestedGeneId).length;
2753
+ const totalLearned = sessions.filter((s) => s.completedAt).length;
2754
+ const adoptedSessions = sessions.filter((s) => s.adopted && s.completedAt);
2755
+ const adoptedCount = adoptedSessions.length;
2756
+ const nonAdopted = sessions.filter((s) => !s.adopted && s.completedAt);
2757
+ const durations = sessions.filter((s) => s.durationMs != null).map((s) => s.durationMs);
2758
+ const avgDurationMs = durations.length > 0 ? Math.round(durations.reduce((a, b) => a + b, 0) / durations.length) : 0;
2759
+ const adoptedSuccess = adoptedSessions.filter((s) => s.outcome === "success").length;
2760
+ const nonAdoptedSuccess = nonAdopted.filter((s) => s.outcome === "success").length;
2761
+ const cacheHits = sessions.filter((s) => s.fromCache).length;
2762
+ return {
2763
+ totalSuggestions,
2764
+ suggestionsWithGene,
2765
+ totalLearned,
2766
+ adoptedCount,
2767
+ geneUtilizationRate: suggestionsWithGene > 0 ? Math.round(adoptedCount / suggestionsWithGene * 100) / 100 : 0,
2768
+ avgDurationMs,
2769
+ adoptedSuccessRate: adoptedCount > 0 ? Math.round(adoptedSuccess / adoptedCount * 100) / 100 : 0,
2770
+ nonAdoptedSuccessRate: nonAdopted.length > 0 ? Math.round(nonAdoptedSuccess / nonAdopted.length * 100) / 100 : 0,
2771
+ cacheHitRate: totalSuggestions > 0 ? Math.round(cacheHits / totalSuggestions * 100) / 100 : 0
2772
+ };
2773
+ }
2774
+ /** Reset session history. */
2775
+ resetMetrics() {
2776
+ this._sessions = [];
2777
+ }
2778
+ // ─── Internal ───────────────────────────────────────
2779
+ /** Sync cache with server */
2780
+ async sync() {
2781
+ try {
2782
+ const result = await this.client.sync({
2783
+ pull: { since: this.cache.cursor },
2784
+ scope: this.scope
2785
+ });
2786
+ if (result.data?.pulled) {
2787
+ this.cache.applyDelta({ pulled: result.data.pulled });
2788
+ }
2789
+ } catch {
2790
+ }
2791
+ }
2792
+ /** Flush outbox to server */
2793
+ async flush() {
2794
+ if (this.outbox.length === 0) return;
2795
+ const batch = this.outbox.splice(0, this.config.outboxMaxSize);
2796
+ const promises = batch.map(
2797
+ (entry) => this.client.record({
2798
+ gene_id: entry.geneId,
2799
+ signals: entry.signals.map((s) => s.type),
2800
+ outcome: entry.outcome,
2801
+ summary: entry.summary,
2802
+ score: entry.score,
2803
+ metadata: entry.metadata,
2804
+ scope: this.scope
2805
+ }).catch(() => {
2806
+ this.outbox.push(entry);
2807
+ })
2808
+ );
2809
+ await Promise.allSettled(promises);
2810
+ }
2811
+ };
2812
+
2270
2813
  // src/index.ts
2271
2814
  var AccountClient = class {
2272
2815
  constructor(_r) {
@@ -2392,8 +2935,8 @@ var MessagesClient = class {
2392
2935
  return this._r("GET", `/api/im/messages/${conversationId}`, void 0, query);
2393
2936
  }
2394
2937
  /** Edit a message */
2395
- async edit(conversationId, messageId, content) {
2396
- return this._r("PATCH", `/api/im/messages/${conversationId}/${messageId}`, { content });
2938
+ async edit(conversationId, messageId, content, options) {
2939
+ return this._r("PATCH", `/api/im/messages/${conversationId}/${messageId}`, { content, ...options?.metadata ? { metadata: options.metadata } : {} });
2397
2940
  }
2398
2941
  /** Delete a message */
2399
2942
  async delete(conversationId, messageId) {
@@ -2480,6 +3023,549 @@ var WorkspaceClient = class {
2480
3023
  return this._r("GET", "/api/im/workspace/mentions/autocomplete", void 0, q);
2481
3024
  }
2482
3025
  };
3026
+ var TasksClient = class {
3027
+ constructor(_r) {
3028
+ this._r = _r;
3029
+ }
3030
+ /** Create a new task */
3031
+ async create(options) {
3032
+ return this._r("POST", "/api/im/tasks", options);
3033
+ }
3034
+ /** List tasks with optional filters */
3035
+ async list(options) {
3036
+ const query = {};
3037
+ if (options?.status) query.status = options.status;
3038
+ if (options?.capability) query.capability = options.capability;
3039
+ if (options?.assigneeId) query.assigneeId = options.assigneeId;
3040
+ if (options?.creatorId) query.creatorId = options.creatorId;
3041
+ if (options?.scheduleType) query.scheduleType = options.scheduleType;
3042
+ if (options?.limit != null) query.limit = String(options.limit);
3043
+ if (options?.cursor) query.cursor = options.cursor;
3044
+ return this._r("GET", "/api/im/tasks", void 0, query);
3045
+ }
3046
+ /** Get task details with logs */
3047
+ async get(taskId) {
3048
+ return this._r("GET", `/api/im/tasks/${taskId}`);
3049
+ }
3050
+ /** Update a task */
3051
+ async update(taskId, options) {
3052
+ return this._r("PATCH", `/api/im/tasks/${taskId}`, options);
3053
+ }
3054
+ /** Claim a pending task */
3055
+ async claim(taskId) {
3056
+ return this._r("POST", `/api/im/tasks/${taskId}/claim`);
3057
+ }
3058
+ /** Report progress on a task */
3059
+ async progress(taskId, options) {
3060
+ return this._r("POST", `/api/im/tasks/${taskId}/progress`, options);
3061
+ }
3062
+ /** Complete a task with result */
3063
+ async complete(taskId, options) {
3064
+ return this._r("POST", `/api/im/tasks/${taskId}/complete`, options);
3065
+ }
3066
+ /** Fail a task with error */
3067
+ async fail(taskId, error, metadata) {
3068
+ return this._r("POST", `/api/im/tasks/${taskId}/fail`, { error, metadata });
3069
+ }
3070
+ };
3071
+ var MemoryClient = class {
3072
+ constructor(_r) {
3073
+ this._r = _r;
3074
+ }
3075
+ /** Create a memory file */
3076
+ async createFile(options) {
3077
+ return this._r("POST", "/api/im/memory/files", options);
3078
+ }
3079
+ /** List memory files */
3080
+ async listFiles(options) {
3081
+ const query = {};
3082
+ if (options?.scope) query.scope = options.scope;
3083
+ if (options?.path) query.path = options.path;
3084
+ return this._r("GET", "/api/im/memory/files", void 0, query);
3085
+ }
3086
+ /** Get a memory file by ID */
3087
+ async getFile(fileId) {
3088
+ return this._r("GET", `/api/im/memory/files/${fileId}`);
3089
+ }
3090
+ /** Update a memory file (append, replace, or replace_section) */
3091
+ async updateFile(fileId, options) {
3092
+ return this._r("PATCH", `/api/im/memory/files/${fileId}`, options);
3093
+ }
3094
+ /** Delete a memory file */
3095
+ async deleteFile(fileId) {
3096
+ return this._r("DELETE", `/api/im/memory/files/${fileId}`);
3097
+ }
3098
+ /** Compact conversation messages into a summary */
3099
+ async compact(options) {
3100
+ return this._r("POST", "/api/im/memory/compact", options);
3101
+ }
3102
+ /** Get compaction summaries for a conversation */
3103
+ async getCompaction(conversationId) {
3104
+ return this._r("GET", `/api/im/memory/compact/${conversationId}`);
3105
+ }
3106
+ /** Load memory for session context */
3107
+ async load(scope) {
3108
+ const query = {};
3109
+ if (scope) query.scope = scope;
3110
+ return this._r("GET", "/api/im/memory/load", void 0, query);
3111
+ }
3112
+ };
3113
+ var IdentityClient = class {
3114
+ constructor(_r) {
3115
+ this._r = _r;
3116
+ }
3117
+ /** Get server public key */
3118
+ async getServerKey() {
3119
+ return this._r("GET", "/api/im/keys/server");
3120
+ }
3121
+ /** Register or rotate an identity key */
3122
+ async registerKey(options) {
3123
+ return this._r("PUT", "/api/im/keys/identity", options);
3124
+ }
3125
+ /** Get a user's identity key */
3126
+ async getKey(userId) {
3127
+ return this._r("GET", `/api/im/keys/identity/${userId}`);
3128
+ }
3129
+ /** Revoke own identity key */
3130
+ async revokeKey() {
3131
+ return this._r("POST", "/api/im/keys/identity/revoke");
3132
+ }
3133
+ /** Get key audit log for a user */
3134
+ async getAuditLog(userId) {
3135
+ return this._r("GET", `/api/im/keys/audit/${userId}`);
3136
+ }
3137
+ /** Verify key audit log integrity */
3138
+ async verifyAuditLog(userId) {
3139
+ return this._r("GET", `/api/im/keys/audit/${userId}/verify`);
3140
+ }
3141
+ };
3142
+ var SecurityClient = class {
3143
+ constructor(_r) {
3144
+ this._r = _r;
3145
+ }
3146
+ /** Get conversation security settings */
3147
+ async getConversationSecurity(conversationId) {
3148
+ return this._r("GET", `/api/im/conversations/${conversationId}/security`);
3149
+ }
3150
+ /** Update conversation security settings */
3151
+ async setConversationSecurity(conversationId, options) {
3152
+ return this._r("PATCH", `/api/im/conversations/${conversationId}/security`, options);
3153
+ }
3154
+ /** Upload a public key for a conversation */
3155
+ async uploadKey(conversationId, publicKey, algorithm) {
3156
+ const body = { publicKey };
3157
+ if (algorithm) body.algorithm = algorithm;
3158
+ return this._r("POST", `/api/im/conversations/${conversationId}/keys`, body);
3159
+ }
3160
+ /** Get keys for a conversation */
3161
+ async getKeys(conversationId) {
3162
+ return this._r("GET", `/api/im/conversations/${conversationId}/keys`);
3163
+ }
3164
+ /** Revoke a key for a specific user in a conversation */
3165
+ async revokeKey(conversationId, keyUserId) {
3166
+ return this._r("DELETE", `/api/im/conversations/${conversationId}/keys/${keyUserId}`);
3167
+ }
3168
+ };
3169
+ var EvolutionClient = class {
3170
+ constructor(_r) {
3171
+ this._r = _r;
3172
+ }
3173
+ // ── Public endpoints (no auth required) ──
3174
+ /** Get evolution stats */
3175
+ async getStats() {
3176
+ return this._r("GET", "/api/im/evolution/public/stats");
3177
+ }
3178
+ /** Get hot/trending genes */
3179
+ async getHotGenes(limit) {
3180
+ const query = {};
3181
+ if (limit != null) query.limit = String(limit);
3182
+ return this._r("GET", "/api/im/evolution/public/hot", void 0, query);
3183
+ }
3184
+ /** Browse published genes */
3185
+ async browseGenes(options) {
3186
+ const query = {};
3187
+ if (options?.category) query.category = options.category;
3188
+ if (options?.search) query.search = options.search;
3189
+ if (options?.sort) query.sort = options.sort;
3190
+ if (options?.page != null) query.page = String(options.page);
3191
+ if (options?.limit != null) query.limit = String(options.limit);
3192
+ return this._r("GET", "/api/im/evolution/public/genes", void 0, query);
3193
+ }
3194
+ /** Get a public gene by ID */
3195
+ async getPublicGene(geneId) {
3196
+ return this._r("GET", `/api/im/evolution/public/genes/${geneId}`);
3197
+ }
3198
+ /** Get capsules for a public gene */
3199
+ async getGeneCapsules(geneId, limit) {
3200
+ const query = {};
3201
+ if (limit != null) query.limit = String(limit);
3202
+ return this._r("GET", `/api/im/evolution/public/genes/${geneId}/capsules`, void 0, query);
3203
+ }
3204
+ /** Get gene lineage (parent + children) */
3205
+ async getGeneLineage(geneId) {
3206
+ return this._r("GET", `/api/im/evolution/public/genes/${geneId}/lineage`);
3207
+ }
3208
+ /** Get public evolution feed */
3209
+ async getFeed(limit) {
3210
+ const query = {};
3211
+ if (limit != null) query.limit = String(limit);
3212
+ return this._r("GET", "/api/im/evolution/public/feed", void 0, query);
3213
+ }
3214
+ // ── Authenticated endpoints ──
3215
+ /** Analyze signals and get gene recommendation */
3216
+ async analyze(options) {
3217
+ const { scope, ...body } = options;
3218
+ const q = {};
3219
+ if (scope) q.scope = scope;
3220
+ return this._r("POST", "/api/im/evolution/analyze", body, q);
3221
+ }
3222
+ /** Record an outcome (success/failure) for a gene */
3223
+ async record(options) {
3224
+ const { scope, ...body } = options;
3225
+ const q = {};
3226
+ if (scope) q.scope = scope;
3227
+ return this._r("POST", "/api/im/evolution/record", body, q);
3228
+ }
3229
+ /**
3230
+ * One-step evolution: analyze context → get gene recommendation → auto-record outcome.
3231
+ * Combines analyze() + record() into a single call for the common case.
3232
+ *
3233
+ * Usage:
3234
+ * const result = await client.evolution.evolve({
3235
+ * error: 'Connection timeout after 10s',
3236
+ * outcome: 'success',
3237
+ * score: 0.85,
3238
+ * summary: 'Fixed with exponential backoff',
3239
+ * });
3240
+ */
3241
+ async evolve(options) {
3242
+ const { outcome, score, summary, strategy_used, scope, ...analyzeOpts } = options;
3243
+ const analysis = await this.analyze({ ...analyzeOpts, ...scope ? { scope } : {} });
3244
+ if (!analysis.ok || !analysis.data) {
3245
+ return { ok: false, error: analysis.error };
3246
+ }
3247
+ const data = analysis.data;
3248
+ const geneId = data.gene_id;
3249
+ if (geneId && (data.action === "apply_gene" || data.action === "explore")) {
3250
+ const recordResult = await this.record({
3251
+ gene_id: geneId,
3252
+ signals: data.signals || analyzeOpts.signals || [],
3253
+ outcome,
3254
+ score: score ?? (outcome === "success" ? 0.8 : 0.2),
3255
+ summary: summary || `${outcome === "success" ? "Resolved" : "Failed to resolve"} using ${geneId}`,
3256
+ strategy_used,
3257
+ ...scope ? { scope } : {}
3258
+ });
3259
+ return {
3260
+ ok: true,
3261
+ data: {
3262
+ analysis: data,
3263
+ recorded: true,
3264
+ edge_updated: recordResult.data?.edge_updated
3265
+ }
3266
+ };
3267
+ }
3268
+ return {
3269
+ ok: true,
3270
+ data: { analysis: data, recorded: false }
3271
+ };
3272
+ }
3273
+ /** Trigger gene distillation */
3274
+ async distill(dryRun) {
3275
+ const query = {};
3276
+ if (dryRun) query.dry_run = "true";
3277
+ return this._r("POST", "/api/im/evolution/distill", void 0, query);
3278
+ }
3279
+ /** List own genes */
3280
+ async listGenes(signals, scope) {
3281
+ const query = {};
3282
+ if (signals) query.signals = signals;
3283
+ if (scope) query.scope = scope;
3284
+ return this._r("GET", "/api/im/evolution/genes", void 0, query);
3285
+ }
3286
+ /** Create a new gene */
3287
+ async createGene(options) {
3288
+ const { scope, ...body } = options;
3289
+ const q = {};
3290
+ if (scope) q.scope = scope;
3291
+ return this._r("POST", "/api/im/evolution/genes", body, q);
3292
+ }
3293
+ /** Delete a gene */
3294
+ async deleteGene(geneId) {
3295
+ return this._r("DELETE", `/api/im/evolution/genes/${geneId}`);
3296
+ }
3297
+ /** Publish a gene. Pass skipCanary=true to bypass canary validation (MVP/admin). */
3298
+ async publishGene(geneId, options) {
3299
+ return this._r("POST", `/api/im/evolution/genes/${geneId}/publish`, options?.skipCanary ? { skipCanary: true } : void 0);
3300
+ }
3301
+ /** Import a published gene */
3302
+ async importGene(geneId) {
3303
+ return this._r("POST", "/api/im/evolution/genes/import", { gene_id: geneId });
3304
+ }
3305
+ /** Fork a gene with modifications */
3306
+ async forkGene(options) {
3307
+ return this._r("POST", "/api/im/evolution/genes/fork", options);
3308
+ }
3309
+ /** Get signal-gene edges */
3310
+ async getEdges(options) {
3311
+ const query = {};
3312
+ if (options?.signalKey) query.signal_key = options.signalKey;
3313
+ if (options?.geneId) query.gene_id = options.geneId;
3314
+ if (options?.limit != null) query.limit = String(options.limit);
3315
+ if (options?.scope) query.scope = options.scope;
3316
+ return this._r("GET", "/api/im/evolution/edges", void 0, query);
3317
+ }
3318
+ /** Get agent personality profile */
3319
+ async getPersonality(agentId) {
3320
+ return this._r("GET", `/api/im/evolution/personality/${agentId}`);
3321
+ }
3322
+ /** Get own capsule history */
3323
+ async getCapsules(options) {
3324
+ const query = {};
3325
+ if (options?.page != null) query.page = String(options.page);
3326
+ if (options?.limit != null) query.limit = String(options.limit);
3327
+ if (options?.scope) query.scope = options.scope;
3328
+ return this._r("GET", "/api/im/evolution/capsules", void 0, query);
3329
+ }
3330
+ /** Get evolution report */
3331
+ async getReport(agentId, scope) {
3332
+ const query = {};
3333
+ if (agentId) query.agent_id = agentId;
3334
+ if (scope) query.scope = scope;
3335
+ return this._r("GET", "/api/im/evolution/report", void 0, query);
3336
+ }
3337
+ /** List available evolution scopes */
3338
+ async listScopes() {
3339
+ return this._r("GET", "/api/im/evolution/scopes");
3340
+ }
3341
+ // ─── v0.3.1: Stories, Metrics, Skills ──────────────
3342
+ /** Get recent evolution stories (for L1 narrative embedding) */
3343
+ async getStories(options) {
3344
+ const query = {};
3345
+ if (options?.limit != null) query.limit = String(options.limit);
3346
+ if (options?.since != null) query.since = String(options.since);
3347
+ return this._r("GET", "/api/im/evolution/stories", void 0, query);
3348
+ }
3349
+ /** Get north-star metrics comparison (standard vs hypergraph) */
3350
+ async getMetrics() {
3351
+ return this._r("GET", "/api/im/evolution/metrics");
3352
+ }
3353
+ /** Trigger metrics collection snapshot */
3354
+ async collectMetrics(windowHours) {
3355
+ return this._r("POST", "/api/im/evolution/metrics/collect", { window_hours: windowHours ?? 1 });
3356
+ }
3357
+ /** Search skills catalog */
3358
+ async searchSkills(options) {
3359
+ const q = {};
3360
+ if (options?.query) q.query = options.query;
3361
+ if (options?.category) q.category = options.category;
3362
+ if (options?.limit != null) q.limit = String(options.limit);
3363
+ return this._r("GET", "/api/im/skills/search", void 0, q);
3364
+ }
3365
+ /** Get skill catalog stats */
3366
+ async getSkillStats() {
3367
+ return this._r("GET", "/api/im/skills/stats");
3368
+ }
3369
+ /** Install a skill — creates Gene + returns content + install guide */
3370
+ async installSkill(slugOrId) {
3371
+ return this._r("POST", `/api/im/skills/${encodeURIComponent(slugOrId)}/install`);
3372
+ }
3373
+ /** Uninstall a skill */
3374
+ async uninstallSkill(slugOrId) {
3375
+ return this._r("DELETE", `/api/im/skills/${encodeURIComponent(slugOrId)}/install`);
3376
+ }
3377
+ /** List installed skills for this agent */
3378
+ async installedSkills() {
3379
+ return this._r("GET", "/api/im/skills/installed");
3380
+ }
3381
+ /** Get full skill content (SKILL.md + package info) */
3382
+ async getSkillContent(slugOrId) {
3383
+ return this._r("GET", `/api/im/skills/${encodeURIComponent(slugOrId)}/content`);
3384
+ }
3385
+ /**
3386
+ * Install a skill and write SKILL.md to local filesystem.
3387
+ * Combines cloud install + local file sync for Claude Code / OpenClaw / OpenCode.
3388
+ * @param slugOrId - Skill slug or ID
3389
+ * @param options - Local install options
3390
+ */
3391
+ async installSkillLocal(slugOrId, options) {
3392
+ const result = await this.installSkill(slugOrId);
3393
+ if (!result.ok || !result.data) return result;
3394
+ let content = result.data.skill?.content || "";
3395
+ if (!content) {
3396
+ const contentResult = await this.getSkillContent(slugOrId);
3397
+ content = contentResult.data?.content || "";
3398
+ }
3399
+ if (!content) {
3400
+ return { ...result, data: { ...result.data, localPaths: [] } };
3401
+ }
3402
+ const rawSlug = result.data.skill?.slug || slugOrId;
3403
+ const slug = rawSlug.replace(/[\/\\]/g, "").replace(/\.\./g, "");
3404
+ if (!slug) {
3405
+ return { ...result, data: { ...result.data, localPaths: [] } };
3406
+ }
3407
+ const localPaths = [];
3408
+ try {
3409
+ const fs = await import("fs");
3410
+ const path = await import("path");
3411
+ const os = await import("os");
3412
+ const home = os.homedir();
3413
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path.join(home, ".claude", "plugins", "prismer");
3414
+ const platformPaths = options?.project ? {
3415
+ "claude-code": path.join(options.projectRoot || ".", ".claude", "skills", slug),
3416
+ "openclaw": path.join(options.projectRoot || ".", "skills", slug),
3417
+ "opencode": path.join(options.projectRoot || ".", ".opencode", "skills", slug),
3418
+ "plugin": path.join(options.projectRoot || ".", ".claude", "plugins", "prismer", "skills", slug)
3419
+ } : {
3420
+ "claude-code": path.join(home, ".claude", "skills", slug),
3421
+ "openclaw": path.join(home, ".openclaw", "skills", slug),
3422
+ "opencode": path.join(home, ".config", "opencode", "skills", slug),
3423
+ "plugin": path.join(pluginBase, "skills", slug)
3424
+ };
3425
+ const targets = options?.platforms || Object.keys(platformPaths);
3426
+ for (const platform of targets) {
3427
+ const dir = platformPaths[platform];
3428
+ if (!dir) continue;
3429
+ try {
3430
+ fs.mkdirSync(dir, { recursive: true });
3431
+ const filePath = path.join(dir, "SKILL.md");
3432
+ fs.writeFileSync(filePath, content, "utf-8");
3433
+ localPaths.push(filePath);
3434
+ } catch {
3435
+ }
3436
+ }
3437
+ } catch {
3438
+ }
3439
+ return { ...result, data: { ...result.data, localPaths } };
3440
+ }
3441
+ /**
3442
+ * Uninstall a skill and remove local SKILL.md files.
3443
+ */
3444
+ async uninstallSkillLocal(slugOrId) {
3445
+ const result = await this.uninstallSkill(slugOrId);
3446
+ const removedPaths = [];
3447
+ const safeSlug = slugOrId.replace(/[\/\\]/g, "").replace(/\.\./g, "");
3448
+ if (!safeSlug) return { ...result, data: { uninstalled: result.data?.uninstalled ?? false, removedPaths } };
3449
+ try {
3450
+ const fs = await import("fs");
3451
+ const path = await import("path");
3452
+ const os = await import("os");
3453
+ const home = os.homedir();
3454
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path.join(home, ".claude", "plugins", "prismer");
3455
+ const dirs = [
3456
+ path.join(home, ".claude", "skills", safeSlug),
3457
+ path.join(home, ".openclaw", "skills", safeSlug),
3458
+ path.join(home, ".config", "opencode", "skills", safeSlug),
3459
+ path.join(pluginBase, "skills", safeSlug)
3460
+ ];
3461
+ for (const dir of dirs) {
3462
+ try {
3463
+ if (fs.existsSync(dir)) {
3464
+ fs.rmSync(dir, { recursive: true });
3465
+ removedPaths.push(dir);
3466
+ }
3467
+ } catch {
3468
+ }
3469
+ }
3470
+ } catch {
3471
+ }
3472
+ return { ...result, data: { uninstalled: result.data?.uninstalled ?? false, removedPaths } };
3473
+ }
3474
+ /**
3475
+ * Sync all installed skills to local filesystem.
3476
+ */
3477
+ async syncSkillsLocal(options) {
3478
+ const installed = await this.installedSkills();
3479
+ if (!installed.ok || !installed.data) return { synced: 0, failed: 0, paths: [] };
3480
+ let synced = 0;
3481
+ let failed = 0;
3482
+ const paths = [];
3483
+ for (const record of installed.data) {
3484
+ const rawSlug = record.skill?.slug;
3485
+ if (!rawSlug) {
3486
+ failed++;
3487
+ continue;
3488
+ }
3489
+ const slug = rawSlug.replace(/[\/\\]/g, "").replace(/\.\./g, "");
3490
+ if (!slug) {
3491
+ failed++;
3492
+ continue;
3493
+ }
3494
+ try {
3495
+ const contentResult = await this.getSkillContent(slug);
3496
+ const content = contentResult.data?.content;
3497
+ if (!content) {
3498
+ failed++;
3499
+ continue;
3500
+ }
3501
+ const fs = await import("fs");
3502
+ const path = await import("path");
3503
+ const os = await import("os");
3504
+ const home = os.homedir();
3505
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path.join(home, ".claude", "plugins", "prismer");
3506
+ const platformPaths = {
3507
+ "claude-code": path.join(home, ".claude", "skills", slug),
3508
+ "openclaw": path.join(home, ".openclaw", "skills", slug),
3509
+ "opencode": path.join(home, ".config", "opencode", "skills", slug),
3510
+ "plugin": path.join(pluginBase, "skills", slug)
3511
+ };
3512
+ const targets = options?.platforms || Object.keys(platformPaths);
3513
+ for (const platform of targets) {
3514
+ const dir = platformPaths[platform];
3515
+ if (!dir) continue;
3516
+ try {
3517
+ fs.mkdirSync(dir, { recursive: true });
3518
+ const filePath = path.join(dir, "SKILL.md");
3519
+ fs.writeFileSync(filePath, content, "utf-8");
3520
+ paths.push(filePath);
3521
+ } catch {
3522
+ }
3523
+ }
3524
+ synced++;
3525
+ } catch {
3526
+ failed++;
3527
+ }
3528
+ }
3529
+ return { synced, failed, paths };
3530
+ }
3531
+ /** Export a Gene as a Skill */
3532
+ async exportAsSkill(geneId, options) {
3533
+ return this._r("POST", `/api/im/evolution/genes/${geneId}/export-skill`, options);
3534
+ }
3535
+ // ─── P0: Report, Achievements, Sync ──────────────
3536
+ /** Submit a raw-context evolution report (auto-creates signals + gene match) */
3537
+ async submitReport(options) {
3538
+ return this._r("POST", "/api/im/evolution/report", {
3539
+ raw_context: options.rawContext,
3540
+ outcome: options.outcome,
3541
+ task_context: options.taskContext,
3542
+ task_error: options.taskError,
3543
+ task_id: options.taskId,
3544
+ metadata: options.metadata
3545
+ });
3546
+ }
3547
+ /** Get status of a submitted report by traceId */
3548
+ async getReportStatus(traceId) {
3549
+ return this._r("GET", `/api/im/evolution/report/${traceId}`);
3550
+ }
3551
+ /** Get evolution achievements for the current agent */
3552
+ async getAchievements() {
3553
+ return this._r("GET", "/api/im/evolution/achievements");
3554
+ }
3555
+ /** Get a sync snapshot (global gene/edge state since a sequence number) */
3556
+ async getSyncSnapshot(since) {
3557
+ const query = { scope: "global" };
3558
+ if (since != null) query.since = String(since);
3559
+ return this._r("GET", "/api/im/evolution/sync/snapshot", void 0, query);
3560
+ }
3561
+ /** Bidirectional sync: push local outcomes and pull remote updates */
3562
+ async sync(options) {
3563
+ const body = {};
3564
+ if (options?.pushOutcomes) body.push = { outcomes: options.pushOutcomes };
3565
+ if (options?.pullSince != null) body.pull = { since: options.pullSince };
3566
+ return this._r("POST", "/api/im/evolution/sync", body);
3567
+ }
3568
+ };
2483
3569
  function guessMimeType(fileName) {
2484
3570
  const ext = fileName.split(".").pop()?.toLowerCase() || "";
2485
3571
  const map = {
@@ -2718,6 +3804,11 @@ var IMClient = class {
2718
3804
  this.bindings = new BindingsClient(request);
2719
3805
  this.credits = new CreditsClient(request);
2720
3806
  this.workspace = new WorkspaceClient(request);
3807
+ this.tasks = new TasksClient(request);
3808
+ this.memory = new MemoryClient(request);
3809
+ this.identity = new IdentityClient(request);
3810
+ this.security = new SecurityClient(request);
3811
+ this.evolution = new EvolutionClient(request);
2721
3812
  this.files = new FilesClient(request, wsBase, fetchFn, getAuthHeaders);
2722
3813
  this.realtime = new IMRealtimeClient(wsBase);
2723
3814
  this.offline = offlineManager ?? null;
@@ -2900,11 +3991,16 @@ export {
2900
3991
  DirectClient,
2901
3992
  E2EEncryption,
2902
3993
  ENVIRONMENTS,
3994
+ EvolutionCache,
3995
+ EvolutionClient,
3996
+ EvolutionRuntime,
2903
3997
  FilesClient,
2904
3998
  GroupsClient,
2905
3999
  IMClient,
2906
4000
  IMRealtimeClient,
4001
+ IdentityClient,
2907
4002
  IndexedDBStorage,
4003
+ MemoryClient,
2908
4004
  MemoryStorage,
2909
4005
  MessagesClient,
2910
4006
  OfflineManager,
@@ -2912,8 +4008,19 @@ export {
2912
4008
  RealtimeSSEClient,
2913
4009
  RealtimeWSClient,
2914
4010
  SQLiteStorage,
4011
+ SecurityClient,
2915
4012
  TabCoordinator,
4013
+ TasksClient,
2916
4014
  WorkspaceClient,
2917
4015
  createClient,
2918
- index_default as default
4016
+ createEnrichedExtractor,
4017
+ decryptContext,
4018
+ decryptFile,
4019
+ decryptMessages,
4020
+ decryptOnReceive,
4021
+ index_default as default,
4022
+ encryptContext,
4023
+ encryptFile,
4024
+ encryptForSend,
4025
+ extractSignals
2919
4026
  };