om-memory-system 3.0.0
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/LICENSE +21 -0
- package/README.md +587 -0
- package/dist/adapters/opencode/auto-capture-host.d.ts +3 -0
- package/dist/adapters/opencode/auto-capture-host.js +29 -0
- package/dist/adapters/opencode/auto-capture-summary.d.ts +4 -0
- package/dist/adapters/opencode/auto-capture-summary.js +147 -0
- package/dist/adapters/opencode/conversation.d.ts +2 -0
- package/dist/adapters/opencode/conversation.js +50 -0
- package/dist/adapters/opencode/user-prompt.d.ts +9 -0
- package/dist/adapters/opencode/user-prompt.js +26 -0
- package/dist/adapters/pi/capture.d.ts +41 -0
- package/dist/adapters/pi/capture.js +91 -0
- package/dist/adapters/pi/conversation.d.ts +38 -0
- package/dist/adapters/pi/conversation.js +118 -0
- package/dist/adapters/pi/extension.d.ts +18 -0
- package/dist/adapters/pi/extension.js +234 -0
- package/dist/adapters/pi/import-command.d.ts +29 -0
- package/dist/adapters/pi/import-command.js +232 -0
- package/dist/adapters/pi/profile.d.ts +39 -0
- package/dist/adapters/pi/profile.js +148 -0
- package/dist/adapters/pi/provider.d.ts +50 -0
- package/dist/adapters/pi/provider.js +77 -0
- package/dist/config.d.ts +290 -0
- package/dist/config.js +742 -0
- package/dist/core/capture-context.d.ts +4 -0
- package/dist/core/capture-context.js +132 -0
- package/dist/core/capture.d.ts +15 -0
- package/dist/core/capture.js +68 -0
- package/dist/core/extraction.d.ts +80 -0
- package/dist/core/extraction.js +140 -0
- package/dist/core/host.d.ts +52 -0
- package/dist/core/host.js +1 -0
- package/dist/core/memory-operations.d.ts +27 -0
- package/dist/core/memory-operations.js +247 -0
- package/dist/core/retrieval.d.ts +12 -0
- package/dist/core/retrieval.js +72 -0
- package/dist/importer/discovery.d.ts +31 -0
- package/dist/importer/discovery.js +88 -0
- package/dist/importer/importer.d.ts +87 -0
- package/dist/importer/importer.js +260 -0
- package/dist/importer/ledger.d.ts +44 -0
- package/dist/importer/ledger.js +137 -0
- package/dist/importer/session-loader.d.ts +19 -0
- package/dist/importer/session-loader.js +12 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +601 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.js +11 -0
- package/dist/services/ai/ai-provider-factory.d.ts +7 -0
- package/dist/services/ai/ai-provider-factory.js +41 -0
- package/dist/services/ai/api-key-placeholder.d.ts +1 -0
- package/dist/services/ai/api-key-placeholder.js +14 -0
- package/dist/services/ai/internal-capture-sessions.d.ts +6 -0
- package/dist/services/ai/internal-capture-sessions.js +33 -0
- package/dist/services/ai/opencode-diagnostics.d.ts +7 -0
- package/dist/services/ai/opencode-diagnostics.js +36 -0
- package/dist/services/ai/opencode-host-config.d.ts +10 -0
- package/dist/services/ai/opencode-host-config.js +51 -0
- package/dist/services/ai/opencode-provider-loader.d.ts +3 -0
- package/dist/services/ai/opencode-provider-loader.js +4 -0
- package/dist/services/ai/opencode-provider.d.ts +92 -0
- package/dist/services/ai/opencode-provider.js +419 -0
- package/dist/services/ai/opencode-sdk-client.d.ts +6 -0
- package/dist/services/ai/opencode-sdk-client.js +38 -0
- package/dist/services/ai/profile-llm-client.d.ts +2 -0
- package/dist/services/ai/profile-llm-client.js +27 -0
- package/dist/services/ai/provider-config.d.ts +17 -0
- package/dist/services/ai/provider-config.js +30 -0
- package/dist/services/ai/providers/anthropic-messages.d.ts +34 -0
- package/dist/services/ai/providers/anthropic-messages.js +220 -0
- package/dist/services/ai/providers/base-provider.d.ts +24 -0
- package/dist/services/ai/providers/base-provider.js +24 -0
- package/dist/services/ai/providers/google-gemini.d.ts +15 -0
- package/dist/services/ai/providers/google-gemini.js +228 -0
- package/dist/services/ai/providers/minimax.d.ts +35 -0
- package/dist/services/ai/providers/minimax.js +55 -0
- package/dist/services/ai/providers/openai-chat-completion.d.ts +22 -0
- package/dist/services/ai/providers/openai-chat-completion.js +387 -0
- package/dist/services/ai/providers/openai-responses.d.ts +13 -0
- package/dist/services/ai/providers/openai-responses.js +182 -0
- package/dist/services/ai/providers/orcarouter.d.ts +51 -0
- package/dist/services/ai/providers/orcarouter.js +66 -0
- package/dist/services/ai/session/ai-session-manager.d.ts +24 -0
- package/dist/services/ai/session/ai-session-manager.js +211 -0
- package/dist/services/ai/session/session-types.d.ts +42 -0
- package/dist/services/ai/session/session-types.js +1 -0
- package/dist/services/ai/tools/tool-schema.d.ts +40 -0
- package/dist/services/ai/tools/tool-schema.js +24 -0
- package/dist/services/ai/validators/user-profile-validator.d.ts +12 -0
- package/dist/services/ai/validators/user-profile-validator.js +114 -0
- package/dist/services/api-handlers.d.ts +186 -0
- package/dist/services/api-handlers.js +1284 -0
- package/dist/services/auth-token.d.ts +14 -0
- package/dist/services/auth-token.js +59 -0
- package/dist/services/auto-capture.d.ts +3 -0
- package/dist/services/auto-capture.js +127 -0
- package/dist/services/cleanup-service.d.ts +22 -0
- package/dist/services/cleanup-service.js +109 -0
- package/dist/services/client.d.ts +134 -0
- package/dist/services/client.js +327 -0
- package/dist/services/context.d.ts +10 -0
- package/dist/services/context.js +27 -0
- package/dist/services/cors.d.ts +12 -0
- package/dist/services/cors.js +52 -0
- package/dist/services/deduplication-service.d.ts +28 -0
- package/dist/services/deduplication-service.js +111 -0
- package/dist/services/embedding.d.ts +36 -0
- package/dist/services/embedding.js +200 -0
- package/dist/services/jsonc.d.ts +6 -0
- package/dist/services/jsonc.js +76 -0
- package/dist/services/language-detector.d.ts +2 -0
- package/dist/services/language-detector.js +33 -0
- package/dist/services/legacy-migration.d.ts +77 -0
- package/dist/services/legacy-migration.js +343 -0
- package/dist/services/logger.d.ts +1 -0
- package/dist/services/logger.js +119 -0
- package/dist/services/memory-portability-service.d.ts +37 -0
- package/dist/services/memory-portability-service.js +340 -0
- package/dist/services/memory-scope.d.ts +16 -0
- package/dist/services/memory-scope.js +43 -0
- package/dist/services/migration-service.d.ts +42 -0
- package/dist/services/migration-service.js +307 -0
- package/dist/services/onnxruntime-resolve.d.ts +24 -0
- package/dist/services/onnxruntime-resolve.js +174 -0
- package/dist/services/privacy.d.ts +26 -0
- package/dist/services/privacy.js +69 -0
- package/dist/services/request-timeouts.d.ts +9 -0
- package/dist/services/request-timeouts.js +11 -0
- package/dist/services/runtime-require.d.ts +17 -0
- package/dist/services/runtime-require.js +75 -0
- package/dist/services/secret-resolver.d.ts +1 -0
- package/dist/services/secret-resolver.js +65 -0
- package/dist/services/shard-inventory-service.d.ts +69 -0
- package/dist/services/shard-inventory-service.js +315 -0
- package/dist/services/shard-path-migration-service.d.ts +31 -0
- package/dist/services/shard-path-migration-service.js +367 -0
- package/dist/services/tag-prefix-migration.d.ts +60 -0
- package/dist/services/tag-prefix-migration.js +439 -0
- package/dist/services/tag-prefix-scan.d.ts +26 -0
- package/dist/services/tag-prefix-scan.js +91 -0
- package/dist/services/tags.d.ts +29 -0
- package/dist/services/tags.js +251 -0
- package/dist/services/turso/connection-manager.d.ts +15 -0
- package/dist/services/turso/connection-manager.js +163 -0
- package/dist/services/turso/cross-process-write-lock.d.ts +1 -0
- package/dist/services/turso/cross-process-write-lock.js +89 -0
- package/dist/services/turso/legacy-migrator.d.ts +1 -0
- package/dist/services/turso/legacy-migrator.js +540 -0
- package/dist/services/turso/lifecycle.d.ts +1 -0
- package/dist/services/turso/lifecycle.js +14 -0
- package/dist/services/turso/operation-lock.d.ts +2 -0
- package/dist/services/turso/operation-lock.js +61 -0
- package/dist/services/turso/ready.d.ts +2 -0
- package/dist/services/turso/ready.js +36 -0
- package/dist/services/turso/shard-manager.d.ts +38 -0
- package/dist/services/turso/shard-manager.js +496 -0
- package/dist/services/turso/sqlite-handle-release.d.ts +16 -0
- package/dist/services/turso/sqlite-handle-release.js +56 -0
- package/dist/services/turso/turso-db.d.ts +18 -0
- package/dist/services/turso/turso-db.js +53 -0
- package/dist/services/turso/types.d.ts +42 -0
- package/dist/services/turso/types.js +1 -0
- package/dist/services/turso/vector-search.d.ts +41 -0
- package/dist/services/turso/vector-search.js +384 -0
- package/dist/services/turso/vector-utils.d.ts +7 -0
- package/dist/services/turso/vector-utils.js +67 -0
- package/dist/services/user-memory-learning.d.ts +97 -0
- package/dist/services/user-memory-learning.js +673 -0
- package/dist/services/user-profile/ai-cleanup.d.ts +58 -0
- package/dist/services/user-profile/ai-cleanup.js +486 -0
- package/dist/services/user-profile/profile-context.d.ts +1 -0
- package/dist/services/user-profile/profile-context.js +105 -0
- package/dist/services/user-profile/profile-utils.d.ts +2 -0
- package/dist/services/user-profile/profile-utils.js +45 -0
- package/dist/services/user-profile/types.d.ts +92 -0
- package/dist/services/user-profile/types.js +1 -0
- package/dist/services/user-profile/user-profile-manager.d.ts +65 -0
- package/dist/services/user-profile/user-profile-manager.js +1660 -0
- package/dist/services/user-prompt/user-prompt-manager.d.ts +53 -0
- package/dist/services/user-prompt/user-prompt-manager.js +303 -0
- package/dist/services/web-api-auth.d.ts +3 -0
- package/dist/services/web-api-auth.js +25 -0
- package/dist/services/web-auth.d.ts +46 -0
- package/dist/services/web-auth.js +105 -0
- package/dist/services/web-server.d.ts +57 -0
- package/dist/services/web-server.js +659 -0
- package/dist/shared/api/index.d.ts +4 -0
- package/dist/shared/api/index.js +2 -0
- package/dist/shared/api/portability-schemas.d.ts +56 -0
- package/dist/shared/api/portability-schemas.js +39 -0
- package/dist/shared/api/schemas.d.ts +295 -0
- package/dist/shared/api/schemas.js +134 -0
- package/dist/shared/api/types.d.ts +28 -0
- package/dist/shared/api/types.js +1 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/context-limit.d.ts +10 -0
- package/dist/utils/context-limit.js +43 -0
- package/dist/utils/math.d.ts +7 -0
- package/dist/utils/math.js +48 -0
- package/dist/utils/profile.d.ts +2 -0
- package/dist/utils/profile.js +15 -0
- package/dist/v2/adapter.d.ts +5 -0
- package/dist/v2/adapter.js +218 -0
- package/dist/v2/legacy-client.d.ts +15 -0
- package/dist/v2/legacy-client.js +257 -0
- package/dist/v2/memory-bridge.d.ts +18 -0
- package/dist/v2/memory-bridge.js +29 -0
- package/dist/v2/plugin.d.ts +3 -0
- package/dist/v2/plugin.js +24 -0
- package/dist/web/assets/index-DPjEpD1h.css +2 -0
- package/dist/web/assets/index-do26c4JJ.js +122 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist/web/favicon.ico +0 -0
- package/dist/web/index.html +14 -0
- package/dist/web/omms-icon.png +0 -0
- package/package.json +138 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { CONFIG } from "../config.js";
|
|
2
|
+
import { log } from "./logger.js";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { formatOnnxruntimeInitError, prepareOnnxruntimeForTransformers, } from "./onnxruntime-resolve.js";
|
|
5
|
+
import { createRuntimeRequire } from "./runtime-require.js";
|
|
6
|
+
const requireFromHere = createRuntimeRequire(import.meta);
|
|
7
|
+
const TIMEOUT_MS = 30000;
|
|
8
|
+
const GLOBAL_EMBEDDING_KEY = Symbol.for("omms.embedding.instance");
|
|
9
|
+
const MAX_CACHE_SIZE = 100;
|
|
10
|
+
const TASK_PREFIXES = {
|
|
11
|
+
document: "search_document: ",
|
|
12
|
+
query: "search_query: ",
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Apply Nomic-style task prefixes when enabled.
|
|
16
|
+
* Cache keys and API/local inputs should use the returned string.
|
|
17
|
+
*/
|
|
18
|
+
export function applyEmbeddingTaskPrefix(text, options, useTaskPrefixes = CONFIG.embeddingUseTaskPrefixes) {
|
|
19
|
+
if (!useTaskPrefixes || !options?.task)
|
|
20
|
+
return text;
|
|
21
|
+
const prefix = TASK_PREFIXES[options.task];
|
|
22
|
+
if (text.startsWith(prefix))
|
|
23
|
+
return text;
|
|
24
|
+
return `${prefix}${text}`;
|
|
25
|
+
}
|
|
26
|
+
let _transformers = null;
|
|
27
|
+
function getTransformersPackageSpecifier() {
|
|
28
|
+
// Keep this non-literal so OpenCode/Bun plugin-loader bundling does not eagerly
|
|
29
|
+
// traverse @huggingface/transformers internals during plugin startup. The package
|
|
30
|
+
// is only needed for the local embedding backend, and should stay lazy.
|
|
31
|
+
return ["@huggingface", "transformers"].join("/");
|
|
32
|
+
}
|
|
33
|
+
async function ensureTransformersLoaded() {
|
|
34
|
+
if (_transformers !== null)
|
|
35
|
+
return _transformers;
|
|
36
|
+
// Pin onnxruntime-node (+ common) to our direct 1.20.1 stack before transformers
|
|
37
|
+
// resolves them (#184 / #210 / #225). Load the CJS export so Module._resolveFilename
|
|
38
|
+
// shim applies — the ESM entry's static import bypasses it under OpenCode nested installs.
|
|
39
|
+
//
|
|
40
|
+
// Critical ordering for OpenCode's Bun --compile host (#210 follow-up):
|
|
41
|
+
// resolve the transformers absolute path BEFORE installOnnxruntimeResolveShim().
|
|
42
|
+
// After the shim is installed, non-onnx Module._resolveFilename fallbacks fail with
|
|
43
|
+
// `Cannot find module '@huggingface/transformers' from ''` even though the package
|
|
44
|
+
// exists. Loading via the pre-resolved absolute path keeps the onnx pin shim active
|
|
45
|
+
// for transformers' nested requires without needing a post-shim package resolve.
|
|
46
|
+
const transformersSpecifier = getTransformersPackageSpecifier();
|
|
47
|
+
let transformersEntry;
|
|
48
|
+
try {
|
|
49
|
+
transformersEntry = requireFromHere.resolve(transformersSpecifier);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
throw new Error(`Cannot resolve ${transformersSpecifier} before installing the onnxruntime pin shim. ` +
|
|
53
|
+
`Original error: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
54
|
+
}
|
|
55
|
+
prepareOnnxruntimeForTransformers();
|
|
56
|
+
const mod = requireFromHere(transformersEntry);
|
|
57
|
+
mod.env.allowLocalModels = true;
|
|
58
|
+
mod.env.allowRemoteModels = true;
|
|
59
|
+
mod.env.cacheDir = join(CONFIG.storagePath, ".cache");
|
|
60
|
+
// Keep ONNX WASM single-threaded for Bun/Node runtimes without SharedArrayBuffer.
|
|
61
|
+
try {
|
|
62
|
+
mod.env.backends.onnx.wasm.numThreads = 1;
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
log("Failed to set wasm.numThreads", { error: String(e) });
|
|
66
|
+
}
|
|
67
|
+
_transformers = mod;
|
|
68
|
+
return _transformers;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Production transformers load path used by nested OpenCode install fixtures (#210).
|
|
72
|
+
* Prefer this over a separately anchored createRequire() so empty-referrer hosts are covered.
|
|
73
|
+
*/
|
|
74
|
+
export async function loadLocalTransformersBackend() {
|
|
75
|
+
return ensureTransformersLoaded();
|
|
76
|
+
}
|
|
77
|
+
function withTimeout(promise, ms) {
|
|
78
|
+
return Promise.race([
|
|
79
|
+
promise,
|
|
80
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms)),
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
export class EmbeddingService {
|
|
84
|
+
pipe = null;
|
|
85
|
+
initPromise = null;
|
|
86
|
+
isWarmedUp = false;
|
|
87
|
+
/** Set when warmup fails permanently; prevents "initializing forever" (#184). */
|
|
88
|
+
initError = null;
|
|
89
|
+
cache = new Map();
|
|
90
|
+
cachedModelName = null;
|
|
91
|
+
static getInstance() {
|
|
92
|
+
if (!globalThis[GLOBAL_EMBEDDING_KEY]) {
|
|
93
|
+
globalThis[GLOBAL_EMBEDDING_KEY] = new EmbeddingService();
|
|
94
|
+
}
|
|
95
|
+
return globalThis[GLOBAL_EMBEDDING_KEY];
|
|
96
|
+
}
|
|
97
|
+
async warmup(progressCallback) {
|
|
98
|
+
if (this.isWarmedUp)
|
|
99
|
+
return;
|
|
100
|
+
if (this.initError)
|
|
101
|
+
throw new Error(this.initError);
|
|
102
|
+
if (this.initPromise)
|
|
103
|
+
return this.initPromise;
|
|
104
|
+
this.initPromise = this.initializeModel(progressCallback);
|
|
105
|
+
return this.initPromise;
|
|
106
|
+
}
|
|
107
|
+
async initializeModel(progressCallback) {
|
|
108
|
+
try {
|
|
109
|
+
if (CONFIG.embeddingApiUrl && CONFIG.embeddingApiKey) {
|
|
110
|
+
// Send a probe request to verify the API endpoint is actually reachable
|
|
111
|
+
// Uses a minimal embedding of "ping" to test the full request pipeline
|
|
112
|
+
const probeResponse = await withTimeout(fetch(`${CONFIG.embeddingApiUrl}/embeddings`, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
headers: {
|
|
115
|
+
"Content-Type": "application/json",
|
|
116
|
+
Authorization: `Bearer ${CONFIG.embeddingApiKey}`,
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify({
|
|
119
|
+
input: "ping",
|
|
120
|
+
model: CONFIG.embeddingModel,
|
|
121
|
+
}),
|
|
122
|
+
}), TIMEOUT_MS);
|
|
123
|
+
if (!probeResponse.ok) {
|
|
124
|
+
throw new Error(`Embedding API health check failed: ${probeResponse.status} ${probeResponse.statusText}`);
|
|
125
|
+
}
|
|
126
|
+
this.isWarmedUp = true;
|
|
127
|
+
this.initError = null;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// Local model path
|
|
131
|
+
const { pipeline } = await ensureTransformersLoaded();
|
|
132
|
+
this.pipe = await pipeline("feature-extraction", CONFIG.embeddingModel, {
|
|
133
|
+
progress_callback: progressCallback,
|
|
134
|
+
});
|
|
135
|
+
this.isWarmedUp = true;
|
|
136
|
+
this.initError = null;
|
|
137
|
+
log("Embedding model warmed up", { model: CONFIG.embeddingModel });
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
const rewritten = formatOnnxruntimeInitError(error);
|
|
141
|
+
this.initPromise = null;
|
|
142
|
+
this.initError = rewritten.message;
|
|
143
|
+
log("Failed to initialize embedding model", { error: rewritten.message });
|
|
144
|
+
throw rewritten;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async embed(text, options) {
|
|
148
|
+
if (this.cachedModelName !== CONFIG.embeddingModel) {
|
|
149
|
+
this.clearCache();
|
|
150
|
+
this.cachedModelName = CONFIG.embeddingModel;
|
|
151
|
+
}
|
|
152
|
+
const input = applyEmbeddingTaskPrefix(text, options);
|
|
153
|
+
const cached = this.cache.get(input);
|
|
154
|
+
if (cached)
|
|
155
|
+
return cached;
|
|
156
|
+
if (!this.isWarmedUp && !this.initPromise) {
|
|
157
|
+
await this.warmup();
|
|
158
|
+
}
|
|
159
|
+
if (this.initPromise) {
|
|
160
|
+
await this.initPromise;
|
|
161
|
+
}
|
|
162
|
+
let result;
|
|
163
|
+
if (CONFIG.embeddingApiUrl && CONFIG.embeddingApiKey) {
|
|
164
|
+
const response = await fetch(`${CONFIG.embeddingApiUrl}/embeddings`, {
|
|
165
|
+
method: "POST",
|
|
166
|
+
headers: {
|
|
167
|
+
"Content-Type": "application/json",
|
|
168
|
+
Authorization: `Bearer ${CONFIG.embeddingApiKey}`,
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
input,
|
|
172
|
+
model: CONFIG.embeddingModel,
|
|
173
|
+
}),
|
|
174
|
+
});
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
throw new Error(`API embedding failed: ${response.statusText}`);
|
|
177
|
+
}
|
|
178
|
+
const data = await response.json();
|
|
179
|
+
result = new Float32Array(data.data[0].embedding);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const output = await this.pipe(input, { pooling: "mean", normalize: true });
|
|
183
|
+
result = new Float32Array(output.data);
|
|
184
|
+
}
|
|
185
|
+
if (this.cache.size >= MAX_CACHE_SIZE) {
|
|
186
|
+
const firstKey = this.cache.keys().next().value;
|
|
187
|
+
if (firstKey !== undefined)
|
|
188
|
+
this.cache.delete(firstKey);
|
|
189
|
+
}
|
|
190
|
+
this.cache.set(input, result);
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
async embedWithTimeout(text, options) {
|
|
194
|
+
return withTimeout(this.embed(text, options), TIMEOUT_MS);
|
|
195
|
+
}
|
|
196
|
+
clearCache() {
|
|
197
|
+
this.cache.clear();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export const embeddingService = EmbeddingService.getInstance();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strips comments from JSONC content while respecting string boundaries.
|
|
3
|
+
* Handles // and /* comments, URLs in strings, and escaped quotes.
|
|
4
|
+
* Also removes trailing commas to support more relaxed JSONC format.
|
|
5
|
+
*/
|
|
6
|
+
export declare function stripJsoncComments(content: string): string;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strips comments from JSONC content while respecting string boundaries.
|
|
3
|
+
* Handles // and /* comments, URLs in strings, and escaped quotes.
|
|
4
|
+
* Also removes trailing commas to support more relaxed JSONC format.
|
|
5
|
+
*/
|
|
6
|
+
export function stripJsoncComments(content) {
|
|
7
|
+
let result = "";
|
|
8
|
+
let i = 0;
|
|
9
|
+
let inString = false;
|
|
10
|
+
let inSingleLineComment = false;
|
|
11
|
+
let inMultiLineComment = false;
|
|
12
|
+
while (i < content.length) {
|
|
13
|
+
const char = content[i];
|
|
14
|
+
const nextChar = content[i + 1];
|
|
15
|
+
if (!inSingleLineComment && !inMultiLineComment) {
|
|
16
|
+
if (char === '"') {
|
|
17
|
+
// Count consecutive backslashes before this quote
|
|
18
|
+
let backslashCount = 0;
|
|
19
|
+
let j = i - 1;
|
|
20
|
+
while (j >= 0 && content[j] === "\\") {
|
|
21
|
+
backslashCount++;
|
|
22
|
+
j--;
|
|
23
|
+
}
|
|
24
|
+
// Quote is escaped only if preceded by ODD number of backslashes
|
|
25
|
+
// e.g., \" = escaped, \\" = not escaped (escaped backslash + quote)
|
|
26
|
+
if (backslashCount % 2 === 0) {
|
|
27
|
+
inString = !inString;
|
|
28
|
+
}
|
|
29
|
+
result += char;
|
|
30
|
+
i++;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (inString) {
|
|
35
|
+
result += char;
|
|
36
|
+
i++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (!inSingleLineComment && !inMultiLineComment) {
|
|
40
|
+
if (char === "/" && nextChar === "/") {
|
|
41
|
+
inSingleLineComment = true;
|
|
42
|
+
i += 2;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (char === "/" && nextChar === "*") {
|
|
46
|
+
inMultiLineComment = true;
|
|
47
|
+
i += 2;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (inSingleLineComment) {
|
|
52
|
+
if (char === "\n") {
|
|
53
|
+
inSingleLineComment = false;
|
|
54
|
+
result += char;
|
|
55
|
+
}
|
|
56
|
+
i++;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (inMultiLineComment) {
|
|
60
|
+
if (char === "*" && nextChar === "/") {
|
|
61
|
+
inMultiLineComment = false;
|
|
62
|
+
i += 2;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (char === "\n") {
|
|
66
|
+
result += char;
|
|
67
|
+
}
|
|
68
|
+
i++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
result += char;
|
|
72
|
+
i++;
|
|
73
|
+
}
|
|
74
|
+
// Remove trailing commas before } or ]
|
|
75
|
+
return result.replace(/,\s*([}\]])/g, "$1");
|
|
76
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { franc } from "franc-min";
|
|
2
|
+
import { iso6393, iso6393To1 } from "iso-639-3";
|
|
3
|
+
// 3-letter codes without ISO 639-1 equivalents
|
|
4
|
+
const FALLBACK_MAP = {
|
|
5
|
+
cmn: "zh", // Mandarin Chinese
|
|
6
|
+
yue: "zh", // Cantonese
|
|
7
|
+
arz: "ar", // Egyptian Arabic
|
|
8
|
+
hbs: "sr", // Serbo-Croatian
|
|
9
|
+
};
|
|
10
|
+
export function detectLanguage(text) {
|
|
11
|
+
if (!text || text.trim().length === 0) {
|
|
12
|
+
return "en";
|
|
13
|
+
}
|
|
14
|
+
const detected = franc(text, { minLength: 5 });
|
|
15
|
+
if (detected === "und") {
|
|
16
|
+
return "en";
|
|
17
|
+
}
|
|
18
|
+
// Try 2-letter mapping first
|
|
19
|
+
const twoLetter = iso6393To1[detected];
|
|
20
|
+
if (twoLetter)
|
|
21
|
+
return twoLetter;
|
|
22
|
+
// Fallback for 3-letter codes without 2-letter equivalent
|
|
23
|
+
return FALLBACK_MAP[detected] || "en";
|
|
24
|
+
}
|
|
25
|
+
export function getLanguageName(code) {
|
|
26
|
+
// Try 2-letter lookup first
|
|
27
|
+
let lang = iso6393.find((l) => l.iso6391 === code);
|
|
28
|
+
// Fallback to 3-letter lookup
|
|
29
|
+
if (!lang) {
|
|
30
|
+
lang = iso6393.find((l) => l.iso6393 === code);
|
|
31
|
+
}
|
|
32
|
+
return lang?.name || "English";
|
|
33
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export interface LegacyMigrationPaths {
|
|
2
|
+
legacyDir: string;
|
|
3
|
+
legacyDataDir: string;
|
|
4
|
+
ommsDir: string;
|
|
5
|
+
ommsDataDir: string;
|
|
6
|
+
backupsDir: string;
|
|
7
|
+
markerPath: string;
|
|
8
|
+
lockPath: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LegacyMigrationMarker {
|
|
11
|
+
version: 1;
|
|
12
|
+
status: "migrated" | "failed";
|
|
13
|
+
source: string;
|
|
14
|
+
destination: string;
|
|
15
|
+
backupPath?: string;
|
|
16
|
+
fileCount?: number;
|
|
17
|
+
startedAt: string;
|
|
18
|
+
completedAt?: string;
|
|
19
|
+
/** Which stage failed, when status is "failed". */
|
|
20
|
+
stage?: "backup" | "copy";
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
export type LegacyMigrationResult = {
|
|
24
|
+
kind: "migrated";
|
|
25
|
+
marker: LegacyMigrationMarker;
|
|
26
|
+
} | {
|
|
27
|
+
kind: "already-migrated";
|
|
28
|
+
marker: LegacyMigrationMarker;
|
|
29
|
+
} | {
|
|
30
|
+
kind: "failed-marker";
|
|
31
|
+
marker: LegacyMigrationMarker;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "failed";
|
|
34
|
+
marker: LegacyMigrationMarker;
|
|
35
|
+
} | {
|
|
36
|
+
kind: "fresh";
|
|
37
|
+
} | {
|
|
38
|
+
kind: "destination-exists";
|
|
39
|
+
} | {
|
|
40
|
+
kind: "in-progress";
|
|
41
|
+
};
|
|
42
|
+
interface BackupManifestEntry {
|
|
43
|
+
path: string;
|
|
44
|
+
size: number;
|
|
45
|
+
sha256: string;
|
|
46
|
+
}
|
|
47
|
+
export type { BackupManifestEntry };
|
|
48
|
+
export declare function legacyMigrationPaths(home?: string): LegacyMigrationPaths;
|
|
49
|
+
export declare function readLegacyMigrationMarker(home?: string): LegacyMigrationMarker | null;
|
|
50
|
+
/**
|
|
51
|
+
* Default storage resolution shared with config.ts. While a legacy store
|
|
52
|
+
* exists and the migration has not succeeded, storage keeps resolving to the
|
|
53
|
+
* legacy layout (covering both "migration pending" and "migration failed").
|
|
54
|
+
* After a successful migration, or on a fresh install, the omms path wins.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveDefaultStoragePath(home?: string): string;
|
|
57
|
+
export interface TreeWalk {
|
|
58
|
+
files: string[];
|
|
59
|
+
dirs: string[];
|
|
60
|
+
}
|
|
61
|
+
export declare function walkTree(root: string): TreeWalk;
|
|
62
|
+
declare function timestampSlug(date?: Date): string;
|
|
63
|
+
export { timestampSlug };
|
|
64
|
+
/**
|
|
65
|
+
* Copy the listed files from `sourceRoot` into `destRoot` (mirroring their
|
|
66
|
+
* relative paths), producing a checksum manifest, then verify every copied
|
|
67
|
+
* file by re-reading it and comparing size and sha256. Throws on any failure.
|
|
68
|
+
* The caller is responsible for creating any missing parent directories and
|
|
69
|
+
* for holding any locks that keep the source quiescent during the copy.
|
|
70
|
+
*/
|
|
71
|
+
export declare function copyFilesWithVerification(sourceRoot: string, destRoot: string, relPaths: string[]): BackupManifestEntry[];
|
|
72
|
+
/**
|
|
73
|
+
* Run the one-time legacy store migration for the given home directory.
|
|
74
|
+
* Pure module: no environment-variable switches, no CONFIG dependency.
|
|
75
|
+
* Hosts integrate it through initConfigWithLegacyMigration in config.ts.
|
|
76
|
+
*/
|
|
77
|
+
export declare function runLegacyStoreMigration(home?: string): LegacyMigrationResult;
|