@hashgraphonline/conversational-agent 0.1.217 → 0.1.218
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/cli/readme.md +181 -0
- package/dist/cjs/constants/entity-references.d.ts +18 -0
- package/dist/cjs/constants/form-priorities.d.ts +24 -0
- package/dist/cjs/constants/index.d.ts +4 -0
- package/dist/cjs/constants/messages.d.ts +19 -0
- package/dist/cjs/constants/test-constants.d.ts +42 -0
- package/dist/cjs/conversational-agent.d.ts +3 -8
- package/dist/cjs/core/{ToolRegistry.d.ts → tool-registry.d.ts} +10 -7
- package/dist/{types/execution/ExecutionPipeline.d.ts → cjs/execution/execution-pipeline.d.ts} +3 -3
- package/dist/cjs/forms/field-guidance-registry.d.ts +108 -0
- package/dist/cjs/forms/form-generator.d.ts +2 -7
- package/dist/cjs/forms/index.d.ts +3 -0
- package/dist/cjs/forms/types.d.ts +9 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +7 -12
- package/dist/cjs/langchain/external-tool-wrapper.d.ts +101 -0
- package/dist/{types/langchain/FormAwareAgentExecutor.d.ts → cjs/langchain/form-aware-agent-executor.d.ts} +19 -12
- package/dist/cjs/langchain/index.d.ts +2 -0
- package/dist/{types → cjs/langchain}/langchain-agent.d.ts +15 -7
- package/dist/cjs/mcp/adapters/index.d.ts +1 -0
- package/dist/cjs/mcp/adapters/langchain.d.ts +1 -1
- package/dist/{types/mcp/ContentProcessor.d.ts → cjs/mcp/content-processor.d.ts} +1 -1
- package/dist/cjs/mcp/index.d.ts +5 -0
- package/dist/{types/mcp/MCPClientManager.d.ts → cjs/mcp/mcp-client-manager.d.ts} +1 -1
- package/dist/cjs/memory/{ContentStorage.d.ts → content-storage.d.ts} +4 -4
- package/dist/cjs/memory/index.d.ts +5 -7
- package/dist/{types/memory/MemoryWindow.d.ts → cjs/memory/memory-window.d.ts} +1 -1
- package/dist/{types/memory/SmartMemoryManager.d.ts → cjs/memory/smart-memory-manager.d.ts} +1 -1
- package/dist/cjs/services/{ContentStoreManager.d.ts → content-store-manager.d.ts} +6 -6
- package/dist/cjs/services/context/resolution-context.d.ts +49 -0
- package/dist/cjs/services/entity-resolver.d.ts +58 -0
- package/dist/cjs/services/formatters/converters/index.d.ts +2 -0
- package/dist/cjs/services/formatters/converters/string-normalization-converter.d.ts +13 -0
- package/dist/cjs/services/formatters/converters/topic-id-to-hrl-converter.d.ts +17 -0
- package/dist/cjs/services/formatters/format-converter-registry.d.ts +66 -0
- package/dist/cjs/services/formatters/index.d.ts +3 -0
- package/dist/cjs/services/formatters/types.d.ts +29 -0
- package/dist/cjs/services/index.d.ts +3 -0
- package/dist/cjs/services/resolution/resolution-pipeline.d.ts +44 -0
- package/dist/cjs/tools/index.d.ts +1 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/esm/index.js +40 -16
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index10.js +669 -13
- package/dist/esm/index10.js.map +1 -1
- package/dist/esm/index11.js +310 -95
- package/dist/esm/index11.js.map +1 -1
- package/dist/esm/index12.js +130 -95
- package/dist/esm/index12.js.map +1 -1
- package/dist/esm/index13.js +262 -153
- package/dist/esm/index13.js.map +1 -1
- package/dist/esm/index14.js +100 -664
- package/dist/esm/index14.js.map +1 -1
- package/dist/esm/index15.js +135 -408
- package/dist/esm/index15.js.map +1 -1
- package/dist/esm/index16.js +240 -122
- package/dist/esm/index16.js.map +1 -1
- package/dist/esm/index17.js +147 -135
- package/dist/esm/index17.js.map +1 -1
- package/dist/esm/index18.js +376 -533
- package/dist/esm/index18.js.map +1 -1
- package/dist/esm/index19.js +87 -214
- package/dist/esm/index19.js.map +1 -1
- package/dist/esm/index2.js +21 -4
- package/dist/esm/index2.js.map +1 -1
- package/dist/esm/index20.js +158 -92
- package/dist/esm/index20.js.map +1 -1
- package/dist/esm/index21.js +717 -44
- package/dist/esm/index21.js.map +1 -1
- package/dist/esm/index22.js +58 -96
- package/dist/esm/index22.js.map +1 -1
- package/dist/esm/index23.js +324 -34
- package/dist/esm/index23.js.map +1 -1
- package/dist/esm/index24.js +125 -712
- package/dist/esm/index24.js.map +1 -1
- package/dist/esm/index25.js +113 -133
- package/dist/esm/index25.js.map +1 -1
- package/dist/esm/index26.js +18 -152
- package/dist/esm/index26.js.map +1 -1
- package/dist/esm/index27.js +14 -210
- package/dist/esm/index27.js.map +1 -1
- package/dist/esm/index28.js +70 -173
- package/dist/esm/index28.js.map +1 -1
- package/dist/esm/index29.js +811 -224
- package/dist/esm/index29.js.map +1 -1
- package/dist/esm/index30.js +1245 -122
- package/dist/esm/index30.js.map +1 -1
- package/dist/esm/index31.js +126 -56
- package/dist/esm/index31.js.map +1 -1
- package/dist/esm/index32.js +111 -24
- package/dist/esm/index32.js.map +1 -1
- package/dist/esm/index33.js +41 -87
- package/dist/esm/index33.js.map +1 -1
- package/dist/esm/index34.js +88 -227
- package/dist/esm/index34.js.map +1 -1
- package/dist/esm/index35.js +24 -0
- package/dist/esm/index35.js.map +1 -0
- package/dist/esm/index36.js +15 -0
- package/dist/esm/index36.js.map +1 -0
- package/dist/esm/index37.js +10 -0
- package/dist/esm/index37.js.map +1 -0
- package/dist/esm/index38.js +8 -0
- package/dist/esm/index38.js.map +1 -0
- package/dist/esm/index39.js +227 -0
- package/dist/esm/index39.js.map +1 -0
- package/dist/esm/index40.js +187 -0
- package/dist/esm/index40.js.map +1 -0
- package/dist/esm/index41.js +30 -0
- package/dist/esm/index41.js.map +1 -0
- package/dist/esm/index42.js +95 -0
- package/dist/esm/index42.js.map +1 -0
- package/dist/esm/index5.js +2 -2
- package/dist/esm/index5.js.map +1 -1
- package/dist/esm/index6.js +44 -67
- package/dist/esm/index6.js.map +1 -1
- package/dist/esm/index7.js +9 -0
- package/dist/esm/index7.js.map +1 -1
- package/dist/esm/index8.js +13 -1095
- package/dist/esm/index8.js.map +1 -1
- package/dist/esm/index9.js +17 -13
- package/dist/esm/index9.js.map +1 -1
- package/dist/types/constants/entity-references.d.ts +18 -0
- package/dist/types/constants/form-priorities.d.ts +24 -0
- package/dist/types/constants/index.d.ts +4 -0
- package/dist/types/constants/messages.d.ts +19 -0
- package/dist/types/constants/test-constants.d.ts +42 -0
- package/dist/types/conversational-agent.d.ts +3 -8
- package/dist/types/core/{ToolRegistry.d.ts → tool-registry.d.ts} +10 -7
- package/dist/{cjs/execution/ExecutionPipeline.d.ts → types/execution/execution-pipeline.d.ts} +3 -3
- package/dist/types/forms/field-guidance-registry.d.ts +108 -0
- package/dist/types/forms/form-generator.d.ts +2 -7
- package/dist/types/forms/index.d.ts +3 -0
- package/dist/types/forms/types.d.ts +9 -1
- package/dist/types/index.d.ts +7 -12
- package/dist/types/langchain/external-tool-wrapper.d.ts +101 -0
- package/dist/{cjs/langchain/FormAwareAgentExecutor.d.ts → types/langchain/form-aware-agent-executor.d.ts} +19 -12
- package/dist/types/langchain/index.d.ts +2 -0
- package/dist/{cjs → types/langchain}/langchain-agent.d.ts +15 -7
- package/dist/types/mcp/adapters/index.d.ts +1 -0
- package/dist/types/mcp/adapters/langchain.d.ts +1 -1
- package/dist/{cjs/mcp/ContentProcessor.d.ts → types/mcp/content-processor.d.ts} +1 -1
- package/dist/types/mcp/index.d.ts +5 -0
- package/dist/{cjs/mcp/MCPClientManager.d.ts → types/mcp/mcp-client-manager.d.ts} +1 -1
- package/dist/types/memory/{ContentStorage.d.ts → content-storage.d.ts} +4 -4
- package/dist/types/memory/index.d.ts +5 -7
- package/dist/{cjs/memory/MemoryWindow.d.ts → types/memory/memory-window.d.ts} +1 -1
- package/dist/{cjs/memory/SmartMemoryManager.d.ts → types/memory/smart-memory-manager.d.ts} +1 -1
- package/dist/types/services/{ContentStoreManager.d.ts → content-store-manager.d.ts} +6 -6
- package/dist/types/services/context/resolution-context.d.ts +49 -0
- package/dist/types/services/entity-resolver.d.ts +58 -0
- package/dist/types/services/formatters/converters/index.d.ts +2 -0
- package/dist/types/services/formatters/converters/string-normalization-converter.d.ts +13 -0
- package/dist/types/services/formatters/converters/topic-id-to-hrl-converter.d.ts +17 -0
- package/dist/types/services/formatters/format-converter-registry.d.ts +66 -0
- package/dist/types/services/formatters/index.d.ts +3 -0
- package/dist/types/services/formatters/types.d.ts +29 -0
- package/dist/types/services/index.d.ts +3 -0
- package/dist/types/services/resolution/resolution-pipeline.d.ts +44 -0
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/package.json +30 -27
- package/src/agent-factory.ts +1 -1
- package/src/base-agent.ts +9 -0
- package/src/config/system-message.ts +2 -15
- package/src/constants/entity-references.ts +23 -0
- package/src/constants/form-priorities.ts +25 -0
- package/src/constants/index.ts +4 -0
- package/src/constants/messages.ts +20 -0
- package/src/constants/test-constants.ts +49 -0
- package/src/conversational-agent.ts +42 -69
- package/src/core/{ToolRegistry.ts → tool-registry.ts} +70 -44
- package/src/examples/external-tool-wrapper-example.ts +56 -0
- package/src/execution/{ExecutionPipeline.ts → execution-pipeline.ts} +3 -3
- package/src/forms/field-guidance-registry.ts +415 -0
- package/src/forms/field-type-registry.ts +49 -48
- package/src/forms/{FormEngine.ts → form-engine.ts} +66 -43
- package/src/forms/form-generator.ts +91 -17
- package/src/forms/index.ts +4 -1
- package/src/forms/types.ts +9 -1
- package/src/index.ts +7 -37
- package/src/langchain/external-tool-wrapper.ts +90 -0
- package/src/langchain/{FormAwareAgentExecutor.ts → form-aware-agent-executor.ts} +579 -351
- package/src/langchain/index.ts +2 -0
- package/src/{langchain-agent.ts → langchain/langchain-agent.ts} +389 -113
- package/src/mcp/adapters/index.ts +1 -0
- package/src/mcp/adapters/langchain.ts +27 -18
- package/src/mcp/{ContentProcessor.ts → content-processor.ts} +71 -47
- package/src/mcp/index.ts +5 -0
- package/src/mcp/{MCPClientManager.ts → mcp-client-manager.ts} +2 -2
- package/src/memory/{ContentStorage.ts → content-storage.ts} +263 -167
- package/src/memory/index.ts +5 -8
- package/src/memory/{MemoryWindow.ts → memory-window.ts} +47 -24
- package/src/memory/{SmartMemoryManager.ts → smart-memory-manager.ts} +49 -22
- package/src/plugins/hbar/HbarPlugin.ts +1 -1
- package/src/plugins/hcs-10/HCS10Plugin.ts +46 -28
- package/src/scripts/test-external-tool-wrapper.ts +6 -6
- package/src/scripts/test-inscribe-form-generation.ts +22 -21
- package/src/scripts/test-inscribe-wrapper-verification.ts +5 -4
- package/src/services/{ContentStoreManager.ts → content-store-manager.ts} +75 -33
- package/src/services/context/resolution-context.ts +80 -0
- package/src/services/entity-resolver.ts +425 -0
- package/src/services/formatters/converters/index.ts +2 -0
- package/src/services/formatters/converters/string-normalization-converter.ts +106 -0
- package/src/services/formatters/converters/topic-id-to-hrl-converter.ts +25 -0
- package/src/services/formatters/format-converter-registry.ts +229 -0
- package/src/services/formatters/index.ts +3 -0
- package/src/services/formatters/types.ts +31 -0
- package/src/services/index.ts +3 -0
- package/src/services/resolution/resolution-pipeline.ts +106 -0
- package/src/tools/index.ts +1 -0
- package/src/types/content-reference.ts +87 -60
- package/src/utils/index.ts +1 -0
- package/cli/dist/CLIApp.d.ts +0 -9
- package/cli/dist/CLIApp.js +0 -127
- package/cli/dist/LocalConversationalAgent.d.ts +0 -37
- package/cli/dist/LocalConversationalAgent.js +0 -58
- package/cli/dist/app.d.ts +0 -16
- package/cli/dist/app.js +0 -13
- package/cli/dist/cli.d.ts +0 -2
- package/cli/dist/cli.js +0 -51
- package/cli/dist/components/AppContainer.d.ts +0 -16
- package/cli/dist/components/AppContainer.js +0 -24
- package/cli/dist/components/AppScreens.d.ts +0 -2
- package/cli/dist/components/AppScreens.js +0 -259
- package/cli/dist/components/ChatScreen.d.ts +0 -15
- package/cli/dist/components/ChatScreen.js +0 -39
- package/cli/dist/components/DebugLoadingScreen.d.ts +0 -5
- package/cli/dist/components/DebugLoadingScreen.js +0 -31
- package/cli/dist/components/LoadingScreen.d.ts +0 -2
- package/cli/dist/components/LoadingScreen.js +0 -16
- package/cli/dist/components/LoadingScreenDebug.d.ts +0 -5
- package/cli/dist/components/LoadingScreenDebug.js +0 -27
- package/cli/dist/components/MCPConfigScreen.d.ts +0 -28
- package/cli/dist/components/MCPConfigScreen.js +0 -168
- package/cli/dist/components/ScreenRouter.d.ts +0 -12
- package/cli/dist/components/ScreenRouter.js +0 -22
- package/cli/dist/components/SetupScreen.d.ts +0 -15
- package/cli/dist/components/SetupScreen.js +0 -65
- package/cli/dist/components/SingleLoadingScreen.d.ts +0 -5
- package/cli/dist/components/SingleLoadingScreen.js +0 -27
- package/cli/dist/components/StatusBadge.d.ts +0 -7
- package/cli/dist/components/StatusBadge.js +0 -28
- package/cli/dist/components/TerminalWindow.d.ts +0 -8
- package/cli/dist/components/TerminalWindow.js +0 -24
- package/cli/dist/components/WelcomeScreen.d.ts +0 -11
- package/cli/dist/components/WelcomeScreen.js +0 -47
- package/cli/dist/context/AppContext.d.ts +0 -68
- package/cli/dist/context/AppContext.js +0 -363
- package/cli/dist/hooks/useInitializeAgent.d.ts +0 -19
- package/cli/dist/hooks/useInitializeAgent.js +0 -28
- package/cli/dist/hooks/useStableState.d.ts +0 -38
- package/cli/dist/hooks/useStableState.js +0 -68
- package/cli/dist/managers/AgentManager.d.ts +0 -57
- package/cli/dist/managers/AgentManager.js +0 -119
- package/cli/dist/managers/ConfigManager.d.ts +0 -53
- package/cli/dist/managers/ConfigManager.js +0 -173
- package/cli/dist/types.d.ts +0 -31
- package/cli/dist/types.js +0 -19
- package/dist/cjs/context/ReferenceContextManager.d.ts +0 -84
- package/dist/cjs/context/ReferenceResponseProcessor.d.ts +0 -76
- package/dist/cjs/langchain/FormValidatingToolWrapper.d.ts +0 -81
- package/dist/cjs/services/EntityResolver.d.ts +0 -26
- package/dist/types/context/ReferenceContextManager.d.ts +0 -84
- package/dist/types/context/ReferenceResponseProcessor.d.ts +0 -76
- package/dist/types/langchain/FormValidatingToolWrapper.d.ts +0 -81
- package/dist/types/services/EntityResolver.d.ts +0 -26
- package/src/context/ReferenceContextManager.ts +0 -350
- package/src/context/ReferenceResponseProcessor.ts +0 -295
- package/src/langchain/FormValidatingToolWrapper.ts +0 -355
- package/src/scripts/test-hedera-kit-wrapper.ts +0 -265
- package/src/services/EntityResolver.ts +0 -128
- /package/dist/cjs/forms/{FormEngine.d.ts → form-engine.d.ts} +0 -0
- /package/dist/cjs/memory/{ReferenceIdGenerator.d.ts → reference-id-generator.d.ts} +0 -0
- /package/dist/cjs/memory/{TokenCounter.d.ts → token-counter.d.ts} +0 -0
- /package/dist/cjs/tools/{EntityResolverTool.d.ts → entity-resolver-tool.d.ts} +0 -0
- /package/dist/cjs/utils/{ResponseFormatter.d.ts → response-formatter.d.ts} +0 -0
- /package/dist/types/forms/{FormEngine.d.ts → form-engine.d.ts} +0 -0
- /package/dist/types/memory/{ReferenceIdGenerator.d.ts → reference-id-generator.d.ts} +0 -0
- /package/dist/types/memory/{TokenCounter.d.ts → token-counter.d.ts} +0 -0
- /package/dist/types/tools/{EntityResolverTool.d.ts → entity-resolver-tool.d.ts} +0 -0
- /package/dist/types/utils/{ResponseFormatter.d.ts → response-formatter.d.ts} +0 -0
- /package/src/memory/{ReferenceIdGenerator.ts → reference-id-generator.ts} +0 -0
- /package/src/memory/{TokenCounter.ts → token-counter.ts} +0 -0
- /package/src/tools/{EntityResolverTool.ts → entity-resolver-tool.ts} +0 -0
- /package/src/utils/{ResponseFormatter.ts → response-formatter.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
2
|
-
import { ReferenceIdGenerator } from './
|
|
2
|
+
import { ReferenceIdGenerator } from './reference-id-generator';
|
|
3
3
|
import {
|
|
4
4
|
ReferenceId,
|
|
5
5
|
ContentReference,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ContentType,
|
|
13
13
|
ContentSource,
|
|
14
14
|
ReferenceLifecycleState,
|
|
15
|
-
DEFAULT_CONTENT_REFERENCE_CONFIG
|
|
15
|
+
DEFAULT_CONTENT_REFERENCE_CONFIG,
|
|
16
16
|
} from '../types/content-reference';
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -68,13 +68,13 @@ export interface StorageStats {
|
|
|
68
68
|
interface StoredContent {
|
|
69
69
|
/** The actual content buffer */
|
|
70
70
|
content: Buffer;
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
/** Complete metadata */
|
|
73
73
|
metadata: ContentMetadata;
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
/** Current lifecycle state */
|
|
76
76
|
state: ReferenceLifecycleState;
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
/** When this reference expires (if applicable) */
|
|
79
79
|
expiresAt?: Date;
|
|
80
80
|
}
|
|
@@ -82,7 +82,7 @@ interface StoredContent {
|
|
|
82
82
|
/**
|
|
83
83
|
* Content storage for managing pruned conversation messages and large content references
|
|
84
84
|
* Provides searchable storage with time-based querying and automatic cleanup.
|
|
85
|
-
*
|
|
85
|
+
*
|
|
86
86
|
* Extended to support reference-based storage for large content to optimize context window usage.
|
|
87
87
|
*/
|
|
88
88
|
export class ContentStorage implements ContentReferenceStore {
|
|
@@ -108,8 +108,11 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
108
108
|
referenceConfig?: Partial<ContentReferenceConfig>
|
|
109
109
|
) {
|
|
110
110
|
this.maxStorage = maxStorage;
|
|
111
|
-
|
|
112
|
-
this.referenceConfig = {
|
|
111
|
+
|
|
112
|
+
this.referenceConfig = {
|
|
113
|
+
...DEFAULT_CONTENT_REFERENCE_CONFIG,
|
|
114
|
+
...referenceConfig,
|
|
115
|
+
};
|
|
113
116
|
this.referenceStats = {
|
|
114
117
|
activeReferences: 0,
|
|
115
118
|
totalStorageBytes: 0,
|
|
@@ -124,10 +127,10 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
124
127
|
averageCleanupTimeMs: 0,
|
|
125
128
|
creationTimes: [],
|
|
126
129
|
resolutionTimes: [],
|
|
127
|
-
cleanupTimes: []
|
|
128
|
-
}
|
|
130
|
+
cleanupTimes: [],
|
|
131
|
+
},
|
|
129
132
|
};
|
|
130
|
-
|
|
133
|
+
|
|
131
134
|
if (this.referenceConfig.enableAutoCleanup) {
|
|
132
135
|
this.startReferenceCleanupTimer();
|
|
133
136
|
}
|
|
@@ -147,10 +150,10 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
147
150
|
const now = new Date();
|
|
148
151
|
let dropped = 0;
|
|
149
152
|
|
|
150
|
-
const storedMessages: StoredMessage[] = messages.map(message => ({
|
|
153
|
+
const storedMessages: StoredMessage[] = messages.map((message) => ({
|
|
151
154
|
message,
|
|
152
155
|
storedAt: now,
|
|
153
|
-
id: this.generateId()
|
|
156
|
+
id: this.generateId(),
|
|
154
157
|
}));
|
|
155
158
|
|
|
156
159
|
this.messages.push(...storedMessages);
|
|
@@ -162,7 +165,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
162
165
|
|
|
163
166
|
return {
|
|
164
167
|
stored: storedMessages.length,
|
|
165
|
-
dropped
|
|
168
|
+
dropped,
|
|
166
169
|
};
|
|
167
170
|
}
|
|
168
171
|
|
|
@@ -177,9 +180,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
const startIndex = Math.max(0, this.messages.length - count);
|
|
180
|
-
return this.messages
|
|
181
|
-
.slice(startIndex)
|
|
182
|
-
.map(stored => stored.message);
|
|
183
|
+
return this.messages.slice(startIndex).map((stored) => stored.message);
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
/**
|
|
@@ -193,11 +194,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
193
194
|
return [];
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
const {
|
|
197
|
-
caseSensitive = false,
|
|
198
|
-
limit,
|
|
199
|
-
useRegex = false
|
|
200
|
-
} = options;
|
|
197
|
+
const { caseSensitive = false, limit, useRegex = false } = options;
|
|
201
198
|
|
|
202
199
|
let matches: BaseMessage[] = [];
|
|
203
200
|
|
|
@@ -205,20 +202,20 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
205
202
|
try {
|
|
206
203
|
const regex = new RegExp(query, caseSensitive ? 'g' : 'gi');
|
|
207
204
|
matches = this.messages
|
|
208
|
-
.filter(stored => regex.test(stored.message.content as string))
|
|
209
|
-
.map(stored => stored.message);
|
|
205
|
+
.filter((stored) => regex.test(stored.message.content as string))
|
|
206
|
+
.map((stored) => stored.message);
|
|
210
207
|
} catch {
|
|
211
208
|
return [];
|
|
212
209
|
}
|
|
213
210
|
} else {
|
|
214
211
|
const searchTerm = caseSensitive ? query : query.toLowerCase();
|
|
215
212
|
matches = this.messages
|
|
216
|
-
.filter(stored => {
|
|
213
|
+
.filter((stored) => {
|
|
217
214
|
const content = stored.message.content as string;
|
|
218
215
|
const searchContent = caseSensitive ? content : content.toLowerCase();
|
|
219
216
|
return searchContent.includes(searchTerm);
|
|
220
217
|
})
|
|
221
|
-
.map(stored => stored.message);
|
|
218
|
+
.map((stored) => stored.message);
|
|
222
219
|
}
|
|
223
220
|
|
|
224
221
|
return limit ? matches.slice(0, limit) : matches;
|
|
@@ -236,10 +233,10 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
236
233
|
}
|
|
237
234
|
|
|
238
235
|
return this.messages
|
|
239
|
-
.filter(
|
|
240
|
-
stored.storedAt >= startTime && stored.storedAt <= endTime
|
|
236
|
+
.filter(
|
|
237
|
+
(stored) => stored.storedAt >= startTime && stored.storedAt <= endTime
|
|
241
238
|
)
|
|
242
|
-
.map(stored => stored.message);
|
|
239
|
+
.map((stored) => stored.message);
|
|
243
240
|
}
|
|
244
241
|
|
|
245
242
|
/**
|
|
@@ -248,9 +245,10 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
248
245
|
*/
|
|
249
246
|
getStorageStats(): StorageStats {
|
|
250
247
|
const totalMessages = this.messages.length;
|
|
251
|
-
const usagePercentage =
|
|
252
|
-
|
|
253
|
-
|
|
248
|
+
const usagePercentage =
|
|
249
|
+
totalMessages > 0
|
|
250
|
+
? Math.round((totalMessages / this.maxStorage) * 100)
|
|
251
|
+
: 0;
|
|
254
252
|
|
|
255
253
|
let oldestMessageTime: Date | undefined;
|
|
256
254
|
let newestMessageTime: Date | undefined;
|
|
@@ -265,7 +263,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
265
263
|
maxStorageLimit: this.maxStorage,
|
|
266
264
|
usagePercentage,
|
|
267
265
|
oldestMessageTime,
|
|
268
|
-
newestMessageTime
|
|
266
|
+
newestMessageTime,
|
|
269
267
|
};
|
|
270
268
|
}
|
|
271
269
|
|
|
@@ -309,8 +307,8 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
309
307
|
*/
|
|
310
308
|
getMessagesByType(messageType: string, limit?: number): BaseMessage[] {
|
|
311
309
|
const filtered = this.messages
|
|
312
|
-
.filter(stored => stored.message._getType() === messageType)
|
|
313
|
-
.map(stored => stored.message);
|
|
310
|
+
.filter((stored) => stored.message._getType() === messageType)
|
|
311
|
+
.map((stored) => stored.message);
|
|
314
312
|
|
|
315
313
|
return limit ? filtered.slice(0, limit) : filtered;
|
|
316
314
|
}
|
|
@@ -319,11 +317,11 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
319
317
|
* Get the current storage configuration
|
|
320
318
|
* @returns Storage configuration object
|
|
321
319
|
*/
|
|
322
|
-
getConfig() {
|
|
320
|
+
getConfig(): { maxStorage: number; currentUsage: number; utilizationPercentage: number } {
|
|
323
321
|
return {
|
|
324
322
|
maxStorage: this.maxStorage,
|
|
325
323
|
currentUsage: this.messages.length,
|
|
326
|
-
utilizationPercentage: (this.messages.length / this.maxStorage) * 100
|
|
324
|
+
utilizationPercentage: (this.messages.length / this.maxStorage) * 100,
|
|
327
325
|
};
|
|
328
326
|
}
|
|
329
327
|
|
|
@@ -345,23 +343,23 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
345
343
|
return [];
|
|
346
344
|
}
|
|
347
345
|
|
|
348
|
-
const cutoffTime = new Date(Date.now() -
|
|
349
|
-
|
|
346
|
+
const cutoffTime = new Date(Date.now() - minutes * 60 * 1000);
|
|
347
|
+
|
|
350
348
|
return this.messages
|
|
351
|
-
.filter(stored => stored.storedAt >= cutoffTime)
|
|
352
|
-
.map(stored => stored.message);
|
|
349
|
+
.filter((stored) => stored.storedAt >= cutoffTime)
|
|
350
|
+
.map((stored) => stored.message);
|
|
353
351
|
}
|
|
354
352
|
|
|
355
353
|
/**
|
|
356
354
|
* Export messages to a JSON-serializable format
|
|
357
355
|
* @returns Serializable representation of stored messages
|
|
358
356
|
*/
|
|
359
|
-
exportMessages() {
|
|
360
|
-
return this.messages.map(stored => ({
|
|
357
|
+
exportMessages(): Array<{ content: string; type: string; storedAt: string; id: string }> {
|
|
358
|
+
return this.messages.map((stored) => ({
|
|
361
359
|
content: stored.message.content,
|
|
362
360
|
type: stored.message._getType(),
|
|
363
361
|
storedAt: stored.storedAt.toISOString(),
|
|
364
|
-
id: stored.id
|
|
362
|
+
id: stored.id,
|
|
365
363
|
}));
|
|
366
364
|
}
|
|
367
365
|
|
|
@@ -369,14 +367,16 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
369
367
|
* Determine if content should be stored as a reference based on size
|
|
370
368
|
*/
|
|
371
369
|
shouldUseReference(content: Buffer | string): boolean {
|
|
372
|
-
const size = Buffer.isBuffer(content)
|
|
370
|
+
const size = Buffer.isBuffer(content)
|
|
371
|
+
? content.length
|
|
372
|
+
: Buffer.byteLength(content, 'utf8');
|
|
373
373
|
return size > this.referenceConfig.sizeThresholdBytes;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
/**
|
|
377
377
|
* Store content and return a reference if it exceeds the size threshold
|
|
378
378
|
* Otherwise returns null to indicate direct content should be used
|
|
379
|
-
*
|
|
379
|
+
*
|
|
380
380
|
* Special case: Image files are ALWAYS stored as references regardless of size
|
|
381
381
|
* because they need special handling for inscription tools
|
|
382
382
|
*/
|
|
@@ -392,21 +392,31 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
392
392
|
customMetadata?: Record<string, unknown>;
|
|
393
393
|
}
|
|
394
394
|
): Promise<ContentReference | null> {
|
|
395
|
-
const buffer = Buffer.isBuffer(content)
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
395
|
+
const buffer = Buffer.isBuffer(content)
|
|
396
|
+
? content
|
|
397
|
+
: Buffer.from(content, 'utf8');
|
|
398
|
+
|
|
399
|
+
const isImageFile = this.isImageContent(
|
|
400
|
+
metadata.mimeType,
|
|
401
|
+
metadata.fileName
|
|
402
|
+
);
|
|
403
|
+
|
|
399
404
|
if (!isImageFile && !this.shouldUseReference(buffer)) {
|
|
400
405
|
return null;
|
|
401
406
|
}
|
|
402
|
-
|
|
403
|
-
const storeMetadata: Omit<
|
|
404
|
-
|
|
407
|
+
|
|
408
|
+
const storeMetadata: Omit<
|
|
409
|
+
ContentMetadata,
|
|
410
|
+
'createdAt' | 'lastAccessedAt' | 'accessCount'
|
|
411
|
+
> = {
|
|
412
|
+
contentType:
|
|
413
|
+
metadata.contentType ||
|
|
414
|
+
this.detectContentType(buffer, metadata.mimeType),
|
|
405
415
|
sizeBytes: buffer.length,
|
|
406
416
|
source: metadata.source,
|
|
407
|
-
tags: []
|
|
417
|
+
tags: [],
|
|
408
418
|
};
|
|
409
|
-
|
|
419
|
+
|
|
410
420
|
if (metadata.mimeType !== undefined) {
|
|
411
421
|
storeMetadata.mimeType = metadata.mimeType;
|
|
412
422
|
}
|
|
@@ -422,7 +432,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
422
432
|
if (metadata.customMetadata !== undefined) {
|
|
423
433
|
storeMetadata.customMetadata = metadata.customMetadata;
|
|
424
434
|
}
|
|
425
|
-
|
|
435
|
+
|
|
426
436
|
return await this.storeContent(buffer, storeMetadata);
|
|
427
437
|
}
|
|
428
438
|
|
|
@@ -431,72 +441,83 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
431
441
|
*/
|
|
432
442
|
async storeContent(
|
|
433
443
|
content: Buffer,
|
|
434
|
-
metadata: Omit<
|
|
444
|
+
metadata: Omit<
|
|
445
|
+
ContentMetadata,
|
|
446
|
+
'createdAt' | 'lastAccessedAt' | 'accessCount'
|
|
447
|
+
>
|
|
435
448
|
): Promise<ContentReference> {
|
|
436
449
|
const startTime = Date.now();
|
|
437
|
-
|
|
450
|
+
|
|
438
451
|
try {
|
|
439
452
|
const now = new Date();
|
|
440
453
|
const referenceId = ReferenceIdGenerator.generateId(content);
|
|
441
|
-
|
|
454
|
+
|
|
442
455
|
const fullMetadata: ContentMetadata = {
|
|
443
456
|
...metadata,
|
|
444
457
|
createdAt: now,
|
|
445
458
|
lastAccessedAt: now,
|
|
446
|
-
accessCount: 0
|
|
459
|
+
accessCount: 0,
|
|
447
460
|
};
|
|
448
|
-
|
|
461
|
+
|
|
449
462
|
const storedContent: StoredContent = {
|
|
450
463
|
content,
|
|
451
464
|
metadata: fullMetadata,
|
|
452
|
-
state: 'active'
|
|
465
|
+
state: 'active',
|
|
453
466
|
};
|
|
454
|
-
|
|
467
|
+
|
|
455
468
|
const expirationTime = this.calculateExpirationTime(metadata.source);
|
|
456
469
|
if (expirationTime !== undefined) {
|
|
457
470
|
storedContent.expiresAt = expirationTime;
|
|
458
471
|
}
|
|
459
|
-
|
|
472
|
+
|
|
460
473
|
this.contentStore.set(referenceId, storedContent);
|
|
461
|
-
|
|
474
|
+
|
|
462
475
|
this.updateStatsAfterStore(content.length);
|
|
463
|
-
|
|
476
|
+
|
|
464
477
|
await this.enforceReferenceStorageLimits();
|
|
465
|
-
|
|
466
|
-
const preview = this.createContentPreview(
|
|
467
|
-
|
|
468
|
-
|
|
478
|
+
|
|
479
|
+
const preview = this.createContentPreview(
|
|
480
|
+
content,
|
|
481
|
+
fullMetadata.contentType
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
const referenceMetadata: Pick<
|
|
485
|
+
ContentMetadata,
|
|
486
|
+
'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'
|
|
487
|
+
> = {
|
|
469
488
|
contentType: fullMetadata.contentType,
|
|
470
489
|
sizeBytes: fullMetadata.sizeBytes,
|
|
471
|
-
source: fullMetadata.source
|
|
490
|
+
source: fullMetadata.source,
|
|
472
491
|
};
|
|
473
|
-
|
|
492
|
+
|
|
474
493
|
if (fullMetadata.fileName !== undefined) {
|
|
475
494
|
referenceMetadata.fileName = fullMetadata.fileName;
|
|
476
495
|
}
|
|
477
496
|
if (fullMetadata.mimeType !== undefined) {
|
|
478
497
|
referenceMetadata.mimeType = fullMetadata.mimeType;
|
|
479
498
|
}
|
|
480
|
-
|
|
499
|
+
|
|
481
500
|
const reference: ContentReference = {
|
|
482
501
|
referenceId,
|
|
483
502
|
state: 'active',
|
|
484
503
|
preview,
|
|
485
504
|
metadata: referenceMetadata,
|
|
486
505
|
createdAt: now,
|
|
487
|
-
format: 'ref://{id}' as const
|
|
506
|
+
format: 'ref://{id}' as const,
|
|
488
507
|
};
|
|
489
|
-
|
|
508
|
+
|
|
490
509
|
const duration = Date.now() - startTime;
|
|
491
510
|
this.recordPerformanceMetric('creation', duration);
|
|
492
|
-
|
|
511
|
+
|
|
493
512
|
return reference;
|
|
494
513
|
} catch (error) {
|
|
495
514
|
const duration = Date.now() - startTime;
|
|
496
515
|
this.recordPerformanceMetric('creation', duration);
|
|
497
|
-
|
|
516
|
+
|
|
498
517
|
throw new ContentReferenceError(
|
|
499
|
-
`Failed to store content: ${
|
|
518
|
+
`Failed to store content: ${
|
|
519
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
520
|
+
}`,
|
|
500
521
|
'system_error',
|
|
501
522
|
undefined,
|
|
502
523
|
['Try again', 'Check storage limits', 'Contact administrator']
|
|
@@ -507,9 +528,11 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
507
528
|
/**
|
|
508
529
|
* Resolve a reference to its content (implements ContentReferenceStore)
|
|
509
530
|
*/
|
|
510
|
-
async resolveReference(
|
|
531
|
+
async resolveReference(
|
|
532
|
+
referenceId: ReferenceId
|
|
533
|
+
): Promise<ReferenceResolutionResult> {
|
|
511
534
|
const startTime = Date.now();
|
|
512
|
-
|
|
535
|
+
|
|
513
536
|
try {
|
|
514
537
|
if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {
|
|
515
538
|
this.referenceStats.failedResolutions++;
|
|
@@ -517,22 +540,29 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
517
540
|
success: false,
|
|
518
541
|
error: 'Invalid reference ID format',
|
|
519
542
|
errorType: 'not_found',
|
|
520
|
-
suggestedActions: [
|
|
543
|
+
suggestedActions: [
|
|
544
|
+
'Check the reference ID format',
|
|
545
|
+
'Ensure the reference ID is complete',
|
|
546
|
+
],
|
|
521
547
|
};
|
|
522
548
|
}
|
|
523
|
-
|
|
549
|
+
|
|
524
550
|
const storedContent = this.contentStore.get(referenceId);
|
|
525
|
-
|
|
551
|
+
|
|
526
552
|
if (!storedContent) {
|
|
527
553
|
this.referenceStats.failedResolutions++;
|
|
528
554
|
return {
|
|
529
555
|
success: false,
|
|
530
556
|
error: 'Reference not found',
|
|
531
557
|
errorType: 'not_found',
|
|
532
|
-
suggestedActions: [
|
|
558
|
+
suggestedActions: [
|
|
559
|
+
'Verify the reference ID',
|
|
560
|
+
'Check if the content has expired',
|
|
561
|
+
'Request fresh content',
|
|
562
|
+
],
|
|
533
563
|
};
|
|
534
564
|
}
|
|
535
|
-
|
|
565
|
+
|
|
536
566
|
if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {
|
|
537
567
|
storedContent.state = 'expired';
|
|
538
568
|
this.referenceStats.failedResolutions++;
|
|
@@ -540,44 +570,53 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
540
570
|
success: false,
|
|
541
571
|
error: 'Reference has expired',
|
|
542
572
|
errorType: 'expired',
|
|
543
|
-
suggestedActions: [
|
|
573
|
+
suggestedActions: [
|
|
574
|
+
'Request fresh content',
|
|
575
|
+
'Use alternative content source',
|
|
576
|
+
],
|
|
544
577
|
};
|
|
545
578
|
}
|
|
546
|
-
|
|
579
|
+
|
|
547
580
|
if (storedContent.state !== 'active') {
|
|
548
581
|
this.referenceStats.failedResolutions++;
|
|
549
582
|
return {
|
|
550
583
|
success: false,
|
|
551
584
|
error: `Reference is ${storedContent.state}`,
|
|
552
|
-
errorType:
|
|
553
|
-
|
|
585
|
+
errorType:
|
|
586
|
+
storedContent.state === 'expired' ? 'expired' : 'corrupted',
|
|
587
|
+
suggestedActions: [
|
|
588
|
+
'Request fresh content',
|
|
589
|
+
'Check reference validity',
|
|
590
|
+
],
|
|
554
591
|
};
|
|
555
592
|
}
|
|
556
|
-
|
|
593
|
+
|
|
557
594
|
storedContent.metadata.lastAccessedAt = new Date();
|
|
558
595
|
storedContent.metadata.accessCount++;
|
|
559
|
-
|
|
596
|
+
|
|
560
597
|
this.referenceStats.totalResolutions++;
|
|
561
|
-
|
|
598
|
+
|
|
562
599
|
const duration = Date.now() - startTime;
|
|
563
600
|
this.recordPerformanceMetric('resolution', duration);
|
|
564
|
-
|
|
601
|
+
|
|
565
602
|
return {
|
|
566
603
|
success: true,
|
|
567
604
|
content: storedContent.content,
|
|
568
|
-
metadata: storedContent.metadata
|
|
605
|
+
metadata: storedContent.metadata,
|
|
569
606
|
};
|
|
570
607
|
} catch (error) {
|
|
571
608
|
const duration = Date.now() - startTime;
|
|
572
609
|
this.recordPerformanceMetric('resolution', duration);
|
|
573
|
-
|
|
610
|
+
|
|
574
611
|
this.referenceStats.failedResolutions++;
|
|
575
|
-
|
|
612
|
+
|
|
576
613
|
return {
|
|
577
614
|
success: false,
|
|
578
|
-
error: `System error resolving reference: ${
|
|
615
|
+
error: `System error resolving reference: ${
|
|
616
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
617
|
+
}`,
|
|
579
618
|
errorType: 'system_error',
|
|
580
|
-
suggestedActions: ['Try again', 'Contact administrator']
|
|
619
|
+
suggestedActions: ['Try again', 'Contact administrator'],
|
|
581
620
|
};
|
|
582
621
|
}
|
|
583
622
|
}
|
|
@@ -589,17 +628,17 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
589
628
|
if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {
|
|
590
629
|
return false;
|
|
591
630
|
}
|
|
592
|
-
|
|
631
|
+
|
|
593
632
|
const storedContent = this.contentStore.get(referenceId);
|
|
594
633
|
if (!storedContent) {
|
|
595
634
|
return false;
|
|
596
635
|
}
|
|
597
|
-
|
|
636
|
+
|
|
598
637
|
if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {
|
|
599
638
|
storedContent.state = 'expired';
|
|
600
639
|
return false;
|
|
601
640
|
}
|
|
602
|
-
|
|
641
|
+
|
|
603
642
|
return storedContent.state === 'active';
|
|
604
643
|
}
|
|
605
644
|
|
|
@@ -611,13 +650,13 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
611
650
|
if (!storedContent) {
|
|
612
651
|
return false;
|
|
613
652
|
}
|
|
614
|
-
|
|
653
|
+
|
|
615
654
|
this.referenceStats.totalStorageBytes -= storedContent.content.length;
|
|
616
655
|
this.referenceStats.activeReferences--;
|
|
617
656
|
this.referenceStats.recentlyCleanedUp++;
|
|
618
|
-
|
|
657
|
+
|
|
619
658
|
this.contentStore.delete(referenceId);
|
|
620
|
-
|
|
659
|
+
|
|
621
660
|
return true;
|
|
622
661
|
}
|
|
623
662
|
|
|
@@ -626,14 +665,20 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
626
665
|
*/
|
|
627
666
|
async getStats(): Promise<ContentReferenceStats> {
|
|
628
667
|
this.updateReferenceStorageStats();
|
|
629
|
-
|
|
668
|
+
|
|
630
669
|
return {
|
|
631
670
|
...this.referenceStats,
|
|
632
671
|
performanceMetrics: {
|
|
633
|
-
averageCreationTimeMs: this.calculateAverage(
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
672
|
+
averageCreationTimeMs: this.calculateAverage(
|
|
673
|
+
this.referenceStats.performanceMetrics.creationTimes
|
|
674
|
+
),
|
|
675
|
+
averageResolutionTimeMs: this.calculateAverage(
|
|
676
|
+
this.referenceStats.performanceMetrics.resolutionTimes
|
|
677
|
+
),
|
|
678
|
+
averageCleanupTimeMs: this.calculateAverage(
|
|
679
|
+
this.referenceStats.performanceMetrics.cleanupTimes
|
|
680
|
+
),
|
|
681
|
+
},
|
|
637
682
|
};
|
|
638
683
|
}
|
|
639
684
|
|
|
@@ -642,12 +687,12 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
642
687
|
*/
|
|
643
688
|
async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {
|
|
644
689
|
this.referenceConfig = { ...this.referenceConfig, ...config };
|
|
645
|
-
|
|
690
|
+
|
|
646
691
|
if (this.cleanupTimer) {
|
|
647
692
|
clearInterval(this.cleanupTimer);
|
|
648
693
|
delete this.cleanupTimer;
|
|
649
694
|
}
|
|
650
|
-
|
|
695
|
+
|
|
651
696
|
if (this.referenceConfig.enableAutoCleanup) {
|
|
652
697
|
this.startReferenceCleanupTimer();
|
|
653
698
|
}
|
|
@@ -660,43 +705,48 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
660
705
|
const startTime = Date.now();
|
|
661
706
|
const errors: string[] = [];
|
|
662
707
|
let cleanedUp = 0;
|
|
663
|
-
|
|
708
|
+
|
|
664
709
|
try {
|
|
665
710
|
const now = new Date();
|
|
666
711
|
const toCleanup: ReferenceId[] = [];
|
|
667
|
-
|
|
712
|
+
|
|
668
713
|
for (const [referenceId, storedContent] of this.contentStore.entries()) {
|
|
669
714
|
let shouldCleanup = false;
|
|
670
|
-
|
|
715
|
+
|
|
671
716
|
if (storedContent.expiresAt && storedContent.expiresAt < now) {
|
|
672
717
|
shouldCleanup = true;
|
|
673
718
|
storedContent.state = 'expired';
|
|
674
719
|
}
|
|
675
|
-
|
|
676
|
-
const ageMs =
|
|
720
|
+
|
|
721
|
+
const ageMs =
|
|
722
|
+
now.getTime() - storedContent.metadata.createdAt.getTime();
|
|
677
723
|
const policy = this.getCleanupPolicy(storedContent.metadata.source);
|
|
678
|
-
|
|
724
|
+
|
|
679
725
|
if (ageMs > policy.maxAgeMs) {
|
|
680
726
|
shouldCleanup = true;
|
|
681
727
|
}
|
|
682
|
-
|
|
728
|
+
|
|
683
729
|
if (storedContent.state === 'cleanup_pending') {
|
|
684
730
|
shouldCleanup = true;
|
|
685
731
|
}
|
|
686
|
-
|
|
732
|
+
|
|
687
733
|
if (shouldCleanup) {
|
|
688
734
|
toCleanup.push(referenceId);
|
|
689
735
|
}
|
|
690
736
|
}
|
|
691
|
-
|
|
737
|
+
|
|
692
738
|
toCleanup.sort((a, b) => {
|
|
693
739
|
const aContent = this.contentStore.get(a)!;
|
|
694
740
|
const bContent = this.contentStore.get(b)!;
|
|
695
|
-
const aPriority = this.getCleanupPolicy(
|
|
696
|
-
|
|
741
|
+
const aPriority = this.getCleanupPolicy(
|
|
742
|
+
aContent.metadata.source
|
|
743
|
+
).priority;
|
|
744
|
+
const bPriority = this.getCleanupPolicy(
|
|
745
|
+
bContent.metadata.source
|
|
746
|
+
).priority;
|
|
697
747
|
return bPriority - aPriority;
|
|
698
748
|
});
|
|
699
|
-
|
|
749
|
+
|
|
700
750
|
for (const referenceId of toCleanup) {
|
|
701
751
|
try {
|
|
702
752
|
const success = await this.cleanupReference(referenceId);
|
|
@@ -704,15 +754,23 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
704
754
|
cleanedUp++;
|
|
705
755
|
}
|
|
706
756
|
} catch (error) {
|
|
707
|
-
errors.push(
|
|
757
|
+
errors.push(
|
|
758
|
+
`Failed to cleanup ${referenceId}: ${
|
|
759
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
760
|
+
}`
|
|
761
|
+
);
|
|
708
762
|
}
|
|
709
763
|
}
|
|
710
|
-
|
|
764
|
+
|
|
711
765
|
if (this.contentStore.size > this.referenceConfig.maxReferences) {
|
|
712
|
-
const sortedByAge = Array.from(this.contentStore.entries())
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
766
|
+
const sortedByAge = Array.from(this.contentStore.entries()).sort(
|
|
767
|
+
([, a], [, b]) =>
|
|
768
|
+
a.metadata.lastAccessedAt.getTime() -
|
|
769
|
+
b.metadata.lastAccessedAt.getTime()
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
const excessCount =
|
|
773
|
+
this.contentStore.size - this.referenceConfig.maxReferences;
|
|
716
774
|
for (let i = 0; i < excessCount && i < sortedByAge.length; i++) {
|
|
717
775
|
const [referenceId] = sortedByAge[i];
|
|
718
776
|
try {
|
|
@@ -721,22 +779,28 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
721
779
|
cleanedUp++;
|
|
722
780
|
}
|
|
723
781
|
} catch (error) {
|
|
724
|
-
errors.push(
|
|
782
|
+
errors.push(
|
|
783
|
+
`Failed to cleanup excess reference ${referenceId}: ${
|
|
784
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
785
|
+
}`
|
|
786
|
+
);
|
|
725
787
|
}
|
|
726
788
|
}
|
|
727
789
|
}
|
|
728
|
-
|
|
790
|
+
|
|
729
791
|
const duration = Date.now() - startTime;
|
|
730
792
|
this.recordPerformanceMetric('cleanup', duration);
|
|
731
|
-
|
|
793
|
+
|
|
732
794
|
return { cleanedUp, errors };
|
|
733
795
|
} catch (error) {
|
|
734
796
|
const duration = Date.now() - startTime;
|
|
735
797
|
this.recordPerformanceMetric('cleanup', duration);
|
|
736
|
-
|
|
737
|
-
const errorMessage = `Cleanup process failed: ${
|
|
798
|
+
|
|
799
|
+
const errorMessage = `Cleanup process failed: ${
|
|
800
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
801
|
+
}`;
|
|
738
802
|
errors.push(errorMessage);
|
|
739
|
-
|
|
803
|
+
|
|
740
804
|
return { cleanedUp, errors };
|
|
741
805
|
}
|
|
742
806
|
}
|
|
@@ -752,8 +816,11 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
752
816
|
if (this.contentStore.size >= this.referenceConfig.maxReferences) {
|
|
753
817
|
await this.performCleanup();
|
|
754
818
|
}
|
|
755
|
-
|
|
756
|
-
if (
|
|
819
|
+
|
|
820
|
+
if (
|
|
821
|
+
this.referenceStats.totalStorageBytes >=
|
|
822
|
+
this.referenceConfig.maxTotalStorageBytes
|
|
823
|
+
) {
|
|
757
824
|
await this.performCleanup();
|
|
758
825
|
}
|
|
759
826
|
}
|
|
@@ -763,7 +830,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
763
830
|
return new Date(Date.now() + policy.maxAgeMs);
|
|
764
831
|
}
|
|
765
832
|
|
|
766
|
-
private getCleanupPolicy(source: ContentSource) {
|
|
833
|
+
private getCleanupPolicy(source: ContentSource): { maxAgeMs: number; priority: number } {
|
|
767
834
|
switch (source) {
|
|
768
835
|
case 'mcp_tool':
|
|
769
836
|
return this.referenceConfig.cleanupPolicies.recent;
|
|
@@ -784,19 +851,32 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
784
851
|
if (mimeType.startsWith('text/')) return 'text';
|
|
785
852
|
return 'binary';
|
|
786
853
|
}
|
|
787
|
-
|
|
788
|
-
const contentStr = content.toString(
|
|
854
|
+
|
|
855
|
+
const contentStr = content.toString(
|
|
856
|
+
'utf8',
|
|
857
|
+
0,
|
|
858
|
+
Math.min(content.length, 1000)
|
|
859
|
+
);
|
|
789
860
|
if (contentStr.startsWith('{') || contentStr.startsWith('[')) return 'json';
|
|
790
|
-
if (contentStr.includes('<html>') || contentStr.includes('<!DOCTYPE'))
|
|
791
|
-
|
|
792
|
-
|
|
861
|
+
if (contentStr.includes('<html>') || contentStr.includes('<!DOCTYPE'))
|
|
862
|
+
return 'html';
|
|
863
|
+
if (contentStr.includes('#') && contentStr.includes('\n'))
|
|
864
|
+
return 'markdown';
|
|
865
|
+
|
|
793
866
|
return 'text';
|
|
794
867
|
}
|
|
795
868
|
|
|
796
|
-
private createContentPreview(
|
|
869
|
+
private createContentPreview(
|
|
870
|
+
content: Buffer,
|
|
871
|
+
contentType: ContentType
|
|
872
|
+
): string {
|
|
797
873
|
const maxLength = 200;
|
|
798
|
-
let preview = content.toString(
|
|
799
|
-
|
|
874
|
+
let preview = content.toString(
|
|
875
|
+
'utf8',
|
|
876
|
+
0,
|
|
877
|
+
Math.min(content.length, maxLength * 2)
|
|
878
|
+
);
|
|
879
|
+
|
|
800
880
|
if (contentType === 'html') {
|
|
801
881
|
preview = preview
|
|
802
882
|
.replace(/<[^>]*>/g, '')
|
|
@@ -806,15 +886,14 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
806
886
|
try {
|
|
807
887
|
const parsed = JSON.parse(preview);
|
|
808
888
|
preview = JSON.stringify(parsed, null, 0);
|
|
809
|
-
} catch {
|
|
810
|
-
}
|
|
889
|
+
} catch {}
|
|
811
890
|
}
|
|
812
|
-
|
|
891
|
+
|
|
813
892
|
preview = preview.trim();
|
|
814
893
|
if (preview.length > maxLength) {
|
|
815
894
|
preview = preview.substring(0, maxLength) + '...';
|
|
816
895
|
}
|
|
817
|
-
|
|
896
|
+
|
|
818
897
|
return preview || '[Binary content]';
|
|
819
898
|
}
|
|
820
899
|
|
|
@@ -826,21 +905,26 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
826
905
|
|
|
827
906
|
private updateReferenceStorageStats(): void {
|
|
828
907
|
if (this.referenceStats.activeReferences > 0) {
|
|
829
|
-
this.referenceStats.averageContentSize =
|
|
908
|
+
this.referenceStats.averageContentSize =
|
|
909
|
+
this.referenceStats.totalStorageBytes /
|
|
910
|
+
this.referenceStats.activeReferences;
|
|
830
911
|
}
|
|
831
|
-
|
|
832
|
-
this.referenceStats.storageUtilization =
|
|
833
|
-
|
|
912
|
+
|
|
913
|
+
this.referenceStats.storageUtilization =
|
|
914
|
+
(this.referenceStats.totalStorageBytes /
|
|
915
|
+
this.referenceConfig.maxTotalStorageBytes) *
|
|
916
|
+
100;
|
|
917
|
+
|
|
834
918
|
let mostAccessedId: ReferenceId | undefined;
|
|
835
919
|
let maxAccess = 0;
|
|
836
|
-
|
|
920
|
+
|
|
837
921
|
for (const [referenceId, storedContent] of this.contentStore.entries()) {
|
|
838
922
|
if (storedContent.metadata.accessCount > maxAccess) {
|
|
839
923
|
maxAccess = storedContent.metadata.accessCount;
|
|
840
924
|
mostAccessedId = referenceId;
|
|
841
925
|
}
|
|
842
926
|
}
|
|
843
|
-
|
|
927
|
+
|
|
844
928
|
if (mostAccessedId !== undefined) {
|
|
845
929
|
this.referenceStats.mostAccessedReferenceId = mostAccessedId;
|
|
846
930
|
} else {
|
|
@@ -855,20 +939,33 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
855
939
|
if (mimeType && mimeType.startsWith('image/')) {
|
|
856
940
|
return true;
|
|
857
941
|
}
|
|
858
|
-
|
|
942
|
+
|
|
859
943
|
if (fileName) {
|
|
860
944
|
const lowerFileName = fileName.toLowerCase();
|
|
861
|
-
const imageExtensions = [
|
|
862
|
-
|
|
945
|
+
const imageExtensions = [
|
|
946
|
+
'.png',
|
|
947
|
+
'.jpg',
|
|
948
|
+
'.jpeg',
|
|
949
|
+
'.gif',
|
|
950
|
+
'.bmp',
|
|
951
|
+
'.webp',
|
|
952
|
+
'.svg',
|
|
953
|
+
'.tiff',
|
|
954
|
+
'.ico',
|
|
955
|
+
];
|
|
956
|
+
return imageExtensions.some((ext) => lowerFileName.endsWith(ext));
|
|
863
957
|
}
|
|
864
|
-
|
|
958
|
+
|
|
865
959
|
return false;
|
|
866
960
|
}
|
|
867
961
|
|
|
868
|
-
private recordPerformanceMetric(
|
|
962
|
+
private recordPerformanceMetric(
|
|
963
|
+
type: 'creation' | 'resolution' | 'cleanup',
|
|
964
|
+
timeMs: number
|
|
965
|
+
): void {
|
|
869
966
|
const metrics = this.referenceStats.performanceMetrics;
|
|
870
967
|
const maxRecords = 100;
|
|
871
|
-
|
|
968
|
+
|
|
872
969
|
switch (type) {
|
|
873
970
|
case 'creation':
|
|
874
971
|
metrics.creationTimes.push(timeMs);
|
|
@@ -900,8 +997,7 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
900
997
|
this.cleanupTimer = setInterval(async () => {
|
|
901
998
|
try {
|
|
902
999
|
await this.performCleanup();
|
|
903
|
-
} catch {
|
|
904
|
-
}
|
|
1000
|
+
} catch {}
|
|
905
1001
|
}, this.referenceConfig.cleanupIntervalMs);
|
|
906
1002
|
}
|
|
907
1003
|
|
|
@@ -913,9 +1009,9 @@ export class ContentStorage implements ContentReferenceStore {
|
|
|
913
1009
|
clearInterval(this.cleanupTimer);
|
|
914
1010
|
delete this.cleanupTimer;
|
|
915
1011
|
}
|
|
916
|
-
|
|
1012
|
+
|
|
917
1013
|
this.contentStore.clear();
|
|
918
|
-
|
|
1014
|
+
|
|
919
1015
|
this.clear();
|
|
920
1016
|
}
|
|
921
|
-
}
|
|
1017
|
+
}
|