tachibot-mcp 2.0.2
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/.env.example +260 -0
- package/CHANGELOG.md +54 -0
- package/CODE_OF_CONDUCT.md +56 -0
- package/CONTRIBUTING.md +54 -0
- package/Dockerfile +36 -0
- package/LICENSE +644 -0
- package/README.md +201 -0
- package/SECURITY.md +95 -0
- package/dist/personality/komaai-expressions.js +12 -0
- package/dist/profiles/balanced.json +33 -0
- package/dist/profiles/code_focus.json +33 -0
- package/dist/profiles/full.json +33 -0
- package/dist/profiles/minimal.json +33 -0
- package/dist/profiles/research_power.json +33 -0
- package/dist/scripts/build-profiles.js +46 -0
- package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
- package/dist/src/application/services/focus/FocusTool.service.js +109 -0
- package/dist/src/application/services/focus/ModeRegistry.js +46 -0
- package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
- package/dist/src/application/services/focus/modes/status.mode.js +50 -0
- package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
- package/dist/src/collaborative-orchestrator.js +391 -0
- package/dist/src/config/model-constants.js +188 -0
- package/dist/src/config/model-defaults.js +57 -0
- package/dist/src/config/model-preferences.js +382 -0
- package/dist/src/config/timeout-config.js +130 -0
- package/dist/src/config.js +173 -0
- package/dist/src/domain/interfaces/IFocusMode.js +5 -0
- package/dist/src/domain/interfaces/IProvider.js +6 -0
- package/dist/src/domain/interfaces/ITool.js +5 -0
- package/dist/src/focus-deep.js +245 -0
- package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
- package/dist/src/mcp-client.js +90 -0
- package/dist/src/memory/index.js +17 -0
- package/dist/src/memory/memory-config.js +135 -0
- package/dist/src/memory/memory-interface.js +174 -0
- package/dist/src/memory/memory-manager.js +383 -0
- package/dist/src/memory/providers/devlog-provider.js +385 -0
- package/dist/src/memory/providers/hybrid-provider.js +399 -0
- package/dist/src/memory/providers/local-provider.js +388 -0
- package/dist/src/memory/providers/mem0-provider.js +337 -0
- package/dist/src/modes/architect.js +477 -0
- package/dist/src/modes/auditor.js +362 -0
- package/dist/src/modes/challenger.js +841 -0
- package/dist/src/modes/code-reviewer.js +382 -0
- package/dist/src/modes/commit-guardian.js +424 -0
- package/dist/src/modes/documentation-writer.js +572 -0
- package/dist/src/modes/scout.js +587 -0
- package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
- package/dist/src/modes/shared/helpers/index.js +17 -0
- package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
- package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
- package/dist/src/modes/test-architect.js +767 -0
- package/dist/src/modes/verifier.js +378 -0
- package/dist/src/monitoring/performance-monitor.js +435 -0
- package/dist/src/optimization/batch-executor.js +121 -0
- package/dist/src/optimization/context-pruner.js +196 -0
- package/dist/src/optimization/cost-monitor.js +338 -0
- package/dist/src/optimization/index.js +65 -0
- package/dist/src/optimization/model-router.js +264 -0
- package/dist/src/optimization/result-cache.js +114 -0
- package/dist/src/optimization/token-optimizer.js +257 -0
- package/dist/src/optimization/token-tracker.js +118 -0
- package/dist/src/orchestrator-instructions.js +128 -0
- package/dist/src/orchestrator-lite.js +139 -0
- package/dist/src/orchestrator.js +191 -0
- package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
- package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
- package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
- package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
- package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
- package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
- package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
- package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
- package/dist/src/profiles/balanced.js +37 -0
- package/dist/src/profiles/code_focus.js +37 -0
- package/dist/src/profiles/debug_intensive.js +59 -0
- package/dist/src/profiles/full.js +37 -0
- package/dist/src/profiles/minimal.js +37 -0
- package/dist/src/profiles/research_code.js +59 -0
- package/dist/src/profiles/research_power.js +37 -0
- package/dist/src/profiles/types.js +5 -0
- package/dist/src/profiles/workflow_builder.js +53 -0
- package/dist/src/prompt-engineer-lite.js +78 -0
- package/dist/src/prompt-engineer.js +399 -0
- package/dist/src/reasoning-chain.js +508 -0
- package/dist/src/sequential-thinking.js +291 -0
- package/dist/src/server-diagnostic.js +74 -0
- package/dist/src/server-raw.js +158 -0
- package/dist/src/server-simple.js +58 -0
- package/dist/src/server.js +514 -0
- package/dist/src/session/session-logger.js +617 -0
- package/dist/src/session/session-manager.js +571 -0
- package/dist/src/session/session-tools.js +400 -0
- package/dist/src/tools/advanced-modes.js +200 -0
- package/dist/src/tools/claude-integration.js +356 -0
- package/dist/src/tools/consolidated/ai-router.js +174 -0
- package/dist/src/tools/consolidated/ai-tool.js +48 -0
- package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
- package/dist/src/tools/consolidated/environment-detector.js +80 -0
- package/dist/src/tools/consolidated/index.js +50 -0
- package/dist/src/tools/consolidated/search-tool.js +110 -0
- package/dist/src/tools/consolidated/workflow-tool.js +238 -0
- package/dist/src/tools/gemini-tools.js +329 -0
- package/dist/src/tools/grok-enhanced.js +376 -0
- package/dist/src/tools/grok-tools.js +299 -0
- package/dist/src/tools/lmstudio-tools.js +223 -0
- package/dist/src/tools/openai-tools.js +498 -0
- package/dist/src/tools/openrouter-tools.js +317 -0
- package/dist/src/tools/optimized-wrapper.js +204 -0
- package/dist/src/tools/perplexity-tools.js +294 -0
- package/dist/src/tools/pingpong-tool.js +343 -0
- package/dist/src/tools/qwen-wrapper.js +74 -0
- package/dist/src/tools/tool-router.js +444 -0
- package/dist/src/tools/unified-ai-provider.js +260 -0
- package/dist/src/tools/workflow-runner.js +425 -0
- package/dist/src/tools/workflow-validator-tool.js +107 -0
- package/dist/src/types.js +23 -0
- package/dist/src/utils/input-validator.js +130 -0
- package/dist/src/utils/model-router.js +91 -0
- package/dist/src/utils/progress-stream.js +255 -0
- package/dist/src/utils/provider-router.js +88 -0
- package/dist/src/utils/smart-api-client.js +146 -0
- package/dist/src/utils/table-builder.js +218 -0
- package/dist/src/utils/timestamp-formatter.js +134 -0
- package/dist/src/utils/tool-compressor.js +257 -0
- package/dist/src/utils/tool-config.js +201 -0
- package/dist/src/validators/dependency-graph-validator.js +147 -0
- package/dist/src/validators/interpolation-validator.js +222 -0
- package/dist/src/validators/output-usage-validator.js +151 -0
- package/dist/src/validators/syntax-validator.js +102 -0
- package/dist/src/validators/tool-registry-validator.js +123 -0
- package/dist/src/validators/tool-types.js +97 -0
- package/dist/src/validators/types.js +8 -0
- package/dist/src/validators/workflow-validator.js +134 -0
- package/dist/src/visualizer-lite.js +42 -0
- package/dist/src/visualizer.js +179 -0
- package/dist/src/workflows/circuit-breaker.js +199 -0
- package/dist/src/workflows/custom-workflows.js +451 -0
- package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
- package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
- package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
- package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
- package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
- package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
- package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
- package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
- package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
- package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
- package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
- package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
- package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
- package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
- package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
- package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
- package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
- package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
- package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
- package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
- package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
- package/dist/src/workflows/fallback-strategies.js +373 -0
- package/dist/src/workflows/message-queue.js +455 -0
- package/dist/src/workflows/model-router.js +189 -0
- package/dist/src/workflows/orchestrator-examples.js +174 -0
- package/dist/src/workflows/orchestrator-integration.js +200 -0
- package/dist/src/workflows/self-healing.js +524 -0
- package/dist/src/workflows/tool-mapper.js +407 -0
- package/dist/src/workflows/tool-orchestrator.js +796 -0
- package/dist/src/workflows/workflow-engine.js +573 -0
- package/dist/src/workflows/workflow-parser.js +283 -0
- package/dist/src/workflows/workflow-types.js +95 -0
- package/dist/src/workflows.js +568 -0
- package/dist/test-workflow-file-output.js +93 -0
- package/docs/API_KEYS.md +570 -0
- package/docs/CLAUDE_CODE_SETUP.md +181 -0
- package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
- package/docs/CONFIGURATION.md +745 -0
- package/docs/FOCUS_MODES.md +240 -0
- package/docs/INSTALLATION_BOTH.md +145 -0
- package/docs/TERMS.md +352 -0
- package/docs/TOOLS_REFERENCE.md +1622 -0
- package/docs/TOOL_PARAMETERS.md +496 -0
- package/docs/TOOL_PROFILES.md +236 -0
- package/docs/WORKFLOWS.md +987 -0
- package/docs/WORKFLOW_OUTPUT.md +198 -0
- package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
- package/docs/workflows/design-brainstorm.md +335 -0
- package/package.json +97 -0
- package/profiles/balanced.json +37 -0
- package/profiles/code_focus.json +37 -0
- package/profiles/debug_intensive.json +34 -0
- package/profiles/full.json +37 -0
- package/profiles/minimal.json +37 -0
- package/profiles/research_power.json +37 -0
- package/profiles/workflow_builder.json +37 -0
- package/smithery.yaml +66 -0
- package/start.sh +8 -0
- package/tools.config.json +81 -0
- package/tsconfig.json +18 -0
- package/workflows/accessibility-code-audit.yaml +92 -0
- package/workflows/code-architecture-review.yaml +202 -0
- package/workflows/code-review.yaml +142 -0
- package/workflows/core/iterative-problem-solver.yaml +283 -0
- package/workflows/creative-brainstorm-yaml.yaml +215 -0
- package/workflows/pingpong.yaml +141 -0
- package/workflows/system/README.md +412 -0
- package/workflows/system/challenger.yaml +175 -0
- package/workflows/system/scout.yaml +164 -0
- package/workflows/system/verifier.yaml +133 -0
- package/workflows/ultra-creative-brainstorm.yaml +318 -0
- package/workflows/ux-research-flow.yaml +92 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hybrid Memory Provider
|
|
3
|
+
* Combines multiple memory providers with fallback and sync capabilities
|
|
4
|
+
*/
|
|
5
|
+
import { BaseMemoryProvider } from '../memory-interface.js';
|
|
6
|
+
import { createMem0Provider } from './mem0-provider.js';
|
|
7
|
+
import { createDevLogProvider } from './devlog-provider.js';
|
|
8
|
+
import { createLocalProvider } from './local-provider.js';
|
|
9
|
+
/**
|
|
10
|
+
* Hybrid provider implementation
|
|
11
|
+
*/
|
|
12
|
+
export class HybridProvider extends BaseMemoryProvider {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
super();
|
|
15
|
+
this.name = 'hybrid';
|
|
16
|
+
this.primaryProvider = null;
|
|
17
|
+
this.fallbackProvider = null;
|
|
18
|
+
this.syncInterval = null;
|
|
19
|
+
this.syncQueue = new Map();
|
|
20
|
+
this.isSyncing = false;
|
|
21
|
+
this.config = {
|
|
22
|
+
syncInterval: config.syncInterval || 60000, // Default 1 minute
|
|
23
|
+
preferPrimaryFor: config.preferPrimaryFor || ['team', 'global'],
|
|
24
|
+
...config
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async doInitialize() {
|
|
28
|
+
try {
|
|
29
|
+
// Initialize primary provider
|
|
30
|
+
this.primaryProvider = await this.createProvider(this.config.primary);
|
|
31
|
+
if (!this.primaryProvider) {
|
|
32
|
+
throw new Error(`Failed to create primary provider: ${this.config.primary}`);
|
|
33
|
+
}
|
|
34
|
+
// Initialize fallback provider
|
|
35
|
+
this.fallbackProvider = await this.createProvider(this.config.fallback);
|
|
36
|
+
if (!this.fallbackProvider) {
|
|
37
|
+
throw new Error(`Failed to create fallback provider: ${this.config.fallback}`);
|
|
38
|
+
}
|
|
39
|
+
// Set up sync interval if enabled
|
|
40
|
+
if (this.config.syncInterval && this.config.syncInterval > 0) {
|
|
41
|
+
this.startSync();
|
|
42
|
+
}
|
|
43
|
+
console.error(`Hybrid provider initialized with primary=${this.config.primary}, fallback=${this.config.fallback}`);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('Failed to initialize hybrid provider:', error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async store(item) {
|
|
51
|
+
const preferPrimary = this.shouldUsePrimary(item.tier);
|
|
52
|
+
let primaryId = null;
|
|
53
|
+
let fallbackId = null;
|
|
54
|
+
// Try primary first if preferred
|
|
55
|
+
if (preferPrimary && this.primaryProvider) {
|
|
56
|
+
try {
|
|
57
|
+
if (await this.primaryProvider.isAvailable()) {
|
|
58
|
+
primaryId = await this.primaryProvider.store(item);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.warn(`Primary provider store failed: ${error}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Always store in fallback for redundancy
|
|
66
|
+
if (this.fallbackProvider) {
|
|
67
|
+
try {
|
|
68
|
+
fallbackId = await this.fallbackProvider.store(item);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(`Fallback provider store failed: ${error}`);
|
|
72
|
+
if (!primaryId)
|
|
73
|
+
throw error; // Fail if both failed
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Try primary if not already tried and fallback succeeded
|
|
77
|
+
if (!preferPrimary && !primaryId && fallbackId && this.primaryProvider) {
|
|
78
|
+
try {
|
|
79
|
+
if (await this.primaryProvider.isAvailable()) {
|
|
80
|
+
primaryId = await this.primaryProvider.store(item);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// Non-critical, we have fallback
|
|
85
|
+
console.warn(`Primary provider store failed (non-critical): ${error}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Queue for sync if only stored in one provider
|
|
89
|
+
if ((primaryId && !fallbackId) || (!primaryId && fallbackId)) {
|
|
90
|
+
this.syncQueue.set(item.id, item);
|
|
91
|
+
}
|
|
92
|
+
// Update metrics
|
|
93
|
+
this.metrics.totalItems++;
|
|
94
|
+
this.metrics.itemsByTier[item.tier]++;
|
|
95
|
+
return primaryId || fallbackId || item.id;
|
|
96
|
+
}
|
|
97
|
+
async retrieve(query) {
|
|
98
|
+
const results = new Map();
|
|
99
|
+
// Try primary provider
|
|
100
|
+
if (this.primaryProvider && await this.primaryProvider.isAvailable()) {
|
|
101
|
+
try {
|
|
102
|
+
const primaryItems = await this.primaryProvider.retrieve(query);
|
|
103
|
+
primaryItems.forEach(item => results.set(item.id, item));
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.warn(`Primary provider retrieve failed: ${error}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Try fallback provider
|
|
110
|
+
if (this.fallbackProvider) {
|
|
111
|
+
try {
|
|
112
|
+
const fallbackItems = await this.fallbackProvider.retrieve(query);
|
|
113
|
+
fallbackItems.forEach(item => {
|
|
114
|
+
// Merge with primary results, primary takes precedence
|
|
115
|
+
if (!results.has(item.id)) {
|
|
116
|
+
results.set(item.id, item);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error(`Fallback provider retrieve failed: ${error}`);
|
|
122
|
+
if (results.size === 0)
|
|
123
|
+
throw error; // Fail if both failed
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return Array.from(results.values());
|
|
127
|
+
}
|
|
128
|
+
async retrieveContext(query) {
|
|
129
|
+
// Try primary first
|
|
130
|
+
if (this.primaryProvider && await this.primaryProvider.isAvailable()) {
|
|
131
|
+
try {
|
|
132
|
+
return await this.primaryProvider.retrieveContext(query);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.warn(`Primary provider context retrieval failed: ${error}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Fallback
|
|
139
|
+
if (this.fallbackProvider) {
|
|
140
|
+
try {
|
|
141
|
+
return await this.fallbackProvider.retrieveContext(query);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error(`Fallback provider context retrieval failed: ${error}`);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Return empty context if both failed
|
|
149
|
+
return {
|
|
150
|
+
items: [],
|
|
151
|
+
synthesis: '',
|
|
152
|
+
relevanceScore: 0,
|
|
153
|
+
tokenCount: 0,
|
|
154
|
+
sources: {
|
|
155
|
+
session: 0,
|
|
156
|
+
working: 0,
|
|
157
|
+
project: 0,
|
|
158
|
+
team: 0,
|
|
159
|
+
global: 0
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
async update(id, updates) {
|
|
164
|
+
let primarySuccess = false;
|
|
165
|
+
let fallbackSuccess = false;
|
|
166
|
+
// Update in both providers
|
|
167
|
+
if (this.primaryProvider && await this.primaryProvider.isAvailable()) {
|
|
168
|
+
try {
|
|
169
|
+
primarySuccess = await this.primaryProvider.update(id, updates);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.warn(`Primary provider update failed: ${error}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (this.fallbackProvider) {
|
|
176
|
+
try {
|
|
177
|
+
fallbackSuccess = await this.fallbackProvider.update(id, updates);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.warn(`Fallback provider update failed: ${error}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return primarySuccess || fallbackSuccess;
|
|
184
|
+
}
|
|
185
|
+
async delete(id) {
|
|
186
|
+
let primarySuccess = false;
|
|
187
|
+
let fallbackSuccess = false;
|
|
188
|
+
// Delete from both providers
|
|
189
|
+
if (this.primaryProvider && await this.primaryProvider.isAvailable()) {
|
|
190
|
+
try {
|
|
191
|
+
primarySuccess = await this.primaryProvider.delete(id);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
console.warn(`Primary provider delete failed: ${error}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (this.fallbackProvider) {
|
|
198
|
+
try {
|
|
199
|
+
fallbackSuccess = await this.fallbackProvider.delete(id);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
console.warn(`Fallback provider delete failed: ${error}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (primarySuccess || fallbackSuccess) {
|
|
206
|
+
this.metrics.totalItems--;
|
|
207
|
+
// Remove from sync queue if present
|
|
208
|
+
this.syncQueue.delete(id);
|
|
209
|
+
}
|
|
210
|
+
return primarySuccess || fallbackSuccess;
|
|
211
|
+
}
|
|
212
|
+
async semanticSearch(text, limit, threshold) {
|
|
213
|
+
const results = new Map();
|
|
214
|
+
// Try primary if it supports semantic search
|
|
215
|
+
if (this.primaryProvider && 'semanticSearch' in this.primaryProvider) {
|
|
216
|
+
try {
|
|
217
|
+
const items = await this.primaryProvider.semanticSearch(text, limit, threshold);
|
|
218
|
+
items.forEach((item) => results.set(item.id, item));
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.warn(`Primary provider semantic search failed: ${error}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Try fallback if it supports semantic search
|
|
225
|
+
if (this.fallbackProvider && 'semanticSearch' in this.fallbackProvider) {
|
|
226
|
+
try {
|
|
227
|
+
const items = await this.fallbackProvider.semanticSearch(text, limit, threshold);
|
|
228
|
+
items.forEach((item) => {
|
|
229
|
+
if (!results.has(item.id)) {
|
|
230
|
+
results.set(item.id, item);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.warn(`Fallback provider semantic search failed: ${error}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return Array.from(results.values()).slice(0, limit);
|
|
239
|
+
}
|
|
240
|
+
async cleanup() {
|
|
241
|
+
let totalCleaned = 0;
|
|
242
|
+
// Cleanup both providers
|
|
243
|
+
if (this.primaryProvider) {
|
|
244
|
+
try {
|
|
245
|
+
totalCleaned += await this.primaryProvider.cleanup();
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
console.warn(`Primary provider cleanup failed: ${error}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (this.fallbackProvider) {
|
|
252
|
+
try {
|
|
253
|
+
totalCleaned += await this.fallbackProvider.cleanup();
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.warn(`Fallback provider cleanup failed: ${error}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return totalCleaned;
|
|
260
|
+
}
|
|
261
|
+
async export() {
|
|
262
|
+
const allItems = new Map();
|
|
263
|
+
// Export from both providers
|
|
264
|
+
if (this.primaryProvider) {
|
|
265
|
+
try {
|
|
266
|
+
const items = await this.primaryProvider.export();
|
|
267
|
+
items.forEach(item => allItems.set(item.id, item));
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
console.warn(`Primary provider export failed: ${error}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (this.fallbackProvider) {
|
|
274
|
+
try {
|
|
275
|
+
const items = await this.fallbackProvider.export();
|
|
276
|
+
items.forEach(item => {
|
|
277
|
+
if (!allItems.has(item.id)) {
|
|
278
|
+
allItems.set(item.id, item);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
console.warn(`Fallback provider export failed: ${error}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return Array.from(allItems.values());
|
|
287
|
+
}
|
|
288
|
+
async import(items) {
|
|
289
|
+
let totalImported = 0;
|
|
290
|
+
// Import to both providers
|
|
291
|
+
if (this.primaryProvider) {
|
|
292
|
+
try {
|
|
293
|
+
totalImported = await this.primaryProvider.import(items);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
console.warn(`Primary provider import failed: ${error}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (this.fallbackProvider) {
|
|
300
|
+
try {
|
|
301
|
+
await this.fallbackProvider.import(items);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
console.warn(`Fallback provider import failed: ${error}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return totalImported;
|
|
308
|
+
}
|
|
309
|
+
async isAvailable() {
|
|
310
|
+
const primaryAvailable = this.primaryProvider ?
|
|
311
|
+
await this.primaryProvider.isAvailable() : false;
|
|
312
|
+
const fallbackAvailable = this.fallbackProvider ?
|
|
313
|
+
await this.fallbackProvider.isAvailable() : false;
|
|
314
|
+
return primaryAvailable || fallbackAvailable;
|
|
315
|
+
}
|
|
316
|
+
async close() {
|
|
317
|
+
// Stop sync
|
|
318
|
+
if (this.syncInterval) {
|
|
319
|
+
clearInterval(this.syncInterval);
|
|
320
|
+
this.syncInterval = null;
|
|
321
|
+
}
|
|
322
|
+
// Perform final sync
|
|
323
|
+
await this.performSync();
|
|
324
|
+
// Close providers
|
|
325
|
+
if (this.primaryProvider) {
|
|
326
|
+
await this.primaryProvider.close();
|
|
327
|
+
}
|
|
328
|
+
if (this.fallbackProvider) {
|
|
329
|
+
await this.fallbackProvider.close();
|
|
330
|
+
}
|
|
331
|
+
await super.close();
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Helper methods
|
|
335
|
+
*/
|
|
336
|
+
async createProvider(type) {
|
|
337
|
+
const config = global.memoryConfig || {};
|
|
338
|
+
switch (type) {
|
|
339
|
+
case 'mem0':
|
|
340
|
+
return await createMem0Provider(config.mem0 || {});
|
|
341
|
+
case 'devlog':
|
|
342
|
+
return await createDevLogProvider(config.devlog || {});
|
|
343
|
+
case 'local':
|
|
344
|
+
return await createLocalProvider(config.local || {
|
|
345
|
+
storageType: 'json',
|
|
346
|
+
path: './.focus-memory-hybrid',
|
|
347
|
+
maxSizeMB: 100
|
|
348
|
+
});
|
|
349
|
+
default:
|
|
350
|
+
throw new Error(`Unknown provider type: ${type}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
shouldUsePrimary(tier) {
|
|
354
|
+
return this.config.preferPrimaryFor?.includes(tier) || false;
|
|
355
|
+
}
|
|
356
|
+
startSync() {
|
|
357
|
+
this.syncInterval = setInterval(() => {
|
|
358
|
+
this.performSync().catch(console.error);
|
|
359
|
+
}, this.config.syncInterval);
|
|
360
|
+
}
|
|
361
|
+
async performSync() {
|
|
362
|
+
if (this.isSyncing || this.syncQueue.size === 0)
|
|
363
|
+
return;
|
|
364
|
+
this.isSyncing = true;
|
|
365
|
+
const itemsToSync = Array.from(this.syncQueue.values());
|
|
366
|
+
for (const item of itemsToSync) {
|
|
367
|
+
try {
|
|
368
|
+
// Check if item exists in both providers
|
|
369
|
+
const primaryHas = this.primaryProvider ?
|
|
370
|
+
(await this.primaryProvider.retrieve({ text: item.id, limit: 1 })).length > 0 : false;
|
|
371
|
+
const fallbackHas = this.fallbackProvider ?
|
|
372
|
+
(await this.fallbackProvider.retrieve({ text: item.id, limit: 1 })).length > 0 : false;
|
|
373
|
+
// Sync to missing provider
|
|
374
|
+
if (!primaryHas && this.primaryProvider && await this.primaryProvider.isAvailable()) {
|
|
375
|
+
await this.primaryProvider.store(item);
|
|
376
|
+
}
|
|
377
|
+
if (!fallbackHas && this.fallbackProvider) {
|
|
378
|
+
await this.fallbackProvider.store(item);
|
|
379
|
+
}
|
|
380
|
+
// Remove from queue if synced
|
|
381
|
+
if (primaryHas || fallbackHas) {
|
|
382
|
+
this.syncQueue.delete(item.id);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
console.warn(`Failed to sync item ${item.id}: ${error}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
this.isSyncing = false;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Factory function to create hybrid provider
|
|
394
|
+
*/
|
|
395
|
+
export async function createHybridProvider(config) {
|
|
396
|
+
const provider = new HybridProvider(config);
|
|
397
|
+
await provider.initialize();
|
|
398
|
+
return provider;
|
|
399
|
+
}
|