@axiom-lattice/core 1.0.50 → 2.0.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/index.d.mts CHANGED
@@ -13,6 +13,7 @@ import * as _langchain_core_tools from '@langchain/core/tools';
13
13
  import { StructuredTool } from '@langchain/core/tools';
14
14
  import { CompiledStateGraph } from '@langchain/langgraph';
15
15
  import { BaseCheckpointSaver } from '@langchain/langgraph-checkpoint';
16
+ import { ReplaySubject } from 'rxjs';
16
17
 
17
18
  /**
18
19
  * BaseLatticeManager - 抽象基类,为各种Lattice管理器提供通用功能
@@ -476,7 +477,7 @@ interface ThreadBufferConfig {
476
477
  */
477
478
  interface ThreadBuffer {
478
479
  threadId: string;
479
- chunks: MessageChunk[];
480
+ chunks$: ReplaySubject<MessageChunk>;
480
481
  status: ThreadStatus;
481
482
  createdAt: number;
482
483
  updatedAt: number;
@@ -490,7 +491,6 @@ interface BufferStats {
490
491
  activeThreads: number;
491
492
  completedThreads: number;
492
493
  abortedThreads: number;
493
- totalChunks: number;
494
494
  config: Required<ThreadBufferConfig>;
495
495
  }
496
496
 
@@ -506,18 +506,6 @@ declare abstract class ChunkBuffer {
506
506
  * Chunks are appended in order
507
507
  */
508
508
  abstract addChunk(threadId: string, content: MessageChunk): Promise<void>;
509
- /**
510
- * Get all chunks for a thread in order
511
- */
512
- abstract getChunks(threadId: string): Promise<MessageChunk[]>;
513
- /**
514
- * Get accumulated content for a thread (all chunks concatenated)
515
- */
516
- abstract getAccumulatedContent(threadId: string): Promise<string>;
517
- /**
518
- * Get chunks for a specific message within a thread
519
- */
520
- abstract getChunksByMessageId(threadId: string, messageId: string): Promise<MessageChunk[]>;
521
509
  /**
522
510
  * Mark thread as completed (explicit call)
523
511
  */
@@ -563,12 +551,7 @@ declare abstract class ChunkBuffer {
563
551
  * Check if a thread exists (valid or expired)
564
552
  */
565
553
  abstract hasThread(threadId: string): Promise<boolean>;
566
- /**
567
- * Get new chunks since known content
568
- * Used for resuming streams from a known position
569
- * Matches the known content and returns chunks after that position
570
- */
571
- abstract getNewChunksSinceContent(threadId: string, messageId: string, knownContent: string): AsyncGenerator<MessageChunk>;
554
+ abstract getNewChunksSinceContentIterator(threadId: string, messageId: string, knownContent: string): AsyncIterable<MessageChunk>;
572
555
  }
573
556
 
574
557
  /**
@@ -583,7 +566,9 @@ declare class InMemoryChunkBuffer extends ChunkBuffer {
583
566
  private buffers;
584
567
  private config;
585
568
  private cleanupTimer?;
586
- constructor(config?: ThreadBufferConfig);
569
+ constructor(config?: ThreadBufferConfig & {
570
+ maxChunks?: number;
571
+ });
587
572
  /**
588
573
  * Start automatic periodic cleanup timer
589
574
  */
@@ -605,9 +590,6 @@ declare class InMemoryChunkBuffer extends ChunkBuffer {
605
590
  */
606
591
  private getOrCreateBuffer;
607
592
  addChunk(threadId: string, content: MessageChunk): Promise<void>;
608
- getChunks(threadId: string): Promise<MessageChunk[]>;
609
- getAccumulatedContent(threadId: string): Promise<string>;
610
- getChunksByMessageId(threadId: string, messageId: string): Promise<MessageChunk[]>;
611
593
  completeThread(threadId: string): Promise<void>;
612
594
  abortThread(threadId: string): Promise<void>;
613
595
  isThreadActive(threadId: string): Promise<boolean>;
@@ -622,24 +604,9 @@ declare class InMemoryChunkBuffer extends ChunkBuffer {
622
604
  * Returns number of threads cleaned up
623
605
  */
624
606
  cleanupExpiredThreads(): Promise<number>;
625
- /**
626
- * Extend thread TTL
627
- */
628
607
  extendThreadTTL(threadId: string, additionalMs?: number): Promise<void>;
629
- /**
630
- * Get new chunks since known content
631
- * Used for resuming streams from a known position
632
- * Matches the known content and returns chunks after that position
633
- * Continues to yield new chunks as they are added until thread completes/aborts
634
- */
635
- getNewChunksSinceContent(threadId: string, messageId: string, knownContent: string): AsyncGenerator<MessageChunk>;
636
- /**
637
- * Get statistics about the buffer
638
- */
608
+ getNewChunksSinceContentIterator(threadId: string, messageId: string, knownContent: string): AsyncIterable<MessageChunk>;
639
609
  getStats(): BufferStats;
640
- /**
641
- * Cleanup method for graceful shutdown
642
- */
643
610
  dispose(): void;
644
611
  }
645
612
 
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ import * as _langchain_core_tools from '@langchain/core/tools';
13
13
  import { StructuredTool } from '@langchain/core/tools';
14
14
  import { CompiledStateGraph } from '@langchain/langgraph';
15
15
  import { BaseCheckpointSaver } from '@langchain/langgraph-checkpoint';
16
+ import { ReplaySubject } from 'rxjs';
16
17
 
17
18
  /**
18
19
  * BaseLatticeManager - 抽象基类,为各种Lattice管理器提供通用功能
@@ -476,7 +477,7 @@ interface ThreadBufferConfig {
476
477
  */
477
478
  interface ThreadBuffer {
478
479
  threadId: string;
479
- chunks: MessageChunk[];
480
+ chunks$: ReplaySubject<MessageChunk>;
480
481
  status: ThreadStatus;
481
482
  createdAt: number;
482
483
  updatedAt: number;
@@ -490,7 +491,6 @@ interface BufferStats {
490
491
  activeThreads: number;
491
492
  completedThreads: number;
492
493
  abortedThreads: number;
493
- totalChunks: number;
494
494
  config: Required<ThreadBufferConfig>;
495
495
  }
496
496
 
@@ -506,18 +506,6 @@ declare abstract class ChunkBuffer {
506
506
  * Chunks are appended in order
507
507
  */
508
508
  abstract addChunk(threadId: string, content: MessageChunk): Promise<void>;
509
- /**
510
- * Get all chunks for a thread in order
511
- */
512
- abstract getChunks(threadId: string): Promise<MessageChunk[]>;
513
- /**
514
- * Get accumulated content for a thread (all chunks concatenated)
515
- */
516
- abstract getAccumulatedContent(threadId: string): Promise<string>;
517
- /**
518
- * Get chunks for a specific message within a thread
519
- */
520
- abstract getChunksByMessageId(threadId: string, messageId: string): Promise<MessageChunk[]>;
521
509
  /**
522
510
  * Mark thread as completed (explicit call)
523
511
  */
@@ -563,12 +551,7 @@ declare abstract class ChunkBuffer {
563
551
  * Check if a thread exists (valid or expired)
564
552
  */
565
553
  abstract hasThread(threadId: string): Promise<boolean>;
566
- /**
567
- * Get new chunks since known content
568
- * Used for resuming streams from a known position
569
- * Matches the known content and returns chunks after that position
570
- */
571
- abstract getNewChunksSinceContent(threadId: string, messageId: string, knownContent: string): AsyncGenerator<MessageChunk>;
554
+ abstract getNewChunksSinceContentIterator(threadId: string, messageId: string, knownContent: string): AsyncIterable<MessageChunk>;
572
555
  }
573
556
 
574
557
  /**
@@ -583,7 +566,9 @@ declare class InMemoryChunkBuffer extends ChunkBuffer {
583
566
  private buffers;
584
567
  private config;
585
568
  private cleanupTimer?;
586
- constructor(config?: ThreadBufferConfig);
569
+ constructor(config?: ThreadBufferConfig & {
570
+ maxChunks?: number;
571
+ });
587
572
  /**
588
573
  * Start automatic periodic cleanup timer
589
574
  */
@@ -605,9 +590,6 @@ declare class InMemoryChunkBuffer extends ChunkBuffer {
605
590
  */
606
591
  private getOrCreateBuffer;
607
592
  addChunk(threadId: string, content: MessageChunk): Promise<void>;
608
- getChunks(threadId: string): Promise<MessageChunk[]>;
609
- getAccumulatedContent(threadId: string): Promise<string>;
610
- getChunksByMessageId(threadId: string, messageId: string): Promise<MessageChunk[]>;
611
593
  completeThread(threadId: string): Promise<void>;
612
594
  abortThread(threadId: string): Promise<void>;
613
595
  isThreadActive(threadId: string): Promise<boolean>;
@@ -622,24 +604,9 @@ declare class InMemoryChunkBuffer extends ChunkBuffer {
622
604
  * Returns number of threads cleaned up
623
605
  */
624
606
  cleanupExpiredThreads(): Promise<number>;
625
- /**
626
- * Extend thread TTL
627
- */
628
607
  extendThreadTTL(threadId: string, additionalMs?: number): Promise<void>;
629
- /**
630
- * Get new chunks since known content
631
- * Used for resuming streams from a known position
632
- * Matches the known content and returns chunks after that position
633
- * Continues to yield new chunks as they are added until thread completes/aborts
634
- */
635
- getNewChunksSinceContent(threadId: string, messageId: string, knownContent: string): AsyncGenerator<MessageChunk>;
636
- /**
637
- * Get statistics about the buffer
638
- */
608
+ getNewChunksSinceContentIterator(threadId: string, messageId: string, knownContent: string): AsyncIterable<MessageChunk>;
639
609
  getStats(): BufferStats;
640
- /**
641
- * Cleanup method for graceful shutdown
642
- */
643
610
  dispose(): void;
644
611
  }
645
612
 
package/dist/index.js CHANGED
@@ -1436,12 +1436,13 @@ var DeepAgentGraphBuilder = class {
1436
1436
  return createDeepAgent({
1437
1437
  tools,
1438
1438
  model: params.model,
1439
+ stateSchema: params.stateSchema,
1439
1440
  instructions: params.prompt,
1440
1441
  subagents: params.subAgents.map((sa) => ({
1441
1442
  name: sa.key,
1442
1443
  description: sa.config.description,
1443
1444
  prompt: sa.config.prompt,
1444
- tools: sa.config.tools || []
1445
+ tools: sa.config.tools
1445
1446
  }))
1446
1447
  });
1447
1448
  }
@@ -2253,13 +2254,16 @@ var ThreadStatus = /* @__PURE__ */ ((ThreadStatus2) => {
2253
2254
  })(ThreadStatus || {});
2254
2255
 
2255
2256
  // src/chunk_buffer_lattice/InMemoryChunkBuffer.ts
2257
+ var import_rxjs = require("rxjs");
2256
2258
  var InMemoryChunkBuffer = class extends ChunkBuffer {
2257
2259
  constructor(config) {
2258
2260
  super();
2259
2261
  this.buffers = /* @__PURE__ */ new Map();
2260
2262
  this.config = {
2261
2263
  ttl: config?.ttl ?? 60 * 60 * 1e3,
2262
- cleanupInterval: config?.cleanupInterval ?? 0
2264
+ cleanupInterval: config?.cleanupInterval ?? 0,
2265
+ maxChunks: config?.maxChunks ?? 1e3
2266
+ // Default max chunks per thread
2263
2267
  };
2264
2268
  if (this.config.cleanupInterval > 0) {
2265
2269
  this.startCleanupTimer();
@@ -2308,11 +2312,14 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2308
2312
  */
2309
2313
  getOrCreateBuffer(threadId) {
2310
2314
  let buffer = this.getBufferIfValid(threadId);
2315
+ 4;
2311
2316
  if (!buffer) {
2312
2317
  const now = Date.now();
2313
2318
  buffer = {
2314
2319
  threadId,
2315
- chunks: [],
2320
+ chunks$: new import_rxjs.ReplaySubject(
2321
+ this.config.maxChunks ?? 1e4
2322
+ ),
2316
2323
  status: "active" /* ACTIVE */,
2317
2324
  createdAt: now,
2318
2325
  updatedAt: now,
@@ -2320,34 +2327,30 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2320
2327
  };
2321
2328
  this.buffers.set(threadId, buffer);
2322
2329
  }
2330
+ if (buffer.status !== "active" /* ACTIVE */) {
2331
+ buffer.status = "active" /* ACTIVE */;
2332
+ buffer.chunks$ = new import_rxjs.ReplaySubject(
2333
+ this.config.maxChunks ?? 1e4
2334
+ );
2335
+ buffer.updatedAt = Date.now();
2336
+ buffer.expiresAt = Date.now() + this.config.ttl;
2337
+ }
2323
2338
  return buffer;
2324
2339
  }
2325
2340
  async addChunk(threadId, content) {
2326
2341
  const buffer = this.getOrCreateBuffer(threadId);
2327
2342
  const chunk = content;
2328
- buffer.chunks.push(chunk);
2343
+ buffer.chunks$.next(chunk);
2329
2344
  buffer.updatedAt = Date.now();
2330
2345
  buffer.expiresAt = Date.now() + this.config.ttl;
2331
- }
2332
- async getChunks(threadId) {
2333
- const buffer = this.getBufferIfValid(threadId);
2334
- return buffer ? [...buffer.chunks] : [];
2335
- }
2336
- async getAccumulatedContent(threadId) {
2337
- const buffer = this.getBufferIfValid(threadId);
2338
- if (!buffer) return "";
2339
- return buffer.chunks.map((chunk) => chunk.data?.content).join("");
2340
- }
2341
- async getChunksByMessageId(threadId, messageId) {
2342
- const buffer = this.getBufferIfValid(threadId);
2343
- if (!buffer) return [];
2344
- return buffer.chunks.filter((chunk) => chunk.data?.id === messageId);
2346
+ buffer.status = "active" /* ACTIVE */;
2345
2347
  }
2346
2348
  async completeThread(threadId) {
2347
2349
  const buffer = this.getBufferIfValid(threadId);
2348
2350
  if (buffer) {
2349
2351
  buffer.status = "completed" /* COMPLETED */;
2350
2352
  buffer.updatedAt = Date.now();
2353
+ buffer.chunks$.complete();
2351
2354
  }
2352
2355
  }
2353
2356
  async abortThread(threadId) {
@@ -2355,6 +2358,7 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2355
2358
  if (buffer) {
2356
2359
  buffer.status = "aborted" /* ABORTED */;
2357
2360
  buffer.updatedAt = Date.now();
2361
+ buffer.chunks$.error(new Error("Thread aborted"));
2358
2362
  }
2359
2363
  }
2360
2364
  async isThreadActive(threadId) {
@@ -2367,10 +2371,7 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2367
2371
  async getThreadBuffer(threadId) {
2368
2372
  const buffer = this.getBufferIfValid(threadId);
2369
2373
  if (!buffer) return void 0;
2370
- return {
2371
- ...buffer,
2372
- chunks: [...buffer.chunks]
2373
- };
2374
+ return buffer;
2374
2375
  }
2375
2376
  async clearThread(threadId) {
2376
2377
  this.buffers.delete(threadId);
@@ -2417,9 +2418,6 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2417
2418
  }
2418
2419
  return cleanedCount;
2419
2420
  }
2420
- /**
2421
- * Extend thread TTL
2422
- */
2423
2421
  async extendThreadTTL(threadId, additionalMs) {
2424
2422
  const buffer = this.getBufferIfValid(threadId);
2425
2423
  if (buffer) {
@@ -2428,62 +2426,69 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2428
2426
  buffer.updatedAt = Date.now();
2429
2427
  }
2430
2428
  }
2431
- /**
2432
- * Get new chunks since known content
2433
- * Used for resuming streams from a known position
2434
- * Matches the known content and returns chunks after that position
2435
- * Continues to yield new chunks as they are added until thread completes/aborts
2436
- */
2437
- async *getNewChunksSinceContent(threadId, messageId, knownContent) {
2438
- let buffer = this.getBufferIfValid(threadId);
2429
+ async *getNewChunksSinceContentIterator(threadId, messageId, knownContent) {
2430
+ const buffer = this.getBufferIfValid(threadId);
2439
2431
  if (!buffer) return;
2440
- let lastYieldedIndex = -1;
2441
2432
  let accumulatedContent = "";
2442
- for (let i = 0; i < buffer.chunks.length; i++) {
2443
- const chunk = buffer.chunks[i];
2444
- if (chunk.data?.id === messageId) {
2445
- accumulatedContent += chunk.data?.content || "";
2446
- if (accumulatedContent === knownContent) {
2447
- lastYieldedIndex = i;
2448
- break;
2433
+ const queue = [];
2434
+ let resolveNext = null;
2435
+ let errorNext = null;
2436
+ let isCompleted = false;
2437
+ const subscription = buffer.chunks$.subscribe({
2438
+ next: (chunk) => {
2439
+ queue.push(chunk);
2440
+ if (resolveNext) {
2441
+ const resolve = resolveNext;
2442
+ resolveNext = null;
2443
+ resolve();
2449
2444
  }
2450
- if (accumulatedContent.length > knownContent.length) {
2451
- if (accumulatedContent.startsWith(knownContent)) {
2452
- lastYieldedIndex = i;
2453
- break;
2454
- }
2445
+ },
2446
+ error: (err) => {
2447
+ if (errorNext) {
2448
+ const reject = errorNext;
2449
+ errorNext = null;
2450
+ reject(err);
2455
2451
  }
2456
- }
2457
- }
2458
- const pollingInterval = 100;
2459
- while (true) {
2460
- buffer = this.getBufferIfValid(threadId);
2461
- if (!buffer) break;
2462
- let hasNewChunks = false;
2463
- for (let i = lastYieldedIndex + 1; i < buffer.chunks.length; i++) {
2464
- const chunk = buffer.chunks[i];
2465
- if (chunk.data?.id === messageId) {
2466
- yield chunk;
2467
- lastYieldedIndex = i;
2468
- hasNewChunks = true;
2452
+ },
2453
+ complete: () => {
2454
+ isCompleted = true;
2455
+ if (resolveNext) {
2456
+ const resolve = resolveNext;
2457
+ resolveNext = null;
2458
+ resolve();
2469
2459
  }
2470
2460
  }
2471
- if (buffer.status === "completed" /* COMPLETED */ || buffer.status === "aborted" /* ABORTED */) {
2472
- break;
2473
- }
2474
- if (!hasNewChunks) {
2475
- await new Promise((resolve) => setTimeout(resolve, pollingInterval));
2461
+ });
2462
+ try {
2463
+ while (true) {
2464
+ if (queue.length === 0) {
2465
+ if (isCompleted) break;
2466
+ await new Promise((resolve, reject) => {
2467
+ resolveNext = resolve;
2468
+ errorNext = reject;
2469
+ });
2470
+ }
2471
+ while (queue.length > 0) {
2472
+ const chunk = queue.shift();
2473
+ if (!chunk) continue;
2474
+ if (chunk.data?.id === messageId) {
2475
+ accumulatedContent += chunk.data?.content || "";
2476
+ }
2477
+ if (accumulatedContent.length > knownContent.length) {
2478
+ if (accumulatedContent.startsWith(knownContent)) {
2479
+ yield chunk;
2480
+ }
2481
+ }
2482
+ }
2476
2483
  }
2484
+ } finally {
2485
+ subscription.unsubscribe();
2477
2486
  }
2478
2487
  }
2479
- /**
2480
- * Get statistics about the buffer
2481
- */
2482
2488
  getStats() {
2483
2489
  let activeCount = 0;
2484
2490
  let completedCount = 0;
2485
2491
  let abortedCount = 0;
2486
- let totalChunks = 0;
2487
2492
  const validBuffers = [];
2488
2493
  for (const [threadId, buffer] of this.buffers.entries()) {
2489
2494
  if (this.isExpired(buffer)) {
@@ -2493,7 +2498,6 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2493
2498
  }
2494
2499
  }
2495
2500
  for (const buffer of validBuffers) {
2496
- totalChunks += buffer.chunks.length;
2497
2501
  switch (buffer.status) {
2498
2502
  case "active" /* ACTIVE */:
2499
2503
  activeCount++;
@@ -2511,13 +2515,9 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
2511
2515
  activeThreads: activeCount,
2512
2516
  completedThreads: completedCount,
2513
2517
  abortedThreads: abortedCount,
2514
- totalChunks,
2515
2518
  config: this.config
2516
2519
  };
2517
2520
  }
2518
- /**
2519
- * Cleanup method for graceful shutdown
2520
- */
2521
2521
  dispose() {
2522
2522
  this.stopCleanupTimer();
2523
2523
  this.buffers.clear();