archondev 0.1.0 → 1.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.
- package/README.md +84 -51
- package/dist/auth-2QIFQZTL.js +12 -0
- package/dist/bug-DXLBBW3U.js +10 -0
- package/dist/{chunk-R6IMTNKV.js → chunk-2CFO5GVH.js} +0 -35
- package/dist/chunk-A7QU6JC6.js +119 -0
- package/dist/chunk-CAYCSBNX.js +202 -0
- package/dist/chunk-EDP55FCI.js +485 -0
- package/dist/chunk-I4ZVNLNO.js +4648 -0
- package/dist/chunk-IMZN36GC.js +159 -0
- package/dist/chunk-JBKFAD4M.js +650 -0
- package/dist/chunk-MOZHC2GX.js +351 -0
- package/dist/chunk-PK3OQVBG.js +91 -0
- package/dist/chunk-QGM4M3NI.js +37 -0
- package/dist/chunk-SMR7JQK6.js +399 -0
- package/dist/chunk-UDBFDXJI.js +696 -0
- package/dist/chunk-UG2ZZ7CM.js +737 -0
- package/dist/chunk-VKM3HAHW.js +832 -0
- package/dist/chunk-WCCBJSNI.js +62 -0
- package/dist/code-review-FSTYDHNG.js +16 -0
- package/dist/execute-LYID2ODD.js +13 -0
- package/dist/index.js +1250 -7206
- package/dist/keys-EL3FUM5O.js +15 -0
- package/dist/list-VXMVEIL5.js +13 -0
- package/dist/{parser-D6PBQUJH.js → parser-M4DI7A24.js} +2 -1
- package/dist/plan-7VSFESVD.js +16 -0
- package/dist/preferences-PL2ON5VY.js +17 -0
- package/dist/review-3R6QXAXQ.js +27 -0
- package/package.json +21 -1
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnthropicClient,
|
|
3
|
+
generateId,
|
|
4
|
+
getDefaultModel
|
|
5
|
+
} from "./chunk-A7QU6JC6.js";
|
|
6
|
+
|
|
7
|
+
// src/core/atoms/types.ts
|
|
8
|
+
var ATOM_TRANSITIONS = {
|
|
9
|
+
DRAFT: ["READY"],
|
|
10
|
+
READY: ["IN_PROGRESS", "BLOCKED"],
|
|
11
|
+
IN_PROGRESS: ["TESTING", "FAILED"],
|
|
12
|
+
TESTING: ["DONE", "FAILED"],
|
|
13
|
+
DONE: [],
|
|
14
|
+
// Terminal state
|
|
15
|
+
FAILED: ["IN_PROGRESS", "BLOCKED"],
|
|
16
|
+
// Can retry or escalate
|
|
17
|
+
BLOCKED: ["READY"]
|
|
18
|
+
// Can unblock and retry
|
|
19
|
+
};
|
|
20
|
+
var MAX_RETRIES = 3;
|
|
21
|
+
|
|
22
|
+
// src/core/atoms/atoms.ts
|
|
23
|
+
var MAX_RETRIES2 = MAX_RETRIES;
|
|
24
|
+
var atomCounter = 0;
|
|
25
|
+
function generateAtomId() {
|
|
26
|
+
atomCounter++;
|
|
27
|
+
return `ATOM-${String(atomCounter).padStart(3, "0")}`;
|
|
28
|
+
}
|
|
29
|
+
function createAtom(input, context) {
|
|
30
|
+
const now = /* @__PURE__ */ new Date();
|
|
31
|
+
const externalId = generateAtomId();
|
|
32
|
+
return {
|
|
33
|
+
id: generateId("atom"),
|
|
34
|
+
externalId,
|
|
35
|
+
title: input.title,
|
|
36
|
+
description: input.description ?? null,
|
|
37
|
+
goals: input.goals ?? [],
|
|
38
|
+
acceptanceCriteria: input.acceptanceCriteria,
|
|
39
|
+
ownershipPaths: input.ownershipPaths ?? [],
|
|
40
|
+
status: "DRAFT",
|
|
41
|
+
priority: input.priority ?? 100,
|
|
42
|
+
plan: null,
|
|
43
|
+
diffContract: null,
|
|
44
|
+
retryCount: 0,
|
|
45
|
+
errorMessage: null,
|
|
46
|
+
tags: input.tags ?? [],
|
|
47
|
+
metadata: input.metadata ?? {},
|
|
48
|
+
context: context ?? {},
|
|
49
|
+
createdAt: now,
|
|
50
|
+
updatedAt: now
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function validateAtom(atom) {
|
|
54
|
+
const errors = [];
|
|
55
|
+
if (!atom.title || atom.title.trim() === "") {
|
|
56
|
+
errors.push({
|
|
57
|
+
field: "title",
|
|
58
|
+
message: "Title is required",
|
|
59
|
+
code: "REQUIRED"
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (!atom.acceptanceCriteria || atom.acceptanceCriteria.length === 0) {
|
|
63
|
+
errors.push({
|
|
64
|
+
field: "acceptanceCriteria",
|
|
65
|
+
message: "At least one acceptance criterion is required",
|
|
66
|
+
code: "REQUIRED"
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
atom.acceptanceCriteria.forEach((criterion, index) => {
|
|
70
|
+
if (typeof criterion !== "string" || criterion.trim() === "") {
|
|
71
|
+
errors.push({
|
|
72
|
+
field: `acceptanceCriteria[${index}]`,
|
|
73
|
+
message: "Acceptance criterion must be a non-empty string",
|
|
74
|
+
code: "INVALID_FORMAT"
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
if (atom.priority < 0) {
|
|
79
|
+
errors.push({
|
|
80
|
+
field: "priority",
|
|
81
|
+
message: "Priority must be a non-negative number",
|
|
82
|
+
code: "INVALID_VALUE"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const validStatuses = [
|
|
86
|
+
"DRAFT",
|
|
87
|
+
"READY",
|
|
88
|
+
"IN_PROGRESS",
|
|
89
|
+
"TESTING",
|
|
90
|
+
"DONE",
|
|
91
|
+
"FAILED",
|
|
92
|
+
"BLOCKED"
|
|
93
|
+
];
|
|
94
|
+
if (!validStatuses.includes(atom.status)) {
|
|
95
|
+
errors.push({
|
|
96
|
+
field: "status",
|
|
97
|
+
message: `Invalid status: ${atom.status}`,
|
|
98
|
+
code: "INVALID_VALUE"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
valid: errors.length === 0,
|
|
103
|
+
errors
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function validateTransition(currentStatus, newStatus) {
|
|
107
|
+
const allowedTransitions = ATOM_TRANSITIONS[currentStatus];
|
|
108
|
+
if (!allowedTransitions) {
|
|
109
|
+
return {
|
|
110
|
+
valid: false,
|
|
111
|
+
errors: [
|
|
112
|
+
{
|
|
113
|
+
field: "status",
|
|
114
|
+
message: `Unknown current status: ${currentStatus}`,
|
|
115
|
+
code: "INVALID_VALUE"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (!allowedTransitions.includes(newStatus)) {
|
|
121
|
+
return {
|
|
122
|
+
valid: false,
|
|
123
|
+
errors: [
|
|
124
|
+
{
|
|
125
|
+
field: "status",
|
|
126
|
+
message: `Cannot transition from ${currentStatus} to ${newStatus}. Allowed: ${allowedTransitions.join(", ") || "none"}`,
|
|
127
|
+
code: "INVALID_TRANSITION"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { valid: true, errors: [] };
|
|
133
|
+
}
|
|
134
|
+
function transitionAtom(atom, newStatus, errorMessage) {
|
|
135
|
+
const validation = validateTransition(atom.status, newStatus);
|
|
136
|
+
if (!validation.valid) {
|
|
137
|
+
const error = validation.errors[0];
|
|
138
|
+
throw new Error(error?.message ?? "Invalid transition");
|
|
139
|
+
}
|
|
140
|
+
const now = /* @__PURE__ */ new Date();
|
|
141
|
+
const updates = {
|
|
142
|
+
status: newStatus,
|
|
143
|
+
updatedAt: now
|
|
144
|
+
};
|
|
145
|
+
if (newStatus === "FAILED") {
|
|
146
|
+
updates.retryCount = atom.retryCount + 1;
|
|
147
|
+
updates.errorMessage = errorMessage ?? null;
|
|
148
|
+
if (updates.retryCount >= MAX_RETRIES2) {
|
|
149
|
+
updates.status = "BLOCKED";
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (newStatus === "IN_PROGRESS" && atom.status === "FAILED") {
|
|
153
|
+
updates.errorMessage = null;
|
|
154
|
+
}
|
|
155
|
+
return { ...atom, ...updates };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/agents/architect.ts
|
|
159
|
+
import { readFile } from "fs/promises";
|
|
160
|
+
import { existsSync } from "fs";
|
|
161
|
+
var SYSTEM_PROMPT = `You are the Architect, an expert software engineer responsible for creating detailed implementation plans.
|
|
162
|
+
|
|
163
|
+
Your role:
|
|
164
|
+
- Analyze the atom's goals and acceptance criteria
|
|
165
|
+
- Review the architecture constraints and boundaries
|
|
166
|
+
- Generate a step-by-step implementation plan
|
|
167
|
+
- Identify files to modify and potential risks
|
|
168
|
+
- Consider learnings from previous iterations
|
|
169
|
+
|
|
170
|
+
Output your plan in the following JSON format:
|
|
171
|
+
{
|
|
172
|
+
"steps": ["Step 1: ...", "Step 2: ...", ...],
|
|
173
|
+
"files_to_modify": ["path/to/file1.ts", "path/to/file2.ts", ...],
|
|
174
|
+
"dependencies": ["dependency1", "dependency2", ...],
|
|
175
|
+
"risks": ["Risk 1: ...", "Risk 2: ...", ...],
|
|
176
|
+
"estimated_complexity": "LOW" | "MEDIUM" | "HIGH",
|
|
177
|
+
"reasoning": "Brief explanation of your approach..."
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
Guidelines:
|
|
181
|
+
- Keep steps atomic and verifiable
|
|
182
|
+
- List ALL files that will be modified
|
|
183
|
+
- Identify any external dependencies needed
|
|
184
|
+
- Flag security, performance, or breaking change risks
|
|
185
|
+
- Be conservative with complexity estimates`;
|
|
186
|
+
var ArchitectAgent = class {
|
|
187
|
+
client;
|
|
188
|
+
config;
|
|
189
|
+
constructor(config, apiKey) {
|
|
190
|
+
this.config = {
|
|
191
|
+
provider: "anthropic",
|
|
192
|
+
model: config?.model ?? getDefaultModel("architect"),
|
|
193
|
+
maxTokens: config?.maxTokens ?? 4096,
|
|
194
|
+
temperature: config?.temperature ?? 0.7
|
|
195
|
+
};
|
|
196
|
+
this.client = new AnthropicClient(this.config, apiKey);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Generate an implementation plan for an atom
|
|
200
|
+
*/
|
|
201
|
+
async generatePlan(atom, architecture, context) {
|
|
202
|
+
const userMessage = await this.buildPrompt(atom, architecture, context);
|
|
203
|
+
const response = await this.client.chat(SYSTEM_PROMPT, userMessage, {
|
|
204
|
+
temperature: 0.7,
|
|
205
|
+
maxTokens: 4096
|
|
206
|
+
});
|
|
207
|
+
const plan = this.parsePlanResponse(response.content);
|
|
208
|
+
return {
|
|
209
|
+
plan,
|
|
210
|
+
reasoning: this.extractReasoning(response.content),
|
|
211
|
+
usage: response.usage
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Build the prompt with all necessary context
|
|
216
|
+
*/
|
|
217
|
+
async buildPrompt(atom, architecture, context) {
|
|
218
|
+
const parts = [];
|
|
219
|
+
parts.push("# Atom to Implement");
|
|
220
|
+
parts.push(`**Title:** ${atom.title}`);
|
|
221
|
+
parts.push(`**Description:** ${atom.description ?? "No description"}`);
|
|
222
|
+
parts.push("");
|
|
223
|
+
parts.push("**Goals:**");
|
|
224
|
+
atom.goals.forEach((g, i) => parts.push(`${i + 1}. ${g}`));
|
|
225
|
+
parts.push("");
|
|
226
|
+
parts.push("**Acceptance Criteria:**");
|
|
227
|
+
atom.acceptanceCriteria.forEach((ac, i) => parts.push(`${i + 1}. ${ac}`));
|
|
228
|
+
parts.push("");
|
|
229
|
+
if (atom.ownershipPaths.length > 0) {
|
|
230
|
+
parts.push("**Ownership Paths (files this atom can modify):**");
|
|
231
|
+
atom.ownershipPaths.forEach((p) => parts.push(`- ${p}`));
|
|
232
|
+
parts.push("");
|
|
233
|
+
}
|
|
234
|
+
parts.push("# Architecture Constraints");
|
|
235
|
+
parts.push(`**Profile:** ${architecture.profile}`);
|
|
236
|
+
parts.push(`**Strict Mode:** ${architecture.strictMode}`);
|
|
237
|
+
parts.push("");
|
|
238
|
+
if (architecture.components.length > 0) {
|
|
239
|
+
parts.push("**Components:**");
|
|
240
|
+
architecture.components.forEach((c) => {
|
|
241
|
+
parts.push(`- ${c.name} (${c.id}): ${c.paths.join(", ")}`);
|
|
242
|
+
});
|
|
243
|
+
parts.push("");
|
|
244
|
+
}
|
|
245
|
+
if (architecture.invariants.length > 0) {
|
|
246
|
+
parts.push("**Invariants (rules that must NOT be violated):**");
|
|
247
|
+
architecture.invariants.forEach((inv) => {
|
|
248
|
+
parts.push(`- [${inv.severity}] ${inv.rule}`);
|
|
249
|
+
});
|
|
250
|
+
parts.push("");
|
|
251
|
+
}
|
|
252
|
+
if (architecture.protectedPaths.length > 0) {
|
|
253
|
+
parts.push("**Protected Paths:**");
|
|
254
|
+
architecture.protectedPaths.forEach((p) => {
|
|
255
|
+
parts.push(`- ${p.pattern} (${p.level}): ${p.reason}`);
|
|
256
|
+
});
|
|
257
|
+
parts.push("");
|
|
258
|
+
}
|
|
259
|
+
if (context?.codebasePatterns && context.codebasePatterns.length > 0) {
|
|
260
|
+
parts.push("# Codebase Patterns (from previous iterations)");
|
|
261
|
+
context.codebasePatterns.forEach((p) => parts.push(`- ${p}`));
|
|
262
|
+
parts.push("");
|
|
263
|
+
}
|
|
264
|
+
if (context?.recentLearnings && context.recentLearnings.length > 0) {
|
|
265
|
+
parts.push("# Recent Learnings");
|
|
266
|
+
context.recentLearnings.slice(0, 5).forEach((l) => parts.push(`- ${l}`));
|
|
267
|
+
parts.push("");
|
|
268
|
+
}
|
|
269
|
+
if (context?.progressPath && existsSync(context.progressPath)) {
|
|
270
|
+
try {
|
|
271
|
+
const progressContent = await readFile(context.progressPath, "utf-8");
|
|
272
|
+
const patterns = this.extractCodebasePatterns(progressContent);
|
|
273
|
+
if (patterns.length > 0) {
|
|
274
|
+
parts.push("# Additional Codebase Patterns (from progress.txt)");
|
|
275
|
+
patterns.forEach((p) => parts.push(`- ${p}`));
|
|
276
|
+
parts.push("");
|
|
277
|
+
}
|
|
278
|
+
} catch {
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
parts.push("# Instructions");
|
|
282
|
+
parts.push("Generate a detailed implementation plan for this atom.");
|
|
283
|
+
parts.push("Ensure your plan respects all architecture constraints.");
|
|
284
|
+
parts.push("Output your response as valid JSON.");
|
|
285
|
+
return parts.join("\n");
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Parse the plan from AI response
|
|
289
|
+
*/
|
|
290
|
+
parsePlanResponse(content) {
|
|
291
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
292
|
+
if (!jsonMatch) {
|
|
293
|
+
throw new Error("Failed to parse plan: no JSON found in response");
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
297
|
+
return {
|
|
298
|
+
steps: parsed.steps ?? [],
|
|
299
|
+
files_to_modify: parsed.files_to_modify ?? [],
|
|
300
|
+
dependencies: parsed.dependencies ?? [],
|
|
301
|
+
risks: parsed.risks ?? [],
|
|
302
|
+
estimated_complexity: this.normalizeComplexity(parsed.estimated_complexity)
|
|
303
|
+
};
|
|
304
|
+
} catch (error) {
|
|
305
|
+
throw new Error(`Failed to parse plan JSON: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
normalizeComplexity(value) {
|
|
309
|
+
const normalized = value?.toUpperCase();
|
|
310
|
+
if (normalized === "LOW" || normalized === "MEDIUM" || normalized === "HIGH") {
|
|
311
|
+
return normalized;
|
|
312
|
+
}
|
|
313
|
+
return "MEDIUM";
|
|
314
|
+
}
|
|
315
|
+
extractReasoning(content) {
|
|
316
|
+
try {
|
|
317
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
318
|
+
if (jsonMatch) {
|
|
319
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
320
|
+
return parsed.reasoning ?? "";
|
|
321
|
+
}
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
return "";
|
|
325
|
+
}
|
|
326
|
+
extractCodebasePatterns(progressContent) {
|
|
327
|
+
const patterns = [];
|
|
328
|
+
const lines = progressContent.split("\n");
|
|
329
|
+
let inPatternsSection = false;
|
|
330
|
+
for (const line of lines) {
|
|
331
|
+
if (line.includes("## Codebase Patterns")) {
|
|
332
|
+
inPatternsSection = true;
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (line.startsWith("## ") && inPatternsSection) {
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
if (inPatternsSection && line.startsWith("- ")) {
|
|
339
|
+
patterns.push(line.substring(2).trim());
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return patterns;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
export {
|
|
347
|
+
createAtom,
|
|
348
|
+
validateAtom,
|
|
349
|
+
transitionAtom,
|
|
350
|
+
ArchitectAgent
|
|
351
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listLocalAtoms
|
|
3
|
+
} from "./chunk-EDP55FCI.js";
|
|
4
|
+
|
|
5
|
+
// src/cli/list.ts
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
var STATUS_COLORS = {
|
|
8
|
+
DRAFT: chalk.gray,
|
|
9
|
+
READY: chalk.blue,
|
|
10
|
+
IN_PROGRESS: chalk.yellow,
|
|
11
|
+
TESTING: chalk.cyan,
|
|
12
|
+
DONE: chalk.green,
|
|
13
|
+
FAILED: chalk.red,
|
|
14
|
+
BLOCKED: chalk.magenta
|
|
15
|
+
};
|
|
16
|
+
async function list(options) {
|
|
17
|
+
const atoms = await listLocalAtoms();
|
|
18
|
+
if (atoms.length === 0) {
|
|
19
|
+
console.log(chalk.dim("No atoms found."));
|
|
20
|
+
console.log(chalk.dim("Create one with: archon plan <description>"));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
let filteredAtoms = atoms;
|
|
24
|
+
if (options.status) {
|
|
25
|
+
const statusFilter = options.status.toUpperCase();
|
|
26
|
+
filteredAtoms = atoms.filter((a) => a.status === statusFilter);
|
|
27
|
+
if (filteredAtoms.length === 0) {
|
|
28
|
+
console.log(chalk.dim(`No atoms with status "${options.status}" found.`));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const sortBy = options.sortBy ?? "priority";
|
|
33
|
+
filteredAtoms.sort((a, b) => {
|
|
34
|
+
switch (sortBy) {
|
|
35
|
+
case "priority":
|
|
36
|
+
return a.priority - b.priority;
|
|
37
|
+
case "created":
|
|
38
|
+
return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
39
|
+
case "updated":
|
|
40
|
+
return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
|
|
41
|
+
case "status":
|
|
42
|
+
return a.status.localeCompare(b.status);
|
|
43
|
+
default:
|
|
44
|
+
return a.priority - b.priority;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
console.log("");
|
|
48
|
+
console.log(
|
|
49
|
+
chalk.bold(
|
|
50
|
+
padRight("ID", 12) + padRight("Title", 40) + padRight("Status", 14) + padRight("Priority", 10) + "Created"
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
console.log(chalk.dim("\u2500".repeat(90)));
|
|
54
|
+
for (const atom of filteredAtoms) {
|
|
55
|
+
const colorFn = STATUS_COLORS[atom.status] ?? chalk.white;
|
|
56
|
+
const createdDate = formatDate(atom.createdAt);
|
|
57
|
+
console.log(
|
|
58
|
+
padRight(atom.externalId, 12) + padRight(truncate(atom.title, 38), 40) + colorFn(padRight(atom.status, 14)) + padRight(String(atom.priority), 10) + chalk.dim(createdDate)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
console.log(chalk.dim("\u2500".repeat(90)));
|
|
62
|
+
const statusCounts = countByStatus(filteredAtoms);
|
|
63
|
+
const summaryParts = [];
|
|
64
|
+
for (const [status, count] of Object.entries(statusCounts)) {
|
|
65
|
+
const colorFn = STATUS_COLORS[status] ?? chalk.white;
|
|
66
|
+
summaryParts.push(`${count} ${colorFn(status.toLowerCase())}`);
|
|
67
|
+
}
|
|
68
|
+
console.log(`Showing ${filteredAtoms.length} atom(s): ${summaryParts.join(", ")}`);
|
|
69
|
+
}
|
|
70
|
+
function padRight(str, width) {
|
|
71
|
+
return str.padEnd(width);
|
|
72
|
+
}
|
|
73
|
+
function truncate(str, maxLen) {
|
|
74
|
+
if (str.length <= maxLen) return str;
|
|
75
|
+
return str.substring(0, maxLen - 1) + "\u2026";
|
|
76
|
+
}
|
|
77
|
+
function formatDate(date) {
|
|
78
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
79
|
+
return d.toISOString().split("T")[0] ?? "";
|
|
80
|
+
}
|
|
81
|
+
function countByStatus(atoms) {
|
|
82
|
+
const counts = {};
|
|
83
|
+
for (const atom of atoms) {
|
|
84
|
+
counts[atom.status] = (counts[atom.status] ?? 0) + 1;
|
|
85
|
+
}
|
|
86
|
+
return counts;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
list
|
|
91
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
14
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
__require,
|
|
35
|
+
__commonJS,
|
|
36
|
+
__toESM
|
|
37
|
+
};
|