@sylphx/flow 1.8.0 → 1.8.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/CHANGELOG.md +72 -0
- package/assets/output-styles/silent.md +145 -8
- package/assets/rules/core.md +19 -2
- package/package.json +2 -12
- package/src/commands/flow/execute.ts +470 -0
- package/src/commands/flow/index.ts +11 -0
- package/src/commands/flow/prompt.ts +35 -0
- package/src/commands/flow/setup.ts +312 -0
- package/src/commands/flow/targets.ts +18 -0
- package/src/commands/flow/types.ts +47 -0
- package/src/commands/flow-command.ts +18 -967
- package/src/commands/flow-orchestrator.ts +14 -5
- package/src/commands/hook-command.ts +1 -1
- package/src/commands/init-core.ts +12 -3
- package/src/commands/run-command.ts +1 -1
- package/src/config/rules.ts +1 -1
- package/src/core/error-handling.ts +1 -1
- package/src/core/loop-controller.ts +1 -1
- package/src/core/state-detector.ts +1 -1
- package/src/core/target-manager.ts +1 -1
- package/src/index.ts +1 -1
- package/src/shared/files/index.ts +1 -1
- package/src/shared/processing/index.ts +1 -1
- package/src/targets/claude-code.ts +3 -3
- package/src/targets/opencode.ts +3 -3
- package/src/utils/agent-enhancer.ts +2 -2
- package/src/utils/{mcp-config.ts → config/mcp-config.ts} +4 -4
- package/src/utils/{paths.ts → config/paths.ts} +1 -1
- package/src/utils/{settings.ts → config/settings.ts} +1 -1
- package/src/utils/{target-config.ts → config/target-config.ts} +5 -5
- package/src/utils/{target-utils.ts → config/target-utils.ts} +3 -3
- package/src/utils/display/banner.ts +25 -0
- package/src/utils/display/status.ts +55 -0
- package/src/utils/{file-operations.ts → files/file-operations.ts} +2 -2
- package/src/utils/files/jsonc.ts +36 -0
- package/src/utils/{sync-utils.ts → files/sync-utils.ts} +3 -3
- package/src/utils/index.ts +42 -61
- package/src/utils/version.ts +47 -0
- package/src/components/benchmark-monitor.tsx +0 -331
- package/src/components/reindex-progress.tsx +0 -261
- package/src/composables/functional/index.ts +0 -14
- package/src/composables/functional/useEnvironment.ts +0 -171
- package/src/composables/functional/useFileSystem.ts +0 -139
- package/src/composables/index.ts +0 -4
- package/src/composables/useEnv.ts +0 -13
- package/src/composables/useRuntimeConfig.ts +0 -27
- package/src/core/ai-sdk.ts +0 -603
- package/src/core/app-factory.ts +0 -381
- package/src/core/builtin-agents.ts +0 -9
- package/src/core/command-system.ts +0 -550
- package/src/core/config-system.ts +0 -550
- package/src/core/connection-pool.ts +0 -390
- package/src/core/di-container.ts +0 -155
- package/src/core/headless-display.ts +0 -96
- package/src/core/interfaces/index.ts +0 -22
- package/src/core/interfaces/repository.interface.ts +0 -91
- package/src/core/interfaces/service.interface.ts +0 -133
- package/src/core/interfaces.ts +0 -96
- package/src/core/result.ts +0 -351
- package/src/core/service-config.ts +0 -252
- package/src/core/session-service.ts +0 -121
- package/src/core/storage-factory.ts +0 -115
- package/src/core/stream-handler.ts +0 -288
- package/src/core/type-utils.ts +0 -427
- package/src/core/unified-storage.ts +0 -456
- package/src/core/validation/limit.ts +0 -46
- package/src/core/validation/query.ts +0 -20
- package/src/db/auto-migrate.ts +0 -322
- package/src/db/base-database-client.ts +0 -144
- package/src/db/cache-db.ts +0 -218
- package/src/db/cache-schema.ts +0 -75
- package/src/db/database.ts +0 -70
- package/src/db/index.ts +0 -252
- package/src/db/memory-db.ts +0 -153
- package/src/db/memory-schema.ts +0 -29
- package/src/db/schema.ts +0 -289
- package/src/db/session-repository.ts +0 -733
- package/src/domains/index.ts +0 -6
- package/src/domains/utilities/index.ts +0 -6
- package/src/domains/utilities/time/index.ts +0 -5
- package/src/domains/utilities/time/tools.ts +0 -291
- package/src/services/agent-service.ts +0 -273
- package/src/services/evaluation-service.ts +0 -271
- package/src/services/functional/evaluation-logic.ts +0 -296
- package/src/services/functional/file-processor.ts +0 -273
- package/src/services/functional/index.ts +0 -12
- package/src/services/memory.service.ts +0 -476
- package/src/types/api/batch.ts +0 -108
- package/src/types/api/errors.ts +0 -118
- package/src/types/api/index.ts +0 -55
- package/src/types/api/requests.ts +0 -76
- package/src/types/api/responses.ts +0 -180
- package/src/types/api/websockets.ts +0 -85
- package/src/types/benchmark.ts +0 -49
- package/src/types/database.types.ts +0 -510
- package/src/types/memory-types.ts +0 -63
- package/src/utils/advanced-tokenizer.ts +0 -191
- package/src/utils/ai-model-fetcher.ts +0 -19
- package/src/utils/async-file-operations.ts +0 -516
- package/src/utils/audio-player.ts +0 -345
- package/src/utils/codebase-helpers.ts +0 -211
- package/src/utils/console-ui.ts +0 -79
- package/src/utils/database-errors.ts +0 -140
- package/src/utils/debug-logger.ts +0 -49
- package/src/utils/file-scanner.ts +0 -259
- package/src/utils/help.ts +0 -20
- package/src/utils/immutable-cache.ts +0 -106
- package/src/utils/jsonc.ts +0 -158
- package/src/utils/memory-tui.ts +0 -414
- package/src/utils/models-dev.ts +0 -91
- package/src/utils/parallel-operations.ts +0 -487
- package/src/utils/process-manager.ts +0 -155
- package/src/utils/prompts.ts +0 -120
- package/src/utils/search-tool-builder.ts +0 -214
- package/src/utils/session-manager.ts +0 -168
- package/src/utils/session-title.ts +0 -87
- package/src/utils/simplified-errors.ts +0 -410
- package/src/utils/template-engine.ts +0 -94
- package/src/utils/test-audio.ts +0 -71
- package/src/utils/todo-context.ts +0 -46
- package/src/utils/token-counter.ts +0 -288
- /package/src/utils/{cli-output.ts → display/cli-output.ts} +0 -0
- /package/src/utils/{logger.ts → display/logger.ts} +0 -0
- /package/src/utils/{notifications.ts → display/notifications.ts} +0 -0
- /package/src/utils/{secret-utils.ts → security/secret-utils.ts} +0 -0
- /package/src/utils/{security.ts → security/security.ts} +0 -0
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Storage - 統一存儲層
|
|
3
|
-
* Feature-first, composable, functional approach
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { StorageConfig } from '../interfaces/unified-storage.js';
|
|
7
|
-
import { logger } from '../utils/logger.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Base storage interface with functional approach
|
|
11
|
-
*/
|
|
12
|
-
export interface BaseStorage<T = unknown> {
|
|
13
|
-
readonly type: string;
|
|
14
|
-
initialize(): Promise<void>;
|
|
15
|
-
close(): Promise<void>;
|
|
16
|
-
getStats(): Promise<Record<string, unknown>>;
|
|
17
|
-
|
|
18
|
-
// Core storage operations
|
|
19
|
-
get(key: string): Promise<T | null>;
|
|
20
|
-
set(key: string, value: T): Promise<void>;
|
|
21
|
-
delete(key: string): Promise<boolean>;
|
|
22
|
-
exists(key: string): Promise<boolean>;
|
|
23
|
-
clear(): Promise<void>;
|
|
24
|
-
keys(): Promise<string[]>;
|
|
25
|
-
size(): Promise<number>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Memory storage implementation
|
|
30
|
-
*/
|
|
31
|
-
export class MemoryStorage<T = unknown> implements BaseStorage<T> {
|
|
32
|
-
readonly type = 'memory';
|
|
33
|
-
private data = new Map<string, T>();
|
|
34
|
-
private initialized = false;
|
|
35
|
-
|
|
36
|
-
async initialize(): Promise<void> {
|
|
37
|
-
if (this.initialized) return;
|
|
38
|
-
this.initialized = true;
|
|
39
|
-
logger.debug('Memory storage initialized');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async close(): Promise<void> {
|
|
43
|
-
this.data.clear();
|
|
44
|
-
this.initialized = false;
|
|
45
|
-
logger.debug('Memory storage closed');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async getStats(): Promise<Record<string, unknown>> {
|
|
49
|
-
return {
|
|
50
|
-
type: this.type,
|
|
51
|
-
size: this.data.size,
|
|
52
|
-
initialized: this.initialized,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async get(key: string): Promise<T | null> {
|
|
57
|
-
const value = this.data.get(key);
|
|
58
|
-
// Return deep copy for objects to ensure immutability
|
|
59
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
60
|
-
return JSON.parse(JSON.stringify(value));
|
|
61
|
-
}
|
|
62
|
-
if (Array.isArray(value)) {
|
|
63
|
-
return [...value] as T;
|
|
64
|
-
}
|
|
65
|
-
return value;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async set(key: string, value: T): Promise<void> {
|
|
69
|
-
// Store deep copy to ensure immutability
|
|
70
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
71
|
-
this.data.set(key, JSON.parse(JSON.stringify(value)));
|
|
72
|
-
} else if (Array.isArray(value)) {
|
|
73
|
-
this.data.set(key, [...value] as T);
|
|
74
|
-
} else {
|
|
75
|
-
this.data.set(key, value);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async delete(key: string): Promise<boolean> {
|
|
80
|
-
return this.data.delete(key);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async exists(key: string): Promise<boolean> {
|
|
84
|
-
return this.data.has(key);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async clear(): Promise<void> {
|
|
88
|
-
this.data.clear();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async keys(): Promise<string[]> {
|
|
92
|
-
return Array.from(this.data.keys());
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async size(): Promise<number> {
|
|
96
|
-
return this.data.size;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Cache storage with TTL support
|
|
102
|
-
*/
|
|
103
|
-
export class CacheStorage<T = unknown> implements BaseStorage<T> {
|
|
104
|
-
readonly type = 'cache';
|
|
105
|
-
private data = new Map<string, { value: T; expires: number }>();
|
|
106
|
-
private defaultTTL: number;
|
|
107
|
-
private initialized = false;
|
|
108
|
-
private cleanupTimer?: NodeJS.Timeout;
|
|
109
|
-
|
|
110
|
-
constructor(config: StorageConfig) {
|
|
111
|
-
this.defaultTTL = config.defaultTTL ?? 3600; // 1 hour default
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async initialize(): Promise<void> {
|
|
115
|
-
if (this.initialized) return;
|
|
116
|
-
this.initialized = true;
|
|
117
|
-
this.startCleanupTimer();
|
|
118
|
-
logger.debug('Cache storage initialized', { defaultTTL: this.defaultTTL });
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
async close(): Promise<void> {
|
|
122
|
-
if (this.cleanupTimer) {
|
|
123
|
-
clearInterval(this.cleanupTimer);
|
|
124
|
-
}
|
|
125
|
-
this.data.clear();
|
|
126
|
-
this.initialized = false;
|
|
127
|
-
logger.debug('Cache storage closed');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async getStats(): Promise<Record<string, unknown>> {
|
|
131
|
-
const now = Date.now();
|
|
132
|
-
const expired = Array.from(this.data.values()).filter(item => item.expires <= now).length;
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
type: this.type,
|
|
136
|
-
size: this.data.size,
|
|
137
|
-
expiredItems: expired,
|
|
138
|
-
initialized: this.initialized,
|
|
139
|
-
defaultTTL: this.defaultTTL,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private startCleanupTimer(): void {
|
|
144
|
-
// Clean up expired items every 5 minutes
|
|
145
|
-
this.cleanupTimer = setInterval(() => {
|
|
146
|
-
this.cleanup().catch(error => {
|
|
147
|
-
logger.error('Cache cleanup error:', error);
|
|
148
|
-
});
|
|
149
|
-
}, 5 * 60 * 1000);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async get(key: string): Promise<T | null> {
|
|
153
|
-
const item = this.data.get(key);
|
|
154
|
-
if (!item) return null;
|
|
155
|
-
|
|
156
|
-
if (item.expires <= Date.now()) {
|
|
157
|
-
this.data.delete(key);
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return item.value;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async set(key: string, value: T, ttl?: number): Promise<void> {
|
|
165
|
-
const expires = Date.now() + (ttl ?? this.defaultTTL) * 1000;
|
|
166
|
-
this.data.set(key, { value, expires });
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async delete(key: string): Promise<boolean> {
|
|
170
|
-
return this.data.delete(key);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
async exists(key: string): Promise<boolean> {
|
|
174
|
-
const item = this.data.get(key);
|
|
175
|
-
if (!item) return false;
|
|
176
|
-
|
|
177
|
-
if (item.expires <= Date.now()) {
|
|
178
|
-
this.data.delete(key);
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async clear(): Promise<void> {
|
|
186
|
-
this.data.clear();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async keys(): Promise<string[]> {
|
|
190
|
-
const now = Date.now();
|
|
191
|
-
return Array.from(this.data.keys()).filter(key => {
|
|
192
|
-
const item = this.data.get(key);
|
|
193
|
-
return item && item.expires > now;
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async size(): Promise<number> {
|
|
198
|
-
const now = Date.now();
|
|
199
|
-
return Array.from(this.data.values()).filter(item => item.expires > now).length;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
async cleanup(): Promise<number> {
|
|
203
|
-
const now = Date.now();
|
|
204
|
-
let cleaned = 0;
|
|
205
|
-
|
|
206
|
-
for (const [key, item] of this.data.entries()) {
|
|
207
|
-
if (item.expires <= now) {
|
|
208
|
-
this.data.delete(key);
|
|
209
|
-
cleaned++;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return cleaned;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Cache-specific methods
|
|
217
|
-
async getWithTTL(key: string): Promise<{ value: T; ttl: number } | null> {
|
|
218
|
-
const item = this.data.get(key);
|
|
219
|
-
if (!item) return null;
|
|
220
|
-
|
|
221
|
-
const now = Date.now();
|
|
222
|
-
if (item.expires <= now) {
|
|
223
|
-
this.data.delete(key);
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const ttl = Math.floor((item.expires - now) / 1000);
|
|
228
|
-
return { value: item.value, ttl };
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
async setWithTTL(key: string, value: T, ttl?: number): Promise<void> {
|
|
232
|
-
await this.set(key, value, ttl);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Vector storage for embeddings
|
|
238
|
-
*/
|
|
239
|
-
export class VectorStorage implements BaseStorage<{
|
|
240
|
-
content: string;
|
|
241
|
-
embedding: number[];
|
|
242
|
-
metadata?: Record<string, unknown>;
|
|
243
|
-
}> {
|
|
244
|
-
readonly type = 'vector';
|
|
245
|
-
private documents = new Map<string, {
|
|
246
|
-
content: string;
|
|
247
|
-
embedding: number[];
|
|
248
|
-
metadata?: Record<string, unknown>;
|
|
249
|
-
}>();
|
|
250
|
-
private initialized = false;
|
|
251
|
-
|
|
252
|
-
async initialize(): Promise<void> {
|
|
253
|
-
if (this.initialized) return;
|
|
254
|
-
this.initialized = true;
|
|
255
|
-
logger.debug('Vector storage initialized');
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
async close(): Promise<void> {
|
|
259
|
-
this.documents.clear();
|
|
260
|
-
this.initialized = false;
|
|
261
|
-
logger.debug('Vector storage closed');
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async getStats(): Promise<Record<string, unknown>> {
|
|
265
|
-
return {
|
|
266
|
-
type: this.type,
|
|
267
|
-
documentCount: this.documents.size,
|
|
268
|
-
initialized: this.initialized,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
async get(key: string): Promise<{
|
|
273
|
-
id: string;
|
|
274
|
-
content: string;
|
|
275
|
-
embedding: number[];
|
|
276
|
-
metadata?: Record<string, unknown>;
|
|
277
|
-
} | null> {
|
|
278
|
-
const doc = this.documents.get(key);
|
|
279
|
-
return doc ? { id: key, ...doc } : null;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
async set(
|
|
283
|
-
key: string,
|
|
284
|
-
value: {
|
|
285
|
-
content: string;
|
|
286
|
-
embedding: number[];
|
|
287
|
-
metadata?: Record<string, unknown>;
|
|
288
|
-
}
|
|
289
|
-
): Promise<void> {
|
|
290
|
-
this.documents.set(key, value);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
async delete(key: string): Promise<boolean> {
|
|
294
|
-
return this.documents.delete(key);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async exists(key: string): Promise<boolean> {
|
|
298
|
-
return this.documents.has(key);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
async clear(): Promise<void> {
|
|
302
|
-
this.documents.clear();
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
async keys(): Promise<string[]> {
|
|
306
|
-
return Array.from(this.documents.keys());
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
async size(): Promise<number> {
|
|
310
|
-
return this.documents.size;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Vector-specific methods implementing the interface
|
|
314
|
-
async add(document: {
|
|
315
|
-
id: string;
|
|
316
|
-
content: string;
|
|
317
|
-
embedding: number[];
|
|
318
|
-
metadata?: Record<string, unknown>;
|
|
319
|
-
}): Promise<void> {
|
|
320
|
-
this.documents.set(document.id, {
|
|
321
|
-
content: document.content,
|
|
322
|
-
embedding: document.embedding,
|
|
323
|
-
metadata: document.metadata,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
async update(id: string, document: {
|
|
328
|
-
id: string;
|
|
329
|
-
content: string;
|
|
330
|
-
embedding: number[];
|
|
331
|
-
metadata?: Record<string, unknown>;
|
|
332
|
-
}): Promise<void> {
|
|
333
|
-
if (!this.documents.has(id)) {
|
|
334
|
-
throw new Error(`Document not found: ${id}`);
|
|
335
|
-
}
|
|
336
|
-
this.documents.set(id, {
|
|
337
|
-
content: document.content,
|
|
338
|
-
embedding: document.embedding,
|
|
339
|
-
metadata: document.metadata,
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
async search(
|
|
344
|
-
query: number[],
|
|
345
|
-
limit = 10
|
|
346
|
-
): Promise<Array<{
|
|
347
|
-
document: {
|
|
348
|
-
id: string;
|
|
349
|
-
content: string;
|
|
350
|
-
embedding: number[];
|
|
351
|
-
metadata?: Record<string, unknown>;
|
|
352
|
-
};
|
|
353
|
-
score: number;
|
|
354
|
-
distance: number;
|
|
355
|
-
}>> {
|
|
356
|
-
const results = Array.from(this.documents.entries())
|
|
357
|
-
.map(([id, doc]) => ({
|
|
358
|
-
document: { id, ...doc },
|
|
359
|
-
score: this.cosineSimilarity(query, doc.embedding),
|
|
360
|
-
distance: this.euclideanDistance(query, doc.embedding),
|
|
361
|
-
}))
|
|
362
|
-
.filter(result => result.score > 0)
|
|
363
|
-
.sort((a, b) => b.score - a.score)
|
|
364
|
-
.slice(0, limit);
|
|
365
|
-
|
|
366
|
-
return results;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
private cosineSimilarity(a: number[], b: number[]): number {
|
|
370
|
-
if (a.length !== b.length) return 0;
|
|
371
|
-
|
|
372
|
-
let dotProduct = 0;
|
|
373
|
-
let normA = 0;
|
|
374
|
-
let normB = 0;
|
|
375
|
-
|
|
376
|
-
for (let i = 0; i < a.length; i++) {
|
|
377
|
-
dotProduct += a[i] * b[i];
|
|
378
|
-
normA += a[i] * a[i];
|
|
379
|
-
normB += b[i] * b[i];
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
normA = Math.sqrt(normA);
|
|
383
|
-
normB = Math.sqrt(normB);
|
|
384
|
-
|
|
385
|
-
return normA === 0 || normB === 0 ? 0 : dotProduct / (normA * normB);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
private euclideanDistance(a: number[], b: number[]): number {
|
|
389
|
-
if (a.length !== b.length) return Infinity;
|
|
390
|
-
|
|
391
|
-
let sum = 0;
|
|
392
|
-
for (let i = 0; i < a.length; i++) {
|
|
393
|
-
const diff = a[i] - b[i];
|
|
394
|
-
sum += diff * diff;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
return Math.sqrt(sum);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Storage factory function - functional approach
|
|
403
|
-
*/
|
|
404
|
-
export function createStorage<T = unknown>(config: StorageConfig): BaseStorage<T> {
|
|
405
|
-
switch (config.type) {
|
|
406
|
-
case 'memory':
|
|
407
|
-
return new MemoryStorage<T>();
|
|
408
|
-
case 'cache':
|
|
409
|
-
return new CacheStorage<T>(config) as BaseStorage<T>;
|
|
410
|
-
case 'vector':
|
|
411
|
-
return new VectorStorage() as BaseStorage<T>;
|
|
412
|
-
default:
|
|
413
|
-
throw new Error(`Unsupported storage type: ${config.type}`);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Storage type guards
|
|
419
|
-
*/
|
|
420
|
-
export const StorageTypes = {
|
|
421
|
-
isMemory: (storage: BaseStorage): storage is MemoryStorage => storage.type === 'memory',
|
|
422
|
-
isCache: (storage: BaseStorage): storage is CacheStorage => storage.type === 'cache',
|
|
423
|
-
isVector: (storage: BaseStorage): storage is VectorStorage => storage.type === 'vector',
|
|
424
|
-
} as const;
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Storage configuration builders
|
|
428
|
-
*/
|
|
429
|
-
export const StorageConfig = {
|
|
430
|
-
memory: (options?: Partial<StorageConfig>): StorageConfig => ({
|
|
431
|
-
type: 'memory',
|
|
432
|
-
...options,
|
|
433
|
-
}),
|
|
434
|
-
|
|
435
|
-
cache: (options?: {
|
|
436
|
-
defaultTTL?: number;
|
|
437
|
-
maxCacheSize?: number;
|
|
438
|
-
storageDir?: string;
|
|
439
|
-
}): StorageConfig => ({
|
|
440
|
-
type: 'cache',
|
|
441
|
-
defaultTTL: options?.defaultTTL || 3600,
|
|
442
|
-
maxCacheSize: options?.maxCacheSize,
|
|
443
|
-
storageDir: options?.storageDir,
|
|
444
|
-
}),
|
|
445
|
-
|
|
446
|
-
vector: (options?: {
|
|
447
|
-
vectorDimensions?: number;
|
|
448
|
-
connectionString?: string;
|
|
449
|
-
storageDir?: string;
|
|
450
|
-
}): StorageConfig => ({
|
|
451
|
-
type: 'vector',
|
|
452
|
-
vectorDimensions: options?.vectorDimensions || 1536,
|
|
453
|
-
connectionString: options?.connectionString,
|
|
454
|
-
storageDir: options?.storageDir,
|
|
455
|
-
}),
|
|
456
|
-
} as const;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Limit Validation Utilities
|
|
3
|
-
* Shared validation for limit parameters across features
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Result } from '../functional/result.js';
|
|
7
|
-
import { success, failure } from '../functional/result.js';
|
|
8
|
-
import type { AppError } from '../functional/error-types.js';
|
|
9
|
-
import { validationError } from '../functional/error-types.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Validate limit parameter with configurable defaults and max
|
|
13
|
-
* Pure - validation with explicit parameters
|
|
14
|
-
*
|
|
15
|
-
* @param limit - The limit value to validate (string, number, or undefined)
|
|
16
|
-
* @param defaultLimit - Default limit if undefined (default: 50)
|
|
17
|
-
* @param maxLimit - Maximum allowed limit (default: 1000)
|
|
18
|
-
* @returns Result with validated limit number or validation error
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* validateLimit(undefined, 10, 100) // success(10)
|
|
22
|
-
* validateLimit('50', 10, 100) // success(50)
|
|
23
|
-
* validateLimit('150', 10, 100) // failure("Limit cannot exceed 100")
|
|
24
|
-
* validateLimit('invalid', 10, 100) // failure("Limit must be a positive number")
|
|
25
|
-
*/
|
|
26
|
-
export function validateLimit(
|
|
27
|
-
limit: string | number | undefined,
|
|
28
|
-
defaultLimit: number = 50,
|
|
29
|
-
maxLimit: number = 1000
|
|
30
|
-
): Result<number, AppError> {
|
|
31
|
-
if (limit === undefined) {
|
|
32
|
-
return success(defaultLimit);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const numLimit = typeof limit === 'string' ? Number.parseInt(limit, 10) : limit;
|
|
36
|
-
|
|
37
|
-
if (Number.isNaN(numLimit) || numLimit < 1) {
|
|
38
|
-
return failure(validationError('Limit must be a positive number', 'limit', limit));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (numLimit > maxLimit) {
|
|
42
|
-
return failure(validationError(`Limit cannot exceed ${maxLimit}`, 'limit', limit));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return success(numLimit);
|
|
46
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Validation Utilities
|
|
3
|
-
* Shared validation and normalization for query parameters
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Normalize query string by trimming whitespace
|
|
8
|
-
* Pure - string transformation
|
|
9
|
-
*
|
|
10
|
-
* @param query - The query string to normalize
|
|
11
|
-
* @returns Trimmed query string
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* normalizeQuery(' hello ') // 'hello'
|
|
15
|
-
* normalizeQuery('test') // 'test'
|
|
16
|
-
* normalizeQuery('') // ''
|
|
17
|
-
*/
|
|
18
|
-
export function normalizeQuery(query: string): string {
|
|
19
|
-
return query.trim();
|
|
20
|
-
}
|