@bastani/atomic 0.5.0-1 → 0.5.0-3

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 (70) hide show
  1. package/.atomic/workflows/hello/claude/index.ts +44 -0
  2. package/.atomic/workflows/hello/copilot/index.ts +58 -0
  3. package/.atomic/workflows/hello/opencode/index.ts +58 -0
  4. package/.atomic/workflows/hello-parallel/claude/index.ts +76 -0
  5. package/.atomic/workflows/hello-parallel/copilot/index.ts +105 -0
  6. package/.atomic/workflows/hello-parallel/opencode/index.ts +115 -0
  7. package/.atomic/workflows/package-lock.json +31 -0
  8. package/.atomic/workflows/package.json +8 -0
  9. package/.atomic/workflows/ralph/claude/index.ts +149 -0
  10. package/.atomic/workflows/ralph/copilot/index.ts +162 -0
  11. package/.atomic/workflows/ralph/helpers/git.ts +34 -0
  12. package/.atomic/workflows/ralph/helpers/prompts.ts +538 -0
  13. package/.atomic/workflows/ralph/helpers/review.ts +32 -0
  14. package/.atomic/workflows/ralph/opencode/index.ts +164 -0
  15. package/.atomic/workflows/tsconfig.json +22 -0
  16. package/.claude/agents/code-simplifier.md +52 -0
  17. package/.claude/agents/codebase-analyzer.md +166 -0
  18. package/.claude/agents/codebase-locator.md +122 -0
  19. package/.claude/agents/codebase-online-researcher.md +148 -0
  20. package/.claude/agents/codebase-pattern-finder.md +247 -0
  21. package/.claude/agents/codebase-research-analyzer.md +179 -0
  22. package/.claude/agents/codebase-research-locator.md +145 -0
  23. package/.claude/agents/debugger.md +91 -0
  24. package/.claude/agents/orchestrator.md +19 -0
  25. package/.claude/agents/planner.md +106 -0
  26. package/.claude/agents/reviewer.md +97 -0
  27. package/.claude/agents/worker.md +165 -0
  28. package/.github/agents/code-simplifier.md +52 -0
  29. package/.github/agents/codebase-analyzer.md +166 -0
  30. package/.github/agents/codebase-locator.md +122 -0
  31. package/.github/agents/codebase-online-researcher.md +146 -0
  32. package/.github/agents/codebase-pattern-finder.md +247 -0
  33. package/.github/agents/codebase-research-analyzer.md +179 -0
  34. package/.github/agents/codebase-research-locator.md +145 -0
  35. package/.github/agents/debugger.md +98 -0
  36. package/.github/agents/orchestrator.md +27 -0
  37. package/.github/agents/planner.md +131 -0
  38. package/.github/agents/reviewer.md +94 -0
  39. package/.github/agents/worker.md +237 -0
  40. package/.github/lsp.json +93 -0
  41. package/.opencode/agents/code-simplifier.md +62 -0
  42. package/.opencode/agents/codebase-analyzer.md +171 -0
  43. package/.opencode/agents/codebase-locator.md +127 -0
  44. package/.opencode/agents/codebase-online-researcher.md +152 -0
  45. package/.opencode/agents/codebase-pattern-finder.md +252 -0
  46. package/.opencode/agents/codebase-research-analyzer.md +183 -0
  47. package/.opencode/agents/codebase-research-locator.md +149 -0
  48. package/.opencode/agents/debugger.md +99 -0
  49. package/.opencode/agents/orchestrator.md +27 -0
  50. package/.opencode/agents/planner.md +146 -0
  51. package/.opencode/agents/reviewer.md +102 -0
  52. package/.opencode/agents/worker.md +165 -0
  53. package/README.md +355 -299
  54. package/assets/settings.schema.json +0 -5
  55. package/package.json +9 -3
  56. package/src/cli.ts +16 -8
  57. package/src/commands/cli/workflow.ts +209 -15
  58. package/src/lib/spawn.ts +106 -31
  59. package/src/sdk/runtime/loader.ts +1 -1
  60. package/src/services/config/config-path.ts +1 -1
  61. package/src/services/config/settings.ts +0 -9
  62. package/src/services/system/agents.ts +94 -0
  63. package/src/services/system/auto-sync.ts +131 -0
  64. package/src/services/system/install-ui.ts +158 -0
  65. package/src/services/system/skills.ts +26 -17
  66. package/src/services/system/workflows.ts +105 -0
  67. package/src/theme/colors.ts +2 -0
  68. package/tsconfig.json +34 -0
  69. package/src/commands/cli/update.ts +0 -46
  70. package/src/services/system/download.ts +0 -325
@@ -1,325 +0,0 @@
1
- /**
2
- * GitHub release and download utilities for atomic updates
3
- *
4
- * Provides functions to:
5
- * - Fetch latest release information from GitHub API
6
- * - Download files with progress reporting
7
- * - Verify SHA256 checksums
8
- * - Get platform-specific filenames for binaries and config archives
9
- */
10
-
11
-
12
-
13
- /**
14
- * Error thrown when a file's checksum does not match the expected value.
15
- * Indicates the file may be corrupted or tampered with.
16
- */
17
- export class ChecksumMismatchError extends Error {
18
- constructor(filename: string) {
19
- super(`Checksum verification failed for ${filename}`);
20
- this.name = "ChecksumMismatchError";
21
- }
22
- }
23
-
24
- /** GitHub repository for atomic */
25
- export const GITHUB_REPO = "flora131/atomic";
26
-
27
- /** Information about a GitHub release */
28
- export interface ReleaseInfo {
29
- /** Version string without 'v' prefix (e.g., "0.2.0") */
30
- version: string;
31
- /** Full tag name (e.g., "v0.2.0") */
32
- tagName: string;
33
- /** ISO date when the release was published */
34
- publishedAt: string;
35
- /** Release notes in markdown format */
36
- body: string;
37
- }
38
-
39
- /** GitHub API release response structure */
40
- interface GitHubReleaseResponse {
41
- tag_name: string;
42
- published_at: string;
43
- body: string | null;
44
- prerelease: boolean;
45
- }
46
-
47
- /**
48
- * Fetch the latest release info from GitHub API.
49
- *
50
- * @returns Release information for the latest version
51
- * @throws Error if the API request fails or rate limit is exceeded
52
- */
53
- export async function getLatestRelease(): Promise<ReleaseInfo> {
54
- const url = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
55
-
56
- const headers: Record<string, string> = {
57
- Accept: "application/vnd.github.v3+json",
58
- };
59
-
60
- // Include token if available to avoid rate limits
61
- if (process.env.GITHUB_TOKEN) {
62
- headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
63
- }
64
-
65
- const response = await fetch(url, { headers });
66
-
67
- if (!response.ok) {
68
- if (response.status === 403) {
69
- throw new Error(
70
- "GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable to increase limit."
71
- );
72
- }
73
- if (response.status === 404) {
74
- throw new Error("No releases found for this repository.");
75
- }
76
- throw new Error(`Failed to fetch release info: ${response.status} ${response.statusText}`);
77
- }
78
-
79
- const data = (await response.json()) as GitHubReleaseResponse;
80
- return {
81
- version: data.tag_name.replace(/^v/, ""),
82
- tagName: data.tag_name,
83
- publishedAt: data.published_at,
84
- body: data.body || "",
85
- };
86
- }
87
-
88
- /**
89
- * Fetch the latest prerelease info from GitHub API.
90
- *
91
- * Queries the releases list and returns the first release marked as a prerelease.
92
- *
93
- * @returns Release information for the latest prerelease version
94
- * @throws Error if no prerelease is found or the API request fails
95
- */
96
- export async function getLatestPrerelease(): Promise<ReleaseInfo> {
97
- const url = `https://api.github.com/repos/${GITHUB_REPO}/releases`;
98
-
99
- const headers: Record<string, string> = {
100
- Accept: "application/vnd.github.v3+json",
101
- };
102
-
103
- if (process.env.GITHUB_TOKEN) {
104
- headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
105
- }
106
-
107
- const response = await fetch(url, { headers });
108
-
109
- if (!response.ok) {
110
- if (response.status === 403) {
111
- throw new Error(
112
- "GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable to increase limit."
113
- );
114
- }
115
- throw new Error(`Failed to fetch releases: ${response.status} ${response.statusText}`);
116
- }
117
-
118
- const releases = (await response.json()) as GitHubReleaseResponse[];
119
- const prerelease = releases.find((r) => r.prerelease);
120
-
121
- if (!prerelease) {
122
- throw new Error("No prerelease found for this repository.");
123
- }
124
-
125
- return {
126
- version: prerelease.tag_name.replace(/^v/, ""),
127
- tagName: prerelease.tag_name,
128
- publishedAt: prerelease.published_at,
129
- body: prerelease.body || "",
130
- };
131
- }
132
-
133
- /**
134
- * Fetch release info for a specific version from GitHub API.
135
- *
136
- * @param version - Version string with or without 'v' prefix (e.g., "0.2.0" or "v0.2.0")
137
- * @returns Release information for the specified version
138
- * @throws Error if the version is not found or API request fails
139
- */
140
- export async function getReleaseByVersion(version: string): Promise<ReleaseInfo> {
141
- // Ensure version has 'v' prefix for tag lookup
142
- const tagName = version.startsWith("v") ? version : `v${version}`;
143
- const url = `https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${tagName}`;
144
-
145
- const headers: Record<string, string> = {
146
- Accept: "application/vnd.github.v3+json",
147
- };
148
-
149
- if (process.env.GITHUB_TOKEN) {
150
- headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
151
- }
152
-
153
- const response = await fetch(url, { headers });
154
-
155
- if (!response.ok) {
156
- if (response.status === 403) {
157
- throw new Error(
158
- "GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable to increase limit."
159
- );
160
- }
161
- if (response.status === 404) {
162
- throw new Error(`Version ${tagName} not found.`);
163
- }
164
- throw new Error(`Failed to fetch release info: ${response.status} ${response.statusText}`);
165
- }
166
-
167
- const data = (await response.json()) as GitHubReleaseResponse;
168
- return {
169
- version: data.tag_name.replace(/^v/, ""),
170
- tagName: data.tag_name,
171
- publishedAt: data.published_at,
172
- body: data.body || "",
173
- };
174
- }
175
-
176
- /**
177
- * Progress callback type for download operations.
178
- * Called periodically with the download percentage (0-100).
179
- */
180
- export type ProgressCallback = (percent: number) => void;
181
-
182
- /**
183
- * Download a file from a URL to a local path with optional progress reporting.
184
- *
185
- * @param url - The URL to download from
186
- * @param destPath - The local path to save the file to
187
- * @param onProgress - Optional callback for progress updates (percentage 0-100)
188
- * @throws Error if the download fails
189
- */
190
- export async function downloadFile(
191
- url: string,
192
- destPath: string,
193
- onProgress?: ProgressCallback
194
- ): Promise<void> {
195
- const headers: Record<string, string> = {};
196
-
197
- // Include token if available to avoid rate limits on download URLs
198
- if (process.env.GITHUB_TOKEN) {
199
- headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
200
- }
201
-
202
- const response = await fetch(url, {
203
- redirect: "follow",
204
- headers,
205
- });
206
-
207
- if (!response.ok) {
208
- throw new Error(`Download failed: ${response.status} ${response.statusText}`);
209
- }
210
-
211
- const contentLength = response.headers.get("content-length");
212
- const total = contentLength ? parseInt(contentLength, 10) : 0;
213
- let loaded = 0;
214
-
215
- const reader = response.body?.getReader();
216
- if (!reader) {
217
- throw new Error("Failed to read response body");
218
- }
219
-
220
- const chunks: Uint8Array[] = [];
221
-
222
- while (true) {
223
- const { done, value } = await reader.read();
224
- if (done) break;
225
-
226
- chunks.push(value);
227
- loaded += value.length;
228
-
229
- if (onProgress && total > 0) {
230
- onProgress(Math.round((loaded / total) * 100));
231
- }
232
- }
233
-
234
- // Combine chunks and write to file
235
- const data = new Uint8Array(loaded);
236
- let position = 0;
237
- for (const chunk of chunks) {
238
- data.set(chunk, position);
239
- position += chunk.length;
240
- }
241
-
242
- await Bun.write(destPath, data);
243
- }
244
-
245
- /**
246
- * Parse a checksums.txt file content into a map of filename to hash.
247
- *
248
- * The format is: "<hash> <filename>" (two spaces between hash and filename)
249
- * This is the standard format used by sha256sum command.
250
- *
251
- * @param checksumsTxt - Content of the checksums.txt file
252
- * @returns Map of filename to lowercase hex hash
253
- */
254
- export function parseChecksums(checksumsTxt: string): Map<string, string> {
255
- const checksums = new Map<string, string>();
256
- const lines = checksumsTxt.trim().split("\n");
257
-
258
- for (const line of lines) {
259
- // Format: "<hash> <filename>" (two spaces between)
260
- const match = line.match(/^([a-fA-F0-9]{64})\s{2}(.+)$/);
261
- if (match) {
262
- const hash = match[1];
263
- const filename = match[2];
264
- if (hash && filename) {
265
- checksums.set(filename, hash.toLowerCase());
266
- }
267
- }
268
- }
269
-
270
- return checksums;
271
- }
272
-
273
- /**
274
- * Verify SHA256 checksum of a file against checksums.txt content.
275
- *
276
- * @param filePath - Path to the file to verify
277
- * @param checksumsTxt - Content of checksums.txt file
278
- * @param expectedFilename - The filename to look up in checksums.txt
279
- * @returns True if the checksum matches, false otherwise
280
- * @throws Error if the filename is not found in checksums.txt
281
- */
282
- export async function verifyChecksum(
283
- filePath: string,
284
- checksumsTxt: string,
285
- expectedFilename: string
286
- ): Promise<boolean> {
287
- const checksums = parseChecksums(checksumsTxt);
288
- const expectedHash = checksums.get(expectedFilename);
289
-
290
- if (!expectedHash) {
291
- throw new Error(`No checksum found for ${expectedFilename}`);
292
- }
293
-
294
- // Calculate actual hash using Bun's crypto
295
- const file = Bun.file(filePath);
296
- const data = await file.arrayBuffer();
297
- const hasher = new Bun.CryptoHasher("sha256");
298
- hasher.update(data);
299
- const actualHash = hasher.digest("hex");
300
-
301
- return actualHash === expectedHash;
302
- }
303
-
304
- declare const __ATOMIC_BASELINE__: boolean | undefined;
305
-
306
- /**
307
- * Get platform-specific binary filename for download.
308
- *
309
- * Returns the filename used in GitHub releases, e.g.:
310
- * @param packageName - Full package name including scope (e.g. "atomic")
311
- * @param version - Semver version without 'v' prefix (e.g. "0.4.30")
312
- * @returns true if the package version exists, false otherwise
313
- */
314
- export async function checkNpmPackageExists(
315
- packageName: string,
316
- version: string,
317
- ): Promise<boolean> {
318
- const url = `https://registry.npmjs.org/${packageName}/${version}`;
319
- try {
320
- const response = await fetch(url);
321
- return response.ok;
322
- } catch {
323
- return false;
324
- }
325
- }