@nameczz/skill-sync 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/LICENSE +21 -0
- package/README.md +246 -0
- package/dist/src/autoSync.d.ts +36 -0
- package/dist/src/autoSync.js +235 -0
- package/dist/src/autoSync.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +211 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/codexArchive.d.ts +38 -0
- package/dist/src/codexArchive.js +340 -0
- package/dist/src/codexArchive.js.map +1 -0
- package/dist/src/config.d.ts +12 -0
- package/dist/src/config.js +78 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/copy.d.ts +1 -0
- package/dist/src/copy.js +42 -0
- package/dist/src/copy.js.map +1 -0
- package/dist/src/directoryPicker.d.ts +8 -0
- package/dist/src/directoryPicker.js +49 -0
- package/dist/src/directoryPicker.js.map +1 -0
- package/dist/src/format.d.ts +2 -0
- package/dist/src/format.js +27 -0
- package/dist/src/format.js.map +1 -0
- package/dist/src/frontmatter.d.ts +5 -0
- package/dist/src/frontmatter.js +36 -0
- package/dist/src/frontmatter.js.map +1 -0
- package/dist/src/git.d.ts +25 -0
- package/dist/src/git.js +227 -0
- package/dist/src/git.js.map +1 -0
- package/dist/src/hash.d.ts +1 -0
- package/dist/src/hash.js +34 -0
- package/dist/src/hash.js.map +1 -0
- package/dist/src/importSkill.d.ts +6 -0
- package/dist/src/importSkill.js +58 -0
- package/dist/src/importSkill.js.map +1 -0
- package/dist/src/init.d.ts +5 -0
- package/dist/src/init.js +13 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/installSkill.d.ts +6 -0
- package/dist/src/installSkill.js +62 -0
- package/dist/src/installSkill.js.map +1 -0
- package/dist/src/json.d.ts +2 -0
- package/dist/src/json.js +11 -0
- package/dist/src/json.js.map +1 -0
- package/dist/src/metadata.d.ts +11 -0
- package/dist/src/metadata.js +115 -0
- package/dist/src/metadata.js.map +1 -0
- package/dist/src/paths.d.ts +22 -0
- package/dist/src/paths.js +103 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/removeLocalSkill.d.ts +5 -0
- package/dist/src/removeLocalSkill.js +79 -0
- package/dist/src/removeLocalSkill.js.map +1 -0
- package/dist/src/resolveConflict.d.ts +10 -0
- package/dist/src/resolveConflict.js +146 -0
- package/dist/src/resolveConflict.js.map +1 -0
- package/dist/src/scanner.d.ts +5 -0
- package/dist/src/scanner.js +57 -0
- package/dist/src/scanner.js.map +1 -0
- package/dist/src/server.d.ts +10 -0
- package/dist/src/server.js +494 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/sessionUsage.d.ts +14 -0
- package/dist/src/sessionUsage.js +180 -0
- package/dist/src/sessionUsage.js.map +1 -0
- package/dist/src/skillDependencies.d.ts +2 -0
- package/dist/src/skillDependencies.js +56 -0
- package/dist/src/skillDependencies.js.map +1 -0
- package/dist/src/skillMentions.d.ts +3 -0
- package/dist/src/skillMentions.js +111 -0
- package/dist/src/skillMentions.js.map +1 -0
- package/dist/src/status.d.ts +3 -0
- package/dist/src/status.js +134 -0
- package/dist/src/status.js.map +1 -0
- package/dist/src/stopSyncingSkill.d.ts +2 -0
- package/dist/src/stopSyncingSkill.js +31 -0
- package/dist/src/stopSyncingSkill.js.map +1 -0
- package/dist/src/sync.d.ts +48 -0
- package/dist/src/sync.js +741 -0
- package/dist/src/sync.js.map +1 -0
- package/dist/src/types.d.ts +84 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/updateLocalSkill.d.ts +6 -0
- package/dist/src/updateLocalSkill.js +19 -0
- package/dist/src/updateLocalSkill.js.map +1 -0
- package/dist/src/usage.d.ts +6 -0
- package/dist/src/usage.js +84 -0
- package/dist/src/usage.js.map +1 -0
- package/dist/src/usageMonitor.d.ts +17 -0
- package/dist/src/usageMonitor.js +90 -0
- package/dist/src/usageMonitor.js.map +1 -0
- package/dist/web/assets/index-CPJdd8n0.js +59 -0
- package/dist/web/assets/index-T4bm09OX.css +2 -0
- package/dist/web/index.html +13 -0
- package/dist/web/style-options/common.css +515 -0
- package/dist/web/style-options/console.html +143 -0
- package/dist/web/style-options/desktop.html +144 -0
- package/dist/web/style-options/index.html +36 -0
- package/dist/web/style-options/workbench.html +112 -0
- package/package.json +84 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { copySkillDirectory } from "./copy.js";
|
|
5
|
+
import { hashDirectory } from "./hash.js";
|
|
6
|
+
import { readSkillFrontmatter } from "./frontmatter.js";
|
|
7
|
+
import { repoSkillsDir, resolveSkillPath, validateSkillId } from "./paths.js";
|
|
8
|
+
import { upsertSkillRecord } from "./metadata.js";
|
|
9
|
+
export async function importLocalSkill(config, skillId, options = {}) {
|
|
10
|
+
const id = validateSkillId(skillId);
|
|
11
|
+
const localSource = options.source ?? findExistingLocalSource(config, id);
|
|
12
|
+
const localPath = resolveSkillPath(localRootForSource(config, localSource), id);
|
|
13
|
+
const targetPath = resolveSkillPath(repoSkillsDir(config.syncRepo), id);
|
|
14
|
+
if (!existsSync(path.join(localPath, "SKILL.md"))) {
|
|
15
|
+
throw new Error(`Local skill not found: ${localPath}`);
|
|
16
|
+
}
|
|
17
|
+
if (existsSync(targetPath)) {
|
|
18
|
+
if (!options.force) {
|
|
19
|
+
throw new Error(`Repo skill already exists: ${targetPath}. Re-run with --force to overwrite.`);
|
|
20
|
+
}
|
|
21
|
+
await rm(targetPath, { recursive: true, force: true });
|
|
22
|
+
}
|
|
23
|
+
await copySkillDirectory(localPath, targetPath);
|
|
24
|
+
const hash = await hashDirectory(targetPath);
|
|
25
|
+
const frontmatter = await readSkillFrontmatter(targetPath);
|
|
26
|
+
const now = new Date().toISOString();
|
|
27
|
+
const record = {
|
|
28
|
+
id,
|
|
29
|
+
name: frontmatter.name,
|
|
30
|
+
description: frontmatter.description,
|
|
31
|
+
status: "managed",
|
|
32
|
+
localSource,
|
|
33
|
+
installed: true,
|
|
34
|
+
syncState: "clean",
|
|
35
|
+
lastSyncedHash: hash,
|
|
36
|
+
currentRepoHash: hash,
|
|
37
|
+
currentLocalHash: hash,
|
|
38
|
+
lastUsedAt: null,
|
|
39
|
+
createdAt: now,
|
|
40
|
+
updatedAt: now
|
|
41
|
+
};
|
|
42
|
+
await upsertSkillRecord(config.syncRepo, record);
|
|
43
|
+
return record;
|
|
44
|
+
}
|
|
45
|
+
function findExistingLocalSource(config, id) {
|
|
46
|
+
const sources = ["codex", "agents"];
|
|
47
|
+
for (const source of sources) {
|
|
48
|
+
const candidate = resolveSkillPath(localRootForSource(config, source), id);
|
|
49
|
+
if (existsSync(path.join(candidate, "SKILL.md"))) {
|
|
50
|
+
return source;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return "codex";
|
|
54
|
+
}
|
|
55
|
+
function localRootForSource(config, source) {
|
|
56
|
+
return source === "agents" ? config.agentsSkillsDir : config.codexSkillsDir;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=importSkill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importSkill.js","sourceRoot":"","sources":["../../src/importSkill.ts"],"names":[],"mappings":"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"}
|
package/dist/src/init.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { createLocalConfig } from "./config.js";
|
|
3
|
+
import { ensureRepoMetadata } from "./metadata.js";
|
|
4
|
+
import { ensureGitRepository } from "./git.js";
|
|
5
|
+
export async function initialize(options = {}) {
|
|
6
|
+
const config = await createLocalConfig(options);
|
|
7
|
+
await mkdir(config.codexSkillsDir, { recursive: true });
|
|
8
|
+
await mkdir(config.agentsSkillsDir, { recursive: true });
|
|
9
|
+
await ensureRepoMetadata(config.syncRepo);
|
|
10
|
+
const gitInitialized = await ensureGitRepository(config.syncRepo);
|
|
11
|
+
return { config, gitInitialized };
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAA6B,EAAE;IAC9D,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InstallRepoSkillResult, LocalConfig, LocalSkillSource } from "./types.js";
|
|
2
|
+
export type InstallOptions = {
|
|
3
|
+
force?: boolean;
|
|
4
|
+
source?: LocalSkillSource;
|
|
5
|
+
};
|
|
6
|
+
export declare function installRepoSkill(config: LocalConfig, skillId: string, options?: InstallOptions): Promise<InstallRepoSkillResult>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { ensureSkillDependenciesInstalled } from "./skillDependencies.js";
|
|
5
|
+
import { copySkillDirectory } from "./copy.js";
|
|
6
|
+
import { hashDirectory } from "./hash.js";
|
|
7
|
+
import { readSkillsMetadata, upsertSkillRecord } from "./metadata.js";
|
|
8
|
+
import { repoSkillsDir, resolveSkillPath, validateSkillId } from "./paths.js";
|
|
9
|
+
import { readSkillFrontmatter } from "./frontmatter.js";
|
|
10
|
+
export async function installRepoSkill(config, skillId, options = {}) {
|
|
11
|
+
const id = validateSkillId(skillId);
|
|
12
|
+
const metadata = await readSkillsMetadata(config.syncRepo);
|
|
13
|
+
const existing = metadata.skills.find((skill) => skill.id === id && skill.status === "managed");
|
|
14
|
+
if (!existing) {
|
|
15
|
+
throw new Error(`Managed skill not found in metadata: ${id}`);
|
|
16
|
+
}
|
|
17
|
+
const sourcePath = resolveSkillPath(repoSkillsDir(config.syncRepo), id);
|
|
18
|
+
const localSource = options.source ?? existing.localSource ?? "codex";
|
|
19
|
+
const targetPath = resolveSkillPath(localRootForSource(config, localSource), id);
|
|
20
|
+
if (!existsSync(path.join(sourcePath, "SKILL.md"))) {
|
|
21
|
+
throw new Error(`Repo skill not found: ${sourcePath}`);
|
|
22
|
+
}
|
|
23
|
+
if (existsSync(targetPath)) {
|
|
24
|
+
if (!options.force) {
|
|
25
|
+
throw new Error(`Local skill already exists: ${targetPath}. Re-run with --force to overwrite.`);
|
|
26
|
+
}
|
|
27
|
+
await rm(targetPath, { recursive: true, force: true });
|
|
28
|
+
}
|
|
29
|
+
await copySkillDirectory(sourcePath, targetPath);
|
|
30
|
+
const hash = await hashDirectory(sourcePath);
|
|
31
|
+
const frontmatter = await readSkillFrontmatter(sourcePath);
|
|
32
|
+
const now = new Date().toISOString();
|
|
33
|
+
const record = {
|
|
34
|
+
...existing,
|
|
35
|
+
name: frontmatter.name,
|
|
36
|
+
description: frontmatter.description,
|
|
37
|
+
localSource,
|
|
38
|
+
installed: true,
|
|
39
|
+
syncState: "clean",
|
|
40
|
+
lastSyncedHash: hash,
|
|
41
|
+
currentRepoHash: hash,
|
|
42
|
+
currentLocalHash: hash,
|
|
43
|
+
lastUsedAt: existing.lastUsedAt ?? null,
|
|
44
|
+
updatedAt: now
|
|
45
|
+
};
|
|
46
|
+
const dependencyInstall = await installDependencies(targetPath, record.id);
|
|
47
|
+
await upsertSkillRecord(config.syncRepo, record);
|
|
48
|
+
return { record, dependencyInstall };
|
|
49
|
+
}
|
|
50
|
+
function localRootForSource(config, source) {
|
|
51
|
+
return source === "agents" ? config.agentsSkillsDir : config.codexSkillsDir;
|
|
52
|
+
}
|
|
53
|
+
async function installDependencies(skillPath, skillId) {
|
|
54
|
+
try {
|
|
55
|
+
return await ensureSkillDependenciesInstalled(skillPath);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
59
|
+
throw new Error(`Failed to install dependencies for ${skillId}: ${message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=installSkill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installSkill.js","sourceRoot":"","sources":["../../src/installSkill.ts"],"names":[],"mappings":"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"}
|
package/dist/src/json.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function readJsonFile(filePath) {
|
|
4
|
+
const raw = await readFile(filePath, "utf8");
|
|
5
|
+
return JSON.parse(raw);
|
|
6
|
+
}
|
|
7
|
+
export async function writeJsonFile(filePath, value) {
|
|
8
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
9
|
+
await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,QAAgB;IACpD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,KAAc;IAClE,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SkillRecord, SkillsMetadata } from "./types.js";
|
|
2
|
+
export type LegacyArchiveCleanupResult = {
|
|
3
|
+
removedArchiveDir: boolean;
|
|
4
|
+
removedSkillIds: string[];
|
|
5
|
+
};
|
|
6
|
+
export declare function emptySkillsMetadata(): SkillsMetadata;
|
|
7
|
+
export declare function ensureRepoMetadata(syncRepo: string): Promise<void>;
|
|
8
|
+
export declare function readSkillsMetadata(syncRepo: string): Promise<SkillsMetadata>;
|
|
9
|
+
export declare function cleanupLegacyArchiveArtifacts(syncRepo: string): Promise<LegacyArchiveCleanupResult>;
|
|
10
|
+
export declare function writeSkillsMetadata(syncRepo: string, metadata: SkillsMetadata): Promise<void>;
|
|
11
|
+
export declare function upsertSkillRecord(syncRepo: string, record: SkillRecord): Promise<void>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { repoSettingsPath, repoSkillsMetadataPath, repoUsageEventsPath } from "./paths.js";
|
|
3
|
+
import { readJsonFile, writeJsonFile } from "./json.js";
|
|
4
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
export function emptySkillsMetadata() {
|
|
7
|
+
return { schemaVersion: 1, skills: [] };
|
|
8
|
+
}
|
|
9
|
+
export async function ensureRepoMetadata(syncRepo) {
|
|
10
|
+
const now = new Date().toISOString();
|
|
11
|
+
await mkdir(path.join(syncRepo, "skills"), { recursive: true });
|
|
12
|
+
await mkdir(path.join(syncRepo, "metadata"), { recursive: true });
|
|
13
|
+
await ensureGitignore(syncRepo);
|
|
14
|
+
if (!existsSync(repoSettingsPath(syncRepo))) {
|
|
15
|
+
const settings = {
|
|
16
|
+
schemaVersion: 1,
|
|
17
|
+
createdAt: now,
|
|
18
|
+
updatedAt: now
|
|
19
|
+
};
|
|
20
|
+
await writeJsonFile(repoSettingsPath(syncRepo), settings);
|
|
21
|
+
}
|
|
22
|
+
if (!existsSync(repoSkillsMetadataPath(syncRepo))) {
|
|
23
|
+
await writeJsonFile(repoSkillsMetadataPath(syncRepo), emptySkillsMetadata());
|
|
24
|
+
}
|
|
25
|
+
if (!existsSync(repoUsageEventsPath(syncRepo))) {
|
|
26
|
+
await writeFile(repoUsageEventsPath(syncRepo), "", "utf8");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function ensureGitignore(syncRepo) {
|
|
30
|
+
const gitignorePath = path.join(syncRepo, ".gitignore");
|
|
31
|
+
const localCachePattern = ".skill-sync/";
|
|
32
|
+
const legacyLocalCachePattern = ".codex-skill-manager/";
|
|
33
|
+
if (!existsSync(gitignorePath)) {
|
|
34
|
+
await writeFile(gitignorePath, `${localCachePattern}\n${legacyLocalCachePattern}\n`, "utf8");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const current = await readFile(gitignorePath, "utf8");
|
|
38
|
+
const lines = current.split(/\r?\n/).map((line) => line.trim());
|
|
39
|
+
const missingPatterns = [localCachePattern, legacyLocalCachePattern].filter((pattern) => !lines.includes(pattern));
|
|
40
|
+
if (missingPatterns.length === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const separator = current.endsWith("\n") || current.length === 0 ? "" : "\n";
|
|
44
|
+
await writeFile(gitignorePath, `${current}${separator}${missingPatterns.join("\n")}\n`, "utf8");
|
|
45
|
+
}
|
|
46
|
+
export async function readSkillsMetadata(syncRepo) {
|
|
47
|
+
if (!existsSync(repoSkillsMetadataPath(syncRepo))) {
|
|
48
|
+
return emptySkillsMetadata();
|
|
49
|
+
}
|
|
50
|
+
const metadata = await readJsonFile(repoSkillsMetadataPath(syncRepo));
|
|
51
|
+
if (metadata.schemaVersion !== 1 || !Array.isArray(metadata.skills)) {
|
|
52
|
+
throw new Error(`Invalid skills metadata at ${repoSkillsMetadataPath(syncRepo)}.`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
schemaVersion: 1,
|
|
56
|
+
skills: metadata.skills
|
|
57
|
+
.filter((candidate) => candidate.status !== "archived")
|
|
58
|
+
.map(normalizeManagedRecord)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export async function cleanupLegacyArchiveArtifacts(syncRepo) {
|
|
62
|
+
const archiveDir = path.join(syncRepo, "archive");
|
|
63
|
+
const metadataPath = repoSkillsMetadataPath(syncRepo);
|
|
64
|
+
const removedArchiveDir = existsSync(archiveDir);
|
|
65
|
+
await rm(archiveDir, { recursive: true, force: true });
|
|
66
|
+
if (!existsSync(metadataPath)) {
|
|
67
|
+
return { removedArchiveDir, removedSkillIds: [] };
|
|
68
|
+
}
|
|
69
|
+
const metadata = await readJsonFile(metadataPath);
|
|
70
|
+
if (metadata.schemaVersion !== 1 || !Array.isArray(metadata.skills)) {
|
|
71
|
+
return { removedArchiveDir, removedSkillIds: [] };
|
|
72
|
+
}
|
|
73
|
+
const removedSkillIds = metadata.skills
|
|
74
|
+
.filter((record) => record.status === "archived")
|
|
75
|
+
.map((record) => record.id)
|
|
76
|
+
.filter((id) => typeof id === "string");
|
|
77
|
+
const cleaned = metadata.skills.filter((record) => record.status !== "archived").map(normalizeManagedRecord);
|
|
78
|
+
const isChanged = cleaned.length !== metadata.skills.length ||
|
|
79
|
+
cleaned.some((record, index) => {
|
|
80
|
+
const original = metadata.skills[index];
|
|
81
|
+
return record.id !== original?.id || record.status !== original?.status || record.lastUsedAt !== (original?.lastUsedAt ?? null) || Boolean(original && "archivedAt" in original);
|
|
82
|
+
});
|
|
83
|
+
if (!isChanged) {
|
|
84
|
+
return { removedArchiveDir, removedSkillIds };
|
|
85
|
+
}
|
|
86
|
+
await writeSkillsMetadata(syncRepo, { schemaVersion: 1, skills: cleaned });
|
|
87
|
+
return { removedArchiveDir, removedSkillIds };
|
|
88
|
+
}
|
|
89
|
+
export async function writeSkillsMetadata(syncRepo, metadata) {
|
|
90
|
+
const cleaned = {
|
|
91
|
+
schemaVersion: 1,
|
|
92
|
+
skills: metadata.skills.map(normalizeManagedRecord).sort((a, b) => a.id.localeCompare(b.id))
|
|
93
|
+
};
|
|
94
|
+
await writeJsonFile(repoSkillsMetadataPath(syncRepo), cleaned);
|
|
95
|
+
}
|
|
96
|
+
export async function upsertSkillRecord(syncRepo, record) {
|
|
97
|
+
const metadata = await readSkillsMetadata(syncRepo);
|
|
98
|
+
const index = metadata.skills.findIndex((skill) => skill.id === record.id);
|
|
99
|
+
if (index === -1) {
|
|
100
|
+
metadata.skills.push(record);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
metadata.skills[index] = record;
|
|
104
|
+
}
|
|
105
|
+
await writeSkillsMetadata(syncRepo, metadata);
|
|
106
|
+
}
|
|
107
|
+
function normalizeManagedRecord(candidate) {
|
|
108
|
+
const { archivedAt: _archivedAt, ...record } = candidate;
|
|
109
|
+
return {
|
|
110
|
+
...record,
|
|
111
|
+
status: "managed",
|
|
112
|
+
lastUsedAt: record.lastUsedAt ?? null
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type PathOptions = {
|
|
2
|
+
homeDir?: string;
|
|
3
|
+
env?: NodeJS.ProcessEnv;
|
|
4
|
+
};
|
|
5
|
+
export declare function expandHome(input: string, homeDir?: string): string;
|
|
6
|
+
export declare function getDefaultConfigDir(options?: PathOptions): string;
|
|
7
|
+
export declare function getLegacyConfigDir(options?: PathOptions): string;
|
|
8
|
+
export declare function getDefaultCacheDir(options?: PathOptions): string;
|
|
9
|
+
export declare function getDefaultSyncRepo(options?: PathOptions): string;
|
|
10
|
+
export declare function getDefaultCodexSkillsDir(options?: PathOptions): string;
|
|
11
|
+
export declare function getDefaultAgentsSkillsDir(options?: PathOptions): string;
|
|
12
|
+
export declare function configFilePath(configDir: string): string;
|
|
13
|
+
export declare function repoSkillsDir(syncRepo: string): string;
|
|
14
|
+
export declare function repoMetadataDir(syncRepo: string): string;
|
|
15
|
+
export declare function getDefaultCodexArchiveSessionsDir(options?: PathOptions): string;
|
|
16
|
+
export declare function repoSettingsPath(syncRepo: string): string;
|
|
17
|
+
export declare function repoSkillsMetadataPath(syncRepo: string): string;
|
|
18
|
+
export declare function repoUsageEventsPath(syncRepo: string): string;
|
|
19
|
+
export declare function validateSkillId(skillId: string): string;
|
|
20
|
+
export declare function resolveSkillPath(root: string, skillId: string): string;
|
|
21
|
+
export declare function assertInside(targetPath: string, rootPath: string): void;
|
|
22
|
+
export declare function toSkillId(root: string, skillPath: string): string;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
export function expandHome(input, homeDir = homedir()) {
|
|
4
|
+
if (input === "~") {
|
|
5
|
+
return homeDir;
|
|
6
|
+
}
|
|
7
|
+
if (input.startsWith("~/")) {
|
|
8
|
+
return path.join(homeDir, input.slice(2));
|
|
9
|
+
}
|
|
10
|
+
return input;
|
|
11
|
+
}
|
|
12
|
+
export function getDefaultConfigDir(options = {}) {
|
|
13
|
+
const env = options.env ?? process.env;
|
|
14
|
+
const home = options.homeDir ?? homedir();
|
|
15
|
+
return path.resolve(expandHome(env.SKILL_SYNC_CONFIG_DIR ?? env.CSM_CONFIG_DIR ?? "~/.skill-sync", home));
|
|
16
|
+
}
|
|
17
|
+
export function getLegacyConfigDir(options = {}) {
|
|
18
|
+
const env = options.env ?? process.env;
|
|
19
|
+
const home = options.homeDir ?? homedir();
|
|
20
|
+
return path.resolve(expandHome(env.CSM_CONFIG_DIR ?? "~/.codex-skill-manager", home));
|
|
21
|
+
}
|
|
22
|
+
export function getDefaultCacheDir(options = {}) {
|
|
23
|
+
const env = options.env ?? process.env;
|
|
24
|
+
const home = options.homeDir ?? homedir();
|
|
25
|
+
return path.resolve(expandHome(env.SKILL_SYNC_CACHE_DIR ?? env.CSM_CACHE_DIR ?? "~/.skill-sync/cache", home));
|
|
26
|
+
}
|
|
27
|
+
export function getDefaultSyncRepo(options = {}) {
|
|
28
|
+
const env = options.env ?? process.env;
|
|
29
|
+
const home = options.homeDir ?? homedir();
|
|
30
|
+
return path.resolve(expandHome(env.SKILL_SYNC_REPO ?? env.CSM_SYNC_REPO ?? "~/skill-sync", home));
|
|
31
|
+
}
|
|
32
|
+
export function getDefaultCodexSkillsDir(options = {}) {
|
|
33
|
+
const env = options.env ?? process.env;
|
|
34
|
+
const home = options.homeDir ?? homedir();
|
|
35
|
+
return path.resolve(expandHome(env.SKILL_SYNC_CODEX_SKILLS_DIR ?? env.CSM_CODEX_SKILLS_DIR ?? "~/.codex/skills", home));
|
|
36
|
+
}
|
|
37
|
+
export function getDefaultAgentsSkillsDir(options = {}) {
|
|
38
|
+
const env = options.env ?? process.env;
|
|
39
|
+
const home = options.homeDir ?? homedir();
|
|
40
|
+
return path.resolve(expandHome(env.SKILL_SYNC_AGENTS_SKILLS_DIR ?? env.CSM_AGENTS_SKILLS_DIR ?? "~/.agents/skills", home));
|
|
41
|
+
}
|
|
42
|
+
export function configFilePath(configDir) {
|
|
43
|
+
return path.join(configDir, "config.json");
|
|
44
|
+
}
|
|
45
|
+
export function repoSkillsDir(syncRepo) {
|
|
46
|
+
return path.join(syncRepo, "skills");
|
|
47
|
+
}
|
|
48
|
+
export function repoMetadataDir(syncRepo) {
|
|
49
|
+
return path.join(syncRepo, "metadata");
|
|
50
|
+
}
|
|
51
|
+
export function getDefaultCodexArchiveSessionsDir(options = {}) {
|
|
52
|
+
const env = options.env ?? process.env;
|
|
53
|
+
const home = options.homeDir ?? homedir();
|
|
54
|
+
const codexHome = path.resolve(expandHome(env.SKILL_SYNC_CODEX_HOME ?? env.CSM_CODEX_HOME ?? env.CODEX_HOME ?? "~/.codex", home));
|
|
55
|
+
return path.join(codexHome, "archived_sessions");
|
|
56
|
+
}
|
|
57
|
+
export function repoSettingsPath(syncRepo) {
|
|
58
|
+
return path.join(repoMetadataDir(syncRepo), "settings.json");
|
|
59
|
+
}
|
|
60
|
+
export function repoSkillsMetadataPath(syncRepo) {
|
|
61
|
+
return path.join(repoMetadataDir(syncRepo), "skills.json");
|
|
62
|
+
}
|
|
63
|
+
export function repoUsageEventsPath(syncRepo) {
|
|
64
|
+
return path.join(repoMetadataDir(syncRepo), "usage-events.jsonl");
|
|
65
|
+
}
|
|
66
|
+
export function validateSkillId(skillId) {
|
|
67
|
+
const normalized = skillId.replaceAll("\\", "/").replace(/^\/+|\/+$/g, "");
|
|
68
|
+
if (!normalized) {
|
|
69
|
+
throw new Error("Skill id cannot be empty.");
|
|
70
|
+
}
|
|
71
|
+
const parts = normalized.split("/");
|
|
72
|
+
if (parts.some((part) => part === "." || part === ".." || part.length === 0)) {
|
|
73
|
+
throw new Error(`Skill id "${skillId}" contains an invalid path segment.`);
|
|
74
|
+
}
|
|
75
|
+
if (normalized.startsWith(".") || normalized.includes("/.")) {
|
|
76
|
+
throw new Error(`Skill id "${skillId}" cannot target hidden directories.`);
|
|
77
|
+
}
|
|
78
|
+
if (path.isAbsolute(skillId)) {
|
|
79
|
+
throw new Error(`Skill id "${skillId}" must be relative, not absolute.`);
|
|
80
|
+
}
|
|
81
|
+
return normalized;
|
|
82
|
+
}
|
|
83
|
+
export function resolveSkillPath(root, skillId) {
|
|
84
|
+
const safeId = validateSkillId(skillId);
|
|
85
|
+
const target = path.resolve(root, ...safeId.split("/"));
|
|
86
|
+
assertInside(target, root);
|
|
87
|
+
return target;
|
|
88
|
+
}
|
|
89
|
+
export function assertInside(targetPath, rootPath) {
|
|
90
|
+
const relative = path.relative(path.resolve(rootPath), path.resolve(targetPath));
|
|
91
|
+
if (relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`Path escapes allowed root: ${targetPath}`);
|
|
95
|
+
}
|
|
96
|
+
export function toSkillId(root, skillPath) {
|
|
97
|
+
const relative = path.relative(root, skillPath);
|
|
98
|
+
if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
99
|
+
throw new Error(`Cannot derive skill id outside root: ${skillPath}`);
|
|
100
|
+
}
|
|
101
|
+
return relative.split(path.sep).join("/");
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LocalConfig, LocalSkillSource, SkillRecord } from "./types.js";
|
|
2
|
+
export type RemoveLocalOptions = {
|
|
3
|
+
source?: LocalSkillSource;
|
|
4
|
+
};
|
|
5
|
+
export declare function removeLocalSkill(config: LocalConfig, skillId: string, options?: RemoveLocalOptions): Promise<SkillRecord>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
3
|
+
import { deriveSyncState } from "./status.js";
|
|
4
|
+
import { resolveSkillPath, validateSkillId } from "./paths.js";
|
|
5
|
+
import { readSkillsMetadata, writeSkillsMetadata } from "./metadata.js";
|
|
6
|
+
import { hashDirectory } from "./hash.js";
|
|
7
|
+
export async function removeLocalSkill(config, skillId, options = {}) {
|
|
8
|
+
const id = validateSkillId(skillId);
|
|
9
|
+
const metadata = await readSkillsMetadata(config.syncRepo);
|
|
10
|
+
const index = metadata.skills.findIndex((record) => record.id === id);
|
|
11
|
+
if (index === -1) {
|
|
12
|
+
throw new Error(`Managed skill not found in metadata: ${id}`);
|
|
13
|
+
}
|
|
14
|
+
const existing = metadata.skills[index];
|
|
15
|
+
const targetSource = resolveRemoveSource(config, id, existing, options.source);
|
|
16
|
+
if (targetSource.length === 0) {
|
|
17
|
+
throw new Error(`No local copy found for ${id}.`);
|
|
18
|
+
}
|
|
19
|
+
const removedSources = new Set();
|
|
20
|
+
for (const source of targetSource) {
|
|
21
|
+
const localPath = resolveSkillPath(config[source === "codex" ? "codexSkillsDir" : "agentsSkillsDir"], id);
|
|
22
|
+
if (existsSync(localPath)) {
|
|
23
|
+
await rm(localPath, { recursive: true, force: true });
|
|
24
|
+
removedSources.add(source);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (removedSources.size === 0) {
|
|
28
|
+
throw new Error(`No local copy found for ${id}.`);
|
|
29
|
+
}
|
|
30
|
+
const now = new Date().toISOString();
|
|
31
|
+
const stillInstalled = Boolean(existsSync(resolveSkillPath(config.codexSkillsDir, id)) ||
|
|
32
|
+
existsSync(resolveSkillPath(config.agentsSkillsDir, id)));
|
|
33
|
+
const remainingLocalPath = stillInstalled
|
|
34
|
+
? existsSync(resolveSkillPath(config.codexSkillsDir, id))
|
|
35
|
+
? resolveSkillPath(config.codexSkillsDir, id)
|
|
36
|
+
: resolveSkillPath(config.agentsSkillsDir, id)
|
|
37
|
+
: null;
|
|
38
|
+
const remainingLocalHash = remainingLocalPath ? await hashDirectory(remainingLocalPath) : null;
|
|
39
|
+
const remainingSource = existsSync(resolveSkillPath(config.codexSkillsDir, id))
|
|
40
|
+
? "codex"
|
|
41
|
+
: existsSync(resolveSkillPath(config.agentsSkillsDir, id))
|
|
42
|
+
? "agents"
|
|
43
|
+
: null;
|
|
44
|
+
const localSource = stillInstalled ? remainingSource : null;
|
|
45
|
+
const updated = {
|
|
46
|
+
...existing,
|
|
47
|
+
installed: stillInstalled,
|
|
48
|
+
localSource,
|
|
49
|
+
currentLocalHash: remainingLocalHash,
|
|
50
|
+
syncState: deriveSyncState(existing.lastSyncedHash, remainingLocalHash, existing.currentRepoHash),
|
|
51
|
+
updatedAt: now
|
|
52
|
+
};
|
|
53
|
+
metadata.skills[index] = updated;
|
|
54
|
+
await writeSkillsMetadata(config.syncRepo, metadata);
|
|
55
|
+
return updated;
|
|
56
|
+
}
|
|
57
|
+
function resolveRemoveSource(config, id, record, source) {
|
|
58
|
+
if (source === "codex" || source === "agents") {
|
|
59
|
+
return [source];
|
|
60
|
+
}
|
|
61
|
+
const codexPath = resolveSkillPath(config.codexSkillsDir, id);
|
|
62
|
+
const agentsPath = resolveSkillPath(config.agentsSkillsDir, id);
|
|
63
|
+
const existsInCodex = existsSync(codexPath);
|
|
64
|
+
const existsInAgents = existsSync(agentsPath);
|
|
65
|
+
if (existsInCodex && existsInAgents) {
|
|
66
|
+
return ["codex", "agents"];
|
|
67
|
+
}
|
|
68
|
+
if (existsInCodex) {
|
|
69
|
+
return ["codex"];
|
|
70
|
+
}
|
|
71
|
+
if (existsInAgents) {
|
|
72
|
+
return ["agents"];
|
|
73
|
+
}
|
|
74
|
+
if (record.localSource === "codex" || record.localSource === "agents") {
|
|
75
|
+
return [record.localSource];
|
|
76
|
+
}
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=removeLocalSkill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"removeLocalSkill.js","sourceRoot":"","sources":["../../src/removeLocalSkill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LocalConfig, SkillRecord } from "./types.js";
|
|
2
|
+
import type { SyncResult } from "./sync.js";
|
|
3
|
+
export type ConflictResolutionStrategy = "codex" | "agents" | "repo";
|
|
4
|
+
export type ResolveConflictResult = {
|
|
5
|
+
record: SkillRecord;
|
|
6
|
+
result?: SyncResult;
|
|
7
|
+
};
|
|
8
|
+
export declare function resolveConflict(config: LocalConfig, skillId: string, options: {
|
|
9
|
+
strategy: ConflictResolutionStrategy;
|
|
10
|
+
}): Promise<ResolveConflictResult>;
|