iosm-cli 0.1.2 → 0.2.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/CHANGELOG.md +33 -0
- package/README.md +37 -3
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-profiles.d.ts.map +1 -1
- package/dist/core/agent-profiles.js +1 -0
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +3 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/blast.d.ts +62 -0
- package/dist/core/blast.d.ts.map +1 -0
- package/dist/core/blast.js +448 -0
- package/dist/core/blast.js.map +1 -0
- package/dist/core/contract.d.ts +54 -0
- package/dist/core/contract.d.ts.map +1 -0
- package/dist/core/contract.js +300 -0
- package/dist/core/contract.js.map +1 -0
- package/dist/core/sdk.d.ts +3 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +11 -19
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/semantic/chunking.d.ts +10 -0
- package/dist/core/semantic/chunking.d.ts.map +1 -0
- package/dist/core/semantic/chunking.js +82 -0
- package/dist/core/semantic/chunking.js.map +1 -0
- package/dist/core/semantic/cli.d.ts +23 -0
- package/dist/core/semantic/cli.d.ts.map +1 -0
- package/dist/core/semantic/cli.js +86 -0
- package/dist/core/semantic/cli.js.map +1 -0
- package/dist/core/semantic/config.d.ts +8 -0
- package/dist/core/semantic/config.d.ts.map +1 -0
- package/dist/core/semantic/config.js +266 -0
- package/dist/core/semantic/config.js.map +1 -0
- package/dist/core/semantic/index-store.d.ts +21 -0
- package/dist/core/semantic/index-store.d.ts.map +1 -0
- package/dist/core/semantic/index-store.js +73 -0
- package/dist/core/semantic/index-store.js.map +1 -0
- package/dist/core/semantic/index.d.ts +8 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +7 -0
- package/dist/core/semantic/index.js.map +1 -0
- package/dist/core/semantic/providers.d.ts +22 -0
- package/dist/core/semantic/providers.d.ts.map +1 -0
- package/dist/core/semantic/providers.js +317 -0
- package/dist/core/semantic/providers.js.map +1 -0
- package/dist/core/semantic/runtime.d.ts +32 -0
- package/dist/core/semantic/runtime.d.ts.map +1 -0
- package/dist/core/semantic/runtime.js +510 -0
- package/dist/core/semantic/runtime.js.map +1 -0
- package/dist/core/semantic/types.d.ts +157 -0
- package/dist/core/semantic/types.d.ts.map +1 -0
- package/dist/core/semantic/types.js +23 -0
- package/dist/core/semantic/types.js.map +1 -0
- package/dist/core/shadow-guard.d.ts +30 -0
- package/dist/core/shadow-guard.d.ts.map +1 -0
- package/dist/core/shadow-guard.js +81 -0
- package/dist/core/shadow-guard.js.map +1 -0
- package/dist/core/singular.d.ts +73 -0
- package/dist/core/singular.d.ts.map +1 -0
- package/dist/core/singular.js +413 -0
- package/dist/core/singular.js.map +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +12 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +21 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/ast-grep.js +1 -1
- package/dist/core/tools/ast-grep.js.map +1 -1
- package/dist/core/tools/comby.js +1 -1
- package/dist/core/tools/comby.js.map +1 -1
- package/dist/core/tools/index.d.ts +9 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +6 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/rg.js +1 -1
- package/dist/core/tools/rg.js.map +1 -1
- package/dist/core/tools/semantic-search.d.ts +21 -0
- package/dist/core/tools/semantic-search.d.ts.map +1 -0
- package/dist/core/tools/semantic-search.js +123 -0
- package/dist/core/tools/semantic-search.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +124 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +8 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +70 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +58 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +2067 -104
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/cli-reference.md +36 -1
- package/docs/configuration.md +79 -2
- package/docs/getting-started.md +1 -0
- package/docs/interactive-mode.md +135 -1
- package/package.json +1 -1
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { SemanticConfigError } from "./types.js";
|
|
4
|
+
const DEFAULT_INCLUDE_GLOBS = ["**/*.{ts,tsx,js,jsx,py,go,rs,java,md,json,yaml,yml}"];
|
|
5
|
+
const DEFAULT_EXCLUDE_GLOBS = ["**/.git/**", "**/node_modules/**", "**/dist/**", "**/build/**", "**/.iosm/**"];
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
enabled: true,
|
|
8
|
+
autoIndex: true,
|
|
9
|
+
provider: {
|
|
10
|
+
type: "openrouter",
|
|
11
|
+
model: "openai/text-embedding-3-small",
|
|
12
|
+
batchSize: 32,
|
|
13
|
+
timeoutMs: 30_000,
|
|
14
|
+
},
|
|
15
|
+
index: {
|
|
16
|
+
includeGlobs: [...DEFAULT_INCLUDE_GLOBS],
|
|
17
|
+
excludeGlobs: [...DEFAULT_EXCLUDE_GLOBS],
|
|
18
|
+
chunkMaxChars: 1200,
|
|
19
|
+
chunkOverlapChars: 200,
|
|
20
|
+
maxFileBytes: 262_144,
|
|
21
|
+
maxFiles: 20_000,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
function isRecord(value) {
|
|
25
|
+
return typeof value === "object" && value !== null;
|
|
26
|
+
}
|
|
27
|
+
function asString(value) {
|
|
28
|
+
return typeof value === "string" ? value : undefined;
|
|
29
|
+
}
|
|
30
|
+
function asBoolean(value) {
|
|
31
|
+
return typeof value === "boolean" ? value : undefined;
|
|
32
|
+
}
|
|
33
|
+
function asNumber(value) {
|
|
34
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
35
|
+
}
|
|
36
|
+
function sanitizeStringArray(value) {
|
|
37
|
+
if (!Array.isArray(value))
|
|
38
|
+
return undefined;
|
|
39
|
+
const normalized = value
|
|
40
|
+
.filter((item) => typeof item === "string")
|
|
41
|
+
.map((item) => item.trim())
|
|
42
|
+
.filter((item) => item.length > 0);
|
|
43
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
44
|
+
}
|
|
45
|
+
function sanitizeStringRecord(value) {
|
|
46
|
+
if (!isRecord(value))
|
|
47
|
+
return undefined;
|
|
48
|
+
const result = {};
|
|
49
|
+
for (const [key, rawValue] of Object.entries(value)) {
|
|
50
|
+
if (typeof rawValue !== "string")
|
|
51
|
+
continue;
|
|
52
|
+
const normalizedKey = key.trim();
|
|
53
|
+
if (!normalizedKey)
|
|
54
|
+
continue;
|
|
55
|
+
result[normalizedKey] = rawValue;
|
|
56
|
+
}
|
|
57
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
58
|
+
}
|
|
59
|
+
function sanitizeProviderType(value) {
|
|
60
|
+
if (value === "openrouter" || value === "ollama" || value === "custom_openai") {
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
function clampInt(value, fallback, min, max) {
|
|
66
|
+
if (value === undefined)
|
|
67
|
+
return fallback;
|
|
68
|
+
const normalized = Math.floor(value);
|
|
69
|
+
if (!Number.isFinite(normalized))
|
|
70
|
+
return fallback;
|
|
71
|
+
if (normalized < min)
|
|
72
|
+
return min;
|
|
73
|
+
if (normalized > max)
|
|
74
|
+
return max;
|
|
75
|
+
return normalized;
|
|
76
|
+
}
|
|
77
|
+
function parseSemanticConfigFile(path) {
|
|
78
|
+
if (!existsSync(path)) {
|
|
79
|
+
return {};
|
|
80
|
+
}
|
|
81
|
+
const raw = readFileSync(path, "utf8");
|
|
82
|
+
const parsed = JSON.parse(raw);
|
|
83
|
+
if (!isRecord(parsed)) {
|
|
84
|
+
throw new SemanticConfigError(`Expected JSON object in ${path}`);
|
|
85
|
+
}
|
|
86
|
+
const result = {};
|
|
87
|
+
const rawSemantic = parsed.semanticSearch;
|
|
88
|
+
if (!isRecord(rawSemantic)) {
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
const provider = isRecord(rawSemantic.provider)
|
|
92
|
+
? {
|
|
93
|
+
type: sanitizeProviderType(rawSemantic.provider.type),
|
|
94
|
+
model: asString(rawSemantic.provider.model),
|
|
95
|
+
baseUrl: asString(rawSemantic.provider.baseUrl),
|
|
96
|
+
apiKeyEnv: asString(rawSemantic.provider.apiKeyEnv),
|
|
97
|
+
headers: sanitizeStringRecord(rawSemantic.provider.headers),
|
|
98
|
+
batchSize: asNumber(rawSemantic.provider.batchSize),
|
|
99
|
+
timeoutMs: asNumber(rawSemantic.provider.timeoutMs),
|
|
100
|
+
}
|
|
101
|
+
: undefined;
|
|
102
|
+
const index = isRecord(rawSemantic.index)
|
|
103
|
+
? {
|
|
104
|
+
includeGlobs: sanitizeStringArray(rawSemantic.index.includeGlobs),
|
|
105
|
+
excludeGlobs: sanitizeStringArray(rawSemantic.index.excludeGlobs),
|
|
106
|
+
chunkMaxChars: asNumber(rawSemantic.index.chunkMaxChars),
|
|
107
|
+
chunkOverlapChars: asNumber(rawSemantic.index.chunkOverlapChars),
|
|
108
|
+
maxFileBytes: asNumber(rawSemantic.index.maxFileBytes),
|
|
109
|
+
maxFiles: asNumber(rawSemantic.index.maxFiles),
|
|
110
|
+
}
|
|
111
|
+
: undefined;
|
|
112
|
+
result.semanticSearch = {
|
|
113
|
+
enabled: asBoolean(rawSemantic.enabled),
|
|
114
|
+
autoIndex: asBoolean(rawSemantic.autoIndex),
|
|
115
|
+
provider,
|
|
116
|
+
index,
|
|
117
|
+
};
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
function mergeSemanticConfig(base, override) {
|
|
121
|
+
if (!base && !override)
|
|
122
|
+
return undefined;
|
|
123
|
+
return {
|
|
124
|
+
...(base ?? {}),
|
|
125
|
+
...(override ?? {}),
|
|
126
|
+
provider: {
|
|
127
|
+
...(base?.provider ?? {}),
|
|
128
|
+
...(override?.provider ?? {}),
|
|
129
|
+
},
|
|
130
|
+
index: {
|
|
131
|
+
...(base?.index ?? {}),
|
|
132
|
+
...(override?.index ?? {}),
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function resolveSemanticSearchConfig(partial) {
|
|
137
|
+
if (!partial)
|
|
138
|
+
return undefined;
|
|
139
|
+
const providerType = partial.provider?.type ?? DEFAULT_CONFIG.provider.type;
|
|
140
|
+
const model = (partial.provider?.model ?? DEFAULT_CONFIG.provider.model).trim();
|
|
141
|
+
if (!model) {
|
|
142
|
+
throw new SemanticConfigError(`semanticSearch.provider.model cannot be empty`);
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
enabled: partial.enabled ?? DEFAULT_CONFIG.enabled,
|
|
146
|
+
autoIndex: partial.autoIndex ?? DEFAULT_CONFIG.autoIndex,
|
|
147
|
+
provider: {
|
|
148
|
+
type: providerType,
|
|
149
|
+
model,
|
|
150
|
+
baseUrl: partial.provider?.baseUrl?.trim() || undefined,
|
|
151
|
+
apiKeyEnv: partial.provider?.apiKeyEnv?.trim() || undefined,
|
|
152
|
+
headers: partial.provider?.headers && Object.keys(partial.provider.headers).length > 0 ? partial.provider.headers : undefined,
|
|
153
|
+
batchSize: clampInt(partial.provider?.batchSize, DEFAULT_CONFIG.provider.batchSize, 1, 512),
|
|
154
|
+
timeoutMs: clampInt(partial.provider?.timeoutMs, DEFAULT_CONFIG.provider.timeoutMs, 1_000, 300_000),
|
|
155
|
+
},
|
|
156
|
+
index: {
|
|
157
|
+
includeGlobs: partial.index?.includeGlobs && partial.index.includeGlobs.length > 0 ? partial.index.includeGlobs : [...DEFAULT_CONFIG.index.includeGlobs],
|
|
158
|
+
excludeGlobs: partial.index?.excludeGlobs && partial.index.excludeGlobs.length > 0 ? partial.index.excludeGlobs : [...DEFAULT_CONFIG.index.excludeGlobs],
|
|
159
|
+
chunkMaxChars: clampInt(partial.index?.chunkMaxChars, DEFAULT_CONFIG.index.chunkMaxChars, 200, 20_000),
|
|
160
|
+
chunkOverlapChars: clampInt(partial.index?.chunkOverlapChars, DEFAULT_CONFIG.index.chunkOverlapChars, 0, 5_000),
|
|
161
|
+
maxFileBytes: clampInt(partial.index?.maxFileBytes, DEFAULT_CONFIG.index.maxFileBytes, 1_024, 16 * 1024 * 1024),
|
|
162
|
+
maxFiles: clampInt(partial.index?.maxFiles, DEFAULT_CONFIG.index.maxFiles, 1, 1_000_000),
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
export function getSemanticConfigPath(scope, cwd, agentDir) {
|
|
167
|
+
return scope === "project" ? join(cwd, ".iosm", "semantic.json") : join(agentDir, "semantic.json");
|
|
168
|
+
}
|
|
169
|
+
export function readScopedSemanticConfig(scope, cwd, agentDir) {
|
|
170
|
+
const path = getSemanticConfigPath(scope, cwd, agentDir);
|
|
171
|
+
try {
|
|
172
|
+
return {
|
|
173
|
+
scope,
|
|
174
|
+
path,
|
|
175
|
+
file: parseSemanticConfigFile(path),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
return {
|
|
180
|
+
scope,
|
|
181
|
+
path,
|
|
182
|
+
file: {},
|
|
183
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
export function loadMergedSemanticConfig(cwd, agentDir) {
|
|
188
|
+
const scoped = [readScopedSemanticConfig("user", cwd, agentDir), readScopedSemanticConfig("project", cwd, agentDir)];
|
|
189
|
+
const errors = [];
|
|
190
|
+
for (const entry of scoped) {
|
|
191
|
+
if (entry.error) {
|
|
192
|
+
errors.push(`${entry.scope} config (${entry.path}): ${entry.error.message}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const mergedPartial = mergeSemanticConfig(scoped[0]?.file.semanticSearch, scoped[1]?.file.semanticSearch);
|
|
196
|
+
let config;
|
|
197
|
+
try {
|
|
198
|
+
config = resolveSemanticSearchConfig(mergedPartial);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
202
|
+
errors.push(`semanticSearch: ${message}`);
|
|
203
|
+
config = undefined;
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
config,
|
|
207
|
+
errors,
|
|
208
|
+
scoped,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
export function writeScopedSemanticConfig(scope, file, cwd, agentDir) {
|
|
212
|
+
const path = getSemanticConfigPath(scope, cwd, agentDir);
|
|
213
|
+
const dir = dirname(path);
|
|
214
|
+
if (!existsSync(dir)) {
|
|
215
|
+
mkdirSync(dir, { recursive: true });
|
|
216
|
+
}
|
|
217
|
+
writeFileSync(path, `${JSON.stringify(file, null, 2)}\n`, "utf8");
|
|
218
|
+
return path;
|
|
219
|
+
}
|
|
220
|
+
export function upsertScopedSemanticSearchConfig(scope, config, cwd, agentDir) {
|
|
221
|
+
const current = readScopedSemanticConfig(scope, cwd, agentDir);
|
|
222
|
+
if (current.error) {
|
|
223
|
+
throw new SemanticConfigError(`Cannot update ${scope} semantic config (${current.path}): ${current.error.message}`);
|
|
224
|
+
}
|
|
225
|
+
const nextFile = {
|
|
226
|
+
...current.file,
|
|
227
|
+
semanticSearch: {
|
|
228
|
+
enabled: config.enabled,
|
|
229
|
+
autoIndex: config.autoIndex,
|
|
230
|
+
provider: {
|
|
231
|
+
type: config.provider.type,
|
|
232
|
+
model: config.provider.model,
|
|
233
|
+
baseUrl: config.provider.baseUrl,
|
|
234
|
+
apiKeyEnv: config.provider.apiKeyEnv,
|
|
235
|
+
headers: config.provider.headers,
|
|
236
|
+
batchSize: config.provider.batchSize,
|
|
237
|
+
timeoutMs: config.provider.timeoutMs,
|
|
238
|
+
},
|
|
239
|
+
index: {
|
|
240
|
+
includeGlobs: [...config.index.includeGlobs],
|
|
241
|
+
excludeGlobs: [...config.index.excludeGlobs],
|
|
242
|
+
chunkMaxChars: config.index.chunkMaxChars,
|
|
243
|
+
chunkOverlapChars: config.index.chunkOverlapChars,
|
|
244
|
+
maxFileBytes: config.index.maxFileBytes,
|
|
245
|
+
maxFiles: config.index.maxFiles,
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
return writeScopedSemanticConfig(scope, nextFile, cwd, agentDir);
|
|
250
|
+
}
|
|
251
|
+
export function getDefaultSemanticSearchConfig() {
|
|
252
|
+
return {
|
|
253
|
+
enabled: DEFAULT_CONFIG.enabled,
|
|
254
|
+
autoIndex: DEFAULT_CONFIG.autoIndex,
|
|
255
|
+
provider: { ...DEFAULT_CONFIG.provider },
|
|
256
|
+
index: {
|
|
257
|
+
includeGlobs: [...DEFAULT_CONFIG.index.includeGlobs],
|
|
258
|
+
excludeGlobs: [...DEFAULT_CONFIG.index.excludeGlobs],
|
|
259
|
+
chunkMaxChars: DEFAULT_CONFIG.index.chunkMaxChars,
|
|
260
|
+
chunkOverlapChars: DEFAULT_CONFIG.index.chunkOverlapChars,
|
|
261
|
+
maxFileBytes: DEFAULT_CONFIG.index.maxFileBytes,
|
|
262
|
+
maxFiles: DEFAULT_CONFIG.index.maxFiles,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/core/semantic/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type {\n\tSemanticConfigFile,\n\tSemanticMergedConfig,\n\tSemanticScope,\n\tSemanticScopedLoadResult,\n\tSemanticSearchConfig,\n\tSemanticProviderType,\n} from \"./types.js\";\nimport { SemanticConfigError } from \"./types.js\";\n\nconst DEFAULT_INCLUDE_GLOBS = [\"**/*.{ts,tsx,js,jsx,py,go,rs,java,md,json,yaml,yml}\"];\nconst DEFAULT_EXCLUDE_GLOBS = [\"**/.git/**\", \"**/node_modules/**\", \"**/dist/**\", \"**/build/**\", \"**/.iosm/**\"];\n\nconst DEFAULT_CONFIG: SemanticSearchConfig = {\n\tenabled: true,\n\tautoIndex: true,\n\tprovider: {\n\t\ttype: \"openrouter\",\n\t\tmodel: \"openai/text-embedding-3-small\",\n\t\tbatchSize: 32,\n\t\ttimeoutMs: 30_000,\n\t},\n\tindex: {\n\t\tincludeGlobs: [...DEFAULT_INCLUDE_GLOBS],\n\t\texcludeGlobs: [...DEFAULT_EXCLUDE_GLOBS],\n\t\tchunkMaxChars: 1200,\n\t\tchunkOverlapChars: 200,\n\t\tmaxFileBytes: 262_144,\n\t\tmaxFiles: 20_000,\n\t},\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction asBoolean(value: unknown): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction sanitizeStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst normalized = value\n\t\t.filter((item): item is string => typeof item === \"string\")\n\t\t.map((item) => item.trim())\n\t\t.filter((item) => item.length > 0);\n\treturn normalized.length > 0 ? normalized : undefined;\n}\n\nfunction sanitizeStringRecord(value: unknown): Record<string, string> | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst result: Record<string, string> = {};\n\tfor (const [key, rawValue] of Object.entries(value)) {\n\t\tif (typeof rawValue !== \"string\") continue;\n\t\tconst normalizedKey = key.trim();\n\t\tif (!normalizedKey) continue;\n\t\tresult[normalizedKey] = rawValue;\n\t}\n\treturn Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction sanitizeProviderType(value: unknown): SemanticProviderType | undefined {\n\tif (value === \"openrouter\" || value === \"ollama\" || value === \"custom_openai\") {\n\t\treturn value;\n\t}\n\treturn undefined;\n}\n\nfunction clampInt(value: number | undefined, fallback: number, min: number, max: number): number {\n\tif (value === undefined) return fallback;\n\tconst normalized = Math.floor(value);\n\tif (!Number.isFinite(normalized)) return fallback;\n\tif (normalized < min) return min;\n\tif (normalized > max) return max;\n\treturn normalized;\n}\n\nfunction parseSemanticConfigFile(path: string): SemanticConfigFile {\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\tconst raw = readFileSync(path, \"utf8\");\n\tconst parsed = JSON.parse(raw) as unknown;\n\tif (!isRecord(parsed)) {\n\t\tthrow new SemanticConfigError(`Expected JSON object in ${path}`);\n\t}\n\n\tconst result: SemanticConfigFile = {};\n\tconst rawSemantic = parsed.semanticSearch;\n\tif (!isRecord(rawSemantic)) {\n\t\treturn result;\n\t}\n\n\tconst provider = isRecord(rawSemantic.provider)\n\t\t? {\n\t\t\t\ttype: sanitizeProviderType(rawSemantic.provider.type),\n\t\t\t\tmodel: asString(rawSemantic.provider.model),\n\t\t\t\tbaseUrl: asString(rawSemantic.provider.baseUrl),\n\t\t\t\tapiKeyEnv: asString(rawSemantic.provider.apiKeyEnv),\n\t\t\t\theaders: sanitizeStringRecord(rawSemantic.provider.headers),\n\t\t\t\tbatchSize: asNumber(rawSemantic.provider.batchSize),\n\t\t\t\ttimeoutMs: asNumber(rawSemantic.provider.timeoutMs),\n\t\t\t}\n\t\t: undefined;\n\n\tconst index = isRecord(rawSemantic.index)\n\t\t? {\n\t\t\t\tincludeGlobs: sanitizeStringArray(rawSemantic.index.includeGlobs),\n\t\t\t\texcludeGlobs: sanitizeStringArray(rawSemantic.index.excludeGlobs),\n\t\t\t\tchunkMaxChars: asNumber(rawSemantic.index.chunkMaxChars),\n\t\t\t\tchunkOverlapChars: asNumber(rawSemantic.index.chunkOverlapChars),\n\t\t\t\tmaxFileBytes: asNumber(rawSemantic.index.maxFileBytes),\n\t\t\t\tmaxFiles: asNumber(rawSemantic.index.maxFiles),\n\t\t\t}\n\t\t: undefined;\n\n\tresult.semanticSearch = {\n\t\tenabled: asBoolean(rawSemantic.enabled),\n\t\tautoIndex: asBoolean(rawSemantic.autoIndex),\n\t\tprovider,\n\t\tindex,\n\t};\n\n\treturn result;\n}\n\nfunction mergeSemanticConfig(\n\tbase: SemanticConfigFile[\"semanticSearch\"] | undefined,\n\toverride: SemanticConfigFile[\"semanticSearch\"] | undefined,\n): SemanticConfigFile[\"semanticSearch\"] | undefined {\n\tif (!base && !override) return undefined;\n\treturn {\n\t\t...(base ?? {}),\n\t\t...(override ?? {}),\n\t\tprovider: {\n\t\t\t...(base?.provider ?? {}),\n\t\t\t...(override?.provider ?? {}),\n\t\t},\n\t\tindex: {\n\t\t\t...(base?.index ?? {}),\n\t\t\t...(override?.index ?? {}),\n\t\t},\n\t};\n}\n\nfunction resolveSemanticSearchConfig(\n\tpartial: SemanticConfigFile[\"semanticSearch\"] | undefined,\n): SemanticSearchConfig | undefined {\n\tif (!partial) return undefined;\n\n\tconst providerType = partial.provider?.type ?? DEFAULT_CONFIG.provider.type;\n\tconst model = (partial.provider?.model ?? DEFAULT_CONFIG.provider.model).trim();\n\tif (!model) {\n\t\tthrow new SemanticConfigError(`semanticSearch.provider.model cannot be empty`);\n\t}\n\n\treturn {\n\t\tenabled: partial.enabled ?? DEFAULT_CONFIG.enabled,\n\t\tautoIndex: partial.autoIndex ?? DEFAULT_CONFIG.autoIndex,\n\t\tprovider: {\n\t\t\ttype: providerType,\n\t\t\tmodel,\n\t\t\tbaseUrl: partial.provider?.baseUrl?.trim() || undefined,\n\t\t\tapiKeyEnv: partial.provider?.apiKeyEnv?.trim() || undefined,\n\t\t\theaders: partial.provider?.headers && Object.keys(partial.provider.headers).length > 0 ? partial.provider.headers : undefined,\n\t\t\tbatchSize: clampInt(partial.provider?.batchSize, DEFAULT_CONFIG.provider.batchSize, 1, 512),\n\t\t\ttimeoutMs: clampInt(partial.provider?.timeoutMs, DEFAULT_CONFIG.provider.timeoutMs, 1_000, 300_000),\n\t\t},\n\t\tindex: {\n\t\t\tincludeGlobs: partial.index?.includeGlobs && partial.index.includeGlobs.length > 0 ? partial.index.includeGlobs : [...DEFAULT_CONFIG.index.includeGlobs],\n\t\t\texcludeGlobs: partial.index?.excludeGlobs && partial.index.excludeGlobs.length > 0 ? partial.index.excludeGlobs : [...DEFAULT_CONFIG.index.excludeGlobs],\n\t\t\tchunkMaxChars: clampInt(partial.index?.chunkMaxChars, DEFAULT_CONFIG.index.chunkMaxChars, 200, 20_000),\n\t\t\tchunkOverlapChars: clampInt(partial.index?.chunkOverlapChars, DEFAULT_CONFIG.index.chunkOverlapChars, 0, 5_000),\n\t\t\tmaxFileBytes: clampInt(partial.index?.maxFileBytes, DEFAULT_CONFIG.index.maxFileBytes, 1_024, 16 * 1024 * 1024),\n\t\t\tmaxFiles: clampInt(partial.index?.maxFiles, DEFAULT_CONFIG.index.maxFiles, 1, 1_000_000),\n\t\t},\n\t};\n}\n\nexport function getSemanticConfigPath(scope: SemanticScope, cwd: string, agentDir: string): string {\n\treturn scope === \"project\" ? join(cwd, \".iosm\", \"semantic.json\") : join(agentDir, \"semantic.json\");\n}\n\nexport function readScopedSemanticConfig(scope: SemanticScope, cwd: string, agentDir: string): SemanticScopedLoadResult {\n\tconst path = getSemanticConfigPath(scope, cwd, agentDir);\n\ttry {\n\t\treturn {\n\t\t\tscope,\n\t\t\tpath,\n\t\t\tfile: parseSemanticConfigFile(path),\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tscope,\n\t\t\tpath,\n\t\t\tfile: {},\n\t\t\terror: error instanceof Error ? error : new Error(String(error)),\n\t\t};\n\t}\n}\n\nexport function loadMergedSemanticConfig(cwd: string, agentDir: string): SemanticMergedConfig {\n\tconst scoped = [readScopedSemanticConfig(\"user\", cwd, agentDir), readScopedSemanticConfig(\"project\", cwd, agentDir)];\n\tconst errors: string[] = [];\n\n\tfor (const entry of scoped) {\n\t\tif (entry.error) {\n\t\t\terrors.push(`${entry.scope} config (${entry.path}): ${entry.error.message}`);\n\t\t}\n\t}\n\n\tconst mergedPartial = mergeSemanticConfig(scoped[0]?.file.semanticSearch, scoped[1]?.file.semanticSearch);\n\tlet config: SemanticSearchConfig | undefined;\n\ttry {\n\t\tconfig = resolveSemanticSearchConfig(mergedPartial);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\terrors.push(`semanticSearch: ${message}`);\n\t\tconfig = undefined;\n\t}\n\n\treturn {\n\t\tconfig,\n\t\terrors,\n\t\tscoped,\n\t};\n}\n\nexport function writeScopedSemanticConfig(\n\tscope: SemanticScope,\n\tfile: SemanticConfigFile,\n\tcwd: string,\n\tagentDir: string,\n): string {\n\tconst path = getSemanticConfigPath(scope, cwd, agentDir);\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\twriteFileSync(path, `${JSON.stringify(file, null, 2)}\\n`, \"utf8\");\n\treturn path;\n}\n\nexport function upsertScopedSemanticSearchConfig(\n\tscope: SemanticScope,\n\tconfig: SemanticSearchConfig,\n\tcwd: string,\n\tagentDir: string,\n): string {\n\tconst current = readScopedSemanticConfig(scope, cwd, agentDir);\n\tif (current.error) {\n\t\tthrow new SemanticConfigError(`Cannot update ${scope} semantic config (${current.path}): ${current.error.message}`);\n\t}\n\tconst nextFile: SemanticConfigFile = {\n\t\t...current.file,\n\t\tsemanticSearch: {\n\t\t\tenabled: config.enabled,\n\t\t\tautoIndex: config.autoIndex,\n\t\t\tprovider: {\n\t\t\t\ttype: config.provider.type,\n\t\t\t\tmodel: config.provider.model,\n\t\t\t\tbaseUrl: config.provider.baseUrl,\n\t\t\t\tapiKeyEnv: config.provider.apiKeyEnv,\n\t\t\t\theaders: config.provider.headers,\n\t\t\t\tbatchSize: config.provider.batchSize,\n\t\t\t\ttimeoutMs: config.provider.timeoutMs,\n\t\t\t},\n\t\t\tindex: {\n\t\t\t\tincludeGlobs: [...config.index.includeGlobs],\n\t\t\t\texcludeGlobs: [...config.index.excludeGlobs],\n\t\t\t\tchunkMaxChars: config.index.chunkMaxChars,\n\t\t\t\tchunkOverlapChars: config.index.chunkOverlapChars,\n\t\t\t\tmaxFileBytes: config.index.maxFileBytes,\n\t\t\t\tmaxFiles: config.index.maxFiles,\n\t\t\t},\n\t\t},\n\t};\n\treturn writeScopedSemanticConfig(scope, nextFile, cwd, agentDir);\n}\n\nexport function getDefaultSemanticSearchConfig(): SemanticSearchConfig {\n\treturn {\n\t\tenabled: DEFAULT_CONFIG.enabled,\n\t\tautoIndex: DEFAULT_CONFIG.autoIndex,\n\t\tprovider: { ...DEFAULT_CONFIG.provider },\n\t\tindex: {\n\t\t\tincludeGlobs: [...DEFAULT_CONFIG.index.includeGlobs],\n\t\t\texcludeGlobs: [...DEFAULT_CONFIG.index.excludeGlobs],\n\t\t\tchunkMaxChars: DEFAULT_CONFIG.index.chunkMaxChars,\n\t\t\tchunkOverlapChars: DEFAULT_CONFIG.index.chunkOverlapChars,\n\t\t\tmaxFileBytes: DEFAULT_CONFIG.index.maxFileBytes,\n\t\t\tmaxFiles: DEFAULT_CONFIG.index.maxFiles,\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SemanticIndexMeta, SemanticIndexedChunk, SemanticIndexedVector } from "./types.js";
|
|
2
|
+
export interface SemanticIndexFiles {
|
|
3
|
+
metaPath: string;
|
|
4
|
+
chunksPath: string;
|
|
5
|
+
vectorsPath: string;
|
|
6
|
+
}
|
|
7
|
+
export interface LoadedSemanticIndex {
|
|
8
|
+
exists: boolean;
|
|
9
|
+
meta?: SemanticIndexMeta;
|
|
10
|
+
chunks: SemanticIndexedChunk[];
|
|
11
|
+
vectors: SemanticIndexedVector[];
|
|
12
|
+
}
|
|
13
|
+
export declare function getSemanticRootDir(agentDir: string): string;
|
|
14
|
+
export declare function getSemanticIndexesDir(agentDir: string): string;
|
|
15
|
+
export declare function getSemanticProjectHash(cwd: string): string;
|
|
16
|
+
export declare function getSemanticIndexDir(cwd: string, agentDir: string): string;
|
|
17
|
+
export declare function getSemanticIndexFiles(indexDir: string): SemanticIndexFiles;
|
|
18
|
+
export declare function loadSemanticIndex(indexDir: string): LoadedSemanticIndex;
|
|
19
|
+
export declare function writeSemanticIndex(indexDir: string, meta: SemanticIndexMeta, chunks: SemanticIndexedChunk[], vectors: SemanticIndexedVector[]): SemanticIndexFiles;
|
|
20
|
+
export declare function clearSemanticIndex(indexDir: string): void;
|
|
21
|
+
//# sourceMappingURL=index-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-store.d.ts","sourceRoot":"","sources":["../../../src/core/semantic/index-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEjG,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,OAAO,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAM1E;AAoBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAevE;AAED,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,oBAAoB,EAAE,EAC9B,OAAO,EAAE,qBAAqB,EAAE,GAC9B,kBAAkB,CASpB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAGzD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
export function getSemanticRootDir(agentDir) {
|
|
5
|
+
return join(agentDir, "semantic");
|
|
6
|
+
}
|
|
7
|
+
export function getSemanticIndexesDir(agentDir) {
|
|
8
|
+
return join(getSemanticRootDir(agentDir), "indexes");
|
|
9
|
+
}
|
|
10
|
+
export function getSemanticProjectHash(cwd) {
|
|
11
|
+
return createHash("sha256").update(resolve(cwd)).digest("hex").slice(0, 20);
|
|
12
|
+
}
|
|
13
|
+
export function getSemanticIndexDir(cwd, agentDir) {
|
|
14
|
+
return join(getSemanticIndexesDir(agentDir), getSemanticProjectHash(cwd));
|
|
15
|
+
}
|
|
16
|
+
export function getSemanticIndexFiles(indexDir) {
|
|
17
|
+
return {
|
|
18
|
+
metaPath: join(indexDir, "meta.json"),
|
|
19
|
+
chunksPath: join(indexDir, "chunks.jsonl"),
|
|
20
|
+
vectorsPath: join(indexDir, "vectors.jsonl"),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function parseJsonLines(path) {
|
|
24
|
+
if (!existsSync(path))
|
|
25
|
+
return [];
|
|
26
|
+
const raw = readFileSync(path, "utf8");
|
|
27
|
+
if (!raw.trim())
|
|
28
|
+
return [];
|
|
29
|
+
const rows = [];
|
|
30
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (!trimmed)
|
|
33
|
+
continue;
|
|
34
|
+
rows.push(JSON.parse(trimmed));
|
|
35
|
+
}
|
|
36
|
+
return rows;
|
|
37
|
+
}
|
|
38
|
+
function stringifyJsonLines(values) {
|
|
39
|
+
if (values.length === 0)
|
|
40
|
+
return "";
|
|
41
|
+
return `${values.map((value) => JSON.stringify(value)).join("\n")}\n`;
|
|
42
|
+
}
|
|
43
|
+
export function loadSemanticIndex(indexDir) {
|
|
44
|
+
const files = getSemanticIndexFiles(indexDir);
|
|
45
|
+
if (!existsSync(files.metaPath)) {
|
|
46
|
+
return { exists: false, chunks: [], vectors: [] };
|
|
47
|
+
}
|
|
48
|
+
const meta = JSON.parse(readFileSync(files.metaPath, "utf8"));
|
|
49
|
+
const chunks = parseJsonLines(files.chunksPath);
|
|
50
|
+
const vectors = parseJsonLines(files.vectorsPath);
|
|
51
|
+
return {
|
|
52
|
+
exists: true,
|
|
53
|
+
meta,
|
|
54
|
+
chunks,
|
|
55
|
+
vectors,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function writeSemanticIndex(indexDir, meta, chunks, vectors) {
|
|
59
|
+
if (!existsSync(indexDir)) {
|
|
60
|
+
mkdirSync(indexDir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
const files = getSemanticIndexFiles(indexDir);
|
|
63
|
+
writeFileSync(files.metaPath, `${JSON.stringify(meta, null, 2)}\n`, "utf8");
|
|
64
|
+
writeFileSync(files.chunksPath, stringifyJsonLines(chunks), "utf8");
|
|
65
|
+
writeFileSync(files.vectorsPath, stringifyJsonLines(vectors), "utf8");
|
|
66
|
+
return files;
|
|
67
|
+
}
|
|
68
|
+
export function clearSemanticIndex(indexDir) {
|
|
69
|
+
if (!existsSync(indexDir))
|
|
70
|
+
return;
|
|
71
|
+
rmSync(indexDir, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-store.js","sourceRoot":"","sources":["../../../src/core/semantic/index-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport type { SemanticIndexMeta, SemanticIndexedChunk, SemanticIndexedVector } from \"./types.js\";\n\nexport interface SemanticIndexFiles {\n\tmetaPath: string;\n\tchunksPath: string;\n\tvectorsPath: string;\n}\n\nexport interface LoadedSemanticIndex {\n\texists: boolean;\n\tmeta?: SemanticIndexMeta;\n\tchunks: SemanticIndexedChunk[];\n\tvectors: SemanticIndexedVector[];\n}\n\nexport function getSemanticRootDir(agentDir: string): string {\n\treturn join(agentDir, \"semantic\");\n}\n\nexport function getSemanticIndexesDir(agentDir: string): string {\n\treturn join(getSemanticRootDir(agentDir), \"indexes\");\n}\n\nexport function getSemanticProjectHash(cwd: string): string {\n\treturn createHash(\"sha256\").update(resolve(cwd)).digest(\"hex\").slice(0, 20);\n}\n\nexport function getSemanticIndexDir(cwd: string, agentDir: string): string {\n\treturn join(getSemanticIndexesDir(agentDir), getSemanticProjectHash(cwd));\n}\n\nexport function getSemanticIndexFiles(indexDir: string): SemanticIndexFiles {\n\treturn {\n\t\tmetaPath: join(indexDir, \"meta.json\"),\n\t\tchunksPath: join(indexDir, \"chunks.jsonl\"),\n\t\tvectorsPath: join(indexDir, \"vectors.jsonl\"),\n\t};\n}\n\nfunction parseJsonLines<T>(path: string): T[] {\n\tif (!existsSync(path)) return [];\n\tconst raw = readFileSync(path, \"utf8\");\n\tif (!raw.trim()) return [];\n\tconst rows: T[] = [];\n\tfor (const line of raw.split(/\\r?\\n/)) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed) continue;\n\t\trows.push(JSON.parse(trimmed) as T);\n\t}\n\treturn rows;\n}\n\nfunction stringifyJsonLines(values: unknown[]): string {\n\tif (values.length === 0) return \"\";\n\treturn `${values.map((value) => JSON.stringify(value)).join(\"\\n\")}\\n`;\n}\n\nexport function loadSemanticIndex(indexDir: string): LoadedSemanticIndex {\n\tconst files = getSemanticIndexFiles(indexDir);\n\tif (!existsSync(files.metaPath)) {\n\t\treturn { exists: false, chunks: [], vectors: [] };\n\t}\n\n\tconst meta = JSON.parse(readFileSync(files.metaPath, \"utf8\")) as SemanticIndexMeta;\n\tconst chunks = parseJsonLines<SemanticIndexedChunk>(files.chunksPath);\n\tconst vectors = parseJsonLines<SemanticIndexedVector>(files.vectorsPath);\n\treturn {\n\t\texists: true,\n\t\tmeta,\n\t\tchunks,\n\t\tvectors,\n\t};\n}\n\nexport function writeSemanticIndex(\n\tindexDir: string,\n\tmeta: SemanticIndexMeta,\n\tchunks: SemanticIndexedChunk[],\n\tvectors: SemanticIndexedVector[],\n): SemanticIndexFiles {\n\tif (!existsSync(indexDir)) {\n\t\tmkdirSync(indexDir, { recursive: true });\n\t}\n\tconst files = getSemanticIndexFiles(indexDir);\n\twriteFileSync(files.metaPath, `${JSON.stringify(meta, null, 2)}\\n`, \"utf8\");\n\twriteFileSync(files.chunksPath, stringifyJsonLines(chunks), \"utf8\");\n\twriteFileSync(files.vectorsPath, stringifyJsonLines(vectors), \"utf8\");\n\treturn files;\n}\n\nexport function clearSemanticIndex(indexDir: string): void {\n\tif (!existsSync(indexDir)) return;\n\trmSync(indexDir, { recursive: true, force: true });\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { getDefaultSemanticSearchConfig, getSemanticConfigPath, loadMergedSemanticConfig, readScopedSemanticConfig, upsertScopedSemanticSearchConfig, writeScopedSemanticConfig, } from "./config.js";
|
|
2
|
+
export { getSemanticCommandHelp, parseSemanticCliCommand, type ParseSemanticCliResult, type SemanticCliCommand, } from "./cli.js";
|
|
3
|
+
export { clearSemanticIndex, getSemanticIndexDir, getSemanticIndexFiles, getSemanticIndexesDir, getSemanticProjectHash, getSemanticRootDir, loadSemanticIndex, writeSemanticIndex, } from "./index-store.js";
|
|
4
|
+
export { createSemanticEmbeddingProvider, isLikelyEmbeddingModelId, listOllamaLocalModels, listOpenRouterEmbeddingModels, } from "./providers.js";
|
|
5
|
+
export { SemanticSearchRuntime } from "./runtime.js";
|
|
6
|
+
export type { SemanticAction, SemanticChunkForEmbedding, SemanticConfigFile, SemanticFileFingerprint, SemanticIndexConfig, SemanticIndexMeta, SemanticIndexOperationResult, SemanticIndexedChunk, SemanticIndexedVector, SemanticMergedConfig, SemanticProviderConfig, SemanticProviderType, SemanticQueryHit, SemanticQueryResult, SemanticScope, SemanticScopedLoadResult, SemanticSearchConfig, SemanticStatusResult, SemanticStaleReason, SemanticToolResult, } from "./types.js";
|
|
7
|
+
export { SemanticConfigError, SemanticConfigMissingError, SemanticIndexRequiredError, SemanticRebuildRequiredError, } from "./types.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/semantic/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,8BAA8B,EAC9B,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,GACvB,MAAM,UAAU,CAAC;AAClB,OAAO,EACN,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EACX,cAAc,EACd,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,EACjB,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,4BAA4B,GAC5B,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { getDefaultSemanticSearchConfig, getSemanticConfigPath, loadMergedSemanticConfig, readScopedSemanticConfig, upsertScopedSemanticSearchConfig, writeScopedSemanticConfig, } from "./config.js";
|
|
2
|
+
export { getSemanticCommandHelp, parseSemanticCliCommand, } from "./cli.js";
|
|
3
|
+
export { clearSemanticIndex, getSemanticIndexDir, getSemanticIndexFiles, getSemanticIndexesDir, getSemanticProjectHash, getSemanticRootDir, loadSemanticIndex, writeSemanticIndex, } from "./index-store.js";
|
|
4
|
+
export { createSemanticEmbeddingProvider, isLikelyEmbeddingModelId, listOllamaLocalModels, listOpenRouterEmbeddingModels, } from "./providers.js";
|
|
5
|
+
export { SemanticSearchRuntime } from "./runtime.js";
|
|
6
|
+
export { SemanticConfigError, SemanticConfigMissingError, SemanticIndexRequiredError, SemanticRebuildRequiredError, } from "./types.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/semantic/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,8BAA8B,EAC9B,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,sBAAsB,EACtB,uBAAuB,GAGvB,MAAM,UAAU,CAAC;AAClB,OAAO,EACN,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAuBrD,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,4BAA4B,GAC5B,MAAM,YAAY,CAAC","sourcesContent":["export {\n\tgetDefaultSemanticSearchConfig,\n\tgetSemanticConfigPath,\n\tloadMergedSemanticConfig,\n\treadScopedSemanticConfig,\n\tupsertScopedSemanticSearchConfig,\n\twriteScopedSemanticConfig,\n} from \"./config.js\";\nexport {\n\tgetSemanticCommandHelp,\n\tparseSemanticCliCommand,\n\ttype ParseSemanticCliResult,\n\ttype SemanticCliCommand,\n} from \"./cli.js\";\nexport {\n\tclearSemanticIndex,\n\tgetSemanticIndexDir,\n\tgetSemanticIndexFiles,\n\tgetSemanticIndexesDir,\n\tgetSemanticProjectHash,\n\tgetSemanticRootDir,\n\tloadSemanticIndex,\n\twriteSemanticIndex,\n} from \"./index-store.js\";\nexport {\n\tcreateSemanticEmbeddingProvider,\n\tisLikelyEmbeddingModelId,\n\tlistOllamaLocalModels,\n\tlistOpenRouterEmbeddingModels,\n} from \"./providers.js\";\nexport { SemanticSearchRuntime } from \"./runtime.js\";\nexport type {\n\tSemanticAction,\n\tSemanticChunkForEmbedding,\n\tSemanticConfigFile,\n\tSemanticFileFingerprint,\n\tSemanticIndexConfig,\n\tSemanticIndexMeta,\n\tSemanticIndexOperationResult,\n\tSemanticIndexedChunk,\n\tSemanticIndexedVector,\n\tSemanticMergedConfig,\n\tSemanticProviderConfig,\n\tSemanticProviderType,\n\tSemanticQueryHit,\n\tSemanticQueryResult,\n\tSemanticScope,\n\tSemanticScopedLoadResult,\n\tSemanticSearchConfig,\n\tSemanticStatusResult,\n\tSemanticStaleReason,\n\tSemanticToolResult,\n} from \"./types.js\";\nexport {\n\tSemanticConfigError,\n\tSemanticConfigMissingError,\n\tSemanticIndexRequiredError,\n\tSemanticRebuildRequiredError,\n} from \"./types.js\";\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AuthStorage } from "../auth-storage.js";
|
|
2
|
+
import type { SemanticProviderConfig } from "./types.js";
|
|
3
|
+
export interface SemanticEmbeddingProvider {
|
|
4
|
+
embed(texts: string[]): Promise<number[][]>;
|
|
5
|
+
}
|
|
6
|
+
export interface SemanticProviderFactoryOptions {
|
|
7
|
+
authStorage?: AuthStorage;
|
|
8
|
+
}
|
|
9
|
+
export interface SemanticOpenRouterModelListOptions {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
authStorage?: AuthStorage;
|
|
12
|
+
}
|
|
13
|
+
export interface SemanticOllamaModelListOptions {
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function isLikelyEmbeddingModelId(modelId: string): boolean;
|
|
19
|
+
export declare function listOpenRouterEmbeddingModels(options?: SemanticOpenRouterModelListOptions): Promise<string[]>;
|
|
20
|
+
export declare function listOllamaLocalModels(options?: SemanticOllamaModelListOptions): Promise<string[]>;
|
|
21
|
+
export declare function createSemanticEmbeddingProvider(config: SemanticProviderConfig, options?: SemanticProviderFactoryOptions): Promise<SemanticEmbeddingProvider>;
|
|
22
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/core/semantic/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,yBAAyB;IACzC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,8BAA8B;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,kCAAkC;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,8BAA8B;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAoJD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWjE;AAED,wBAAsB,6BAA6B,CAClD,OAAO,GAAE,kCAAuC,GAC9C,OAAO,CAAC,MAAM,EAAE,CAAC,CA8CnB;AAED,wBAAsB,qBAAqB,CAC1C,OAAO,GAAE,8BAAmC,GAC1C,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BnB;AAED,wBAAsB,+BAA+B,CACpD,MAAM,EAAE,sBAAsB,EAC9B,OAAO,GAAE,8BAAmC,GAC1C,OAAO,CAAC,yBAAyB,CAAC,CAkHpC"}
|