@sentry/dotagents 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/README.md +96 -0
  2. package/dist/cli/commands/add.d.ts +12 -0
  3. package/dist/cli/commands/add.d.ts.map +1 -0
  4. package/dist/cli/commands/add.js +127 -0
  5. package/dist/cli/commands/add.js.map +1 -0
  6. package/dist/cli/commands/init.d.ts +10 -0
  7. package/dist/cli/commands/init.d.ts.map +1 -0
  8. package/dist/cli/commands/init.js +81 -0
  9. package/dist/cli/commands/init.js.map +1 -0
  10. package/dist/cli/commands/init.test.d.ts +2 -0
  11. package/dist/cli/commands/init.test.d.ts.map +1 -0
  12. package/dist/cli/commands/init.test.js +71 -0
  13. package/dist/cli/commands/init.test.js.map +1 -0
  14. package/dist/cli/commands/install.d.ts +15 -0
  15. package/dist/cli/commands/install.d.ts.map +1 -0
  16. package/dist/cli/commands/install.js +139 -0
  17. package/dist/cli/commands/install.js.map +1 -0
  18. package/dist/cli/commands/install.test.d.ts +2 -0
  19. package/dist/cli/commands/install.test.d.ts.map +1 -0
  20. package/dist/cli/commands/install.test.js +94 -0
  21. package/dist/cli/commands/install.test.js.map +1 -0
  22. package/dist/cli/commands/list.d.ts +13 -0
  23. package/dist/cli/commands/list.d.ts.map +1 -0
  24. package/dist/cli/commands/list.js +82 -0
  25. package/dist/cli/commands/list.js.map +1 -0
  26. package/dist/cli/commands/list.test.d.ts +2 -0
  27. package/dist/cli/commands/list.test.d.ts.map +1 -0
  28. package/dist/cli/commands/list.test.js +96 -0
  29. package/dist/cli/commands/list.test.js.map +1 -0
  30. package/dist/cli/commands/remove.d.ts +10 -0
  31. package/dist/cli/commands/remove.d.ts.map +1 -0
  32. package/dist/cli/commands/remove.js +68 -0
  33. package/dist/cli/commands/remove.js.map +1 -0
  34. package/dist/cli/commands/sync.d.ts +16 -0
  35. package/dist/cli/commands/sync.d.ts.map +1 -0
  36. package/dist/cli/commands/sync.js +108 -0
  37. package/dist/cli/commands/sync.js.map +1 -0
  38. package/dist/cli/commands/sync.test.d.ts +2 -0
  39. package/dist/cli/commands/sync.test.d.ts.map +1 -0
  40. package/dist/cli/commands/sync.test.js +100 -0
  41. package/dist/cli/commands/sync.test.js.map +1 -0
  42. package/dist/cli/commands/update.d.ts +15 -0
  43. package/dist/cli/commands/update.d.ts.map +1 -0
  44. package/dist/cli/commands/update.js +113 -0
  45. package/dist/cli/commands/update.js.map +1 -0
  46. package/dist/cli/commands/update.test.d.ts +2 -0
  47. package/dist/cli/commands/update.test.d.ts.map +1 -0
  48. package/dist/cli/commands/update.test.js +90 -0
  49. package/dist/cli/commands/update.test.js.map +1 -0
  50. package/dist/cli/index.d.ts +2 -0
  51. package/dist/cli/index.d.ts.map +1 -0
  52. package/dist/cli/index.js +49 -0
  53. package/dist/cli/index.js.map +1 -0
  54. package/dist/config/index.d.ts +5 -0
  55. package/dist/config/index.d.ts.map +1 -0
  56. package/dist/config/index.js +4 -0
  57. package/dist/config/index.js.map +1 -0
  58. package/dist/config/loader.d.ts +6 -0
  59. package/dist/config/loader.d.ts.map +1 -0
  60. package/dist/config/loader.js +35 -0
  61. package/dist/config/loader.js.map +1 -0
  62. package/dist/config/loader.test.d.ts +2 -0
  63. package/dist/config/loader.test.d.ts.map +1 -0
  64. package/dist/config/loader.test.js +60 -0
  65. package/dist/config/loader.test.js.map +1 -0
  66. package/dist/config/schema.d.ts +37 -0
  67. package/dist/config/schema.d.ts.map +1 -0
  68. package/dist/config/schema.js +43 -0
  69. package/dist/config/schema.js.map +1 -0
  70. package/dist/config/schema.test.d.ts +2 -0
  71. package/dist/config/schema.test.d.ts.map +1 -0
  72. package/dist/config/schema.test.js +138 -0
  73. package/dist/config/schema.test.js.map +1 -0
  74. package/dist/config/writer.d.ts +17 -0
  75. package/dist/config/writer.d.ts.map +1 -0
  76. package/dist/config/writer.js +71 -0
  77. package/dist/config/writer.js.map +1 -0
  78. package/dist/config/writer.test.d.ts +2 -0
  79. package/dist/config/writer.test.d.ts.map +1 -0
  80. package/dist/config/writer.test.js +103 -0
  81. package/dist/config/writer.test.js.map +1 -0
  82. package/dist/gitignore/index.d.ts +2 -0
  83. package/dist/gitignore/index.d.ts.map +1 -0
  84. package/dist/gitignore/index.js +2 -0
  85. package/dist/gitignore/index.js.map +1 -0
  86. package/dist/gitignore/writer.d.ts +16 -0
  87. package/dist/gitignore/writer.d.ts.map +1 -0
  88. package/dist/gitignore/writer.js +40 -0
  89. package/dist/gitignore/writer.js.map +1 -0
  90. package/dist/gitignore/writer.test.d.ts +2 -0
  91. package/dist/gitignore/writer.test.d.ts.map +1 -0
  92. package/dist/gitignore/writer.test.js +99 -0
  93. package/dist/gitignore/writer.test.js.map +1 -0
  94. package/dist/index.d.ts +12 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +8 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/lockfile/index.d.ts +5 -0
  99. package/dist/lockfile/index.d.ts.map +1 -0
  100. package/dist/lockfile/index.js +4 -0
  101. package/dist/lockfile/index.js.map +1 -0
  102. package/dist/lockfile/loader.d.ts +10 -0
  103. package/dist/lockfile/loader.d.ts.map +1 -0
  104. package/dist/lockfile/loader.js +36 -0
  105. package/dist/lockfile/loader.js.map +1 -0
  106. package/dist/lockfile/schema.d.ts +42 -0
  107. package/dist/lockfile/schema.d.ts.map +1 -0
  108. package/dist/lockfile/schema.js +25 -0
  109. package/dist/lockfile/schema.js.map +1 -0
  110. package/dist/lockfile/schema.test.d.ts +2 -0
  111. package/dist/lockfile/schema.test.d.ts.map +1 -0
  112. package/dist/lockfile/schema.test.js +60 -0
  113. package/dist/lockfile/schema.test.js.map +1 -0
  114. package/dist/lockfile/writer.d.ts +7 -0
  115. package/dist/lockfile/writer.d.ts.map +1 -0
  116. package/dist/lockfile/writer.js +17 -0
  117. package/dist/lockfile/writer.js.map +1 -0
  118. package/dist/lockfile/writer.test.d.ts +2 -0
  119. package/dist/lockfile/writer.test.d.ts.map +1 -0
  120. package/dist/lockfile/writer.test.js +73 -0
  121. package/dist/lockfile/writer.test.js.map +1 -0
  122. package/dist/skills/discovery.d.ts +17 -0
  123. package/dist/skills/discovery.d.ts.map +1 -0
  124. package/dist/skills/discovery.js +156 -0
  125. package/dist/skills/discovery.js.map +1 -0
  126. package/dist/skills/discovery.test.d.ts +2 -0
  127. package/dist/skills/discovery.test.d.ts.map +1 -0
  128. package/dist/skills/discovery.test.js +110 -0
  129. package/dist/skills/discovery.test.js.map +1 -0
  130. package/dist/skills/index.d.ts +7 -0
  131. package/dist/skills/index.d.ts.map +1 -0
  132. package/dist/skills/index.js +4 -0
  133. package/dist/skills/index.js.map +1 -0
  134. package/dist/skills/loader.d.ts +14 -0
  135. package/dist/skills/loader.d.ts.map +1 -0
  136. package/dist/skills/loader.js +57 -0
  137. package/dist/skills/loader.js.map +1 -0
  138. package/dist/skills/loader.test.d.ts +2 -0
  139. package/dist/skills/loader.test.d.ts.map +1 -0
  140. package/dist/skills/loader.test.js +69 -0
  141. package/dist/skills/loader.test.js.map +1 -0
  142. package/dist/skills/resolver.d.ts +46 -0
  143. package/dist/skills/resolver.d.ts.map +1 -0
  144. package/dist/skills/resolver.integration.test.d.ts +2 -0
  145. package/dist/skills/resolver.integration.test.d.ts.map +1 -0
  146. package/dist/skills/resolver.integration.test.js +106 -0
  147. package/dist/skills/resolver.integration.test.js.map +1 -0
  148. package/dist/skills/resolver.js +82 -0
  149. package/dist/skills/resolver.js.map +1 -0
  150. package/dist/skills/resolver.test.d.ts +2 -0
  151. package/dist/skills/resolver.test.d.ts.map +1 -0
  152. package/dist/skills/resolver.test.js +36 -0
  153. package/dist/skills/resolver.test.js.map +1 -0
  154. package/dist/sources/cache.d.ts +23 -0
  155. package/dist/sources/cache.d.ts.map +1 -0
  156. package/dist/sources/cache.js +61 -0
  157. package/dist/sources/cache.js.map +1 -0
  158. package/dist/sources/git.d.ts +25 -0
  159. package/dist/sources/git.d.ts.map +1 -0
  160. package/dist/sources/git.js +72 -0
  161. package/dist/sources/git.js.map +1 -0
  162. package/dist/sources/index.d.ts +5 -0
  163. package/dist/sources/index.d.ts.map +1 -0
  164. package/dist/sources/index.js +4 -0
  165. package/dist/sources/index.js.map +1 -0
  166. package/dist/sources/local.d.ts +9 -0
  167. package/dist/sources/local.d.ts.map +1 -0
  168. package/dist/sources/local.js +32 -0
  169. package/dist/sources/local.js.map +1 -0
  170. package/dist/symlinks/index.d.ts +2 -0
  171. package/dist/symlinks/index.d.ts.map +1 -0
  172. package/dist/symlinks/index.js +2 -0
  173. package/dist/symlinks/index.js.map +1 -0
  174. package/dist/symlinks/manager.d.ts +20 -0
  175. package/dist/symlinks/manager.d.ts.map +1 -0
  176. package/dist/symlinks/manager.js +103 -0
  177. package/dist/symlinks/manager.js.map +1 -0
  178. package/dist/symlinks/manager.test.d.ts +2 -0
  179. package/dist/symlinks/manager.test.d.ts.map +1 -0
  180. package/dist/symlinks/manager.test.js +94 -0
  181. package/dist/symlinks/manager.test.js.map +1 -0
  182. package/dist/utils/exec.d.ts +16 -0
  183. package/dist/utils/exec.d.ts.map +1 -0
  184. package/dist/utils/exec.js +37 -0
  185. package/dist/utils/exec.js.map +1 -0
  186. package/dist/utils/fs.d.ts +6 -0
  187. package/dist/utils/fs.d.ts.map +1 -0
  188. package/dist/utils/fs.js +10 -0
  189. package/dist/utils/fs.js.map +1 -0
  190. package/dist/utils/hash.d.ts +16 -0
  191. package/dist/utils/hash.d.ts.map +1 -0
  192. package/dist/utils/hash.js +50 -0
  193. package/dist/utils/hash.js.map +1 -0
  194. package/dist/utils/hash.test.d.ts +2 -0
  195. package/dist/utils/hash.test.d.ts.map +1 -0
  196. package/dist/utils/hash.test.js +61 -0
  197. package/dist/utils/hash.test.js.map +1 -0
  198. package/dist/utils/index.d.ts +4 -0
  199. package/dist/utils/index.d.ts.map +1 -0
  200. package/dist/utils/index.js +4 -0
  201. package/dist/utils/index.js.map +1 -0
  202. package/package.json +56 -0
@@ -0,0 +1,100 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { runSync } from "./sync.js";
6
+ import { writeLockfile } from "../../lockfile/writer.js";
7
+ import { hashDirectory } from "../../utils/hash.js";
8
+ const SKILL_MD = (name) => `---
9
+ name: ${name}
10
+ description: Test skill ${name}
11
+ ---
12
+ `;
13
+ describe("runSync", () => {
14
+ let tmpDir;
15
+ let projectRoot;
16
+ beforeEach(async () => {
17
+ tmpDir = await mkdtemp(join(tmpdir(), "dotagents-sync-"));
18
+ projectRoot = join(tmpDir, "project");
19
+ await mkdir(join(projectRoot, ".agents", "skills"), { recursive: true });
20
+ });
21
+ afterEach(async () => {
22
+ await rm(tmpDir, { recursive: true });
23
+ });
24
+ it("detects orphaned skills", async () => {
25
+ await writeFile(join(projectRoot, "agents.toml"), "version = 1\n");
26
+ // Orphan: installed but not in config
27
+ const orphanDir = join(projectRoot, ".agents", "skills", "orphan");
28
+ await mkdir(orphanDir, { recursive: true });
29
+ await writeFile(join(orphanDir, "SKILL.md"), SKILL_MD("orphan"));
30
+ const result = await runSync({ projectRoot });
31
+ const orphanIssues = result.issues.filter((i) => i.type === "orphan");
32
+ expect(orphanIssues).toHaveLength(1);
33
+ expect(orphanIssues[0].name).toBe("orphan");
34
+ });
35
+ it("detects missing skills", async () => {
36
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "org/repo"\n`);
37
+ const result = await runSync({ projectRoot });
38
+ const missingIssues = result.issues.filter((i) => i.type === "missing");
39
+ expect(missingIssues).toHaveLength(1);
40
+ expect(missingIssues[0].name).toBe("pdf");
41
+ });
42
+ it("detects modified skills", async () => {
43
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "org/repo"\n`);
44
+ const skillDir = join(projectRoot, ".agents", "skills", "pdf");
45
+ await mkdir(skillDir, { recursive: true });
46
+ await writeFile(join(skillDir, "SKILL.md"), SKILL_MD("pdf"));
47
+ await writeLockfile(join(projectRoot, "agents.lock"), {
48
+ version: 1,
49
+ skills: {
50
+ pdf: {
51
+ source: "org/repo",
52
+ resolved_url: "https://github.com/org/repo.git",
53
+ resolved_path: "pdf",
54
+ commit: "a".repeat(40),
55
+ integrity: "sha256-stale",
56
+ },
57
+ },
58
+ });
59
+ const result = await runSync({ projectRoot });
60
+ const modifiedIssues = result.issues.filter((i) => i.type === "modified");
61
+ expect(modifiedIssues).toHaveLength(1);
62
+ });
63
+ it("reports no issues when everything is in sync", async () => {
64
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "org/repo"\n`);
65
+ const skillDir = join(projectRoot, ".agents", "skills", "pdf");
66
+ await mkdir(skillDir, { recursive: true });
67
+ await writeFile(join(skillDir, "SKILL.md"), SKILL_MD("pdf"));
68
+ const integrity = await hashDirectory(skillDir);
69
+ await writeLockfile(join(projectRoot, "agents.lock"), {
70
+ version: 1,
71
+ skills: {
72
+ pdf: {
73
+ source: "org/repo",
74
+ resolved_url: "https://github.com/org/repo.git",
75
+ resolved_path: "pdf",
76
+ commit: "a".repeat(40),
77
+ integrity,
78
+ },
79
+ },
80
+ });
81
+ const result = await runSync({ projectRoot });
82
+ expect(result.issues).toHaveLength(0);
83
+ });
84
+ it("repairs broken symlinks", async () => {
85
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[symlinks]\ntargets = [".claude"]\n`);
86
+ // Create .claude dir without the symlink
87
+ await mkdir(join(projectRoot, ".claude"), { recursive: true });
88
+ const result = await runSync({ projectRoot });
89
+ expect(result.symlinksRepaired).toBe(1);
90
+ });
91
+ it("regenerates gitignore", async () => {
92
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "org/repo"\n`);
93
+ const result = await runSync({ projectRoot });
94
+ expect(result.gitignoreUpdated).toBe(true);
95
+ const { readFile } = await import("node:fs/promises");
96
+ const gitignore = await readFile(join(projectRoot, ".agents", ".gitignore"), "utf-8");
97
+ expect(gitignore).toContain("/skills/pdf/");
98
+ });
99
+ });
100
+ //# sourceMappingURL=sync.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.test.js","sourceRoot":"","sources":["../../../src/cli/commands/sync.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare class UpdateError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export interface UpdateOptions {
5
+ projectRoot: string;
6
+ skillName?: string;
7
+ }
8
+ export interface UpdatedSkill {
9
+ name: string;
10
+ oldCommit: string;
11
+ newCommit: string;
12
+ }
13
+ export declare function runUpdate(opts: UpdateOptions): Promise<UpdatedSkill[]>;
14
+ export default function update(args: string[]): Promise<void>;
15
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/update.ts"],"names":[],"mappings":"AAaA,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA4E5E;AAED,wBAA8B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiClE"}
@@ -0,0 +1,113 @@
1
+ import { join } from "node:path";
2
+ import { parseArgs } from "node:util";
3
+ import chalk from "chalk";
4
+ import { loadConfig } from "../../config/loader.js";
5
+ import { loadLockfile } from "../../lockfile/loader.js";
6
+ import { isGitLocked } from "../../lockfile/schema.js";
7
+ import { resolveSkill } from "../../skills/resolver.js";
8
+ import { hashDirectory } from "../../utils/hash.js";
9
+ import { copyDir } from "../../utils/fs.js";
10
+ import { writeLockfile } from "../../lockfile/writer.js";
11
+ import { updateAgentsGitignore } from "../../gitignore/writer.js";
12
+ export class UpdateError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = "UpdateError";
16
+ }
17
+ }
18
+ export async function runUpdate(opts) {
19
+ const { projectRoot, skillName } = opts;
20
+ const configPath = join(projectRoot, "agents.toml");
21
+ const lockPath = join(projectRoot, "agents.lock");
22
+ const agentsDir = join(projectRoot, ".agents");
23
+ const skillsDir = join(agentsDir, "skills");
24
+ const config = await loadConfig(configPath);
25
+ const lockfile = await loadLockfile(lockPath);
26
+ if (!lockfile) {
27
+ throw new UpdateError("No agents.lock found. Run 'dotagents install' first.");
28
+ }
29
+ // Determine which skills to update
30
+ const toUpdate = skillName ? [skillName] : config.skills.map((s) => s.name);
31
+ const updated = [];
32
+ const newLock = { version: 1, skills: { ...lockfile.skills } };
33
+ for (const name of toUpdate) {
34
+ const dep = config.skills.find((s) => s.name === name);
35
+ if (!dep) {
36
+ throw new UpdateError(`Skill "${name}" not found in agents.toml.`);
37
+ }
38
+ const locked = lockfile.skills[name];
39
+ if (!locked) {
40
+ // Not in lockfile yet — skip, user should run install
41
+ continue;
42
+ }
43
+ // Skip non-git sources (local paths are always re-copied by install)
44
+ if (!isGitLocked(locked))
45
+ continue;
46
+ // Skip pinned commits (SHA refs are immutable)
47
+ if (dep.ref && /^[a-f0-9]{40}$/.test(dep.ref))
48
+ continue;
49
+ // Resolve fresh (no locked commit → forces a new fetch)
50
+ const resolved = await resolveSkill(name, dep, { projectRoot });
51
+ if (resolved.type !== "git")
52
+ continue;
53
+ const oldCommit = locked.commit;
54
+ const newCommit = resolved.commit;
55
+ if (oldCommit === newCommit)
56
+ continue;
57
+ // Copy updated skill
58
+ const destDir = join(skillsDir, name);
59
+ await copyDir(resolved.skillDir, destDir);
60
+ const integrity = await hashDirectory(destDir);
61
+ const lockEntry = {
62
+ source: dep.source,
63
+ resolved_url: resolved.resolvedUrl,
64
+ resolved_path: resolved.resolvedPath,
65
+ ...(resolved.resolvedRef ? { resolved_ref: resolved.resolvedRef } : {}),
66
+ commit: newCommit,
67
+ integrity,
68
+ };
69
+ newLock.skills[name] = lockEntry;
70
+ updated.push({
71
+ name,
72
+ oldCommit: oldCommit.slice(0, 8),
73
+ newCommit: newCommit.slice(0, 8),
74
+ });
75
+ }
76
+ // Write updated lockfile
77
+ if (updated.length > 0) {
78
+ await writeLockfile(lockPath, newLock);
79
+ await updateAgentsGitignore(agentsDir, config.gitignore, config.skills.map((s) => s.name));
80
+ }
81
+ return updated;
82
+ }
83
+ export default async function update(args) {
84
+ const { positionals } = parseArgs({
85
+ args,
86
+ allowPositionals: true,
87
+ strict: true,
88
+ });
89
+ const { resolve } = await import("node:path");
90
+ try {
91
+ const updated = await runUpdate({
92
+ projectRoot: resolve("."),
93
+ skillName: positionals[0],
94
+ });
95
+ if (updated.length === 0) {
96
+ console.log(chalk.dim("All skills are up to date."));
97
+ return;
98
+ }
99
+ for (const u of updated) {
100
+ console.log(chalk.green(` ${u.name}: ${chalk.dim(u.oldCommit)} → ${u.newCommit}`));
101
+ }
102
+ console.log(chalk.green(`Updated ${updated.length} skill(s).`));
103
+ }
104
+ catch (err) {
105
+ if (err instanceof UpdateError) {
106
+ console.error(chalk.red(err.message));
107
+ process.exitCode = 1;
108
+ return;
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/cli/commands/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=update.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/update.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { runUpdate, UpdateError } from "./update.js";
6
+ import { runInstall } from "./install.js";
7
+ import { exec } from "../../utils/exec.js";
8
+ import { loadLockfile } from "../../lockfile/loader.js";
9
+ const SKILL_MD = (name) => `---
10
+ name: ${name}
11
+ description: Test skill ${name}
12
+ ---
13
+ `;
14
+ describe("runUpdate", () => {
15
+ let tmpDir;
16
+ let stateDir;
17
+ let projectRoot;
18
+ let repoDir;
19
+ beforeEach(async () => {
20
+ tmpDir = await mkdtemp(join(tmpdir(), "dotagents-update-"));
21
+ stateDir = join(tmpDir, "state");
22
+ projectRoot = join(tmpDir, "project");
23
+ repoDir = join(tmpDir, "repo");
24
+ process.env["DOTAGENTS_STATE_DIR"] = stateDir;
25
+ await mkdir(join(projectRoot, ".agents", "skills"), { recursive: true });
26
+ // Create a local git repo
27
+ await mkdir(repoDir, { recursive: true });
28
+ await exec("git", ["init"], { cwd: repoDir });
29
+ await exec("git", ["config", "user.email", "test@test.com"], { cwd: repoDir });
30
+ await exec("git", ["config", "user.name", "Test"], { cwd: repoDir });
31
+ await mkdir(join(repoDir, "pdf"), { recursive: true });
32
+ await writeFile(join(repoDir, "pdf", "SKILL.md"), SKILL_MD("pdf"));
33
+ await exec("git", ["add", "."], { cwd: repoDir });
34
+ await exec("git", ["commit", "-m", "initial"], { cwd: repoDir });
35
+ });
36
+ afterEach(async () => {
37
+ delete process.env["DOTAGENTS_STATE_DIR"];
38
+ await rm(tmpDir, { recursive: true });
39
+ });
40
+ it("throws when no lockfile exists", async () => {
41
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "git:${repoDir}"\n`);
42
+ await expect(runUpdate({ projectRoot })).rejects.toThrow(UpdateError);
43
+ });
44
+ it("reports no updates when nothing changed", async () => {
45
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "git:${repoDir}"\n`);
46
+ await runInstall({ projectRoot });
47
+ // Update with no changes to repo — should be up to date
48
+ // Force cache refresh by setting TTL to 0
49
+ const updated = await runUpdate({ projectRoot });
50
+ expect(updated).toHaveLength(0);
51
+ });
52
+ it("detects and applies updates when repo changes", async () => {
53
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "git:${repoDir}"\n`);
54
+ await runInstall({ projectRoot });
55
+ const lockBefore = await loadLockfile(join(projectRoot, "agents.lock"));
56
+ const commitBefore = lockBefore.skills["pdf"].commit;
57
+ // Make a change in the repo
58
+ await writeFile(join(repoDir, "pdf", "extra.md"), "new content");
59
+ await exec("git", ["add", "."], { cwd: repoDir });
60
+ await exec("git", ["commit", "-m", "update pdf"], { cwd: repoDir });
61
+ // Delete cache to force re-clone (simulating TTL expiry)
62
+ await rm(stateDir, { recursive: true, force: true });
63
+ const updated = await runUpdate({ projectRoot });
64
+ expect(updated).toHaveLength(1);
65
+ expect(updated[0].name).toBe("pdf");
66
+ // Lockfile should have new commit
67
+ const lockAfter = await loadLockfile(join(projectRoot, "agents.lock"));
68
+ const commitAfter = lockAfter.skills["pdf"].commit;
69
+ expect(commitAfter).not.toBe(commitBefore);
70
+ });
71
+ it("updates only the specified skill", async () => {
72
+ // Add two skills
73
+ await mkdir(join(repoDir, "skills", "review"), { recursive: true });
74
+ await writeFile(join(repoDir, "skills", "review", "SKILL.md"), SKILL_MD("review"));
75
+ await exec("git", ["add", "."], { cwd: repoDir });
76
+ await exec("git", ["commit", "-m", "add review"], { cwd: repoDir });
77
+ await writeFile(join(projectRoot, "agents.toml"), `version = 1\n\n[[skills]]\nname = "pdf"\nsource = "git:${repoDir}"\n\n[[skills]]\nname = "review"\nsource = "git:${repoDir}"\n`);
78
+ await runInstall({ projectRoot });
79
+ // Change repo
80
+ await writeFile(join(repoDir, "pdf", "extra.md"), "changed");
81
+ await exec("git", ["add", "."], { cwd: repoDir });
82
+ await exec("git", ["commit", "-m", "update"], { cwd: repoDir });
83
+ await rm(stateDir, { recursive: true, force: true });
84
+ // Update only pdf
85
+ const updated = await runUpdate({ projectRoot, skillName: "pdf" });
86
+ // Both changed since they come from the same repo and re-resolved
87
+ expect(updated.some((u) => u.name === "pdf")).toBe(true);
88
+ });
89
+ });
90
+ //# sourceMappingURL=update.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.js","sourceRoot":"","sources":["../../../src/cli/commands/update.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ const COMMANDS = ["init", "install", "add", "remove", "update", "sync", "list"];
2
+ function printUsage() {
3
+ // eslint-disable-next-line no-console
4
+ console.log(`dotagents - package manager for .agents directories
5
+
6
+ Usage: dotagents <command> [options]
7
+
8
+ Commands:
9
+ init Initialize agents.toml and .agents/skills/
10
+ install Install dependencies from agents.toml
11
+ add Add a skill dependency
12
+ remove Remove a skill dependency
13
+ update Update skills to latest versions
14
+ sync Reconcile gitignore, symlinks, verify state
15
+ list Show installed skills
16
+
17
+ Options:
18
+ --help, -h Show this help message
19
+ --version Show version`);
20
+ }
21
+ async function main() {
22
+ const args = process.argv.slice(2);
23
+ const first = args[0];
24
+ // Handle top-level flags before any command
25
+ if (!first || first === "--help" || first === "-h") {
26
+ printUsage();
27
+ return;
28
+ }
29
+ if (first === "--version" || first === "-V") {
30
+ // eslint-disable-next-line no-console
31
+ console.log("0.1.0");
32
+ return;
33
+ }
34
+ if (!COMMANDS.includes(first)) {
35
+ console.error(`Unknown command: ${first}`);
36
+ printUsage();
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ // Pass remaining args (after command name) to the subcommand
41
+ const mod = await import(`./commands/${first}.js`);
42
+ await mod.default(args.slice(1));
43
+ }
44
+ main().catch((err) => {
45
+ console.error(err instanceof Error ? err.message : String(err));
46
+ process.exitCode = 1;
47
+ });
48
+ export {};
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAGzF,SAAS,UAAU;IACjB,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;2BAea,CAAC,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEtB,4CAA4C;IAC5C,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnD,UAAU,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IACD,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC5C,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAgB,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,KAAK,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;QAC3C,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,6DAA6D;IAC7D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC;IACnD,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { loadConfig, ConfigError } from "./loader.js";
2
+ export { addSkillToConfig, removeSkillFromConfig, generateDefaultConfig, } from "./writer.js";
3
+ export { agentsConfigSchema } from "./schema.js";
4
+ export type { AgentsConfig, SkillDependency, SymlinksConfig, ProjectConfig, SkillSource, } from "./schema.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { loadConfig, ConfigError } from "./loader.js";
2
+ export { addSkillToConfig, removeSkillFromConfig, generateDefaultConfig, } from "./writer.js";
3
+ export { agentsConfigSchema } from "./schema.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { AgentsConfig } from "./schema.js";
2
+ export declare class ConfigError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare function loadConfig(filePath: string): Promise<AgentsConfig>;
6
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyBxE"}
@@ -0,0 +1,35 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { parse as parseTOML } from "smol-toml";
3
+ import { agentsConfigSchema } from "./schema.js";
4
+ export class ConfigError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "ConfigError";
8
+ }
9
+ }
10
+ export async function loadConfig(filePath) {
11
+ let raw;
12
+ try {
13
+ raw = await readFile(filePath, "utf-8");
14
+ }
15
+ catch {
16
+ throw new ConfigError(`Config file not found: ${filePath}`);
17
+ }
18
+ let parsed;
19
+ try {
20
+ parsed = parseTOML(raw);
21
+ }
22
+ catch (err) {
23
+ const message = err instanceof Error ? err.message : String(err);
24
+ throw new ConfigError(`Invalid TOML in ${filePath}: ${message}`);
25
+ }
26
+ const result = agentsConfigSchema.safeParse(parsed);
27
+ if (!result.success) {
28
+ const issues = result.error.issues
29
+ .map((i) => ` - ${i.path.join(".")}: ${i.message}`)
30
+ .join("\n");
31
+ throw new ConfigError(`Invalid config in ${filePath}:\n${issues}`);
32
+ }
33
+ return result.data;
34
+ }
35
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,WAAW,CAAC,mBAAmB,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aACnD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,qBAAqB,QAAQ,MAAM,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=loader.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.test.d.ts","sourceRoot":"","sources":["../../src/config/loader.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtemp, writeFile, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { loadConfig, ConfigError } from "./loader.js";
6
+ describe("loadConfig", () => {
7
+ let dir;
8
+ beforeEach(async () => {
9
+ dir = await mkdtemp(join(tmpdir(), "dotagents-test-"));
10
+ });
11
+ afterEach(async () => {
12
+ await rm(dir, { recursive: true });
13
+ });
14
+ it("loads a valid config", async () => {
15
+ const configPath = join(dir, "agents.toml");
16
+ await writeFile(configPath, `version = 1
17
+
18
+ [[skills]]
19
+ name = "pdf"
20
+ source = "anthropics/skills"
21
+ ref = "v1.0.0"
22
+ `);
23
+ const config = await loadConfig(configPath);
24
+ expect(config.version).toBe(1);
25
+ const pdf = config.skills.find((s) => s.name === "pdf");
26
+ expect(pdf?.source).toBe("anthropics/skills");
27
+ expect(pdf?.ref).toBe("v1.0.0");
28
+ });
29
+ it("loads a minimal config", async () => {
30
+ const configPath = join(dir, "agents.toml");
31
+ await writeFile(configPath, "version = 1\n");
32
+ const config = await loadConfig(configPath);
33
+ expect(config.version).toBe(1);
34
+ expect(config.skills).toEqual([]);
35
+ });
36
+ it("throws ConfigError for missing file", async () => {
37
+ await expect(loadConfig(join(dir, "nope.toml"))).rejects.toThrow(ConfigError);
38
+ });
39
+ it("throws ConfigError for invalid TOML", async () => {
40
+ const configPath = join(dir, "agents.toml");
41
+ await writeFile(configPath, "this is not valid toml {{{}");
42
+ await expect(loadConfig(configPath)).rejects.toThrow(ConfigError);
43
+ });
44
+ it("throws ConfigError for wrong schema", async () => {
45
+ const configPath = join(dir, "agents.toml");
46
+ await writeFile(configPath, 'version = 99\nfoo = "bar"\n');
47
+ await expect(loadConfig(configPath)).rejects.toThrow(ConfigError);
48
+ });
49
+ it("parses symlinks config", async () => {
50
+ const configPath = join(dir, "agents.toml");
51
+ await writeFile(configPath, `version = 1
52
+
53
+ [symlinks]
54
+ targets = [".claude"]
55
+ `);
56
+ const config = await loadConfig(configPath);
57
+ expect(config.symlinks?.targets).toEqual([".claude"]);
58
+ });
59
+ });
60
+ //# sourceMappingURL=loader.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.test.js","sourceRoot":"","sources":["../../src/config/loader.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { z } from "zod/v4";
2
+ declare const skillSourceSchema: z.ZodString;
3
+ export type SkillSource = z.infer<typeof skillSourceSchema>;
4
+ declare const skillDependencySchema: z.ZodObject<{
5
+ name: z.ZodString;
6
+ source: z.ZodString;
7
+ ref: z.ZodOptional<z.ZodString>;
8
+ path: z.ZodOptional<z.ZodString>;
9
+ }, z.core.$strip>;
10
+ export type SkillDependency = z.infer<typeof skillDependencySchema>;
11
+ declare const symlinksConfigSchema: z.ZodObject<{
12
+ targets: z.ZodDefault<z.ZodArray<z.ZodString>>;
13
+ }, z.core.$strip>;
14
+ export type SymlinksConfig = z.infer<typeof symlinksConfigSchema>;
15
+ declare const projectConfigSchema: z.ZodObject<{
16
+ name: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>;
18
+ export type ProjectConfig = z.infer<typeof projectConfigSchema>;
19
+ export declare const agentsConfigSchema: z.ZodObject<{
20
+ version: z.ZodLiteral<1>;
21
+ gitignore: z.ZodDefault<z.ZodBoolean>;
22
+ project: z.ZodOptional<z.ZodObject<{
23
+ name: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>>;
25
+ symlinks: z.ZodOptional<z.ZodObject<{
26
+ targets: z.ZodDefault<z.ZodArray<z.ZodString>>;
27
+ }, z.core.$strip>>;
28
+ skills: z.ZodDefault<z.ZodArray<z.ZodObject<{
29
+ name: z.ZodString;
30
+ source: z.ZodString;
31
+ ref: z.ZodOptional<z.ZodString>;
32
+ path: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strip>>>;
34
+ }, z.core.$strip>;
35
+ export type AgentsConfig = z.infer<typeof agentsConfigSchema>;
36
+ export {};
37
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAW3B,QAAA,MAAM,iBAAiB,aAYtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAQ5D,QAAA,MAAM,qBAAqB;;;;;iBAKzB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,QAAA,MAAM,oBAAoB;;iBAExB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,QAAA,MAAM,mBAAmB;;iBAEvB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;iBAM7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}