squads 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 (85) hide show
  1. package/dist/commands/add.d.ts +3 -0
  2. package/dist/commands/add.d.ts.map +1 -0
  3. package/dist/commands/add.js +98 -0
  4. package/dist/commands/add.js.map +1 -0
  5. package/dist/commands/check.d.ts +3 -0
  6. package/dist/commands/check.d.ts.map +1 -0
  7. package/dist/commands/check.js +127 -0
  8. package/dist/commands/check.js.map +1 -0
  9. package/dist/commands/find.d.ts +3 -0
  10. package/dist/commands/find.d.ts.map +1 -0
  11. package/dist/commands/find.js +84 -0
  12. package/dist/commands/find.js.map +1 -0
  13. package/dist/commands/init.d.ts +3 -0
  14. package/dist/commands/init.d.ts.map +1 -0
  15. package/dist/commands/init.js +281 -0
  16. package/dist/commands/init.js.map +1 -0
  17. package/dist/commands/list.d.ts +3 -0
  18. package/dist/commands/list.d.ts.map +1 -0
  19. package/dist/commands/list.js +49 -0
  20. package/dist/commands/list.js.map +1 -0
  21. package/dist/commands/login.d.ts +3 -0
  22. package/dist/commands/login.d.ts.map +1 -0
  23. package/dist/commands/login.js +129 -0
  24. package/dist/commands/login.js.map +1 -0
  25. package/dist/commands/publish.d.ts +3 -0
  26. package/dist/commands/publish.d.ts.map +1 -0
  27. package/dist/commands/publish.js +118 -0
  28. package/dist/commands/publish.js.map +1 -0
  29. package/dist/commands/remove.d.ts +3 -0
  30. package/dist/commands/remove.d.ts.map +1 -0
  31. package/dist/commands/remove.js +67 -0
  32. package/dist/commands/remove.js.map +1 -0
  33. package/dist/commands/update.d.ts +3 -0
  34. package/dist/commands/update.d.ts.map +1 -0
  35. package/dist/commands/update.js +58 -0
  36. package/dist/commands/update.js.map +1 -0
  37. package/dist/commands/validate.d.ts +3 -0
  38. package/dist/commands/validate.d.ts.map +1 -0
  39. package/dist/commands/validate.js +116 -0
  40. package/dist/commands/validate.js.map +1 -0
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +48 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/lib/agents.d.ts +26 -0
  46. package/dist/lib/agents.d.ts.map +1 -0
  47. package/dist/lib/agents.js +87 -0
  48. package/dist/lib/agents.js.map +1 -0
  49. package/dist/lib/config.d.ts +9 -0
  50. package/dist/lib/config.d.ts.map +1 -0
  51. package/dist/lib/config.js +44 -0
  52. package/dist/lib/config.js.map +1 -0
  53. package/dist/lib/installer.d.ts +29 -0
  54. package/dist/lib/installer.d.ts.map +1 -0
  55. package/dist/lib/installer.js +124 -0
  56. package/dist/lib/installer.js.map +1 -0
  57. package/dist/lib/lock-file.d.ts +11 -0
  58. package/dist/lib/lock-file.d.ts.map +1 -0
  59. package/dist/lib/lock-file.js +72 -0
  60. package/dist/lib/lock-file.js.map +1 -0
  61. package/dist/lib/sources/github.d.ts +26 -0
  62. package/dist/lib/sources/github.d.ts.map +1 -0
  63. package/dist/lib/sources/github.js +182 -0
  64. package/dist/lib/sources/github.js.map +1 -0
  65. package/dist/lib/sources/local.d.ts +15 -0
  66. package/dist/lib/sources/local.d.ts.map +1 -0
  67. package/dist/lib/sources/local.js +52 -0
  68. package/dist/lib/sources/local.js.map +1 -0
  69. package/dist/lib/sources/registry.d.ts +21 -0
  70. package/dist/lib/sources/registry.d.ts.map +1 -0
  71. package/dist/lib/sources/registry.js +63 -0
  72. package/dist/lib/sources/registry.js.map +1 -0
  73. package/dist/lib/telemetry.d.ts +6 -0
  74. package/dist/lib/telemetry.d.ts.map +1 -0
  75. package/dist/lib/telemetry.js +68 -0
  76. package/dist/lib/telemetry.js.map +1 -0
  77. package/dist/lib/validator.d.ts +29 -0
  78. package/dist/lib/validator.d.ts.map +1 -0
  79. package/dist/lib/validator.js +107 -0
  80. package/dist/lib/validator.js.map +1 -0
  81. package/dist/types.d.ts +86 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +2 -0
  84. package/dist/types.js.map +1 -0
  85. package/package.json +47 -0
@@ -0,0 +1,182 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join, dirname } from "node:path";
3
+ const GITHUB_API = "https://api.github.com";
4
+ /**
5
+ * Parse a GitHub source string into a SquadSource object.
6
+ *
7
+ * Supported formats:
8
+ * owner/repo
9
+ * owner/repo/squad-name
10
+ * owner/repo#branch
11
+ * owner/repo/squad-name#branch
12
+ * https://github.com/owner/repo
13
+ * https://github.com/owner/repo/tree/branch/path
14
+ */
15
+ export function parseGitHubSource(input) {
16
+ // Handle full GitHub URLs
17
+ const urlMatch = input.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+)(?:\/(.+))?)?$/);
18
+ if (urlMatch) {
19
+ return {
20
+ type: "github",
21
+ owner: urlMatch[1],
22
+ repo: urlMatch[2],
23
+ branch: urlMatch[3] || undefined,
24
+ squad: urlMatch[4] || undefined,
25
+ url: input,
26
+ };
27
+ }
28
+ // Handle owner/repo[/squad]#branch format
29
+ let branch;
30
+ let rest = input;
31
+ const hashIdx = input.indexOf("#");
32
+ if (hashIdx !== -1) {
33
+ branch = input.slice(hashIdx + 1);
34
+ rest = input.slice(0, hashIdx);
35
+ }
36
+ const parts = rest.split("/");
37
+ if (parts.length < 2) {
38
+ throw new Error(`Invalid GitHub source: "${input}". Expected format: owner/repo or owner/repo/squad-name`);
39
+ }
40
+ return {
41
+ type: "github",
42
+ owner: parts[0],
43
+ repo: parts[1],
44
+ squad: parts.length > 2 ? parts.slice(2).join("/") : undefined,
45
+ branch,
46
+ };
47
+ }
48
+ /**
49
+ * Fetch the repository tree from GitHub API.
50
+ */
51
+ async function fetchRepoTree(owner, repo, branch) {
52
+ // Get default branch if not specified
53
+ if (!branch) {
54
+ const repoUrl = `${GITHUB_API}/repos/${owner}/${repo}`;
55
+ const repoRes = await fetch(repoUrl, {
56
+ headers: { Accept: "application/vnd.github.v3+json" },
57
+ });
58
+ if (!repoRes.ok) {
59
+ if (repoRes.status === 404) {
60
+ throw new Error(`Repository not found: ${owner}/${repo}`);
61
+ }
62
+ throw new Error(`GitHub API error: ${repoRes.status} ${repoRes.statusText}`);
63
+ }
64
+ const repoData = (await repoRes.json());
65
+ branch = repoData.default_branch;
66
+ }
67
+ const treeUrl = `${GITHUB_API}/repos/${owner}/${repo}/git/trees/${branch}?recursive=1`;
68
+ const treeRes = await fetch(treeUrl, {
69
+ headers: { Accept: "application/vnd.github.v3+json" },
70
+ });
71
+ if (!treeRes.ok) {
72
+ if (treeRes.status === 404) {
73
+ throw new Error(`Branch "${branch}" not found in ${owner}/${repo}`);
74
+ }
75
+ throw new Error(`GitHub API error: ${treeRes.status} ${treeRes.statusText}`);
76
+ }
77
+ const data = (await treeRes.json());
78
+ return { tree: data.tree, sha: data.sha };
79
+ }
80
+ /**
81
+ * Download a single file from GitHub.
82
+ */
83
+ async function downloadFile(owner, repo, path, branch) {
84
+ const ref = branch ? `?ref=${branch}` : "";
85
+ const url = `${GITHUB_API}/repos/${owner}/${repo}/contents/${path}${ref}`;
86
+ const res = await fetch(url, {
87
+ headers: { Accept: "application/vnd.github.v3.raw" },
88
+ });
89
+ if (!res.ok) {
90
+ throw new Error(`Failed to download ${path}: ${res.status}`);
91
+ }
92
+ return res.text();
93
+ }
94
+ /**
95
+ * Find squad directories in a repository tree.
96
+ * A squad is identified by the presence of squad.yaml.
97
+ */
98
+ export function findSquadsInTree(tree) {
99
+ const squadPaths = [];
100
+ for (const entry of tree) {
101
+ if (entry.type === "blob" && entry.path.endsWith("/squad.yaml")) {
102
+ squadPaths.push(dirname(entry.path));
103
+ }
104
+ // Also check root-level squad.yaml
105
+ if (entry.type === "blob" && entry.path === "squad.yaml") {
106
+ squadPaths.push(".");
107
+ }
108
+ }
109
+ return squadPaths;
110
+ }
111
+ /**
112
+ * Download a squad from GitHub to a local directory.
113
+ */
114
+ export async function downloadSquad(source, targetDir) {
115
+ const { owner, repo, squad, branch } = source;
116
+ if (!owner || !repo) {
117
+ throw new Error("GitHub source requires owner and repo");
118
+ }
119
+ const { tree, sha } = await fetchRepoTree(owner, repo, branch);
120
+ // Determine which files belong to the squad
121
+ let squadPrefix = "";
122
+ if (squad) {
123
+ // User specified a specific squad path
124
+ squadPrefix = squad.endsWith("/") ? squad : `${squad}/`;
125
+ // Verify squad.yaml exists at that path
126
+ const hasManifest = tree.some((e) => e.type === "blob" &&
127
+ (e.path === `${squadPrefix}squad.yaml` ||
128
+ (squad === "." && e.path === "squad.yaml")));
129
+ if (!hasManifest) {
130
+ throw new Error(`No squad.yaml found at "${squad}" in ${owner}/${repo}`);
131
+ }
132
+ }
133
+ else {
134
+ // Auto-detect squad location
135
+ const squads = findSquadsInTree(tree);
136
+ if (squads.length === 0) {
137
+ throw new Error(`No squad found in ${owner}/${repo}. Make sure the repository contains a squad.yaml file.`);
138
+ }
139
+ if (squads.length === 1) {
140
+ squadPrefix = squads[0] === "." ? "" : `${squads[0]}/`;
141
+ }
142
+ else {
143
+ throw new Error(`Multiple squads found in ${owner}/${repo}: ${squads.join(", ")}. ` +
144
+ `Use --skill to specify which one to install.`);
145
+ }
146
+ }
147
+ // Filter tree entries to only those under the squad prefix
148
+ const squadFiles = tree.filter((e) => e.type === "blob" &&
149
+ (squadPrefix === ""
150
+ ? true
151
+ : e.path.startsWith(squadPrefix)));
152
+ if (squadFiles.length === 0) {
153
+ throw new Error(`No files found for squad at "${squadPrefix}"`);
154
+ }
155
+ // Download each file
156
+ await mkdir(targetDir, { recursive: true });
157
+ for (const entry of squadFiles) {
158
+ const relativePath = squadPrefix
159
+ ? entry.path.slice(squadPrefix.length)
160
+ : entry.path;
161
+ // Skip hidden files and directories not part of the squad
162
+ if (relativePath.startsWith(".") && !relativePath.startsWith(".claude")) {
163
+ continue;
164
+ }
165
+ const content = await downloadFile(owner, repo, entry.path, branch);
166
+ const destPath = join(targetDir, relativePath);
167
+ await mkdir(dirname(destPath), { recursive: true });
168
+ await writeFile(destPath, content, "utf-8");
169
+ }
170
+ return { sha };
171
+ }
172
+ export function formatGitHubSource(source) {
173
+ let result = `${source.owner}/${source.repo}`;
174
+ if (source.squad) {
175
+ result += `/${source.squad}`;
176
+ }
177
+ if (source.branch) {
178
+ result += `#${source.branch}`;
179
+ }
180
+ return result;
181
+ }
182
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/lib/sources/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAC1B,sFAAsF,CACvF,CAAC;IACF,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;YAClB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YACjB,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,SAAS;YAChC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,SAAS;YAC/B,GAAG,EAAE,KAAK;SACX,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,IAAI,MAA0B,CAAC;IAC/B,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;QACnB,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QAClC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,2BAA2B,KAAK,yDAAyD,CAC1F,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACf,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QACd,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;QAC9D,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAC1B,KAAa,EACb,IAAY,EACZ,MAAe;IAEf,sCAAsC;IACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,GAAG,UAAU,UAAU,KAAK,IAAI,IAAI,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE;YACnC,OAAO,EAAE,EAAE,MAAM,EAAE,gCAAgC,EAAE;SACtD,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,MAAM,IAAI,KAAK,CACb,qBAAqB,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,EAAE,CAC5D,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAA+B,CAAC;QACtE,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC;IACnC,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,UAAU,UAAU,KAAK,IAAI,IAAI,cAAc,MAAM,cAAc,CAAC;IACvF,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE;QACnC,OAAO,EAAE,EAAE,MAAM,EAAE,gCAAgC,EAAE;KACtD,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,WAAW,MAAM,kBAAkB,KAAK,IAAI,IAAI,EAAE,CACnD,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CACb,qBAAqB,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,EAAE,CAC5D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAuB,CAAC;IAC1D,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,YAAY,CACzB,KAAa,EACb,IAAY,EACZ,IAAY,EACZ,MAAe;IAEf,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,MAAM,GAAG,GAAG,GAAG,UAAU,UAAU,KAAK,IAAI,IAAI,aAAa,IAAI,GAAG,GAAG,EAAE,CAAC;IAC1E,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE;KACrD,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAuB;IACtD,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAChE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,mCAAmC;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACzD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAmB,EACnB,SAAiB;IAEjB,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC9C,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAE/D,4CAA4C;IAC5C,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,KAAK,EAAE,CAAC;QACV,uCAAuC;QACvC,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;QAExD,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,KAAK,MAAM;YACjB,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,WAAW,YAAY;gBACpC,CAAC,KAAK,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAChD,CAAC;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,2BAA2B,KAAK,QAAQ,KAAK,IAAI,IAAI,EAAE,CACxD,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,6BAA6B;QAC7B,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,qBAAqB,KAAK,IAAI,IAAI,wDAAwD,CAC3F,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,4BAA4B,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACjE,8CAA8C,CACjD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,KAAK,MAAM;QACjB,CAAC,WAAW,KAAK,EAAE;YACjB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CACtC,CAAC;IAEF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,gCAAgC,WAAW,GAAG,CAAC,CAAC;IAClE,CAAC;IAED,qBAAqB;IACrB,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,WAAW;YAC9B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QAEf,0DAA0D;QAC1D,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACxE,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC/C,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,IAAI,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { SquadSource } from "../../types.js";
2
+ /**
3
+ * Parse a local path source.
4
+ */
5
+ export declare function parseLocalSource(input: string): SquadSource;
6
+ /**
7
+ * Check if a source string looks like a local path.
8
+ */
9
+ export declare function isLocalPath(input: string): boolean;
10
+ /**
11
+ * Copy a squad from a local path to the target directory.
12
+ * Validates the source directory before copying.
13
+ */
14
+ export declare function copyLocalSquad(source: SquadSource, targetDir: string): Promise<void>;
15
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../src/lib/sources/local.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAK3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
@@ -0,0 +1,52 @@
1
+ import { cp, stat } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { validateSquadDirectory } from "../validator.js";
4
+ /**
5
+ * Parse a local path source.
6
+ */
7
+ export function parseLocalSource(input) {
8
+ return {
9
+ type: "local",
10
+ path: resolve(input),
11
+ };
12
+ }
13
+ /**
14
+ * Check if a source string looks like a local path.
15
+ */
16
+ export function isLocalPath(input) {
17
+ return (input.startsWith("/") ||
18
+ input.startsWith("./") ||
19
+ input.startsWith("../") ||
20
+ input.startsWith("~"));
21
+ }
22
+ /**
23
+ * Copy a squad from a local path to the target directory.
24
+ * Validates the source directory before copying.
25
+ */
26
+ export async function copyLocalSquad(source, targetDir) {
27
+ const sourcePath = source.path;
28
+ if (!sourcePath) {
29
+ throw new Error("Local source requires a path");
30
+ }
31
+ // Verify source exists and is a directory
32
+ try {
33
+ const pathStat = await stat(sourcePath);
34
+ if (!pathStat.isDirectory()) {
35
+ throw new Error(`Source path is not a directory: ${sourcePath}`);
36
+ }
37
+ }
38
+ catch (err) {
39
+ if (err.code === "ENOENT") {
40
+ throw new Error(`Source path does not exist: ${sourcePath}`);
41
+ }
42
+ throw err;
43
+ }
44
+ // Validate source squad
45
+ const validation = await validateSquadDirectory(sourcePath);
46
+ if (!validation.valid) {
47
+ throw new Error(`Invalid squad at ${sourcePath}:\n - ${validation.errors.join("\n - ")}`);
48
+ }
49
+ // Copy files
50
+ await cp(sourcePath, targetDir, { recursive: true });
51
+ }
52
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/lib/sources/local.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;KACrB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,CACL,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QACrB,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QACtB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QACvB,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CACtB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAmB,EACnB,SAAiB;IAEjB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;IAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IAED,0CAA0C;IAC1C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,mCAAmC,UAAU,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,wBAAwB;IACxB,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,oBAAoB,UAAU,UAAU,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAC3E,CAAC;IACJ,CAAC;IAED,aAAa;IACb,MAAM,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { SquadSource, SearchResult } from "../../types.js";
2
+ /**
3
+ * Check if a source string looks like a registry slug (simple name, no slashes or dots).
4
+ */
5
+ export declare function isRegistrySlug(input: string): boolean;
6
+ /**
7
+ * Resolve a registry slug to a SquadSource by fetching metadata from squads.sh API.
8
+ */
9
+ export declare function resolveRegistrySource(slug: string): Promise<SquadSource>;
10
+ /**
11
+ * Download a squad from the registry (resolves to GitHub source, then downloads).
12
+ */
13
+ export declare function downloadRegistrySquad(slug: string, targetDir: string): Promise<{
14
+ sha: string;
15
+ source: SquadSource;
16
+ }>;
17
+ /**
18
+ * Search the registry for squads matching a query.
19
+ */
20
+ export declare function searchRegistry(query: string, limit?: number): Promise<SearchResult[]>;
21
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/sources/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGhE;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,WAAW,CAAC,CA+BtB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAI/C;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyBzB"}
@@ -0,0 +1,63 @@
1
+ import { getRegistryUrl } from "../config.js";
2
+ import { parseGitHubSource, downloadSquad } from "./github.js";
3
+ /**
4
+ * Check if a source string looks like a registry slug (simple name, no slashes or dots).
5
+ */
6
+ export function isRegistrySlug(input) {
7
+ return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(input);
8
+ }
9
+ /**
10
+ * Resolve a registry slug to a SquadSource by fetching metadata from squads.sh API.
11
+ */
12
+ export async function resolveRegistrySource(slug) {
13
+ const registryUrl = await getRegistryUrl();
14
+ const url = `${registryUrl}/api/squads?slug=${encodeURIComponent(slug)}`;
15
+ const res = await fetch(url, {
16
+ headers: { Accept: "application/json" },
17
+ });
18
+ if (!res.ok) {
19
+ if (res.status === 404) {
20
+ throw new Error(`Squad "${slug}" not found on squads.sh. Run "squads find ${slug}" to search.`);
21
+ }
22
+ throw new Error(`Registry API error: ${res.status} ${res.statusText}`);
23
+ }
24
+ const data = (await res.json());
25
+ if (!data.repo_url) {
26
+ throw new Error(`Squad "${slug}" has no repository URL configured.`);
27
+ }
28
+ // Parse the repo URL into a GitHub source
29
+ const source = parseGitHubSource(data.repo_url);
30
+ source.type = "registry";
31
+ return source;
32
+ }
33
+ /**
34
+ * Download a squad from the registry (resolves to GitHub source, then downloads).
35
+ */
36
+ export async function downloadRegistrySquad(slug, targetDir) {
37
+ const source = await resolveRegistrySource(slug);
38
+ const { sha } = await downloadSquad(source, targetDir);
39
+ return { sha, source };
40
+ }
41
+ /**
42
+ * Search the registry for squads matching a query.
43
+ */
44
+ export async function searchRegistry(query, limit = 20) {
45
+ const registryUrl = await getRegistryUrl();
46
+ const url = `${registryUrl}/api/search?q=${encodeURIComponent(query)}&limit=${limit}`;
47
+ const res = await fetch(url, {
48
+ headers: { Accept: "application/json" },
49
+ });
50
+ if (!res.ok) {
51
+ throw new Error(`Registry search failed: ${res.status} ${res.statusText}`);
52
+ }
53
+ const data = (await res.json());
54
+ // Handle both array and wrapped response formats
55
+ if (Array.isArray(data)) {
56
+ return data;
57
+ }
58
+ if (data && "results" in data) {
59
+ return data.results;
60
+ }
61
+ return [];
62
+ }
63
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/sources/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,iCAAiC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAY;IAEZ,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAC3C,MAAM,GAAG,GAAG,GAAG,WAAW,oBAAoB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAEzE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,8CAA8C,IAAI,cAAc,CAC/E,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CACb,uBAAuB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CACtD,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAiB,CAAC;IAEhD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,qCAAqC,CACpD,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAY,EACZ,SAAiB;IAEjB,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,QAAgB,EAAE;IAElB,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAC3C,MAAM,GAAG,GAAG,GAAG,WAAW,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,CAAC;IAEtF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,2BAA2B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAC1D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAiD,CAAC;IAEhF,iDAAiD;IACjD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { TelemetryEvent } from "../types.js";
2
+ export declare function trackEvent(event: TelemetryEvent): Promise<void>;
3
+ export declare function trackInstall(squadSlug: string, sourceType: string, isGlobal: boolean): void;
4
+ export declare function trackRemove(squadSlug: string, sourceType: string): void;
5
+ export declare function trackFind(query: string): void;
6
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/lib/telemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgBlD,wBAAsB,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BrE;AAED,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,OAAO,GAChB,IAAI,CAQN;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAQvE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ7C"}
@@ -0,0 +1,68 @@
1
+ import { readConfig } from "./config.js";
2
+ function isCI() {
3
+ return !!(process.env["CI"] ||
4
+ process.env["GITHUB_ACTIONS"] ||
5
+ process.env["GITLAB_CI"] ||
6
+ process.env["CIRCLECI"] ||
7
+ process.env["TRAVIS"] ||
8
+ process.env["JENKINS_URL"] ||
9
+ process.env["BUILDKITE"] ||
10
+ process.env["TF_BUILD"] ||
11
+ process.env["CODEBUILD_BUILD_ID"]);
12
+ }
13
+ export async function trackEvent(event) {
14
+ try {
15
+ const config = await readConfig();
16
+ if (config.telemetryOptOut)
17
+ return;
18
+ const url = `${config.registry}/api/telemetry`;
19
+ const payload = {
20
+ ...event,
21
+ is_ci: isCI(),
22
+ cli_version: "0.1.0",
23
+ node_version: process.version,
24
+ platform: process.platform,
25
+ timestamp: new Date().toISOString(),
26
+ };
27
+ // Fire-and-forget: do not await, do not throw
28
+ fetch(url, {
29
+ method: "POST",
30
+ headers: { "Content-Type": "application/json" },
31
+ body: JSON.stringify(payload),
32
+ signal: AbortSignal.timeout(5000),
33
+ }).catch(() => {
34
+ // Silently ignore telemetry failures
35
+ });
36
+ }
37
+ catch {
38
+ // Silently ignore all telemetry errors
39
+ }
40
+ }
41
+ export function trackInstall(squadSlug, sourceType, isGlobal) {
42
+ void trackEvent({
43
+ event: "install",
44
+ squad_slug: squadSlug,
45
+ source_type: sourceType,
46
+ is_global: isGlobal,
47
+ is_ci: isCI(),
48
+ });
49
+ }
50
+ export function trackRemove(squadSlug, sourceType) {
51
+ void trackEvent({
52
+ event: "remove",
53
+ squad_slug: squadSlug,
54
+ source_type: sourceType,
55
+ is_global: false,
56
+ is_ci: isCI(),
57
+ });
58
+ }
59
+ export function trackFind(query) {
60
+ void trackEvent({
61
+ event: "find",
62
+ squad_slug: query,
63
+ source_type: "registry",
64
+ is_global: false,
65
+ is_ci: isCI(),
66
+ });
67
+ }
68
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/lib/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,SAAS,IAAI;IACX,OAAO,CAAC,CAAC,CACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAqB;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,eAAe;YAAE,OAAO;QAEnC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,QAAQ,gBAAgB,CAAC;QAE/C,MAAM,OAAO,GAAG;YACd,GAAG,KAAK;YACR,KAAK,EAAE,IAAI,EAAE;YACb,WAAW,EAAE,OAAO;YACpB,YAAY,EAAE,OAAO,CAAC,OAAO;YAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,8CAA8C;QAC9C,KAAK,CAAC,GAAG,EAAE;YACT,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACZ,qCAAqC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,SAAiB,EACjB,UAAkB,EAClB,QAAiB;IAEjB,KAAK,UAAU,CAAC;QACd,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,QAAQ;QACnB,KAAK,EAAE,IAAI,EAAE;KACd,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,UAAkB;IAC/D,KAAK,UAAU,CAAC;QACd,KAAK,EAAE,QAAQ;QACf,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,IAAI,EAAE;KACd,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,KAAK,UAAU,CAAC;QACd,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,IAAI,EAAE;KACd,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { ValidationReport } from "@squads-sh/validator";
2
+ import type { SquadManifest } from "../types.js";
3
+ /** Re-export the deep validation report type */
4
+ export type { ValidationReport as DeepValidationReport };
5
+ /**
6
+ * Backward-compatible validation result.
7
+ * Kept for existing consumers (e.g. publish command).
8
+ */
9
+ export interface ValidationResult {
10
+ valid: boolean;
11
+ errors: string[];
12
+ warnings: string[];
13
+ manifest?: SquadManifest;
14
+ }
15
+ /**
16
+ * Validate a squad directory using the deep validator,
17
+ * then map the result back to the legacy ValidationResult format.
18
+ */
19
+ export declare function validateSquadDirectory(dirPath: string): Promise<ValidationResult>;
20
+ /**
21
+ * Deep validation — returns the full ValidationReport with scores,
22
+ * categories, and per-finding details.
23
+ */
24
+ export declare function validateSquadDeep(dirPath: string): Promise<ValidationReport>;
25
+ /**
26
+ * List agent .md files in the squad's agents/ directory.
27
+ */
28
+ export declare function listAgentFiles(dirPath: string): Promise<string[]>;
29
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/lib/validator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,gDAAgD;AAChD,YAAY,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,CAAC,CA2B3B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQvE"}
@@ -0,0 +1,107 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { validateSquad } from "@squads-sh/validator";
4
+ import { buildFileTreeFromFS } from "@squads-sh/validator/adapters/filesystem";
5
+ /**
6
+ * Validate a squad directory using the deep validator,
7
+ * then map the result back to the legacy ValidationResult format.
8
+ */
9
+ export async function validateSquadDirectory(dirPath) {
10
+ const report = await validateSquadDeep(dirPath);
11
+ const errors = report.findings
12
+ .filter((f) => f.severity === "error")
13
+ .map((f) => (f.file ? `[${f.file}] ${f.message}` : f.message));
14
+ const warnings = report.findings
15
+ .filter((f) => f.severity === "warning")
16
+ .map((f) => (f.file ? `[${f.file}] ${f.message}` : f.message));
17
+ // Try to extract a manifest from the file tree for backward compat
18
+ let manifest;
19
+ if (report.summary.totalErrors === 0) {
20
+ const fileTree = await buildFileTreeFromFS(dirPath);
21
+ const yamlContent = fileTree.get("squad.yaml");
22
+ if (yamlContent) {
23
+ manifest = parseManifestFromYaml(yamlContent);
24
+ }
25
+ }
26
+ return {
27
+ valid: report.summary.totalErrors === 0,
28
+ errors,
29
+ warnings,
30
+ manifest,
31
+ };
32
+ }
33
+ /**
34
+ * Deep validation — returns the full ValidationReport with scores,
35
+ * categories, and per-finding details.
36
+ */
37
+ export async function validateSquadDeep(dirPath) {
38
+ const fileTree = await buildFileTreeFromFS(dirPath);
39
+ return validateSquad(fileTree);
40
+ }
41
+ /**
42
+ * List agent .md files in the squad's agents/ directory.
43
+ */
44
+ export async function listAgentFiles(dirPath) {
45
+ const agentsDir = join(dirPath, "agents");
46
+ try {
47
+ const files = await readdir(agentsDir);
48
+ return files.filter((f) => f.endsWith(".md"));
49
+ }
50
+ catch {
51
+ return [];
52
+ }
53
+ }
54
+ /**
55
+ * Lightweight YAML key-value extraction for building SquadManifest.
56
+ * Not a full YAML parser — only extracts top-level and one-level-nested scalars.
57
+ */
58
+ function parseManifestFromYaml(content) {
59
+ const result = {};
60
+ const lines = content.split("\n");
61
+ const stack = [
62
+ { indent: -1, obj: result },
63
+ ];
64
+ for (const line of lines) {
65
+ const trimmed = line.trimEnd();
66
+ if (!trimmed || trimmed.startsWith("#"))
67
+ continue;
68
+ const indent = line.length - line.trimStart().length;
69
+ const match = trimmed.match(/^(\s*)([^:]+):\s*(.*)$/);
70
+ if (!match)
71
+ continue;
72
+ const key = match[2].trim();
73
+ const value = match[3].trim();
74
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
75
+ stack.pop();
76
+ }
77
+ const parent = stack[stack.length - 1].obj;
78
+ if (value === "" || value === "|" || value === ">") {
79
+ const nested = {};
80
+ parent[key] = nested;
81
+ stack.push({ indent, obj: nested });
82
+ }
83
+ else {
84
+ const stripped = value.replace(/^["'](.*)["']$/, "$1");
85
+ parent[key] = stripped;
86
+ }
87
+ }
88
+ const name = result["name"];
89
+ const version = result["version"];
90
+ const description = result["description"];
91
+ const aios = result["aios"];
92
+ if (!name || !version || !description || !aios?.["minVersion"] || !aios?.["type"]) {
93
+ return undefined;
94
+ }
95
+ return {
96
+ name,
97
+ version,
98
+ description,
99
+ slashPrefix: result["slashPrefix"],
100
+ aios: {
101
+ minVersion: aios["minVersion"],
102
+ type: aios["type"],
103
+ },
104
+ components: result["components"],
105
+ };
106
+ }
107
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/lib/validator.ts"],"names":[],"mappings":"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"}