@hashgraphonline/conversational-agent 0.1.209 → 0.1.211

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.
Files changed (106) hide show
  1. package/bin/conversational-agent-cli.js +30 -0
  2. package/cli/readme.md +181 -0
  3. package/dist/cjs/base-agent.d.ts +3 -1
  4. package/dist/cjs/conversational-agent.d.ts +14 -22
  5. package/dist/cjs/index.cjs +1 -1
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/index.d.ts +5 -3
  8. package/dist/cjs/langchain-agent.d.ts +6 -3
  9. package/dist/cjs/memory/SmartMemoryManager.d.ts +7 -1
  10. package/dist/cjs/memory/TokenCounter.d.ts +1 -1
  11. package/dist/cjs/plugins/hbar/AirdropToolWrapper.d.ts +43 -0
  12. package/dist/{types/plugins/hbar-transfer/HbarTransferPlugin.d.ts → cjs/plugins/hbar/HbarPlugin.d.ts} +2 -1
  13. package/dist/{types/plugins/hbar-transfer → cjs/plugins/hbar}/TransferHbarTool.d.ts +1 -1
  14. package/dist/cjs/plugins/hbar/index.d.ts +3 -0
  15. package/dist/cjs/plugins/index.d.ts +2 -1
  16. package/dist/cjs/services/EntityResolver.d.ts +26 -0
  17. package/dist/cjs/tools/EntityResolverTool.d.ts +104 -0
  18. package/dist/cjs/types/inscription.d.ts +37 -0
  19. package/dist/esm/index.js +8 -2
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/esm/index12.js +1 -4
  22. package/dist/esm/index12.js.map +1 -1
  23. package/dist/esm/index13.js +0 -1
  24. package/dist/esm/index13.js.map +1 -1
  25. package/dist/esm/index14.js +2 -7
  26. package/dist/esm/index14.js.map +1 -1
  27. package/dist/esm/index15.js +31 -69
  28. package/dist/esm/index15.js.map +1 -1
  29. package/dist/esm/index16.js +126 -39
  30. package/dist/esm/index16.js.map +1 -1
  31. package/dist/esm/index17.js +148 -13
  32. package/dist/esm/index17.js.map +1 -1
  33. package/dist/esm/index18.js +44 -146
  34. package/dist/esm/index18.js.map +1 -1
  35. package/dist/esm/index19.js +100 -6
  36. package/dist/esm/index19.js.map +1 -1
  37. package/dist/esm/index20.js +20 -174
  38. package/dist/esm/index20.js.map +1 -1
  39. package/dist/esm/index21.js +7 -151
  40. package/dist/esm/index21.js.map +1 -1
  41. package/dist/esm/index22.js +154 -45
  42. package/dist/esm/index22.js.map +1 -1
  43. package/dist/esm/index23.js +149 -24
  44. package/dist/esm/index23.js.map +1 -1
  45. package/dist/esm/index24.js +56 -83
  46. package/dist/esm/index24.js.map +1 -1
  47. package/dist/esm/index25.js +24 -236
  48. package/dist/esm/index25.js.map +1 -1
  49. package/dist/esm/index26.js +95 -0
  50. package/dist/esm/index26.js.map +1 -0
  51. package/dist/esm/index27.js +242 -0
  52. package/dist/esm/index27.js.map +1 -0
  53. package/dist/esm/index5.js +32 -19
  54. package/dist/esm/index5.js.map +1 -1
  55. package/dist/esm/index6.js +156 -195
  56. package/dist/esm/index6.js.map +1 -1
  57. package/dist/esm/index7.js +2 -2
  58. package/dist/esm/index7.js.map +1 -1
  59. package/dist/esm/index8.js +80 -48
  60. package/dist/esm/index8.js.map +1 -1
  61. package/dist/types/base-agent.d.ts +3 -1
  62. package/dist/types/conversational-agent.d.ts +14 -22
  63. package/dist/types/index.d.ts +5 -3
  64. package/dist/types/langchain-agent.d.ts +6 -3
  65. package/dist/types/memory/SmartMemoryManager.d.ts +7 -1
  66. package/dist/types/memory/TokenCounter.d.ts +1 -1
  67. package/dist/types/plugins/hbar/AirdropToolWrapper.d.ts +43 -0
  68. package/dist/{cjs/plugins/hbar-transfer/HbarTransferPlugin.d.ts → types/plugins/hbar/HbarPlugin.d.ts} +2 -1
  69. package/dist/{cjs/plugins/hbar-transfer → types/plugins/hbar}/TransferHbarTool.d.ts +1 -1
  70. package/dist/types/plugins/hbar/index.d.ts +3 -0
  71. package/dist/types/plugins/index.d.ts +2 -1
  72. package/dist/types/services/EntityResolver.d.ts +26 -0
  73. package/dist/types/tools/EntityResolverTool.d.ts +104 -0
  74. package/dist/types/types/inscription.d.ts +37 -0
  75. package/package.json +13 -4
  76. package/src/base-agent.ts +14 -9
  77. package/src/config/system-message.ts +11 -2
  78. package/src/context/ReferenceContextManager.ts +1 -1
  79. package/src/conversational-agent.ts +221 -254
  80. package/src/index.ts +17 -3
  81. package/src/langchain-agent.ts +130 -78
  82. package/src/mcp/ContentProcessor.ts +0 -2
  83. package/src/mcp/adapters/langchain.ts +0 -1
  84. package/src/memory/ContentStorage.ts +0 -5
  85. package/src/memory/MemoryWindow.ts +0 -1
  86. package/src/memory/ReferenceIdGenerator.ts +4 -4
  87. package/src/memory/SmartMemoryManager.ts +53 -92
  88. package/src/memory/TokenCounter.ts +4 -7
  89. package/src/plugins/hbar/AirdropToolWrapper.ts +157 -0
  90. package/src/plugins/hbar/HbarPlugin.ts +86 -0
  91. package/src/plugins/{hbar-transfer → hbar}/TransferHbarTool.ts +3 -3
  92. package/src/plugins/hbar/index.ts +3 -0
  93. package/src/plugins/index.ts +2 -1
  94. package/src/services/EntityResolver.ts +135 -0
  95. package/src/tools/EntityResolverTool.ts +170 -0
  96. package/src/types/inscription.ts +40 -0
  97. package/dist/cjs/plugins/hbar-transfer/index.d.ts +0 -1
  98. package/dist/types/plugins/hbar-transfer/index.d.ts +0 -1
  99. package/src/plugins/hbar-transfer/HbarTransferPlugin.ts +0 -66
  100. package/src/plugins/hbar-transfer/index.ts +0 -1
  101. /package/dist/cjs/plugins/{hbar-transfer → hbar}/AccountBuilder.d.ts +0 -0
  102. /package/dist/cjs/plugins/{hbar-transfer → hbar}/types.d.ts +0 -0
  103. /package/dist/types/plugins/{hbar-transfer → hbar}/AccountBuilder.d.ts +0 -0
  104. /package/dist/types/plugins/{hbar-transfer → hbar}/types.d.ts +0 -0
  105. /package/src/plugins/{hbar-transfer → hbar}/AccountBuilder.ts +0 -0
  106. /package/src/plugins/{hbar-transfer → hbar}/types.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  export { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';
2
2
  export { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';
3
3
  export { InscribePlugin } from './plugins/inscribe/InscribePlugin';
4
- export { HbarTransferPlugin } from './plugins/hbar-transfer/HbarTransferPlugin';
4
+ export { HbarPlugin } from './plugins/hbar/HbarPlugin';
5
5
  export { HCS10Plugin as OpenConvAIPlugin } from './plugins/hcs-10/HCS10Plugin';
6
6
  export { ConversationalAgent } from './conversational-agent';
7
7
  export type { ConversationalAgentOptions } from './conversational-agent';
@@ -11,6 +11,8 @@ export { createAgent } from './agent-factory';
11
11
  export { LangChainProvider, type AIProvider, type VercelAIProvider, type BAMLProvider, } from './providers';
12
12
  export * from 'hedera-agent-kit';
13
13
  export type { IStateManager } from '@hashgraphonline/standards-agent-kit';
14
- export type { MCPServerConfig, MCPConnectionStatus, MCPToolInfo } from './mcp/types';
15
- export { MCPServers, createMCPConfig, validateServerConfig } from './mcp/helpers';
14
+ export type { MCPServerConfig, MCPConnectionStatus, MCPToolInfo, } from './mcp/types';
15
+ export { MCPServers, createMCPConfig, validateServerConfig, } from './mcp/helpers';
16
16
  export * from './memory';
17
+ export { createEntityTools, ResolveEntitiesTool, ExtractEntitiesTool, } from './tools/EntityResolverTool';
18
+ export { ContentStoreManager } from './services/ContentStoreManager';
@@ -1,10 +1,12 @@
1
1
  import { BaseAgent, ConversationContext, ChatResponse, OperationalMode, UsageStats } from './base-agent';
2
+ import { MCPConnectionStatus } from './mcp/types';
2
3
 
3
4
  export declare class LangChainAgent extends BaseAgent {
4
5
  private executor;
5
6
  private systemMessage;
6
7
  private mcpManager?;
7
8
  private smartMemory;
9
+ private mcpConnectionStatus;
8
10
  boot(): Promise<void>;
9
11
  chat(message: string, context?: ConversationContext): Promise<ChatResponse>;
10
12
  shutdown(): Promise<void>;
@@ -12,18 +14,19 @@ export declare class LangChainAgent extends BaseAgent {
12
14
  getUsageStats(): UsageStats;
13
15
  getUsageLog(): UsageStats[];
14
16
  clearUsageStats(): void;
17
+ getMCPConnectionStatus(): Map<string, MCPConnectionStatus>;
15
18
  private createAgentKit;
16
19
  private createExecutor;
17
20
  private handleError;
18
21
  private initializeMCP;
19
22
  /**
20
- * Connect to MCP servers asynchronously after agent boot
23
+ * Connect to MCP servers asynchronously after agent boot with background timeout pattern
21
24
  */
22
25
  connectMCPServers(): Promise<void>;
23
26
  /**
24
- * Connect to a single MCP server
27
+ * Connect to a single MCP server in background with timeout
25
28
  */
26
- private connectServer;
29
+ private connectServerInBackground;
27
30
  /**
28
31
  * Check if a string is valid JSON
29
32
  */
@@ -69,16 +69,22 @@ export interface MemoryStats {
69
69
  usagePercentage: number;
70
70
  }
71
71
  /**
72
+ * TODO: investigate using chroma / rag for long term memory
72
73
  * Smart memory manager that combines active memory window with long-term storage
73
74
  * Provides context-aware memory management with automatic pruning and searchable history
74
75
  */
75
76
  export declare class SmartMemoryManager {
76
77
  private memoryWindow;
77
- private contentStorage;
78
+ private _contentStorage;
78
79
  private tokenCounter;
79
80
  private config;
80
81
  private static readonly DEFAULT_CONFIG;
81
82
  constructor(config?: SmartMemoryConfig);
83
+ /**
84
+ * Get the content storage instance for file/content reference operations
85
+ * @returns ContentStorage instance
86
+ */
87
+ get contentStorage(): ContentStorage;
82
88
  /**
83
89
  * Add a message to the active memory window
84
90
  * Automatically handles pruning and storage of displaced messages
@@ -10,7 +10,7 @@ export declare class TokenCounter {
10
10
  private modelName;
11
11
  private static readonly MESSAGE_OVERHEAD;
12
12
  private static readonly ROLE_OVERHEAD;
13
- constructor(modelName?: TiktokenModel);
13
+ constructor(modelName?: string | TiktokenModel);
14
14
  /**
15
15
  * Count tokens in raw text content
16
16
  * @param text - The text to count tokens for
@@ -0,0 +1,43 @@
1
+ import { StructuredTool } from '@langchain/core/tools';
2
+ import { z } from 'zod';
3
+
4
+ export declare class AirdropToolWrapper extends StructuredTool {
5
+ name: string;
6
+ description: string;
7
+ schema: z.ZodObject<{
8
+ tokenId: z.ZodString;
9
+ recipients: z.ZodArray<z.ZodObject<{
10
+ accountId: z.ZodString;
11
+ amount: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ accountId: string;
14
+ amount: string | number;
15
+ }, {
16
+ accountId: string;
17
+ amount: string | number;
18
+ }>, "many">;
19
+ memo: z.ZodOptional<z.ZodString>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ tokenId: string;
22
+ recipients: {
23
+ accountId: string;
24
+ amount: string | number;
25
+ }[];
26
+ memo?: string | undefined;
27
+ }, {
28
+ tokenId: string;
29
+ recipients: {
30
+ accountId: string;
31
+ amount: string | number;
32
+ }[];
33
+ memo?: string | undefined;
34
+ }>;
35
+ private originalTool;
36
+ private agentKit;
37
+ private logger;
38
+ constructor(originalTool: StructuredTool, agentKit: unknown);
39
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
40
+ private convertToSmallestUnits;
41
+ private getTokenInfo;
42
+ private queryTokenInfo;
43
+ }
@@ -1,6 +1,6 @@
1
1
  import { GenericPluginContext, HederaTool, BasePlugin } from 'hedera-agent-kit';
2
2
 
3
- export declare class HbarTransferPlugin extends BasePlugin {
3
+ export declare class HbarPlugin extends BasePlugin {
4
4
  id: string;
5
5
  name: string;
6
6
  description: string;
@@ -8,6 +8,7 @@ export declare class HbarTransferPlugin extends BasePlugin {
8
8
  author: string;
9
9
  namespace: string;
10
10
  private tools;
11
+ private originalAirdropTool;
11
12
  initialize(context: GenericPluginContext): Promise<void>;
12
13
  private initializeTools;
13
14
  getTools(): HederaTool[];
@@ -29,7 +29,7 @@ declare const TransferHbarZodSchemaCore: z.ZodObject<{
29
29
  /**
30
30
  * A Hedera transaction tool for transferring HBAR between accounts.
31
31
  * Supports single and multi-party transfers with automatic balance validation.
32
- * Extends BaseHederaTransactionTool to handle HBAR transfer transactions on the Hedera network.
32
+ * Extends BaseHederaTransactionTool to handle HBAR transfer transactions on the Hedera Hashgraph.
33
33
  */
34
34
  export declare class TransferHbarTool extends BaseHederaTransactionTool<typeof TransferHbarZodSchemaCore> {
35
35
  name: string;
@@ -0,0 +1,3 @@
1
+ export * from './TransferHbarTool';
2
+ export * from './AccountBuilder';
3
+ export * from './types';
@@ -1,4 +1,5 @@
1
1
  export { HCS10Plugin } from './hcs-10';
2
2
  export { HCS2Plugin } from './hcs-2';
3
3
  export { InscribePlugin } from './inscribe';
4
- export { HbarTransferPlugin } from './hbar-transfer';
4
+ export { HbarPlugin } from './hbar/HbarPlugin';
5
+ export * from './hbar';
@@ -0,0 +1,26 @@
1
+ import { EntityAssociation } from '../memory/SmartMemoryManager';
2
+
3
+ export interface EntityResolverConfig {
4
+ apiKey: string;
5
+ modelName?: string;
6
+ }
7
+ /**
8
+ * LLM-based entity resolver that replaces brittle regex patterns
9
+ */
10
+ export declare class EntityResolver {
11
+ private llm;
12
+ constructor(config: EntityResolverConfig);
13
+ /**
14
+ * Resolve entity references using LLM instead of regex
15
+ */
16
+ resolveReferences(message: string, entities: EntityAssociation[]): Promise<string>;
17
+ /**
18
+ * Extract entities from agent response using LLM
19
+ */
20
+ extractEntities(response: unknown, userMessage: string): Promise<Array<{
21
+ id: string;
22
+ name: string;
23
+ type: string;
24
+ transactionId?: string;
25
+ }>>;
26
+ }
@@ -0,0 +1,104 @@
1
+ import { StructuredTool } from '@langchain/core/tools';
2
+ import { z } from 'zod';
3
+
4
+ declare const ResolveEntitiesSchema: z.ZodObject<{
5
+ message: z.ZodString;
6
+ entities: z.ZodArray<z.ZodObject<{
7
+ entityId: z.ZodString;
8
+ entityName: z.ZodString;
9
+ entityType: z.ZodString;
10
+ }, "strip", z.ZodTypeAny, {
11
+ entityId: string;
12
+ entityName: string;
13
+ entityType: string;
14
+ }, {
15
+ entityId: string;
16
+ entityName: string;
17
+ entityType: string;
18
+ }>, "many">;
19
+ }, "strip", z.ZodTypeAny, {
20
+ message: string;
21
+ entities: {
22
+ entityId: string;
23
+ entityName: string;
24
+ entityType: string;
25
+ }[];
26
+ }, {
27
+ message: string;
28
+ entities: {
29
+ entityId: string;
30
+ entityName: string;
31
+ entityType: string;
32
+ }[];
33
+ }>;
34
+ declare const ExtractEntitiesSchema: z.ZodObject<{
35
+ response: z.ZodString;
36
+ userMessage: z.ZodString;
37
+ }, "strip", z.ZodTypeAny, {
38
+ response: string;
39
+ userMessage: string;
40
+ }, {
41
+ response: string;
42
+ userMessage: string;
43
+ }>;
44
+ export declare class ResolveEntitiesTool extends StructuredTool {
45
+ name: string;
46
+ description: string;
47
+ schema: z.ZodObject<{
48
+ message: z.ZodString;
49
+ entities: z.ZodArray<z.ZodObject<{
50
+ entityId: z.ZodString;
51
+ entityName: z.ZodString;
52
+ entityType: z.ZodString;
53
+ }, "strip", z.ZodTypeAny, {
54
+ entityId: string;
55
+ entityName: string;
56
+ entityType: string;
57
+ }, {
58
+ entityId: string;
59
+ entityName: string;
60
+ entityType: string;
61
+ }>, "many">;
62
+ }, "strip", z.ZodTypeAny, {
63
+ message: string;
64
+ entities: {
65
+ entityId: string;
66
+ entityName: string;
67
+ entityType: string;
68
+ }[];
69
+ }, {
70
+ message: string;
71
+ entities: {
72
+ entityId: string;
73
+ entityName: string;
74
+ entityType: string;
75
+ }[];
76
+ }>;
77
+ private llm;
78
+ constructor(apiKey: string, modelName?: string);
79
+ _call(input: z.infer<typeof ResolveEntitiesSchema>): Promise<string>;
80
+ private groupEntitiesByType;
81
+ private buildEntityContext;
82
+ }
83
+ export declare class ExtractEntitiesTool extends StructuredTool {
84
+ name: string;
85
+ description: string;
86
+ schema: z.ZodObject<{
87
+ response: z.ZodString;
88
+ userMessage: z.ZodString;
89
+ }, "strip", z.ZodTypeAny, {
90
+ response: string;
91
+ userMessage: string;
92
+ }, {
93
+ response: string;
94
+ userMessage: string;
95
+ }>;
96
+ private llm;
97
+ constructor(apiKey: string, modelName?: string);
98
+ _call(input: z.infer<typeof ExtractEntitiesSchema>): Promise<string>;
99
+ }
100
+ export declare function createEntityTools(apiKey: string, modelName?: string): {
101
+ resolveEntities: ResolveEntitiesTool;
102
+ extractEntities: ExtractEntitiesTool;
103
+ };
104
+ export {};
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Inscription quote response from standards-agent-kit
3
+ */
4
+ export interface InscriptionQuote {
5
+ totalCostHbar: string;
6
+ validUntil: string;
7
+ breakdown: {
8
+ transfers: Array<{
9
+ type: string;
10
+ amount: string;
11
+ description: string;
12
+ }>;
13
+ };
14
+ }
15
+ /**
16
+ * Parameters for inscription tool calls with quote support
17
+ */
18
+ export interface InscriptionToolParams {
19
+ [key: string]: unknown;
20
+ quoteOnly?: boolean;
21
+ }
22
+ /**
23
+ * Result from inscription tool execution
24
+ */
25
+ export interface InscriptionResult {
26
+ success: boolean;
27
+ transactionId?: string;
28
+ message: string;
29
+ quote?: InscriptionQuote;
30
+ }
31
+ /**
32
+ * User confirmation status for inscription
33
+ */
34
+ export interface InscriptionConfirmation {
35
+ confirmed: boolean;
36
+ reason?: string;
37
+ }
package/dist/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { HCS10Plugin, HCS10Plugin as HCS10Plugin2 } from "./index2.js";
2
2
  import { HCS2Plugin } from "./index3.js";
3
3
  import { InscribePlugin } from "./index4.js";
4
- import { HbarTransferPlugin } from "./index5.js";
4
+ import { HbarPlugin } from "./index5.js";
5
5
  import { ConversationalAgent } from "./index6.js";
6
6
  import { BaseAgent } from "./index7.js";
7
7
  import { LangChainAgent } from "./index8.js";
@@ -13,22 +13,28 @@ import { TokenCounter } from "./index12.js";
13
13
  import { MemoryWindow } from "./index13.js";
14
14
  import { ContentStorage } from "./index14.js";
15
15
  import { SmartMemoryManager } from "./index15.js";
16
+ import { ExtractEntitiesTool, ResolveEntitiesTool, createEntityTools } from "./index16.js";
17
+ import { ContentStoreManager } from "./index17.js";
16
18
  export {
17
19
  BaseAgent,
18
20
  ContentStorage,
21
+ ContentStoreManager,
19
22
  ConversationalAgent,
23
+ ExtractEntitiesTool,
20
24
  HCS10Plugin,
21
25
  HCS2Plugin,
22
- HbarTransferPlugin,
26
+ HbarPlugin,
23
27
  InscribePlugin,
24
28
  LangChainAgent,
25
29
  LangChainProvider,
26
30
  MCPServers,
27
31
  MemoryWindow,
28
32
  HCS10Plugin2 as OpenConvAIPlugin,
33
+ ResolveEntitiesTool,
29
34
  SmartMemoryManager,
30
35
  TokenCounter,
31
36
  createAgent,
37
+ createEntityTools,
32
38
  createMCPConfig,
33
39
  validateServerConfig
34
40
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
@@ -1,11 +1,10 @@
1
1
  import { encoding_for_model } from "tiktoken";
2
2
  const _TokenCounter = class _TokenCounter {
3
3
  constructor(modelName = "gpt-4o") {
4
- this.modelName = modelName;
4
+ this.modelName = String(modelName);
5
5
  try {
6
6
  this.encoding = encoding_for_model(modelName);
7
7
  } catch {
8
- console.warn(`Model ${modelName} not found, falling back to gpt-4o encoding`);
9
8
  this.encoding = encoding_for_model("gpt-4o");
10
9
  this.modelName = "gpt-4o";
11
10
  }
@@ -23,7 +22,6 @@ const _TokenCounter = class _TokenCounter {
23
22
  const tokens = this.encoding.encode(text);
24
23
  return tokens.length;
25
24
  } catch (error) {
26
- console.warn("Error counting tokens, falling back to word-based estimation:", error);
27
25
  return Math.ceil(text.split(/\s+/).length * 1.3);
28
26
  }
29
27
  }
@@ -114,7 +112,6 @@ const _TokenCounter = class _TokenCounter {
114
112
  try {
115
113
  this.encoding.free();
116
114
  } catch {
117
- console.warn("Error disposing encoding");
118
115
  }
119
116
  }
120
117
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index12.js","sources":["../../src/memory/TokenCounter.ts"],"sourcesContent":["import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: TiktokenModel;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: TiktokenModel = 'gpt-4o') {\n this.modelName = modelName;\n try {\n this.encoding = encoding_for_model(modelName);\n } catch {\n console.warn(`Model ${modelName} not found, falling back to gpt-4o encoding`);\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch (error) {\n console.warn('Error counting tokens, falling back to word-based estimation:', error);\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n console.warn('Error disposing encoding');\n }\n }\n}"],"names":[],"mappings":";AAQO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAOxB,YAAY,YAA2B,UAAU;AAC/C,SAAK,YAAY;AACjB,QAAI;AACF,WAAK,WAAW,mBAAmB,SAAS;AAAA,IAC9C,QAAQ;AACN,cAAQ,KAAK,SAAS,SAAS,6CAA6C;AAC5E,WAAK,WAAW,mBAAmB,QAAQ;AAC3C,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAAsB;AAChC,QAAI,CAAC,QAAQ,KAAK,KAAA,MAAW,IAAI;AAC/B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,SAAS,KAAK,SAAS,OAAO,IAAI;AACxC,aAAO,OAAO;AAAA,IAChB,SAAS,OAAO;AACd,cAAQ,KAAK,iEAAiE,KAAK;AACnF,aAAO,KAAK,KAAK,KAAK,MAAM,KAAK,EAAE,SAAS,GAAG;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAA8B;AAC/C,UAAM,gBAAgB,KAAK,YAAY,OAAO,QAAQ,WAAW,EAAE,CAAC;AACpE,UAAM,aAAa,KAAK,YAAY,KAAK,eAAe,OAAO,CAAC;AAEhE,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,UAAiC;AACnD,QAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ;AACZ,eAAW,WAAW,UAAU;AAC9B,eAAS,KAAK,mBAAmB,OAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BAA2B,cAA8B;AACvD,QAAI,CAAC,gBAAgB,aAAa,KAAA,MAAW,IAAI;AAC/C,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,KAAK,YAAY,YAAY;AACnD,UAAM,aAAa,KAAK,YAAY,QAAQ;AAE5C,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,cAAsB,UAAiC;AACzE,UAAM,eAAe,KAAK,2BAA2B,YAAY;AACjE,UAAM,gBAAgB,KAAK,oBAAoB,QAAQ;AAEvD,UAAM,qBAAqB;AAE3B,WAAO,eAAe,gBAAgB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,SAA8B;AACnD,UAAM,cAAc,QAAQ,SAAA;AAC5B,YAAQ,aAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI;AACF,WAAK,SAAS,KAAA;AAAA,IAChB,QAAQ;AACN,cAAQ,KAAK,0BAA0B;AAAA,IACzC;AAAA,EACF;AACF;AAvIE,cAAwB,mBAAmB;AAC3C,cAAwB,gBAAgB;AALnC,IAAM,eAAN;"}
1
+ {"version":3,"file":"index12.js","sources":["../../src/memory/TokenCounter.ts"],"sourcesContent":["import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch (error) {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}"],"names":[],"mappings":";AAQO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAOxB,YAAY,YAAoC,UAAU;AACxD,SAAK,YAAY,OAAO,SAAS;AACjC,QAAI;AACF,WAAK,WAAW,mBAAmB,SAA0B;AAAA,IAC/D,QAAQ;AACN,WAAK,WAAW,mBAAmB,QAAQ;AAC3C,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAAsB;AAChC,QAAI,CAAC,QAAQ,KAAK,KAAA,MAAW,IAAI;AAC/B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,SAAS,KAAK,SAAS,OAAO,IAAI;AACxC,aAAO,OAAO;AAAA,IAChB,SAAS,OAAO;AACd,aAAO,KAAK,KAAK,KAAK,MAAM,KAAK,EAAE,SAAS,GAAG;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAA8B;AAC/C,UAAM,gBAAgB,KAAK,YAAY,OAAO,QAAQ,WAAW,EAAE,CAAC;AACpE,UAAM,aAAa,KAAK,YAAY,KAAK,eAAe,OAAO,CAAC;AAEhE,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,UAAiC;AACnD,QAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ;AACZ,eAAW,WAAW,UAAU;AAC9B,eAAS,KAAK,mBAAmB,OAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BAA2B,cAA8B;AACvD,QAAI,CAAC,gBAAgB,aAAa,KAAA,MAAW,IAAI;AAC/C,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,KAAK,YAAY,YAAY;AACnD,UAAM,aAAa,KAAK,YAAY,QAAQ;AAE5C,WAAO,gBAAgB,aAAa,cAAa,mBAAmB,cAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,cAAsB,UAAiC;AACzE,UAAM,eAAe,KAAK,2BAA2B,YAAY;AACjE,UAAM,gBAAgB,KAAK,oBAAoB,QAAQ;AAEvD,UAAM,qBAAqB;AAE3B,WAAO,eAAe,gBAAgB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,SAA8B;AACnD,UAAM,cAAc,QAAQ,SAAA;AAC5B,YAAQ,aAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI;AACF,WAAK,SAAS,KAAA;AAAA,IAChB,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AApIE,cAAwB,mBAAmB;AAC3C,cAAwB,gBAAgB;AALnC,IAAM,eAAN;"}
@@ -51,7 +51,6 @@ const _MemoryWindow = class _MemoryWindow {
51
51
  }
52
52
  }
53
53
  if (prunedMessages.length > 1e3) {
54
- console.warn("MemoryWindow: Excessive pruning detected, stopping to prevent infinite loop");
55
54
  break;
56
55
  }
57
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index13.js","sources":["../../src/memory/MemoryWindow.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './TokenCounter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n \n this.messages.push(message);\n \n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n \n let prunedMessages: BaseMessage[] = [];\n \n if (currentTokens > availableTokens) {\n this.messages.pop();\n \n prunedMessages = this.pruneToFit();\n \n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity()\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n \n while (this.getCurrentTokenCount() > targetTokens && this.messages.length > 0) {\n const batchSize = Math.min(MemoryWindow.PRUNING_BATCH_SIZE, this.messages.length);\n \n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n \n if (prunedMessages.length > 1000) {\n console.warn('MemoryWindow: Excessive pruning detected, stopping to prevent infinite loop');\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve = (currentTokens + messageTokens) > (this.maxTokens - this.reserveTokens);\n \n if (messageTokens > this.maxTokens) {\n return false;\n }\n \n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens = this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig() {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > (this.maxTokens - this.reserveTokens)) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats() {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n \n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index13.js","sources":["../../src/memory/MemoryWindow.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './TokenCounter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n \n this.messages.push(message);\n \n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n \n let prunedMessages: BaseMessage[] = [];\n \n if (currentTokens > availableTokens) {\n this.messages.pop();\n \n prunedMessages = this.pruneToFit();\n \n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity()\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n \n while (this.getCurrentTokenCount() > targetTokens && this.messages.length > 0) {\n const batchSize = Math.min(MemoryWindow.PRUNING_BATCH_SIZE, this.messages.length);\n \n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n \n if (prunedMessages.length > 1000) {\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve = (currentTokens + messageTokens) > (this.maxTokens - this.reserveTokens);\n \n if (messageTokens > this.maxTokens) {\n return false;\n }\n \n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens = this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig() {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > (this.maxTokens - this.reserveTokens)) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats() {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n \n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { ReferenceIdGenerator } from "./index22.js";
2
- import { DEFAULT_CONTENT_REFERENCE_CONFIG, ContentReferenceError } from "./index23.js";
1
+ import { ReferenceIdGenerator } from "./index24.js";
2
+ import { DEFAULT_CONTENT_REFERENCE_CONFIG, ContentReferenceError } from "./index25.js";
3
3
  const _ContentStorage = class _ContentStorage {
4
4
  constructor(maxStorage = _ContentStorage.DEFAULT_MAX_STORAGE, referenceConfig) {
5
5
  this.messages = [];
@@ -88,7 +88,6 @@ const _ContentStorage = class _ContentStorage {
88
88
  const regex = new RegExp(query, caseSensitive ? "g" : "gi");
89
89
  matches = this.messages.filter((stored) => regex.test(stored.message.content)).map((stored) => stored.message);
90
90
  } catch (error) {
91
- console.warn("Invalid regex pattern:", query, error);
92
91
  return [];
93
92
  }
94
93
  } else {
@@ -306,7 +305,6 @@ const _ContentStorage = class _ContentStorage {
306
305
  } catch (error) {
307
306
  const duration = Date.now() - startTime;
308
307
  this.recordPerformanceMetric("creation", duration);
309
- console.error("[ContentStorage] Failed to store content:", error);
310
308
  throw new ContentReferenceError(
311
309
  `Failed to store content: ${error instanceof Error ? error.message : "Unknown error"}`,
312
310
  "system_error",
@@ -373,7 +371,6 @@ const _ContentStorage = class _ContentStorage {
373
371
  const duration = Date.now() - startTime;
374
372
  this.recordPerformanceMetric("resolution", duration);
375
373
  this.referenceStats.failedResolutions++;
376
- console.error(`[ContentStorage] Error resolving reference ${referenceId}:`, error);
377
374
  return {
378
375
  success: false,
379
376
  error: `System error resolving reference: ${error instanceof Error ? error.message : "Unknown error"}`,
@@ -507,7 +504,6 @@ const _ContentStorage = class _ContentStorage {
507
504
  const duration = Date.now() - startTime;
508
505
  this.recordPerformanceMetric("cleanup", duration);
509
506
  const errorMessage = `Cleanup process failed: ${error instanceof Error ? error.message : "Unknown error"}`;
510
- console.error("[ContentStorage]", errorMessage);
511
507
  errors.push(errorMessage);
512
508
  return { cleanedUp, errors };
513
509
  }
@@ -631,7 +627,6 @@ const _ContentStorage = class _ContentStorage {
631
627
  try {
632
628
  await this.performCleanup();
633
629
  } catch (error) {
634
- console.error("Error in scheduled reference cleanup:", error);
635
630
  }
636
631
  }, this.referenceConfig.cleanupIntervalMs);
637
632
  }