@jim80net/memex-core 0.1.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/dist/cache.d.ts +9 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +57 -0
- package/dist/cache.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +47 -0
- package/dist/config.js.map +1 -0
- package/dist/embeddings.d.ts +24 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +143 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/file-lock.d.ts +11 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +63 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/path-encoder.d.ts +12 -0
- package/dist/path-encoder.d.ts.map +1 -0
- package/dist/path-encoder.js +14 -0
- package/dist/path-encoder.js.map +1 -0
- package/dist/project-mapping.d.ts +29 -0
- package/dist/project-mapping.d.ts.map +1 -0
- package/dist/project-mapping.js +106 -0
- package/dist/project-mapping.js.map +1 -0
- package/dist/project-registry.d.ts +12 -0
- package/dist/project-registry.d.ts.map +1 -0
- package/dist/project-registry.js +38 -0
- package/dist/project-registry.js.map +1 -0
- package/dist/session.d.ts +21 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +36 -0
- package/dist/session.js.map +1 -0
- package/dist/skill-index.d.ts +52 -0
- package/dist/skill-index.d.ts.map +1 -0
- package/dist/skill-index.js +467 -0
- package/dist/skill-index.js.map +1 -0
- package/dist/sync.d.ts +23 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +331 -0
- package/dist/sync.js.map +1 -0
- package/dist/telemetry.d.ts +12 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +56 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/traces.d.ts +20 -0
- package/dist/traces.d.ts.map +1 -0
- package/dist/traces.js +82 -0
- package/dist/traces.js.map +1 -0
- package/dist/types.d.ts +125 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +39 -0
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CacheData, CachedSkill, IndexedSkill } from "./types.js";
|
|
2
|
+
export declare function loadCache(cachePath: string, embeddingModel: string): Promise<CacheData>;
|
|
3
|
+
export declare function saveCache(cachePath: string, data: CacheData): Promise<void>;
|
|
4
|
+
export declare function getCachedSkill(cache: CacheData, location: string): CachedSkill | undefined;
|
|
5
|
+
export declare function setCachedSkill(cache: CacheData, location: string, skill: CachedSkill): void;
|
|
6
|
+
export declare function removeCachedSkill(cache: CacheData, location: string): void;
|
|
7
|
+
export declare function toCachedSkill(skill: IndexedSkill, mtime: number): CachedSkill;
|
|
8
|
+
export declare function fromCachedSkill(location: string, cached: CachedSkill): IndexedSkill;
|
|
9
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAIvE,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAY7F;AAED,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE1F;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAE3F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAU7E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,YAAY,CAUnF"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
const CACHE_VERSION = 2;
|
|
5
|
+
export async function loadCache(cachePath, embeddingModel) {
|
|
6
|
+
const empty = { version: CACHE_VERSION, embeddingModel, skills: {} };
|
|
7
|
+
try {
|
|
8
|
+
const raw = await readFile(cachePath, "utf-8");
|
|
9
|
+
const data = JSON.parse(raw);
|
|
10
|
+
if (data.version !== CACHE_VERSION || data.embeddingModel !== embeddingModel) {
|
|
11
|
+
return empty;
|
|
12
|
+
}
|
|
13
|
+
return data;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return empty;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function saveCache(cachePath, data) {
|
|
20
|
+
const dir = dirname(cachePath);
|
|
21
|
+
await mkdir(dir, { recursive: true });
|
|
22
|
+
const tmpPath = `${cachePath}.${randomBytes(4).toString("hex")}.tmp`;
|
|
23
|
+
await writeFile(tmpPath, JSON.stringify(data), "utf-8");
|
|
24
|
+
await rename(tmpPath, cachePath);
|
|
25
|
+
}
|
|
26
|
+
export function getCachedSkill(cache, location) {
|
|
27
|
+
return cache.skills[location];
|
|
28
|
+
}
|
|
29
|
+
export function setCachedSkill(cache, location, skill) {
|
|
30
|
+
cache.skills[location] = skill;
|
|
31
|
+
}
|
|
32
|
+
export function removeCachedSkill(cache, location) {
|
|
33
|
+
delete cache.skills[location];
|
|
34
|
+
}
|
|
35
|
+
export function toCachedSkill(skill, mtime) {
|
|
36
|
+
return {
|
|
37
|
+
name: skill.name,
|
|
38
|
+
description: skill.description,
|
|
39
|
+
queries: skill.queries,
|
|
40
|
+
embeddings: skill.embeddings,
|
|
41
|
+
mtime,
|
|
42
|
+
type: skill.type,
|
|
43
|
+
oneLiner: skill.oneLiner,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function fromCachedSkill(location, cached) {
|
|
47
|
+
return {
|
|
48
|
+
name: cached.name,
|
|
49
|
+
description: cached.description,
|
|
50
|
+
location,
|
|
51
|
+
type: cached.type,
|
|
52
|
+
embeddings: cached.embeddings,
|
|
53
|
+
queries: cached.queries,
|
|
54
|
+
oneLiner: cached.oneLiner,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,aAAa,GAAG,CAAU,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAiB,EAAE,cAAsB;IACvE,MAAM,KAAK,GAAc,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;QAC1C,IAAI,IAAI,CAAC,OAAO,KAAK,aAAa,IAAI,IAAI,CAAC,cAAc,KAAK,cAAc,EAAE,CAAC;YAC7E,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAiB,EAAE,IAAe;IAChE,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,GAAG,SAAS,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IACrE,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACxD,MAAM,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAgB,EAAE,QAAgB;IAC/D,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAgB,EAAE,QAAgB,EAAE,KAAkB;IACnF,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB,EAAE,QAAgB;IAClE,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAmB,EAAE,KAAa;IAC9D,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,MAAmB;IACnE,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,QAAQ;QACR,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC;AACJ,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MemexCoreConfig } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_CORE_CONFIG: MemexCoreConfig;
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a core config from a partial runtime config dict.
|
|
5
|
+
* Merges with defaults, validating types.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveCoreConfig(partial?: Partial<MemexCoreConfig>): MemexCoreConfig;
|
|
8
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,mBAAmB,EAAE,eAajC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAiCrF"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const DEFAULT_CORE_CONFIG = {
|
|
2
|
+
enabled: true,
|
|
3
|
+
embeddingModel: "Xenova/all-MiniLM-L6-v2",
|
|
4
|
+
embeddingBackend: "local",
|
|
5
|
+
cacheTimeMs: 300_000, // 5 min
|
|
6
|
+
topK: 3,
|
|
7
|
+
threshold: 0.35, // floor: best match must clear this to inject anything
|
|
8
|
+
scoringMode: "relative",
|
|
9
|
+
maxDropoff: 0.1, // in relative mode, drop results scoring > this below the best match
|
|
10
|
+
maxInjectedChars: 8000,
|
|
11
|
+
types: ["skill", "memory", "workflow", "session-learning", "rule"],
|
|
12
|
+
skillDirs: [],
|
|
13
|
+
memoryDirs: [],
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a core config from a partial runtime config dict.
|
|
17
|
+
* Merges with defaults, validating types.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveCoreConfig(partial) {
|
|
20
|
+
if (!partial)
|
|
21
|
+
return { ...DEFAULT_CORE_CONFIG };
|
|
22
|
+
return {
|
|
23
|
+
enabled: typeof partial.enabled === "boolean" ? partial.enabled : DEFAULT_CORE_CONFIG.enabled,
|
|
24
|
+
embeddingModel: typeof partial.embeddingModel === "string"
|
|
25
|
+
? partial.embeddingModel
|
|
26
|
+
: DEFAULT_CORE_CONFIG.embeddingModel,
|
|
27
|
+
embeddingBackend: partial.embeddingBackend === "openai" ? "openai" : DEFAULT_CORE_CONFIG.embeddingBackend,
|
|
28
|
+
cacheTimeMs: typeof partial.cacheTimeMs === "number"
|
|
29
|
+
? partial.cacheTimeMs
|
|
30
|
+
: DEFAULT_CORE_CONFIG.cacheTimeMs,
|
|
31
|
+
topK: typeof partial.topK === "number" ? partial.topK : DEFAULT_CORE_CONFIG.topK,
|
|
32
|
+
threshold: typeof partial.threshold === "number" ? partial.threshold : DEFAULT_CORE_CONFIG.threshold,
|
|
33
|
+
scoringMode: partial.scoringMode === "absolute" ? "absolute" : DEFAULT_CORE_CONFIG.scoringMode,
|
|
34
|
+
maxDropoff: typeof partial.maxDropoff === "number" ? partial.maxDropoff : DEFAULT_CORE_CONFIG.maxDropoff,
|
|
35
|
+
maxInjectedChars: typeof partial.maxInjectedChars === "number"
|
|
36
|
+
? partial.maxInjectedChars
|
|
37
|
+
: DEFAULT_CORE_CONFIG.maxInjectedChars,
|
|
38
|
+
types: Array.isArray(partial.types) ? partial.types : DEFAULT_CORE_CONFIG.types,
|
|
39
|
+
skillDirs: Array.isArray(partial.skillDirs)
|
|
40
|
+
? partial.skillDirs.map(String)
|
|
41
|
+
: DEFAULT_CORE_CONFIG.skillDirs,
|
|
42
|
+
memoryDirs: Array.isArray(partial.memoryDirs)
|
|
43
|
+
? partial.memoryDirs.map(String)
|
|
44
|
+
: DEFAULT_CORE_CONFIG.memoryDirs,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAoB;IAClD,OAAO,EAAE,IAAI;IACb,cAAc,EAAE,yBAAyB;IACzC,gBAAgB,EAAE,OAAO;IACzB,WAAW,EAAE,OAAO,EAAE,QAAQ;IAC9B,IAAI,EAAE,CAAC;IACP,SAAS,EAAE,IAAI,EAAE,uDAAuD;IACxE,WAAW,EAAE,UAAU;IACvB,UAAU,EAAE,GAAG,EAAE,qEAAqE;IACtF,gBAAgB,EAAE,IAAI;IACtB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,CAAC;IAClE,SAAS,EAAE,EAAE;IACb,UAAU,EAAE,EAAE;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAkC;IAClE,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAChD,OAAO;QACL,OAAO,EAAE,OAAO,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO;QAC7F,cAAc,EACZ,OAAO,OAAO,CAAC,cAAc,KAAK,QAAQ;YACxC,CAAC,CAAC,OAAO,CAAC,cAAc;YACxB,CAAC,CAAC,mBAAmB,CAAC,cAAc;QACxC,gBAAgB,EACd,OAAO,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,gBAAgB;QACzF,WAAW,EACT,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ;YACrC,CAAC,CAAC,OAAO,CAAC,WAAW;YACrB,CAAC,CAAC,mBAAmB,CAAC,WAAW;QACrC,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI;QAChF,SAAS,EACP,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,SAAS;QAC3F,WAAW,EACT,OAAO,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,WAAW;QACnF,UAAU,EACR,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,UAAU;QAC9F,gBAAgB,EACd,OAAO,OAAO,CAAC,gBAAgB,KAAK,QAAQ;YAC1C,CAAC,CAAC,OAAO,CAAC,gBAAgB;YAC1B,CAAC,CAAC,mBAAmB,CAAC,gBAAgB;QAC1C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK;QAC/E,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;YACzC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;YAC/B,CAAC,CAAC,mBAAmB,CAAC,SAAS;QACjC,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC;YAC3C,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,mBAAmB,CAAC,UAAU;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface EmbeddingProvider {
|
|
2
|
+
embed(texts: string[]): Promise<number[][]>;
|
|
3
|
+
}
|
|
4
|
+
export declare class OpenAIEmbeddingProvider implements EmbeddingProvider {
|
|
5
|
+
private model;
|
|
6
|
+
private apiKey;
|
|
7
|
+
constructor(model: string, apiKey: string);
|
|
8
|
+
embed(texts: string[]): Promise<number[][]>;
|
|
9
|
+
}
|
|
10
|
+
export declare class LocalEmbeddingProvider implements EmbeddingProvider {
|
|
11
|
+
private model;
|
|
12
|
+
private cacheDir?;
|
|
13
|
+
private extractorPromise;
|
|
14
|
+
constructor(model?: string, cacheDir?: string);
|
|
15
|
+
embed(texts: string[]): Promise<number[][]>;
|
|
16
|
+
private getExtractor;
|
|
17
|
+
private initExtractor;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Cosine similarity between two vectors.
|
|
21
|
+
* Optimized: detects pre-normalized vectors (norm ≈ 1.0) and uses dot product directly.
|
|
22
|
+
*/
|
|
23
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
24
|
+
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;CAC7C;AAUD,qBAAa,uBAAwB,YAAW,iBAAiB;IAE7D,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;gBADN,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;IAGlB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CA8BlD;AAMD,qBAAa,sBAAuB,YAAW,iBAAiB;IAC9D,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAiC;gBAE7C,KAAK,GAAE,MAAkC,EAAE,QAAQ,CAAC,EAAE,MAAM;IAKlE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAqBnC,YAAY;YAOZ,aAAa;CAoD5B;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAuBjE"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Embedding provider interface + implementations
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
export class OpenAIEmbeddingProvider {
|
|
5
|
+
model;
|
|
6
|
+
apiKey;
|
|
7
|
+
constructor(model, apiKey) {
|
|
8
|
+
this.model = model;
|
|
9
|
+
this.apiKey = apiKey;
|
|
10
|
+
}
|
|
11
|
+
async embed(texts) {
|
|
12
|
+
if (texts.length === 0)
|
|
13
|
+
return [];
|
|
14
|
+
const BATCH_SIZE = 2048;
|
|
15
|
+
const results = new Array(texts.length);
|
|
16
|
+
for (let offset = 0; offset < texts.length; offset += BATCH_SIZE) {
|
|
17
|
+
const batch = texts.slice(offset, offset + BATCH_SIZE);
|
|
18
|
+
const response = await fetch("https://api.openai.com/v1/embeddings", {
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify({ model: this.model, input: batch }),
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const text = await response.text();
|
|
28
|
+
throw new Error(`OpenAI embeddings API error ${response.status}: ${text}`);
|
|
29
|
+
}
|
|
30
|
+
const json = (await response.json());
|
|
31
|
+
for (const item of json.data) {
|
|
32
|
+
results[offset + item.index] = item.embedding;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Local ONNX provider (requires @huggingface/transformers as optional dep)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
export class LocalEmbeddingProvider {
|
|
42
|
+
model;
|
|
43
|
+
cacheDir;
|
|
44
|
+
extractorPromise = null;
|
|
45
|
+
constructor(model = "Xenova/all-MiniLM-L6-v2", cacheDir) {
|
|
46
|
+
this.model = model;
|
|
47
|
+
this.cacheDir = cacheDir;
|
|
48
|
+
}
|
|
49
|
+
async embed(texts) {
|
|
50
|
+
if (texts.length === 0)
|
|
51
|
+
return [];
|
|
52
|
+
const extractor = await this.getExtractor();
|
|
53
|
+
const output = await extractor(texts, {
|
|
54
|
+
pooling: "mean",
|
|
55
|
+
normalize: true,
|
|
56
|
+
});
|
|
57
|
+
const data = output.data;
|
|
58
|
+
const dims = output.dims;
|
|
59
|
+
const dim = dims[dims.length - 1];
|
|
60
|
+
const results = [];
|
|
61
|
+
for (let i = 0; i < texts.length; i++) {
|
|
62
|
+
results.push(Array.from(data.slice(i * dim, (i + 1) * dim)));
|
|
63
|
+
}
|
|
64
|
+
return results;
|
|
65
|
+
}
|
|
66
|
+
async getExtractor() {
|
|
67
|
+
if (!this.extractorPromise) {
|
|
68
|
+
this.extractorPromise = this.initExtractor();
|
|
69
|
+
}
|
|
70
|
+
return this.extractorPromise;
|
|
71
|
+
}
|
|
72
|
+
async initExtractor() {
|
|
73
|
+
let transformers;
|
|
74
|
+
const { join, dirname } = await import("node:path");
|
|
75
|
+
const { fileURLToPath } = await import("node:url");
|
|
76
|
+
// Dynamic import for createRequire — types may not expose it on the namespace
|
|
77
|
+
const moduleMod = await import("node:module");
|
|
78
|
+
const createRequire = moduleMod.createRequire || moduleMod.default?.createRequire;
|
|
79
|
+
let pluginDir;
|
|
80
|
+
try {
|
|
81
|
+
pluginDir = dirname(fileURLToPath(import.meta.url));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
pluginDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
transformers = (await import("@huggingface/transformers"));
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
try {
|
|
91
|
+
const require = createRequire(join(pluginDir, "package.json"));
|
|
92
|
+
const resolvedPath = require.resolve("@huggingface/transformers");
|
|
93
|
+
transformers = (await import(resolvedPath));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
try {
|
|
97
|
+
const absolutePath = join(pluginDir, "..", "node_modules", "@huggingface", "transformers", "src", "transformers.js");
|
|
98
|
+
transformers = (await import(absolutePath));
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
throw new Error("Local embedding backend requires @huggingface/transformers. " +
|
|
102
|
+
"Install it: npm install @huggingface/transformers");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (this.cacheDir) {
|
|
107
|
+
transformers.env.cacheDir = this.cacheDir;
|
|
108
|
+
}
|
|
109
|
+
return transformers.pipeline("feature-extraction", this.model, {
|
|
110
|
+
dtype: "q8",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Cosine similarity (shared utility)
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
/**
|
|
118
|
+
* Cosine similarity between two vectors.
|
|
119
|
+
* Optimized: detects pre-normalized vectors (norm ≈ 1.0) and uses dot product directly.
|
|
120
|
+
*/
|
|
121
|
+
export function cosineSimilarity(a, b) {
|
|
122
|
+
if (a.length !== b.length)
|
|
123
|
+
return 0;
|
|
124
|
+
let dot = 0;
|
|
125
|
+
for (let i = 0; i < a.length; i++) {
|
|
126
|
+
dot += a[i] * b[i];
|
|
127
|
+
}
|
|
128
|
+
// Fast path: normalized vectors (norm ≈ 1.0) — just return dot product.
|
|
129
|
+
let normSqA = 0;
|
|
130
|
+
let normSqB = 0;
|
|
131
|
+
for (let i = 0; i < a.length; i++) {
|
|
132
|
+
normSqA += a[i] * a[i];
|
|
133
|
+
normSqB += b[i] * b[i];
|
|
134
|
+
}
|
|
135
|
+
if (Math.abs(normSqA - 1.0) < 1e-6 && Math.abs(normSqB - 1.0) < 1e-6) {
|
|
136
|
+
return dot;
|
|
137
|
+
}
|
|
138
|
+
const denom = Math.sqrt(normSqA) * Math.sqrt(normSqB);
|
|
139
|
+
if (denom === 0)
|
|
140
|
+
return 0;
|
|
141
|
+
return dot / denom;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acquire an advisory file lock using mkdir (atomic on all platforms).
|
|
3
|
+
* Returns an unlock function.
|
|
4
|
+
*/
|
|
5
|
+
export declare function acquireLock(filePath: string): Promise<() => Promise<void>>;
|
|
6
|
+
/**
|
|
7
|
+
* Execute a callback while holding a file lock.
|
|
8
|
+
* The lock is released after the callback completes (or throws).
|
|
9
|
+
*/
|
|
10
|
+
export declare function withFileLock<T>(filePath: string, fn: () => Promise<T>): Promise<T>;
|
|
11
|
+
//# sourceMappingURL=file-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.d.ts","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAuChF;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { mkdir, rmdir, stat } from "node:fs/promises";
|
|
2
|
+
const LOCK_TIMEOUT_MS = 5_000;
|
|
3
|
+
const LOCK_RETRY_MS = 50;
|
|
4
|
+
const STALE_LOCK_MS = 30_000;
|
|
5
|
+
/**
|
|
6
|
+
* Acquire an advisory file lock using mkdir (atomic on all platforms).
|
|
7
|
+
* Returns an unlock function.
|
|
8
|
+
*/
|
|
9
|
+
export async function acquireLock(filePath) {
|
|
10
|
+
const lockDir = filePath + ".lock";
|
|
11
|
+
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
12
|
+
while (Date.now() < deadline) {
|
|
13
|
+
try {
|
|
14
|
+
await mkdir(lockDir);
|
|
15
|
+
return async () => {
|
|
16
|
+
try {
|
|
17
|
+
await rmdir(lockDir);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Lock already released or cleaned up
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Lock exists — check if stale
|
|
26
|
+
try {
|
|
27
|
+
const lockStat = await stat(lockDir);
|
|
28
|
+
if (Date.now() - lockStat.mtimeMs > STALE_LOCK_MS) {
|
|
29
|
+
// Stale lock — force remove and retry
|
|
30
|
+
try {
|
|
31
|
+
await rmdir(lockDir);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Another process beat us to it
|
|
35
|
+
}
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Lock was released between our mkdir and stat — retry immediately
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Wait before retrying
|
|
44
|
+
await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Timeout — proceed without lock (best-effort)
|
|
48
|
+
return async () => { };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Execute a callback while holding a file lock.
|
|
52
|
+
* The lock is released after the callback completes (or throws).
|
|
53
|
+
*/
|
|
54
|
+
export async function withFileLock(filePath, fn) {
|
|
55
|
+
const unlock = await acquireLock(filePath);
|
|
56
|
+
try {
|
|
57
|
+
return await fn();
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await unlock();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=file-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB;IAChD,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC;IAE9C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC;oBACH,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,sCAAsC;gBACxC,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;YAC/B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,GAAG,aAAa,EAAE,CAAC;oBAClD,sCAAsC;oBACtC,IAAI,CAAC;wBACH,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;oBACvB,CAAC;oBAAC,MAAM,CAAC;wBACP,gCAAgC;oBAClC,CAAC;oBACD,SAAS;gBACX,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,mEAAmE;gBACnE,SAAS;YACX,CAAC;YAED,uBAAuB;YACvB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,OAAO,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,QAAgB,EAAE,EAAoB;IAC1E,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,EAAE,CAAC;IACjB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./version.js";
|
|
3
|
+
export * from "./file-lock.js";
|
|
4
|
+
export * from "./path-encoder.js";
|
|
5
|
+
export * from "./embeddings.js";
|
|
6
|
+
export * from "./cache.js";
|
|
7
|
+
export * from "./config.js";
|
|
8
|
+
export * from "./session.js";
|
|
9
|
+
export * from "./telemetry.js";
|
|
10
|
+
export * from "./project-mapping.js";
|
|
11
|
+
export * from "./project-registry.js";
|
|
12
|
+
export { autoResolveMarkdownConflict, initSyncRepo, syncPull, syncCommitAndPush, getSyncScanDirs } from "./sync.js";
|
|
13
|
+
export * from "./traces.js";
|
|
14
|
+
export { SkillIndex, parseFrontmatter, parseMemoryFile } from "./skill-index.js";
|
|
15
|
+
export type { ScanDirs } from "./skill-index.js";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,2BAA2B,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACpH,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjF,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./version.js";
|
|
3
|
+
export * from "./file-lock.js";
|
|
4
|
+
export * from "./path-encoder.js";
|
|
5
|
+
export * from "./embeddings.js";
|
|
6
|
+
export * from "./cache.js";
|
|
7
|
+
export * from "./config.js";
|
|
8
|
+
export * from "./session.js";
|
|
9
|
+
export * from "./telemetry.js";
|
|
10
|
+
export * from "./project-mapping.js";
|
|
11
|
+
export * from "./project-registry.js";
|
|
12
|
+
export { autoResolveMarkdownConflict, initSyncRepo, syncPull, syncCommitAndPush, getSyncScanDirs } from "./sync.js";
|
|
13
|
+
export * from "./traces.js";
|
|
14
|
+
export { SkillIndex, parseFrontmatter, parseMemoryFile } from "./skill-index.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,2BAA2B,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACpH,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encode an absolute path to a project directory name.
|
|
3
|
+
* `/home/user/.myproject` → `-home-user--myproject`
|
|
4
|
+
*
|
|
5
|
+
* Rules:
|
|
6
|
+
* - `/` becomes `-`
|
|
7
|
+
* - `.` becomes `-`
|
|
8
|
+
* - `_` becomes `-`
|
|
9
|
+
* - Consecutive `-` are preserved (they encode dots/separators)
|
|
10
|
+
*/
|
|
11
|
+
export declare function encodeProjectPath(cwd: string): string;
|
|
12
|
+
//# sourceMappingURL=path-encoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-encoder.d.ts","sourceRoot":"","sources":["../src/path-encoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encode an absolute path to a project directory name.
|
|
3
|
+
* `/home/user/.myproject` → `-home-user--myproject`
|
|
4
|
+
*
|
|
5
|
+
* Rules:
|
|
6
|
+
* - `/` becomes `-`
|
|
7
|
+
* - `.` becomes `-`
|
|
8
|
+
* - `_` becomes `-`
|
|
9
|
+
* - Consecutive `-` are preserved (they encode dots/separators)
|
|
10
|
+
*/
|
|
11
|
+
export function encodeProjectPath(cwd) {
|
|
12
|
+
return cwd.replace(/\//g, "-").replace(/\./g, "-").replace(/_/g, "-");
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=path-encoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-encoder.js","sourceRoot":"","sources":["../src/path-encoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SyncConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize a git remote URL to a canonical path segment.
|
|
4
|
+
* Handles SSH, HTTPS, and .git suffix variations.
|
|
5
|
+
*
|
|
6
|
+
* Examples:
|
|
7
|
+
* git@github.com:jim80net/repo.git → github.com/jim80net/repo
|
|
8
|
+
* https://github.com/jim80net/repo.git → github.com/jim80net/repo
|
|
9
|
+
*/
|
|
10
|
+
export declare function normalizeGitUrl(url: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the canonical project identifier for a given cwd.
|
|
13
|
+
*
|
|
14
|
+
* Resolution cascade:
|
|
15
|
+
* 1. Manual mapping from config (explicit override)
|
|
16
|
+
* 2. Git remote URL → normalized to host/owner/repo
|
|
17
|
+
* 3. Encoded cwd path → stored under _local/
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveProjectId(cwd: string, syncConfig: SyncConfig): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Find all project memory directories in the sync repo that match the current cwd.
|
|
22
|
+
* Multiple matches are possible (e.g., same project stored under both URL and encoded path).
|
|
23
|
+
*/
|
|
24
|
+
export declare function findMatchingProjectMemoryDirs(cwd: string, syncRepoPath: string, syncConfig: SyncConfig): Promise<string[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the sync repo's memory directory path for the canonical project ID.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getSyncProjectMemoryDir(cwd: string, syncRepoPath: string, syncConfig: SyncConfig): Promise<string>;
|
|
29
|
+
//# sourceMappingURL=project-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-mapping.d.ts","sourceRoot":"","sources":["../src/project-mapping.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAmBnD;AAkBD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAc3F;AAED;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBnB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { stat } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { encodeProjectPath } from "./path-encoder.js";
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
/**
|
|
8
|
+
* Normalize a git remote URL to a canonical path segment.
|
|
9
|
+
* Handles SSH, HTTPS, and .git suffix variations.
|
|
10
|
+
*
|
|
11
|
+
* Examples:
|
|
12
|
+
* git@github.com:jim80net/repo.git → github.com/jim80net/repo
|
|
13
|
+
* https://github.com/jim80net/repo.git → github.com/jim80net/repo
|
|
14
|
+
*/
|
|
15
|
+
export function normalizeGitUrl(url) {
|
|
16
|
+
let normalized = url.trim();
|
|
17
|
+
// Strip trailing .git
|
|
18
|
+
normalized = normalized.replace(/\.git$/, "");
|
|
19
|
+
// SSH format: git@host:owner/repo
|
|
20
|
+
const sshMatch = normalized.match(/^[\w-]+@([^:]+):(.+)$/);
|
|
21
|
+
if (sshMatch) {
|
|
22
|
+
return `${sshMatch[1]}/${sshMatch[2]}`;
|
|
23
|
+
}
|
|
24
|
+
// HTTPS format: https://host/owner/repo
|
|
25
|
+
try {
|
|
26
|
+
const parsed = new URL(normalized);
|
|
27
|
+
return `${parsed.host}${parsed.pathname}`.replace(/^\//, "").replace(/\/$/, "");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return normalized;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the git remote origin URL for a directory, if it's a git repo.
|
|
35
|
+
*/
|
|
36
|
+
async function getGitRemoteUrl(cwd) {
|
|
37
|
+
try {
|
|
38
|
+
const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
|
|
39
|
+
cwd,
|
|
40
|
+
timeout: 5000,
|
|
41
|
+
});
|
|
42
|
+
const url = stdout.trim();
|
|
43
|
+
return url || null;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the canonical project identifier for a given cwd.
|
|
51
|
+
*
|
|
52
|
+
* Resolution cascade:
|
|
53
|
+
* 1. Manual mapping from config (explicit override)
|
|
54
|
+
* 2. Git remote URL → normalized to host/owner/repo
|
|
55
|
+
* 3. Encoded cwd path → stored under _local/
|
|
56
|
+
*/
|
|
57
|
+
export async function resolveProjectId(cwd, syncConfig) {
|
|
58
|
+
// 1. Manual mapping
|
|
59
|
+
if (syncConfig.projectMappings[cwd]) {
|
|
60
|
+
return syncConfig.projectMappings[cwd];
|
|
61
|
+
}
|
|
62
|
+
// 2. Git remote URL
|
|
63
|
+
const remoteUrl = await getGitRemoteUrl(cwd);
|
|
64
|
+
if (remoteUrl) {
|
|
65
|
+
return normalizeGitUrl(remoteUrl);
|
|
66
|
+
}
|
|
67
|
+
// 3. Encoded path fallback
|
|
68
|
+
return `_local/${encodeProjectPath(cwd)}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Find all project memory directories in the sync repo that match the current cwd.
|
|
72
|
+
* Multiple matches are possible (e.g., same project stored under both URL and encoded path).
|
|
73
|
+
*/
|
|
74
|
+
export async function findMatchingProjectMemoryDirs(cwd, syncRepoPath, syncConfig) {
|
|
75
|
+
const projectsDir = join(syncRepoPath, "projects");
|
|
76
|
+
const matches = [];
|
|
77
|
+
const canonicalId = await resolveProjectId(cwd, syncConfig);
|
|
78
|
+
const canonicalMemDir = join(projectsDir, canonicalId, "memory");
|
|
79
|
+
try {
|
|
80
|
+
await stat(canonicalMemDir);
|
|
81
|
+
matches.push(canonicalMemDir);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// doesn't exist yet
|
|
85
|
+
}
|
|
86
|
+
const encodedPath = encodeProjectPath(cwd);
|
|
87
|
+
const localMemDir = join(projectsDir, "_local", encodedPath, "memory");
|
|
88
|
+
if (localMemDir !== canonicalMemDir) {
|
|
89
|
+
try {
|
|
90
|
+
await stat(localMemDir);
|
|
91
|
+
matches.push(localMemDir);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// doesn't exist
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return matches;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get the sync repo's memory directory path for the canonical project ID.
|
|
101
|
+
*/
|
|
102
|
+
export async function getSyncProjectMemoryDir(cwd, syncRepoPath, syncConfig) {
|
|
103
|
+
const canonicalId = await resolveProjectId(cwd, syncConfig);
|
|
104
|
+
return join(syncRepoPath, "projects", canonicalId, "memory");
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=project-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-mapping.js","sourceRoot":"","sources":["../src/project-mapping.ts"],"names":[],"mappings":"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"}
|