@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.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +246 -0
  3. package/dist/src/autoSync.d.ts +36 -0
  4. package/dist/src/autoSync.js +235 -0
  5. package/dist/src/autoSync.js.map +1 -0
  6. package/dist/src/cli.d.ts +2 -0
  7. package/dist/src/cli.js +211 -0
  8. package/dist/src/cli.js.map +1 -0
  9. package/dist/src/codexArchive.d.ts +38 -0
  10. package/dist/src/codexArchive.js +340 -0
  11. package/dist/src/codexArchive.js.map +1 -0
  12. package/dist/src/config.d.ts +12 -0
  13. package/dist/src/config.js +78 -0
  14. package/dist/src/config.js.map +1 -0
  15. package/dist/src/copy.d.ts +1 -0
  16. package/dist/src/copy.js +42 -0
  17. package/dist/src/copy.js.map +1 -0
  18. package/dist/src/directoryPicker.d.ts +8 -0
  19. package/dist/src/directoryPicker.js +49 -0
  20. package/dist/src/directoryPicker.js.map +1 -0
  21. package/dist/src/format.d.ts +2 -0
  22. package/dist/src/format.js +27 -0
  23. package/dist/src/format.js.map +1 -0
  24. package/dist/src/frontmatter.d.ts +5 -0
  25. package/dist/src/frontmatter.js +36 -0
  26. package/dist/src/frontmatter.js.map +1 -0
  27. package/dist/src/git.d.ts +25 -0
  28. package/dist/src/git.js +227 -0
  29. package/dist/src/git.js.map +1 -0
  30. package/dist/src/hash.d.ts +1 -0
  31. package/dist/src/hash.js +34 -0
  32. package/dist/src/hash.js.map +1 -0
  33. package/dist/src/importSkill.d.ts +6 -0
  34. package/dist/src/importSkill.js +58 -0
  35. package/dist/src/importSkill.js.map +1 -0
  36. package/dist/src/init.d.ts +5 -0
  37. package/dist/src/init.js +13 -0
  38. package/dist/src/init.js.map +1 -0
  39. package/dist/src/installSkill.d.ts +6 -0
  40. package/dist/src/installSkill.js +62 -0
  41. package/dist/src/installSkill.js.map +1 -0
  42. package/dist/src/json.d.ts +2 -0
  43. package/dist/src/json.js +11 -0
  44. package/dist/src/json.js.map +1 -0
  45. package/dist/src/metadata.d.ts +11 -0
  46. package/dist/src/metadata.js +115 -0
  47. package/dist/src/metadata.js.map +1 -0
  48. package/dist/src/paths.d.ts +22 -0
  49. package/dist/src/paths.js +103 -0
  50. package/dist/src/paths.js.map +1 -0
  51. package/dist/src/removeLocalSkill.d.ts +5 -0
  52. package/dist/src/removeLocalSkill.js +79 -0
  53. package/dist/src/removeLocalSkill.js.map +1 -0
  54. package/dist/src/resolveConflict.d.ts +10 -0
  55. package/dist/src/resolveConflict.js +146 -0
  56. package/dist/src/resolveConflict.js.map +1 -0
  57. package/dist/src/scanner.d.ts +5 -0
  58. package/dist/src/scanner.js +57 -0
  59. package/dist/src/scanner.js.map +1 -0
  60. package/dist/src/server.d.ts +10 -0
  61. package/dist/src/server.js +494 -0
  62. package/dist/src/server.js.map +1 -0
  63. package/dist/src/sessionUsage.d.ts +14 -0
  64. package/dist/src/sessionUsage.js +180 -0
  65. package/dist/src/sessionUsage.js.map +1 -0
  66. package/dist/src/skillDependencies.d.ts +2 -0
  67. package/dist/src/skillDependencies.js +56 -0
  68. package/dist/src/skillDependencies.js.map +1 -0
  69. package/dist/src/skillMentions.d.ts +3 -0
  70. package/dist/src/skillMentions.js +111 -0
  71. package/dist/src/skillMentions.js.map +1 -0
  72. package/dist/src/status.d.ts +3 -0
  73. package/dist/src/status.js +134 -0
  74. package/dist/src/status.js.map +1 -0
  75. package/dist/src/stopSyncingSkill.d.ts +2 -0
  76. package/dist/src/stopSyncingSkill.js +31 -0
  77. package/dist/src/stopSyncingSkill.js.map +1 -0
  78. package/dist/src/sync.d.ts +48 -0
  79. package/dist/src/sync.js +741 -0
  80. package/dist/src/sync.js.map +1 -0
  81. package/dist/src/types.d.ts +84 -0
  82. package/dist/src/types.js +2 -0
  83. package/dist/src/types.js.map +1 -0
  84. package/dist/src/updateLocalSkill.d.ts +6 -0
  85. package/dist/src/updateLocalSkill.js +19 -0
  86. package/dist/src/updateLocalSkill.js.map +1 -0
  87. package/dist/src/usage.d.ts +6 -0
  88. package/dist/src/usage.js +84 -0
  89. package/dist/src/usage.js.map +1 -0
  90. package/dist/src/usageMonitor.d.ts +17 -0
  91. package/dist/src/usageMonitor.js +90 -0
  92. package/dist/src/usageMonitor.js.map +1 -0
  93. package/dist/web/assets/index-CPJdd8n0.js +59 -0
  94. package/dist/web/assets/index-T4bm09OX.css +2 -0
  95. package/dist/web/index.html +13 -0
  96. package/dist/web/style-options/common.css +515 -0
  97. package/dist/web/style-options/console.html +143 -0
  98. package/dist/web/style-options/desktop.html +144 -0
  99. package/dist/web/style-options/index.html +36 -0
  100. package/dist/web/style-options/workbench.html +112 -0
  101. package/package.json +84 -0
@@ -0,0 +1,180 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync } from "node:fs";
3
+ import { mkdir, open, readFile, readdir, stat, writeFile } from "node:fs/promises";
4
+ import { homedir } from "node:os";
5
+ import path from "node:path";
6
+ import { extractSkillFilePathIdsFromText } from "./skillMentions.js";
7
+ import { readUsageEvents, recordUsageEvent } from "./usage.js";
8
+ import { expandHome } from "./paths.js";
9
+ const STATE_FILE = "usage-session-scan.json";
10
+ const STATE_SCHEMA_VERSION = 2;
11
+ const INITIAL_SCAN_BYTES = 5 * 1024 * 1024;
12
+ const MAX_SEEN_KEYS = 1000;
13
+ const MAX_SESSION_FILES = 20;
14
+ const RECENT_WINDOW_MS = 24 * 60 * 60 * 1000;
15
+ const INITIAL_RECENT_WINDOW_MS = 7 * RECENT_WINDOW_MS;
16
+ export async function recordUsageFromCodexSessions(config, options = {}) {
17
+ const { state, isInitialScan } = await readSessionState(config.cacheDir);
18
+ const files = await findCandidateSessionFiles(options, {
19
+ maxSessionFiles: isInitialScan ? Number.POSITIVE_INFINITY : MAX_SESSION_FILES,
20
+ recentWindowMs: isInitialScan ? INITIAL_RECENT_WINDOW_MS : RECENT_WINDOW_MS
21
+ });
22
+ if (files.length === 0) {
23
+ return { scannedFiles: 0, recorded: 0, skillIds: [] };
24
+ }
25
+ const seen = new Set(state.seen);
26
+ const existingEvents = new Set((await readUsageEvents(config.syncRepo)).map((event) => `${event.skillId}:${event.invokedAt}`));
27
+ const recordedSkillIds = new Set();
28
+ let recorded = 0;
29
+ for (const filePath of files) {
30
+ const stats = await stat(filePath).catch(() => null);
31
+ if (!stats?.isFile()) {
32
+ continue;
33
+ }
34
+ const previous = state.files[filePath];
35
+ const initialScanBytes = options.initialScanBytes ?? INITIAL_SCAN_BYTES;
36
+ const start = previous ? Math.min(previous.offset, stats.size) : Math.max(0, stats.size - initialScanBytes);
37
+ const lines = await readJsonlTail(filePath, start, stats.size);
38
+ for (const line of lines) {
39
+ for (const signal of toSessionUsageSignals(line, config)) {
40
+ for (const skillId of signal.skillIds) {
41
+ const key = usageSeenKey(filePath, signal.timestamp, skillId, signal.message);
42
+ if (seen.has(key)) {
43
+ continue;
44
+ }
45
+ seen.add(key);
46
+ if (existingEvents.has(`${skillId}:${signal.timestamp}`)) {
47
+ continue;
48
+ }
49
+ await recordUsageEvent(config, skillId, { invokedAt: signal.timestamp });
50
+ existingEvents.add(`${skillId}:${signal.timestamp}`);
51
+ recorded += 1;
52
+ recordedSkillIds.add(skillId);
53
+ }
54
+ }
55
+ }
56
+ state.files[filePath] = { offset: stats.size };
57
+ }
58
+ state.seen = [...seen].slice(-MAX_SEEN_KEYS);
59
+ await writeSessionState(config.cacheDir, state);
60
+ return {
61
+ scannedFiles: files.length,
62
+ recorded,
63
+ skillIds: [...recordedSkillIds].sort((a, b) => a.localeCompare(b))
64
+ };
65
+ }
66
+ async function findCandidateSessionFiles(options, scanPolicy) {
67
+ const env = options.env ?? process.env;
68
+ const home = options.homeDir ?? homedir();
69
+ const codexHome = path.resolve(expandHome(env.SKILL_SYNC_CODEX_HOME ?? env.CSM_CODEX_HOME ?? env.CODEX_HOME ?? "~/.codex", home));
70
+ const sessionsDir = path.join(codexHome, "sessions");
71
+ if (!existsSync(sessionsDir)) {
72
+ return [];
73
+ }
74
+ const allFiles = await listJsonlFiles(sessionsDir);
75
+ const threadId = options.threadId === undefined ? env.CODEX_THREAD_ID : options.threadId ?? undefined;
76
+ const now = options.now ?? (() => new Date());
77
+ const cutoff = now().getTime() - scanPolicy.recentWindowMs;
78
+ const candidates = await Promise.all(allFiles.map(async (filePath) => {
79
+ const stats = await stat(filePath).catch(() => null);
80
+ if (!stats?.isFile()) {
81
+ return null;
82
+ }
83
+ return { filePath, mtimeMs: stats.mtimeMs };
84
+ }));
85
+ return candidates
86
+ .filter((entry) => entry !== null)
87
+ .filter((entry) => (threadId ? path.basename(entry.filePath).includes(threadId) : entry.mtimeMs >= cutoff))
88
+ .sort((a, b) => b.mtimeMs - a.mtimeMs)
89
+ .slice(0, scanPolicy.maxSessionFiles)
90
+ .map((entry) => entry.filePath);
91
+ }
92
+ async function listJsonlFiles(root) {
93
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
94
+ const files = [];
95
+ for (const entry of entries) {
96
+ const entryPath = path.join(root, entry.name);
97
+ if (entry.isDirectory()) {
98
+ files.push(...(await listJsonlFiles(entryPath)));
99
+ continue;
100
+ }
101
+ if (entry.isFile() && entry.name.endsWith(".jsonl")) {
102
+ files.push(entryPath);
103
+ }
104
+ }
105
+ return files;
106
+ }
107
+ async function readJsonlTail(filePath, start, end) {
108
+ if (end <= start) {
109
+ return [];
110
+ }
111
+ const length = end - start;
112
+ const handle = await open(filePath, "r");
113
+ try {
114
+ const buffer = Buffer.alloc(length);
115
+ const result = await handle.read(buffer, 0, length, start);
116
+ const lines = buffer.subarray(0, result.bytesRead).toString("utf8").split(/\r?\n/);
117
+ if (start > 0) {
118
+ lines.shift();
119
+ }
120
+ return lines.map((line) => line.trim()).filter(Boolean);
121
+ }
122
+ finally {
123
+ await handle.close();
124
+ }
125
+ }
126
+ function toSessionUsageSignals(line, config) {
127
+ let parsed;
128
+ try {
129
+ parsed = JSON.parse(line);
130
+ }
131
+ catch {
132
+ return [];
133
+ }
134
+ if (!parsed || typeof parsed !== "object") {
135
+ return [];
136
+ }
137
+ const event = parsed;
138
+ if (typeof event.timestamp !== "string" || Number.isNaN(new Date(event.timestamp).getTime())) {
139
+ return [];
140
+ }
141
+ const payload = event.payload;
142
+ if (!payload || typeof payload !== "object") {
143
+ return [];
144
+ }
145
+ const payloadType = payload.type;
146
+ if (event.type === "response_item" && payloadType === "function_call") {
147
+ const args = payload.arguments;
148
+ if (typeof args !== "string" || !args.trim()) {
149
+ return [];
150
+ }
151
+ return [{ timestamp: event.timestamp, message: args, skillIds: extractSkillFilePathIdsFromText(args, config) }];
152
+ }
153
+ return [];
154
+ }
155
+ async function readSessionState(cacheDir) {
156
+ const filePath = path.join(cacheDir, STATE_FILE);
157
+ const raw = await readFile(filePath, "utf8").catch(() => "");
158
+ if (!raw.trim()) {
159
+ return { state: { schemaVersion: STATE_SCHEMA_VERSION, files: {}, seen: [] }, isInitialScan: true };
160
+ }
161
+ try {
162
+ const parsed = JSON.parse(raw);
163
+ if (parsed.schemaVersion === STATE_SCHEMA_VERSION && parsed.files && typeof parsed.files === "object" && Array.isArray(parsed.seen)) {
164
+ return { state: parsed, isInitialScan: false };
165
+ }
166
+ }
167
+ catch {
168
+ // Ignore corrupt local cache and rebuild it from current session tails.
169
+ }
170
+ return { state: { schemaVersion: STATE_SCHEMA_VERSION, files: {}, seen: [] }, isInitialScan: true };
171
+ }
172
+ async function writeSessionState(cacheDir, state) {
173
+ await mkdir(cacheDir, { recursive: true });
174
+ await writeFile(path.join(cacheDir, STATE_FILE), `${JSON.stringify(state, null, 2)}\n`, "utf8");
175
+ }
176
+ function usageSeenKey(filePath, timestamp, skillId, message) {
177
+ const messageHash = createHash("sha256").update(message).digest("hex").slice(0, 16);
178
+ return `${filePath}:${timestamp}:${skillId}:${messageHash}`;
179
+ }
180
+ //# sourceMappingURL=sessionUsage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionUsage.js","sourceRoot":"","sources":["../../src/sessionUsage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { DependencyInstallResult } from "./types.js";
2
+ export declare function ensureSkillDependenciesInstalled(skillPath: string): Promise<DependencyInstallResult>;
@@ -0,0 +1,56 @@
1
+ import { existsSync } from "node:fs";
2
+ import { execFile } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ import path from "node:path";
5
+ const execFileAsync = promisify(execFile);
6
+ const managerPrecedence = [
7
+ { packageManager: "pnpm", lockFile: "pnpm-lock.yaml" },
8
+ { packageManager: "yarn", lockFile: "yarn.lock" },
9
+ { packageManager: "bun", lockFile: "bun.lockb" },
10
+ { packageManager: "bun", lockFile: "bun.lock" },
11
+ { packageManager: "npm", lockFile: "package-lock.json" }
12
+ ];
13
+ export async function ensureSkillDependenciesInstalled(skillPath) {
14
+ const packageJsonPath = path.join(skillPath, "package.json");
15
+ if (!existsSync(packageJsonPath)) {
16
+ return {
17
+ status: "skipped-no-package-json",
18
+ packageManager: null,
19
+ command: "",
20
+ message: "No package.json found; skipped dependency installation."
21
+ };
22
+ }
23
+ const nodeModulesPath = path.join(skillPath, "node_modules");
24
+ if (existsSync(nodeModulesPath)) {
25
+ return {
26
+ status: "skipped-existing-node-modules",
27
+ packageManager: null,
28
+ command: "",
29
+ message: "node_modules already exists; skipped dependency installation."
30
+ };
31
+ }
32
+ const packageManager = detectPackageManager(skillPath);
33
+ const command = `${packageManager} install`;
34
+ try {
35
+ await execFileAsync(packageManager, ["install"], { cwd: skillPath });
36
+ }
37
+ catch (error) {
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ throw new Error(`Dependency install failed for ${path.basename(skillPath)} using ${command}: ${message}`);
40
+ }
41
+ return {
42
+ status: "installed",
43
+ packageManager,
44
+ command,
45
+ message: `Installed dependencies with ${command}.`
46
+ };
47
+ }
48
+ function detectPackageManager(skillPath) {
49
+ for (const entry of managerPrecedence) {
50
+ if (existsSync(path.join(skillPath, entry.lockFile))) {
51
+ return entry.packageManager;
52
+ }
53
+ }
54
+ return "npm";
55
+ }
56
+ //# sourceMappingURL=skillDependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillDependencies.js","sourceRoot":"","sources":["../../src/skillDependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAO1C,MAAM,iBAAiB,GAA4B;IACjD,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE;IACtD,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE;IACjD,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE;IAChD,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE;IAC/C,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE;CACzD,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,SAAiB;IACtE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,MAAM,EAAE,yBAAyB;YACjC,cAAc,EAAE,IAAI;YACpB,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,yDAAyD;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,OAAO;YACL,MAAM,EAAE,+BAA+B;YACvC,cAAc,EAAE,IAAI;YACpB,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,+DAA+D;SACzE,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,GAAG,cAAc,UAAU,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,OAAO,KAAK,OAAO,EAAE,CAAC,CAAC;IAC5G,CAAC;IAED,OAAO;QACL,MAAM,EAAE,WAAW;QACnB,cAAc;QACd,OAAO;QACP,OAAO,EAAE,+BAA+B,OAAO,GAAG;KACnD,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,SAAiB;IAC7C,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACrD,OAAO,KAAK,CAAC,cAAc,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { LocalConfig } from "./types.js";
2
+ export declare function extractSkillIdsFromText(text: string, config: LocalConfig): string[];
3
+ export declare function extractSkillFilePathIdsFromText(text: string, config: LocalConfig): string[];
@@ -0,0 +1,111 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { validateSkillId } from "./paths.js";
4
+ export function extractSkillIdsFromText(text, config) {
5
+ const candidates = new Set();
6
+ const roots = [config.codexSkillsDir, config.agentsSkillsDir].map((root) => path.resolve(root));
7
+ for (const skillId of extractSkillFilePathIdsFromText(text, config)) {
8
+ addValidSkillId(candidates, skillId);
9
+ }
10
+ for (const skillId of extractRelativeSkillIds(text, [".codex/skills/", ".agents/skills/"])) {
11
+ addValidSkillId(candidates, skillId);
12
+ }
13
+ for (const skillId of extractDollarSkillIds(text, roots)) {
14
+ addValidSkillId(candidates, skillId);
15
+ }
16
+ return [...candidates].sort((a, b) => a.localeCompare(b));
17
+ }
18
+ export function extractSkillFilePathIdsFromText(text, config) {
19
+ const candidates = new Set();
20
+ const roots = [config.codexSkillsDir, config.agentsSkillsDir].map((root) => path.resolve(root));
21
+ for (const rawPath of extractSkillFilePaths(text)) {
22
+ const decodedPath = decodeSkillPath(rawPath);
23
+ if (!decodedPath) {
24
+ continue;
25
+ }
26
+ const absolutePath = path.isAbsolute(decodedPath) ? path.resolve(decodedPath) : decodedPath;
27
+ for (const root of roots) {
28
+ if (!path.isAbsolute(absolutePath)) {
29
+ continue;
30
+ }
31
+ const skillDir = path.dirname(absolutePath);
32
+ const relative = path.relative(root, skillDir);
33
+ if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
34
+ continue;
35
+ }
36
+ addValidSkillId(candidates, relative.split(path.sep).join("/"));
37
+ }
38
+ }
39
+ return [...candidates].sort((a, b) => a.localeCompare(b));
40
+ }
41
+ function extractSkillFilePaths(text) {
42
+ const paths = [];
43
+ const markdownLinkPattern = /\]\(([^)\s]+?\/SKILL\.md)(?:#[^)]+)?\)/g;
44
+ const plainPathPattern = /((?:file:\/\/)?(?:~|\/|[A-Za-z]:[\\/])[^\s'"()<>]*?\/SKILL\.md)/g;
45
+ for (const match of text.matchAll(markdownLinkPattern)) {
46
+ if (match[1]) {
47
+ paths.push(match[1]);
48
+ }
49
+ }
50
+ for (const match of text.matchAll(plainPathPattern)) {
51
+ if (match[1]) {
52
+ paths.push(match[1]);
53
+ }
54
+ }
55
+ return paths;
56
+ }
57
+ function extractRelativeSkillIds(text, rootMarkers) {
58
+ const skillIds = [];
59
+ for (const marker of rootMarkers) {
60
+ let index = text.indexOf(marker);
61
+ while (index !== -1) {
62
+ const start = index + marker.length;
63
+ const endMarker = "/SKILL.md";
64
+ const end = text.indexOf(endMarker, start);
65
+ if (end !== -1) {
66
+ skillIds.push(text.slice(start, end));
67
+ }
68
+ index = text.indexOf(marker, start);
69
+ }
70
+ }
71
+ return skillIds;
72
+ }
73
+ function extractDollarSkillIds(text, roots) {
74
+ const skillIds = new Set();
75
+ const pattern = /(^|[^\w/.-])\$([A-Za-z0-9][A-Za-z0-9_-]*(?:\/[A-Za-z0-9][A-Za-z0-9_-]*)*)\b/g;
76
+ for (const match of text.matchAll(pattern)) {
77
+ const candidate = match[2];
78
+ if (!candidate) {
79
+ continue;
80
+ }
81
+ let skillId;
82
+ try {
83
+ skillId = validateSkillId(candidate);
84
+ }
85
+ catch {
86
+ continue;
87
+ }
88
+ if (roots.some((root) => existsSync(path.join(root, ...skillId.split("/"), "SKILL.md")))) {
89
+ skillIds.add(skillId);
90
+ }
91
+ }
92
+ return [...skillIds];
93
+ }
94
+ function decodeSkillPath(rawPath) {
95
+ const withoutFileProtocol = rawPath.startsWith("file://") ? rawPath.slice("file://".length) : rawPath;
96
+ try {
97
+ return decodeURIComponent(withoutFileProtocol);
98
+ }
99
+ catch {
100
+ return withoutFileProtocol;
101
+ }
102
+ }
103
+ function addValidSkillId(candidates, skillId) {
104
+ try {
105
+ candidates.add(validateSkillId(skillId));
106
+ }
107
+ catch {
108
+ // Ignore non-user skill roots and malformed paths.
109
+ }
110
+ }
111
+ //# sourceMappingURL=skillMentions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillMentions.js","sourceRoot":"","sources":["../../src/skillMentions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { LocalConfig, StatusReport, SyncState } from "./types.js";
2
+ export declare function buildStatusReport(config: LocalConfig): Promise<StatusReport>;
3
+ export declare function deriveSyncState(lastSyncedHash: string | null, currentLocalHash: string | null, currentRepoHash: string | null): SyncState;
@@ -0,0 +1,134 @@
1
+ import { repoSkillsDir } from "./paths.js";
2
+ import { readSkillsMetadata } from "./metadata.js";
3
+ import { scanSkills } from "./scanner.js";
4
+ import { getLastUsageBySkill } from "./usage.js";
5
+ export async function buildStatusReport(config) {
6
+ const metadata = await readSkillsMetadata(config.syncRepo);
7
+ const managedRecords = metadata.skills.filter((skill) => skill.status === "managed");
8
+ const codexSkills = await scanSkills(config.codexSkillsDir, "codex");
9
+ const agentsSkills = await scanSkills(config.agentsSkillsDir, "agents");
10
+ const localSkills = [...codexSkills, ...agentsSkills].sort(compareScannedSkills);
11
+ const repoSkills = await scanSkills(repoSkillsDir(config.syncRepo), "repo");
12
+ const localById = groupLocalSkills(localSkills);
13
+ const repoById = new Map(repoSkills.map((skill) => [skill.id, skill]));
14
+ const managedIds = new Set(managedRecords.map((skill) => skill.id));
15
+ const allSkillIds = uniqueSkillIds([...managedRecords, ...localSkills, ...repoSkills].map((skill) => skill.id));
16
+ const lastUsedBySkill = await getLastUsageBySkill(config.syncRepo, allSkillIds);
17
+ const managed = managedRecords.map((record) => {
18
+ const localCandidates = localById.get(record.id) ?? [];
19
+ return refreshRecord(record, findLocalSkill(record, localById), localCandidates, repoById.get(record.id), lastUsedBySkill.get(record.id) ?? null);
20
+ });
21
+ const unmanagedLocal = withLastUsedAt(localSkills.filter((skill) => !managedIds.has(skill.id)), lastUsedBySkill);
22
+ const repoOnly = withLastUsedAt(repoSkills.filter((skill) => !managedIds.has(skill.id)), lastUsedBySkill);
23
+ return {
24
+ syncRepo: config.syncRepo,
25
+ codexSkillsDir: config.codexSkillsDir,
26
+ agentsSkillsDir: config.agentsSkillsDir,
27
+ managed,
28
+ unmanagedLocal,
29
+ repoOnly
30
+ };
31
+ }
32
+ function uniqueSkillIds(skillIds) {
33
+ return [...new Set(skillIds)].sort((a, b) => a.localeCompare(b));
34
+ }
35
+ function withLastUsedAt(skills, lastUsedBySkill) {
36
+ return skills.map((skill) => ({
37
+ ...skill,
38
+ lastUsedAt: lastUsedBySkill.get(skill.id) ?? null
39
+ }));
40
+ }
41
+ function compareScannedSkills(a, b) {
42
+ return a.id.localeCompare(b.id) || a.source.localeCompare(b.source);
43
+ }
44
+ function refreshRecord(record, local, localCandidates, repo, lastUsedAt) {
45
+ const currentLocalHash = currentLocalHashForCandidates(local, localCandidates);
46
+ const currentRepoHash = repo?.hash ?? null;
47
+ const installed = localCandidates.length > 0;
48
+ const localSources = localCandidates
49
+ .map((candidate) => candidate.source)
50
+ .filter((source) => source === "codex" || source === "agents")
51
+ .sort((a, b) => a.localeCompare(b));
52
+ const localCopiesDiffer = localCandidateHashes(localCandidates).length > 1;
53
+ return {
54
+ ...record,
55
+ lastUsedAt,
56
+ name: repo?.name ?? local?.name ?? record.name,
57
+ description: repo?.description ?? local?.description ?? record.description,
58
+ localSource: local?.source === "codex" || local?.source === "agents" ? local.source : record.localSource ?? null,
59
+ localSources,
60
+ localCopiesDiffer,
61
+ localModifiedAt: latestLocalModifiedAt(localCandidates),
62
+ installed,
63
+ syncState: localCopiesDiffer ? "conflict" : deriveSyncState(record.lastSyncedHash, currentLocalHash, currentRepoHash),
64
+ currentLocalHash,
65
+ currentRepoHash
66
+ };
67
+ }
68
+ function currentLocalHashForCandidates(local, localCandidates) {
69
+ const hashes = localCandidateHashes(localCandidates);
70
+ if (hashes.length === 1) {
71
+ return hashes[0] ?? null;
72
+ }
73
+ return local?.hash ?? null;
74
+ }
75
+ function localCandidateHashes(localCandidates) {
76
+ return [...new Set(localCandidates.map((candidate) => candidate.hash))].sort();
77
+ }
78
+ function latestLocalModifiedAt(localCandidates) {
79
+ if (localCandidates.length === 0) {
80
+ return null;
81
+ }
82
+ return localCandidates
83
+ .map((skill) => skill.modifiedAt)
84
+ .sort((a, b) => new Date(b).getTime() - new Date(a).getTime())[0] ?? null;
85
+ }
86
+ function groupLocalSkills(skills) {
87
+ const grouped = new Map();
88
+ for (const skill of skills) {
89
+ const existing = grouped.get(skill.id) ?? [];
90
+ existing.push(skill);
91
+ grouped.set(skill.id, existing);
92
+ }
93
+ return grouped;
94
+ }
95
+ function findLocalSkill(record, localById) {
96
+ const candidates = localById.get(record.id) ?? [];
97
+ if (record.localSource) {
98
+ const preferred = candidates.find((skill) => skill.source === record.localSource);
99
+ if (preferred) {
100
+ return preferred;
101
+ }
102
+ }
103
+ return candidates.find((skill) => skill.source === "codex") ?? candidates.find((skill) => skill.source === "agents");
104
+ }
105
+ export function deriveSyncState(lastSyncedHash, currentLocalHash, currentRepoHash) {
106
+ if (!currentLocalHash && currentRepoHash) {
107
+ return "missing_local";
108
+ }
109
+ if (currentLocalHash && !currentRepoHash) {
110
+ return "missing_repo";
111
+ }
112
+ if (!currentLocalHash && !currentRepoHash) {
113
+ return "missing_repo";
114
+ }
115
+ if (currentLocalHash === currentRepoHash) {
116
+ return "clean";
117
+ }
118
+ if (!lastSyncedHash) {
119
+ return "conflict";
120
+ }
121
+ const localChanged = currentLocalHash !== lastSyncedHash;
122
+ const repoChanged = currentRepoHash !== lastSyncedHash;
123
+ if (localChanged && repoChanged) {
124
+ return "conflict";
125
+ }
126
+ if (localChanged) {
127
+ return "local_modified";
128
+ }
129
+ if (repoChanged) {
130
+ return "repo_modified";
131
+ }
132
+ return "clean";
133
+ }
134
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { LocalConfig, SkillRecord } from "./types.js";
2
+ export declare function stopSyncingSkill(config: LocalConfig, skillId: string): Promise<SkillRecord>;
@@ -0,0 +1,31 @@
1
+ import { existsSync } from "node:fs";
2
+ import { rm } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { repoSkillsDir } from "./paths.js";
5
+ import { readSkillsMetadata, writeSkillsMetadata } from "./metadata.js";
6
+ import { validateSkillId } from "./paths.js";
7
+ export async function stopSyncingSkill(config, skillId) {
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] ?? null;
15
+ if (!existing) {
16
+ throw new Error(`Managed skill not found in metadata: ${id}`);
17
+ }
18
+ const skillsPath = repoSkillsDir(config.syncRepo);
19
+ const repoPath = path.join(skillsPath, ...id.split("/"));
20
+ if (existsSync(repoPath)) {
21
+ await rm(repoPath, { recursive: true, force: true });
22
+ }
23
+ const [removed] = metadata.skills.splice(index, 1);
24
+ await writeSkillsMetadata(config.syncRepo, metadata);
25
+ return {
26
+ ...removed,
27
+ status: "managed",
28
+ updatedAt: new Date().toISOString()
29
+ };
30
+ }
31
+ //# sourceMappingURL=stopSyncingSkill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stopSyncingSkill.js","sourceRoot":"","sources":["../../src/stopSyncingSkill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAmB,EAAE,OAAe;IACzE,MAAM,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wCAAwC,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,wCAAwC,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACnD,MAAM,mBAAmB,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAErD,OAAO;QACL,GAAG,OAAO;QACV,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { LocalConfig, LocalSkillSource } from "./types.js";
2
+ import { type GitBranchSyncStatus } from "./git.js";
3
+ export type SyncSelection = {
4
+ skillId: string;
5
+ source?: LocalSkillSource;
6
+ };
7
+ export type SyncResult = {
8
+ skillIds: string[];
9
+ updatedRepoSkillIds: string[];
10
+ committed: boolean;
11
+ pushed: boolean;
12
+ commitHash: string | null;
13
+ commitMessage: string;
14
+ gitStatus: string;
15
+ };
16
+ export type PullRepositoryResult = {
17
+ pulled: true;
18
+ preSync: SyncResult | null;
19
+ gitStatus: string;
20
+ gitBranchStatus: GitBranchSyncStatus;
21
+ };
22
+ export type RepositoryConflictSource = "github" | "syncRepo" | LocalSkillSource;
23
+ export type RepositoryConflictVersion = {
24
+ source: RepositoryConflictSource;
25
+ label: string;
26
+ path: string;
27
+ exists: boolean;
28
+ content: string | null;
29
+ };
30
+ export type RepositorySkillConflict = {
31
+ skillId: string;
32
+ files: string[];
33
+ versions: RepositoryConflictVersion[];
34
+ };
35
+ export type RepositoryConflictsResult = {
36
+ gitBranchStatus: GitBranchSyncStatus;
37
+ conflicts: RepositorySkillConflict[];
38
+ };
39
+ export type RepositoryConflictResolution = {
40
+ skillId: string;
41
+ source: RepositoryConflictSource;
42
+ };
43
+ export declare function syncSelectedSkills(config: LocalConfig, selections: SyncSelection[]): Promise<SyncResult>;
44
+ export declare function syncSingleSkill(config: LocalConfig, skillId: string): Promise<SyncResult>;
45
+ export declare function syncRepositoryChanges(config: LocalConfig): Promise<SyncResult>;
46
+ export declare function pullRepositoryChanges(config: LocalConfig): Promise<PullRepositoryResult>;
47
+ export declare function listRepositoryConflicts(config: LocalConfig): Promise<RepositoryConflictsResult>;
48
+ export declare function resolveRepositoryConflicts(config: LocalConfig, resolutions: RepositoryConflictResolution[]): Promise<PullRepositoryResult>;