@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,146 @@
1
+ import { existsSync } from "node:fs";
2
+ import { rm } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { readSkillFrontmatter } from "./frontmatter.js";
5
+ import { hashDirectory } from "./hash.js";
6
+ import { copySkillDirectory } from "./copy.js";
7
+ import { deriveSyncState } from "./status.js";
8
+ import { readSkillsMetadata, upsertSkillRecord } from "./metadata.js";
9
+ import { syncRepositoryChanges, syncSingleSkill } from "./sync.js";
10
+ import { resolveSkillPath, repoSkillsDir, validateSkillId } from "./paths.js";
11
+ export async function resolveConflict(config, skillId, options) {
12
+ const id = validateSkillId(skillId);
13
+ const existing = await findManagedRecord(config.syncRepo, id);
14
+ const strategy = options.strategy;
15
+ const repoPath = path.join(repoSkillsDir(config.syncRepo), ...id.split("/"));
16
+ const codexPath = resolveSkillPath(config.codexSkillsDir, id);
17
+ const agentsPath = resolveSkillPath(config.agentsSkillsDir, id);
18
+ const hasCodexCopy = hasCopyAt(codexPath);
19
+ const hasAgentsCopy = hasCopyAt(agentsPath);
20
+ if (strategy === "codex" || strategy === "agents") {
21
+ return resolveFromLocalCopy({
22
+ config,
23
+ id,
24
+ existing,
25
+ repoPath,
26
+ strategy,
27
+ winnerPath: strategy === "codex" ? codexPath : agentsPath,
28
+ loserPath: strategy === "codex" ? (hasAgentsCopy ? agentsPath : null) : hasCodexCopy ? codexPath : null
29
+ });
30
+ }
31
+ if (!hasCopyAt(repoPath)) {
32
+ throw conflictError(`Cannot use repo as strategy for ${id}: repo copy is missing.`);
33
+ }
34
+ const repoHash = await hashDirectory(repoPath);
35
+ const frontmatter = await readSkillFrontmatter(repoPath);
36
+ const localSources = collectLocalSources(hasCodexCopy, hasAgentsCopy);
37
+ await copyRepoToInstalledLocals(config, repoPath, localSources, id);
38
+ const currentLocalHash = await localHashFromSources(config, localSources, id);
39
+ const updated = {
40
+ ...existing,
41
+ name: frontmatter.name,
42
+ description: frontmatter.description,
43
+ localSource: localSources.length > 0 ? (localSources.includes("codex") ? "codex" : "agents") : null,
44
+ installed: localSources.length > 0,
45
+ localCopiesDiffer: false,
46
+ syncState: deriveSyncState(repoHash, currentLocalHash, repoHash),
47
+ lastSyncedHash: repoHash,
48
+ currentRepoHash: repoHash,
49
+ currentLocalHash,
50
+ updatedAt: new Date().toISOString()
51
+ };
52
+ const changed = hasChanged(existing, updated);
53
+ await upsertSkillRecord(config.syncRepo, updated);
54
+ const result = changed ? await syncRepositoryChanges(config) : undefined;
55
+ return { record: updated, result };
56
+ }
57
+ async function resolveFromLocalCopy(args) {
58
+ if (!hasCopyAt(args.winnerPath)) {
59
+ throw conflictError(`Cannot use ${args.strategy} as strategy for ${args.id}: source is missing on this machine.`);
60
+ }
61
+ await replaceDirectory(args.repoPath, args.winnerPath);
62
+ const winnerHash = await hashDirectory(args.repoPath);
63
+ if (args.loserPath) {
64
+ await replaceDirectory(args.loserPath, args.winnerPath);
65
+ }
66
+ const frontmatter = await readSkillFrontmatter(args.winnerPath);
67
+ const updated = {
68
+ ...args.existing,
69
+ name: frontmatter.name,
70
+ description: frontmatter.description,
71
+ localSource: args.strategy,
72
+ localCopiesDiffer: false,
73
+ installed: true,
74
+ syncState: "clean",
75
+ lastSyncedHash: winnerHash,
76
+ currentRepoHash: winnerHash,
77
+ currentLocalHash: winnerHash,
78
+ updatedAt: new Date().toISOString()
79
+ };
80
+ await upsertSkillRecord(args.config.syncRepo, updated);
81
+ const result = await syncSingleSkill(args.config, args.id);
82
+ return { record: updated, result };
83
+ }
84
+ async function findManagedRecord(syncRepo, id) {
85
+ const metadata = await readSkillsMetadata(syncRepo);
86
+ const record = metadata.skills.find((skill) => skill.id === id);
87
+ if (!record) {
88
+ throw conflictError(`Managed skill not found in metadata: ${id}`);
89
+ }
90
+ if (record.status !== "managed") {
91
+ throw conflictError(`Cannot resolve conflicts for ${id}: not a managed skill.`);
92
+ }
93
+ return record;
94
+ }
95
+ function hasCopyAt(skillPath) {
96
+ return existsSync(skillPath) && existsSync(path.join(skillPath, "SKILL.md"));
97
+ }
98
+ function collectLocalSources(hasCodex, hasAgents) {
99
+ const sources = [];
100
+ if (hasCodex) {
101
+ sources.push("codex");
102
+ }
103
+ if (hasAgents) {
104
+ sources.push("agents");
105
+ }
106
+ return sources;
107
+ }
108
+ async function localHashFromSources(config, sources, skillId) {
109
+ if (sources.length === 0) {
110
+ return null;
111
+ }
112
+ const hashes = [];
113
+ for (const source of sources) {
114
+ const localPath = localPathForSource(config, source, skillId);
115
+ hashes.push(await hashDirectory(localPath));
116
+ }
117
+ const unique = [...new Set(hashes)];
118
+ return unique.length === 1 ? unique[0] ?? null : null;
119
+ }
120
+ function localPathForSource(config, source, skillId) {
121
+ return source === "codex" ? resolveSkillPath(config.codexSkillsDir, skillId) : resolveSkillPath(config.agentsSkillsDir, skillId);
122
+ }
123
+ async function copyRepoToInstalledLocals(config, repoPath, sources, skillId) {
124
+ for (const source of sources) {
125
+ const localPath = localPathForSource(config, source, skillId);
126
+ if (hasCopyAt(localPath)) {
127
+ await replaceDirectory(localPath, repoPath);
128
+ }
129
+ }
130
+ }
131
+ async function replaceDirectory(target, source) {
132
+ if (existsSync(target)) {
133
+ await rm(target, { recursive: true, force: true });
134
+ }
135
+ await copySkillDirectory(source, target);
136
+ }
137
+ function hasChanged(before, after) {
138
+ return JSON.stringify(before) !== JSON.stringify(after);
139
+ }
140
+ function conflictError(message) {
141
+ const error = new Error(message);
142
+ error.apiMessage = message;
143
+ error.statusCode = 400;
144
+ return error;
145
+ }
146
+ //# sourceMappingURL=resolveConflict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveConflict.js","sourceRoot":"","sources":["../../src/resolveConflict.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ScanSource, ScannedSkill } from "./types.js";
2
+ export type ScanOptions = {
3
+ includeHidden?: boolean;
4
+ };
5
+ export declare function scanSkills(root: string, source: ScanSource, options?: ScanOptions): Promise<ScannedSkill[]>;
@@ -0,0 +1,57 @@
1
+ import { existsSync } from "node:fs";
2
+ import { lstat, readdir } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { readSkillFrontmatter } from "./frontmatter.js";
5
+ import { hashDirectory } from "./hash.js";
6
+ import { validateSkillId } from "./paths.js";
7
+ export async function scanSkills(root, source, options = {}) {
8
+ if (!existsSync(root)) {
9
+ return [];
10
+ }
11
+ const skills = [];
12
+ const entries = await readdir(root, { withFileTypes: true });
13
+ for (const entry of entries) {
14
+ if (!entry.isDirectory() || shouldSkipDirectory(entry.name, options)) {
15
+ continue;
16
+ }
17
+ const current = path.join(root, entry.name);
18
+ if (!existsSync(path.join(current, "SKILL.md"))) {
19
+ continue;
20
+ }
21
+ const id = validateSkillId(entry.name);
22
+ const frontmatter = await readSkillFrontmatter(current);
23
+ skills.push({
24
+ id,
25
+ name: frontmatter.name,
26
+ description: frontmatter.description,
27
+ path: current,
28
+ source,
29
+ hash: await hashDirectory(current),
30
+ modifiedAt: new Date(await latestModifiedTime(current)).toISOString()
31
+ });
32
+ }
33
+ return skills.sort((a, b) => a.id.localeCompare(b.id));
34
+ }
35
+ async function latestModifiedTime(current) {
36
+ const stat = await lstat(current);
37
+ if (!stat.isDirectory()) {
38
+ return stat.mtimeMs;
39
+ }
40
+ let latest = stat.mtimeMs;
41
+ const entries = await readdir(current, { withFileTypes: true });
42
+ for (const entry of entries) {
43
+ if (entry.name === ".git" || entry.name === "node_modules") {
44
+ continue;
45
+ }
46
+ const childModified = await latestModifiedTime(path.join(current, entry.name));
47
+ latest = Math.max(latest, childModified);
48
+ }
49
+ return latest;
50
+ }
51
+ function shouldSkipDirectory(name, options) {
52
+ if (name === ".git" || name === "node_modules") {
53
+ return true;
54
+ }
55
+ return !options.includeHidden && name.startsWith(".");
56
+ }
57
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM7C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,MAAkB,EAAE,UAAuB,EAAE;IAC1F,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACrE,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YAChD,SAAS;QACX,CAAC;QAED,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC;YACV,EAAE;YACF,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,WAAW,EAAE,WAAW,CAAC,WAAW;YACpC,IAAI,EAAE,OAAO;YACb,MAAM;YACN,IAAI,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC;YAClC,UAAU,EAAE,IAAI,IAAI,CAAC,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE;SACtE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,OAAe;IAC/C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;IAC1B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAC3D,SAAS;QACX,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY,EAAE,OAAoB;IAC7D,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type DirectoryPicker } from "./directoryPicker.js";
2
+ export type ServerOptions = {
3
+ host?: string;
4
+ port?: number;
5
+ directoryPicker?: DirectoryPicker;
6
+ };
7
+ export declare function startServer(options?: ServerOptions): Promise<{
8
+ url: string;
9
+ close: () => Promise<void>;
10
+ }>;