atomism 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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +210 -0
  3. package/dist/chunk-34O5KJWR.js +81 -0
  4. package/dist/chunk-34O5KJWR.js.map +1 -0
  5. package/dist/chunk-55AP34JO.js +116 -0
  6. package/dist/chunk-55AP34JO.js.map +1 -0
  7. package/dist/chunk-6MDHM2B4.js +17 -0
  8. package/dist/chunk-6MDHM2B4.js.map +1 -0
  9. package/dist/chunk-GU2R4KLP.js +43 -0
  10. package/dist/chunk-GU2R4KLP.js.map +1 -0
  11. package/dist/chunk-H7WC3NXZ.js +39 -0
  12. package/dist/chunk-H7WC3NXZ.js.map +1 -0
  13. package/dist/chunk-P33CQFMY.js +329 -0
  14. package/dist/chunk-P33CQFMY.js.map +1 -0
  15. package/dist/chunk-P6X7T4KA.js +200 -0
  16. package/dist/chunk-P6X7T4KA.js.map +1 -0
  17. package/dist/chunk-PLQJM2KT.js +9 -0
  18. package/dist/chunk-PLQJM2KT.js.map +1 -0
  19. package/dist/chunk-RS2IEGW3.js +10 -0
  20. package/dist/chunk-RS2IEGW3.js.map +1 -0
  21. package/dist/chunk-S6Z5G5DB.js +84 -0
  22. package/dist/chunk-S6Z5G5DB.js.map +1 -0
  23. package/dist/chunk-UVUDQ4XP.js +259 -0
  24. package/dist/chunk-UVUDQ4XP.js.map +1 -0
  25. package/dist/chunk-UWVZQSP4.js +597 -0
  26. package/dist/chunk-UWVZQSP4.js.map +1 -0
  27. package/dist/chunk-YKJO3ZFY.js +308 -0
  28. package/dist/chunk-YKJO3ZFY.js.map +1 -0
  29. package/dist/cli.d.ts +1 -0
  30. package/dist/cli.js +152 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/create-atom-AXPDBYQL.js +153 -0
  33. package/dist/create-atom-AXPDBYQL.js.map +1 -0
  34. package/dist/escalate-BTEJT5NL.js +211 -0
  35. package/dist/escalate-BTEJT5NL.js.map +1 -0
  36. package/dist/extract-RPKCTINT.js +514 -0
  37. package/dist/extract-RPKCTINT.js.map +1 -0
  38. package/dist/graduate-453M7ZRQ.js +222 -0
  39. package/dist/graduate-453M7ZRQ.js.map +1 -0
  40. package/dist/helpers-PJPFPYBQ.js +11 -0
  41. package/dist/helpers-PJPFPYBQ.js.map +1 -0
  42. package/dist/history-OPD7NLZW.js +258 -0
  43. package/dist/history-OPD7NLZW.js.map +1 -0
  44. package/dist/import-generator-4CKRBMTE.js +1864 -0
  45. package/dist/import-generator-4CKRBMTE.js.map +1 -0
  46. package/dist/index.d.ts +230 -0
  47. package/dist/index.js +41 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/init-2FINDMYK.js +741 -0
  50. package/dist/init-2FINDMYK.js.map +1 -0
  51. package/dist/list-NEBVBGG3.js +71 -0
  52. package/dist/list-NEBVBGG3.js.map +1 -0
  53. package/dist/parser-3BILOSOO.js +157 -0
  54. package/dist/parser-3BILOSOO.js.map +1 -0
  55. package/dist/plan-DNVARHWH.js +249 -0
  56. package/dist/plan-DNVARHWH.js.map +1 -0
  57. package/dist/register-XTRMSH7Y.js +91 -0
  58. package/dist/register-XTRMSH7Y.js.map +1 -0
  59. package/dist/revert-J4CRDE2K.js +87 -0
  60. package/dist/revert-J4CRDE2K.js.map +1 -0
  61. package/dist/run-3GI3SBYL.js +188 -0
  62. package/dist/run-3GI3SBYL.js.map +1 -0
  63. package/dist/scan-generators-ST4TBEY7.js +375 -0
  64. package/dist/scan-generators-ST4TBEY7.js.map +1 -0
  65. package/dist/signatures-K5QIL4WG.js +258 -0
  66. package/dist/signatures-K5QIL4WG.js.map +1 -0
  67. package/dist/skills-assign-IHOXX4AI.js +182 -0
  68. package/dist/skills-assign-IHOXX4AI.js.map +1 -0
  69. package/dist/skills-load-JSD5UG2K.js +20 -0
  70. package/dist/skills-load-JSD5UG2K.js.map +1 -0
  71. package/dist/skills-scan-WACJFRJN.js +25 -0
  72. package/dist/skills-scan-WACJFRJN.js.map +1 -0
  73. package/dist/skills-suggest-JFI2NUJI.js +269 -0
  74. package/dist/skills-suggest-JFI2NUJI.js.map +1 -0
  75. package/dist/status-KQVSAZFR.js +111 -0
  76. package/dist/status-KQVSAZFR.js.map +1 -0
  77. package/dist/suggest-IFFJQFIW.js +183 -0
  78. package/dist/suggest-IFFJQFIW.js.map +1 -0
  79. package/dist/test-HP3FG3MO.js +152 -0
  80. package/dist/test-HP3FG3MO.js.map +1 -0
  81. package/dist/test-gen-2ZGPOP35.js +347 -0
  82. package/dist/test-gen-2ZGPOP35.js.map +1 -0
  83. package/dist/trust-4R26DULG.js +248 -0
  84. package/dist/trust-4R26DULG.js.map +1 -0
  85. package/dist/validate-generator-46H2LYYQ.js +410 -0
  86. package/dist/validate-generator-46H2LYYQ.js.map +1 -0
  87. package/dist/workflow-5UVLBS7J.js +655 -0
  88. package/dist/workflow-5UVLBS7J.js.map +1 -0
  89. package/package.json +84 -0
@@ -0,0 +1,514 @@
1
+ import {
2
+ resolveAtomPath
3
+ } from "./chunk-RS2IEGW3.js";
4
+ import {
5
+ ATOMIC_DIR,
6
+ fileExists,
7
+ initStorage
8
+ } from "./chunk-YKJO3ZFY.js";
9
+ import {
10
+ fmt
11
+ } from "./chunk-S6Z5G5DB.js";
12
+ import {
13
+ toErrorMessage
14
+ } from "./chunk-PLQJM2KT.js";
15
+
16
+ // src/commands/extract.ts
17
+ import { readFile, stat, mkdir, writeFile } from "fs/promises";
18
+ import { join, basename, dirname, resolve, relative, isAbsolute } from "path";
19
+ function parseFrontmatter(content) {
20
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
21
+ if (!match || !match[1]) {
22
+ return {};
23
+ }
24
+ const frontmatter = {};
25
+ const lines = match[1].split("\n");
26
+ for (const line of lines) {
27
+ const colonIndex = line.indexOf(":");
28
+ if (colonIndex > 0) {
29
+ const key = line.substring(0, colonIndex).trim();
30
+ const value = line.substring(colonIndex + 1).trim();
31
+ frontmatter[key] = value;
32
+ }
33
+ }
34
+ return frontmatter;
35
+ }
36
+ function toSnakeCase(name) {
37
+ return name.replace(/[^a-zA-Z0-9]+/g, "_").replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase().replace(/^_+|_+$/g, "").replace(/_+/g, "_");
38
+ }
39
+ var VALID_JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
40
+ function isSafeZodType(expr) {
41
+ const base = expr.replace(/\.optional\(\)$/, "");
42
+ if (/^z\.[a-z]+\(\)$/.test(base)) return true;
43
+ if (/^z\.[a-z]+\(z\.[a-z]+\(\)(, z\.[a-z]+\(\))?\)$/.test(base)) return true;
44
+ if (/^z\.enum\(\[("[^"\\]*"(, "[^"\\]*")*)\]\)$/.test(base)) return true;
45
+ return false;
46
+ }
47
+ function tsTypeToZodType(tsType) {
48
+ if (!tsType) return "z.unknown()";
49
+ switch (tsType) {
50
+ case "string":
51
+ return "z.string()";
52
+ case "number":
53
+ return "z.number()";
54
+ case "boolean":
55
+ return "z.boolean()";
56
+ case "Date":
57
+ return "z.date()";
58
+ case "bigint":
59
+ return "z.bigint()";
60
+ case "void":
61
+ return "z.void()";
62
+ case "undefined":
63
+ return "z.undefined()";
64
+ case "null":
65
+ return "z.null()";
66
+ case "any":
67
+ return "z.any()";
68
+ case "unknown":
69
+ return "z.unknown()";
70
+ case "never":
71
+ return "z.never()";
72
+ default:
73
+ if (tsType.endsWith("[]")) {
74
+ const inner = tsTypeToZodType(tsType.slice(0, -2));
75
+ return `z.array(${inner})`;
76
+ }
77
+ if (tsType.startsWith("Record<")) {
78
+ const match = tsType.match(/^Record<(.+),\s*(.+)>$/);
79
+ if (match) {
80
+ return `z.record(${tsTypeToZodType(match[1])}, ${tsTypeToZodType(match[2])})`;
81
+ }
82
+ }
83
+ return "z.unknown()";
84
+ }
85
+ }
86
+ function jsonSchemaTypeToZodType(schemaType) {
87
+ switch (schemaType) {
88
+ case "string":
89
+ return "z.string()";
90
+ case "number":
91
+ case "integer":
92
+ return "z.number()";
93
+ case "boolean":
94
+ return "z.boolean()";
95
+ case "array":
96
+ return "z.array(z.unknown())";
97
+ case "object":
98
+ return "z.record(z.string(), z.unknown())";
99
+ case "null":
100
+ return "z.null()";
101
+ default:
102
+ return "z.unknown()";
103
+ }
104
+ }
105
+ function escapeSourcePath(path) {
106
+ return path.replace(/\*\//g, "*\\/");
107
+ }
108
+ async function extractFromSkill(skillPath) {
109
+ const resolvedPath = resolveAtomPath(skillPath, process.cwd());
110
+ const stats = await stat(resolvedPath);
111
+ let skillContent;
112
+ let skillFile;
113
+ if (stats.isDirectory()) {
114
+ skillFile = join(resolvedPath, "SKILL.md");
115
+ if (!await fileExists(skillFile)) {
116
+ throw new Error(`No SKILL.md found in ${resolvedPath}`);
117
+ }
118
+ skillContent = await readFile(skillFile, "utf-8");
119
+ } else {
120
+ skillFile = resolvedPath;
121
+ skillContent = await readFile(skillFile, "utf-8");
122
+ }
123
+ const frontmatter = parseFrontmatter(skillContent);
124
+ const name = frontmatter["name"] || basename(dirname(skillFile));
125
+ const description = frontmatter["description"] || "Extracted from Claude Code skill";
126
+ const inputFields = analyzeSkillInputs(skillContent);
127
+ const outputFields = analyzeSkillOutputs(skillContent);
128
+ return {
129
+ name: toSnakeCase(name),
130
+ description,
131
+ inputFields,
132
+ outputFields,
133
+ sourceType: "skill",
134
+ sourcePath: skillFile
135
+ };
136
+ }
137
+ function analyzeFieldPatterns(content, patterns, defaultField, descriptionSuffix) {
138
+ const found = /* @__PURE__ */ new Set();
139
+ for (const pattern of patterns) {
140
+ for (const match of content.matchAll(pattern)) {
141
+ const name = match[1]?.toLowerCase();
142
+ if (name && !found.has(name) && name.length > 2) {
143
+ found.add(name);
144
+ }
145
+ }
146
+ }
147
+ if (found.size === 0) {
148
+ return [{ name: defaultField.name, type: "string", zodType: "z.string()", description: defaultField.description }];
149
+ }
150
+ const fields = [];
151
+ for (const name of found) {
152
+ fields.push({ name: toSnakeCase(name), type: "string", zodType: "z.string()", description: `${name} ${descriptionSuffix}` });
153
+ }
154
+ return fields.slice(0, 5);
155
+ }
156
+ var INPUT_PATTERNS = [
157
+ /accepts?\s+(?:an?\s+)?([a-z_]+)/gi,
158
+ /input[:\s]+([a-z_]+)/gi,
159
+ /receives?\s+(?:an?\s+)?([a-z_]+)/gi,
160
+ /takes?\s+(?:an?\s+)?([a-z_]+)/gi
161
+ ];
162
+ var OUTPUT_PATTERNS = [
163
+ /outputs?\s+(?:an?\s+)?([a-z_]+)/gi,
164
+ /returns?\s+(?:an?\s+)?([a-z_]+)/gi,
165
+ /produces?\s+(?:an?\s+)?([a-z_]+)/gi,
166
+ /generates?\s+(?:an?\s+)?([a-z_]+)/gi
167
+ ];
168
+ function analyzeSkillInputs(content) {
169
+ return analyzeFieldPatterns(content, INPUT_PATTERNS, { name: "input", description: "Input data to process" }, "parameter");
170
+ }
171
+ function analyzeSkillOutputs(content) {
172
+ return analyzeFieldPatterns(content, OUTPUT_PATTERNS, { name: "result", description: "Processing result" }, "output");
173
+ }
174
+ async function extractFromBmad(bmadPath) {
175
+ const resolvedPath = resolveAtomPath(bmadPath, process.cwd());
176
+ if (!await fileExists(resolvedPath)) {
177
+ throw new Error(`BMAD workflow not found: ${resolvedPath}`);
178
+ }
179
+ const content = await readFile(resolvedPath, "utf-8");
180
+ const frontmatter = parseFrontmatter(content);
181
+ const name = frontmatter["name"] || basename(resolvedPath, ".md");
182
+ const description = frontmatter["description"] || "Extracted from BMAD workflow";
183
+ return {
184
+ name: toSnakeCase(name),
185
+ description,
186
+ inputFields: [{ name: "context", type: "string", zodType: "z.string()", description: "Workflow context" }],
187
+ outputFields: [{ name: "result", type: "string", zodType: "z.string()", description: "Workflow result" }],
188
+ sourceType: "bmad",
189
+ sourcePath: resolvedPath
190
+ };
191
+ }
192
+ async function extractFromMcp(mcpPath) {
193
+ const resolvedPath = resolveAtomPath(mcpPath, process.cwd());
194
+ if (!await fileExists(resolvedPath)) {
195
+ throw new Error(`MCP tool definition not found: ${resolvedPath}`);
196
+ }
197
+ const content = await readFile(resolvedPath, "utf-8");
198
+ let mcpDef;
199
+ try {
200
+ mcpDef = JSON.parse(content);
201
+ } catch (err) {
202
+ console.warn(
203
+ fmt.yellow(`Warning: Could not parse MCP definition as JSON: ${toErrorMessage(err)}`)
204
+ );
205
+ mcpDef = { name: basename(resolvedPath, ".json") };
206
+ }
207
+ const name = mcpDef.name || basename(resolvedPath, ".json");
208
+ const description = mcpDef.description || "Extracted from MCP tool";
209
+ const inputFields = [];
210
+ if (mcpDef.inputSchema && typeof mcpDef.inputSchema === "object") {
211
+ const schema = mcpDef.inputSchema;
212
+ const required = new Set(schema.required ?? []);
213
+ if (schema.properties) {
214
+ for (const [key, value] of Object.entries(schema.properties)) {
215
+ let zodType;
216
+ if (value.enum) {
217
+ zodType = `z.enum([${value.enum.map((v) => JSON.stringify(v)).join(", ")}])`;
218
+ } else {
219
+ zodType = jsonSchemaTypeToZodType(value.type);
220
+ }
221
+ if (!required.has(key)) {
222
+ zodType += ".optional()";
223
+ }
224
+ inputFields.push({
225
+ name: toSnakeCase(key),
226
+ type: value.type ?? "unknown",
227
+ zodType,
228
+ description: value.description || `${key} parameter`
229
+ });
230
+ }
231
+ }
232
+ }
233
+ if (inputFields.length === 0) {
234
+ inputFields.push({ name: "input", type: "string", zodType: "z.string()", description: "Tool input" });
235
+ }
236
+ return {
237
+ name: toSnakeCase(name),
238
+ description,
239
+ inputFields,
240
+ outputFields: [{ name: "result", type: "string", zodType: "z.string()", description: "Tool result" }],
241
+ sourceType: "mcp",
242
+ sourcePath: resolvedPath
243
+ };
244
+ }
245
+ async function extractFromCode(codePath) {
246
+ const resolvedPath = resolveAtomPath(codePath, process.cwd());
247
+ if (!await fileExists(resolvedPath)) {
248
+ throw new Error(`Code file not found: ${resolvedPath}`);
249
+ }
250
+ const content = await readFile(resolvedPath, "utf-8");
251
+ const name = basename(resolvedPath).replace(/\.[^.]+$/, "");
252
+ let description = "Extracted from code";
253
+ const jsdocMatch = content.match(/\/\*\*\s*\n\s*\*\s*([^\n]+)/);
254
+ if (jsdocMatch && jsdocMatch[1]) {
255
+ description = jsdocMatch[1].trim();
256
+ }
257
+ const { detectLanguage, isJavaScriptFamily, parseFile } = await import("./parser-3BILOSOO.js");
258
+ const { extractSignatures } = await import("./signatures-K5QIL4WG.js");
259
+ const lang = detectLanguage(resolvedPath);
260
+ const jsFamily = lang && isJavaScriptFamily(lang);
261
+ if (jsFamily) {
262
+ try {
263
+ const parseResult = await parseFile(content, resolvedPath);
264
+ if (parseResult.success && parseResult.language !== "python") {
265
+ const sigs = extractSignatures(parseResult.ast, content, parseResult.comments);
266
+ const primary = sigs.find((s) => s.exportDefault) ?? sigs.find((s) => s.exported) ?? sigs[0];
267
+ if (primary) {
268
+ const inputFields2 = primary.params.filter((p) => {
269
+ const fieldName = toSnakeCase(p.name);
270
+ return VALID_JS_IDENTIFIER.test(fieldName);
271
+ }).map((p) => ({
272
+ name: toSnakeCase(p.name),
273
+ type: p.type ?? "unknown",
274
+ zodType: tsTypeToZodType(p.type),
275
+ description: `${p.name} parameter`
276
+ }));
277
+ if (inputFields2.length === 0) {
278
+ inputFields2.push({ name: "input", type: "unknown", zodType: "z.unknown()", description: "Function input" });
279
+ }
280
+ return {
281
+ name: toSnakeCase(name),
282
+ description,
283
+ inputFields: inputFields2,
284
+ outputFields: [{ name: "result", type: "string", zodType: "z.string()", description: "Function result" }],
285
+ sourceType: "code",
286
+ sourcePath: resolvedPath
287
+ };
288
+ }
289
+ }
290
+ } catch {
291
+ }
292
+ }
293
+ const inputFields = [];
294
+ const functionMatch = content.match(/(?:function|const|let|var)\s+\w+\s*[=:]\s*(?:async\s+)?(?:\([^)]*\)|[^=]+=>)/);
295
+ if (functionMatch && functionMatch[0]) {
296
+ const paramMatch = functionMatch[0].match(/\(([^)]*)\)/);
297
+ if (paramMatch && paramMatch[1]) {
298
+ const paramsStr = paramMatch[1];
299
+ const params = paramsStr.split(",").map((p) => p.trim().split(":")[0]?.trim() ?? "");
300
+ for (const param of params) {
301
+ if (param && param !== "" && !param.startsWith("{")) {
302
+ inputFields.push({
303
+ name: toSnakeCase(param),
304
+ type: "string",
305
+ zodType: "z.string()",
306
+ description: `${param} parameter`
307
+ });
308
+ }
309
+ }
310
+ }
311
+ }
312
+ if (inputFields.length === 0) {
313
+ inputFields.push({ name: "input", type: "string", zodType: "z.string()", description: "Function input" });
314
+ }
315
+ return {
316
+ name: toSnakeCase(name),
317
+ description,
318
+ inputFields,
319
+ outputFields: [{ name: "result", type: "string", zodType: "z.string()", description: "Function result" }],
320
+ sourceType: "code",
321
+ sourcePath: resolvedPath
322
+ };
323
+ }
324
+ function escapeForTemplate(str) {
325
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/`/g, "\\`").replace(/\$\{/g, "\\${").replace(/\*\//g, "* /").replace(/\n/g, " ").replace(/\r/g, "");
326
+ }
327
+ function generateAtomTemplate(extracted) {
328
+ const escapedName = escapeForTemplate(extracted.name);
329
+ const escapedDescription = escapeForTemplate(extracted.description);
330
+ const escapedPath = escapeSourcePath(extracted.sourcePath);
331
+ const safeInputFields = extracted.inputFields.filter((f) => VALID_JS_IDENTIFIER.test(f.name) && isSafeZodType(f.zodType));
332
+ const safeOutputFields = extracted.outputFields.filter((f) => VALID_JS_IDENTIFIER.test(f.name) && isSafeZodType(f.zodType));
333
+ const droppedInputCount = extracted.inputFields.length - safeInputFields.length;
334
+ const droppedOutputCount = extracted.outputFields.length - safeOutputFields.length;
335
+ if (droppedInputCount > 0 || droppedOutputCount > 0) {
336
+ const parts = [];
337
+ if (droppedInputCount > 0) parts.push(`${droppedInputCount} input`);
338
+ if (droppedOutputCount > 0) parts.push(`${droppedOutputCount} output`);
339
+ console.error(fmt.warning(`Dropped ${parts.join(" and ")} field(s) with unsafe or invalid schema types`));
340
+ }
341
+ const inputSchema = safeInputFields.map((f) => ` ${f.name}: ${f.zodType}.describe('${escapeForTemplate(f.description)}'),`).join("\n");
342
+ const outputSchema = safeOutputFields.map((f) => ` ${f.name}: ${f.zodType}.describe('${escapeForTemplate(f.description)}'),`).join("\n");
343
+ const inputDestructure = safeInputFields.map((f) => f.name).join(", ");
344
+ return `import { defineAtom, success, executionError, z } from 'atomism';
345
+
346
+ /**
347
+ * ${escapedName} atom
348
+ *
349
+ * ${escapeForTemplate(extracted.description)}
350
+ *
351
+ * Extracted from: ${extracted.sourceType} at ${escapedPath}
352
+ */
353
+ export default defineAtom({
354
+ name: '${escapedName}',
355
+ description: '${escapedDescription}',
356
+ input: z.object({
357
+ ${inputSchema}
358
+ }),
359
+ output: z.object({
360
+ ${outputSchema}
361
+ }),
362
+ tests: {
363
+ path: './${escapedName}.test.ts',
364
+ },
365
+ idempotent: true,
366
+ handler: async ({ ${inputDestructure} }) => {
367
+ // TODO: Implement handler logic
368
+ // Original source: ${escapedPath}
369
+
370
+ return success({
371
+ ${safeOutputFields.map((f) => ` ${f.name}: '',`).join("\n")}
372
+ });
373
+ },
374
+ });
375
+ `;
376
+ }
377
+ function generateTestTemplate(extracted) {
378
+ const escapedName = escapeForTemplate(extracted.name);
379
+ const safeInputFields = extracted.inputFields.filter((f) => VALID_JS_IDENTIFIER.test(f.name));
380
+ return `import { describe, it, expect } from 'vitest';
381
+ import atom from './${escapedName}.js';
382
+
383
+ describe('${escapedName}', () => {
384
+ describe('input validation', () => {
385
+ ${safeInputFields.map((f) => ` it.todo('validates ${f.name} field');`).join("\n")}
386
+ });
387
+
388
+ describe('handler behavior', () => {
389
+ it.todo('processes valid input correctly');
390
+ it.todo('returns expected output structure');
391
+ });
392
+
393
+ describe('error handling', () => {
394
+ it.todo('handles invalid input gracefully');
395
+ });
396
+ });
397
+ `;
398
+ }
399
+ function formatExtractedAtom(extracted) {
400
+ const lines = [];
401
+ lines.push(fmt.bold("Proposed Atom Definition"));
402
+ lines.push("\u2500".repeat(60));
403
+ lines.push(` ${fmt.dim("Name:")} ${fmt.cyan(extracted.name)}`);
404
+ lines.push(` ${fmt.dim("Source:")} ${extracted.sourceType} (${extracted.sourcePath})`);
405
+ lines.push(` ${fmt.dim("Description:")} ${extracted.description.substring(0, 60)}${extracted.description.length > 60 ? "..." : ""}`);
406
+ lines.push("");
407
+ lines.push(fmt.bold("Input Schema"));
408
+ lines.push("\u2500".repeat(60));
409
+ for (const field of extracted.inputFields) {
410
+ lines.push(` ${fmt.green(field.name)}: ${field.type}`);
411
+ lines.push(` ${fmt.dim(field.description)}`);
412
+ }
413
+ lines.push("");
414
+ lines.push(fmt.bold("Output Schema"));
415
+ lines.push("\u2500".repeat(60));
416
+ for (const field of extracted.outputFields) {
417
+ lines.push(` ${fmt.green(field.name)}: ${field.type}`);
418
+ lines.push(` ${fmt.dim(field.description)}`);
419
+ }
420
+ return lines.join("\n");
421
+ }
422
+ async function extractCommand(options) {
423
+ const projectRoot = process.cwd();
424
+ try {
425
+ let extracted;
426
+ if (options.skill) {
427
+ extracted = await extractFromSkill(options.skill);
428
+ } else if (options.bmad) {
429
+ extracted = await extractFromBmad(options.bmad);
430
+ } else if (options.mcp) {
431
+ extracted = await extractFromMcp(options.mcp);
432
+ } else if (options.code) {
433
+ extracted = await extractFromCode(options.code);
434
+ } else {
435
+ throw new Error(
436
+ "No source specified.\nUse one of: --skill <path>, --bmad <path>, --mcp <path>, --code <path>"
437
+ );
438
+ }
439
+ if (!options.json) {
440
+ console.log(formatExtractedAtom(extracted));
441
+ console.log("");
442
+ }
443
+ if (!options.yes && !options.json) {
444
+ console.log(fmt.yellow("Use --yes to automatically create the atom."));
445
+ console.log(fmt.dim("Use --json for programmatic output."));
446
+ return;
447
+ }
448
+ if (!options.yes && options.json) {
449
+ const outputDir2 = options.output ? resolveAtomPath(options.output, projectRoot) : join(projectRoot, "atoms");
450
+ const result2 = {
451
+ success: true,
452
+ extracted,
453
+ wouldWriteTo: {
454
+ atom: join(outputDir2, `${extracted.name}.ts`),
455
+ test: join(outputDir2, `${extracted.name}.test.ts`)
456
+ }
457
+ };
458
+ console.log(JSON.stringify(result2, null, 2));
459
+ return;
460
+ }
461
+ const atomicPath = join(projectRoot, ATOMIC_DIR);
462
+ if (!await fileExists(atomicPath)) {
463
+ await initStorage(projectRoot);
464
+ }
465
+ const outputDir = options.output ? resolveAtomPath(options.output, projectRoot) : join(projectRoot, "atoms");
466
+ await mkdir(outputDir, { recursive: true });
467
+ const atomPath = join(outputDir, `${extracted.name}.ts`);
468
+ const testPath = join(outputDir, `${extracted.name}.test.ts`);
469
+ const resolvedOutputDir = resolve(outputDir);
470
+ const rel = relative(resolvedOutputDir, resolve(atomPath));
471
+ if (rel.startsWith("..") || isAbsolute(rel)) {
472
+ throw new Error("Generated path escapes output directory");
473
+ }
474
+ if (await fileExists(atomPath)) {
475
+ throw new Error(`Atom file already exists: ${atomPath}`);
476
+ }
477
+ if (await fileExists(testPath)) {
478
+ throw new Error(`Test file already exists: ${testPath}`);
479
+ }
480
+ await writeFile(atomPath, generateAtomTemplate(extracted));
481
+ await writeFile(testPath, generateTestTemplate(extracted));
482
+ const result = {
483
+ success: true,
484
+ extracted,
485
+ atomPath,
486
+ testPath
487
+ };
488
+ if (options.json) {
489
+ console.log(JSON.stringify(result, null, 2));
490
+ } else {
491
+ console.log(fmt.green("\u2713 Atom extracted successfully"));
492
+ console.log(` ${fmt.dim("Atom:")} ${atomPath}`);
493
+ console.log(` ${fmt.dim("Test:")} ${testPath}`);
494
+ console.log("");
495
+ console.log("Next steps:");
496
+ console.log(` 1. Review and edit ${atomPath}`);
497
+ console.log(` 2. Run: atomic register ${atomPath}`);
498
+ }
499
+ } catch (err) {
500
+ const message = toErrorMessage(err);
501
+ if (options.json) {
502
+ const { deriveErrorCode } = await import("./helpers-PJPFPYBQ.js");
503
+ console.log(JSON.stringify({ success: false, error: message, errorCode: deriveErrorCode(err) }, null, 2));
504
+ } else {
505
+ console.error(fmt.error(`Extraction failed: ${message}`));
506
+ }
507
+ process.exit(1);
508
+ }
509
+ }
510
+ export {
511
+ escapeSourcePath,
512
+ extractCommand
513
+ };
514
+ //# sourceMappingURL=extract-RPKCTINT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/extract.ts"],"sourcesContent":["/**\n * Extract command - Create atoms from existing sources.\n *\n * Story 1.10: AOP-1216\n *\n * Acceptance Criteria:\n * - Extract from Claude Code skills, BMAD workflows, MCP tools, or code\n * - Analyze source for input parameters, output format, description\n * - Display proposed atom definition for user approval\n * - Create atom file with extracted structure\n */\n\nimport { readFile, stat, mkdir, writeFile } from 'node:fs/promises';\nimport { join, basename, dirname, resolve, relative, isAbsolute } from 'node:path';\nimport { fmt } from '../cli/format.js';\nimport { initStorage, ATOMIC_DIR, fileExists } from '../storage/index.js';\nimport { toErrorMessage } from '../utils/errors.js';\nimport { resolveAtomPath } from '../utils/paths.js';\n\n/**\n * Options for the extract command.\n */\nexport interface ExtractOptions {\n skill?: string;\n bmad?: string;\n mcp?: string;\n code?: string;\n output?: string;\n yes?: boolean;\n json?: boolean;\n}\n\n/**\n * A single extracted field with human-readable type and Zod code-gen token.\n */\nexport interface ExtractedField {\n name: string;\n type: string; // human label: 'string', 'number', etc.\n zodType: string; // code-gen token: 'z.string()', 'z.number()', etc.\n description: string;\n}\n\n/**\n * Extracted atom definition.\n */\nexport interface ExtractedAtom {\n name: string;\n description: string;\n inputFields: ExtractedField[];\n outputFields: ExtractedField[];\n sourceType: 'skill' | 'bmad' | 'mcp' | 'code';\n sourcePath: string;\n}\n\n/**\n * Result of extraction.\n */\nexport interface ExtractResult {\n success: boolean;\n extracted?: ExtractedAtom;\n atomPath?: string;\n testPath?: string;\n error?: string;\n}\n\n/**\n * Parse YAML frontmatter from markdown content.\n *\n * Note: This is a simple parser that handles basic key: value pairs.\n * It does not support quoted values with colons, multi-line strings,\n * or nested structures. For complex YAML, consider using a proper parser.\n */\nfunction parseFrontmatter(content: string): Record<string, string> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match || !match[1]) {\n return {};\n }\n\n const frontmatter: Record<string, string> = {};\n const lines = match[1].split('\\n');\n\n for (const line of lines) {\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex).trim();\n const value = line.substring(colonIndex + 1).trim();\n frontmatter[key] = value;\n }\n }\n\n return frontmatter;\n}\n\n/**\n * Convert a name to snake_case.\n */\nfunction toSnakeCase(name: string): string {\n return name\n .replace(/[^a-zA-Z0-9]+/g, '_')\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .toLowerCase()\n .replace(/^_+|_+$/g, '')\n .replace(/_+/g, '_');\n}\n\n/** Valid JS identifier pattern for field names in generated code. */\nconst VALID_JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;\n\n/**\n * Validate that a zodType string is a safe Zod expression.\n * zodType is injected as raw code — structural validation prevents code injection.\n * Matches only the patterns produced by tsTypeToZodType/jsonSchemaTypeToZodType:\n * z.method() — z.string(), z.number(), etc.\n * z.method(z.method()) — z.array(z.string())\n * z.method(z.method(), z.method()) — z.record(z.string(), z.number())\n * z.enum([\"a\", \"b\"]) — enum with JSON-stringified values\n * any of the above + .optional() — optional modifier\n */\nfunction isSafeZodType(expr: string): boolean {\n const base = expr.replace(/\\.optional\\(\\)$/, '');\n // Simple: z.string(), z.number(), z.unknown(), etc.\n if (/^z\\.[a-z]+\\(\\)$/.test(base)) return true;\n // Wrapper: z.array(z.string()), z.record(z.string(), z.number())\n if (/^z\\.[a-z]+\\(z\\.[a-z]+\\(\\)(, z\\.[a-z]+\\(\\))?\\)$/.test(base)) return true;\n // Enum: z.enum([\"a\", \"b\", \"c\"]) — values are JSON.stringify'd (no unescaped quotes/backslashes)\n if (/^z\\.enum\\(\\[(\"[^\"\\\\]*\"(, \"[^\"\\\\]*\")*)\\]\\)$/.test(base)) return true;\n return false;\n}\n\n/**\n * Map a TypeScript type annotation string to a Zod type expression.\n */\nfunction tsTypeToZodType(tsType: string | undefined): string {\n if (!tsType) return 'z.unknown()';\n switch (tsType) {\n case 'string': return 'z.string()';\n case 'number': return 'z.number()';\n case 'boolean': return 'z.boolean()';\n case 'Date': return 'z.date()';\n case 'bigint': return 'z.bigint()';\n case 'void': return 'z.void()';\n case 'undefined': return 'z.undefined()';\n case 'null': return 'z.null()';\n case 'any': return 'z.any()';\n case 'unknown': return 'z.unknown()';\n case 'never': return 'z.never()';\n default:\n if (tsType.endsWith('[]')) {\n const inner = tsTypeToZodType(tsType.slice(0, -2));\n return `z.array(${inner})`;\n }\n if (tsType.startsWith('Record<')) {\n const match = tsType.match(/^Record<(.+),\\s*(.+)>$/);\n if (match) {\n return `z.record(${tsTypeToZodType(match[1])}, ${tsTypeToZodType(match[2])})`;\n }\n }\n return 'z.unknown()';\n }\n}\n\n/**\n * Map a JSON Schema type string to a Zod type expression.\n */\nfunction jsonSchemaTypeToZodType(schemaType: string | undefined): string {\n switch (schemaType) {\n case 'string': return 'z.string()';\n case 'number': case 'integer': return 'z.number()';\n case 'boolean': return 'z.boolean()';\n case 'array': return 'z.array(z.unknown())';\n case 'object': return 'z.record(z.string(), z.unknown())';\n case 'null': return 'z.null()';\n default: return 'z.unknown()';\n }\n}\n\n/**\n * Escape sourcePath to prevent comment injection (close-comment sequence).\n */\nexport function escapeSourcePath(path: string): string {\n return path.replace(/\\*\\//g, '*\\\\/');\n}\n\n/**\n * Extract atom from Claude Code skill.\n */\nasync function extractFromSkill(skillPath: string): Promise<ExtractedAtom> {\n const resolvedPath = resolveAtomPath(skillPath, process.cwd());\n\n // Check if it's a directory or file\n const stats = await stat(resolvedPath);\n let skillContent: string;\n let skillFile: string;\n\n if (stats.isDirectory()) {\n // Look for SKILL.md in directory\n skillFile = join(resolvedPath, 'SKILL.md');\n if (!(await fileExists(skillFile))) {\n throw new Error(`No SKILL.md found in ${resolvedPath}`);\n }\n skillContent = await readFile(skillFile, 'utf-8');\n } else {\n // Direct file path\n skillFile = resolvedPath;\n skillContent = await readFile(skillFile, 'utf-8');\n }\n\n // Parse frontmatter\n const frontmatter = parseFrontmatter(skillContent);\n const name = frontmatter['name'] || basename(dirname(skillFile));\n const description = frontmatter['description'] || 'Extracted from Claude Code skill';\n\n // Analyze content for input/output patterns\n const inputFields = analyzeSkillInputs(skillContent);\n const outputFields = analyzeSkillOutputs(skillContent);\n\n return {\n name: toSnakeCase(name),\n description,\n inputFields,\n outputFields,\n sourceType: 'skill',\n sourcePath: skillFile,\n };\n}\n\n/**\n * Analyze content for field patterns matching a set of regexes.\n * Shared logic for input/output field extraction from skill documentation.\n */\nfunction analyzeFieldPatterns(\n content: string,\n patterns: RegExp[],\n defaultField: { name: string; description: string },\n descriptionSuffix: string,\n): ExtractedAtom['inputFields'] {\n const found = new Set<string>();\n\n for (const pattern of patterns) {\n for (const match of content.matchAll(pattern)) {\n const name = match[1]?.toLowerCase();\n if (name && !found.has(name) && name.length > 2) {\n found.add(name);\n }\n }\n }\n\n if (found.size === 0) {\n return [{ name: defaultField.name, type: 'string', zodType: 'z.string()', description: defaultField.description }];\n }\n\n const fields: ExtractedAtom['inputFields'] = [];\n for (const name of found) {\n fields.push({ name: toSnakeCase(name), type: 'string', zodType: 'z.string()', description: `${name} ${descriptionSuffix}` });\n }\n return fields.slice(0, 5);\n}\n\nconst INPUT_PATTERNS = [\n /accepts?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n /input[:\\s]+([a-z_]+)/gi,\n /receives?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n /takes?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n];\n\nconst OUTPUT_PATTERNS = [\n /outputs?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n /returns?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n /produces?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n /generates?\\s+(?:an?\\s+)?([a-z_]+)/gi,\n];\n\nfunction analyzeSkillInputs(content: string): ExtractedAtom['inputFields'] {\n return analyzeFieldPatterns(content, INPUT_PATTERNS, { name: 'input', description: 'Input data to process' }, 'parameter');\n}\n\nfunction analyzeSkillOutputs(content: string): ExtractedAtom['outputFields'] {\n return analyzeFieldPatterns(content, OUTPUT_PATTERNS, { name: 'result', description: 'Processing result' }, 'output');\n}\n\n/**\n * Extract atom from BMAD workflow.\n */\nasync function extractFromBmad(bmadPath: string): Promise<ExtractedAtom> {\n const resolvedPath = resolveAtomPath(bmadPath, process.cwd());\n\n if (!(await fileExists(resolvedPath))) {\n throw new Error(`BMAD workflow not found: ${resolvedPath}`);\n }\n\n const content = await readFile(resolvedPath, 'utf-8');\n const frontmatter = parseFrontmatter(content);\n\n const name = frontmatter['name'] || basename(resolvedPath, '.md');\n const description = frontmatter['description'] || 'Extracted from BMAD workflow';\n\n return {\n name: toSnakeCase(name),\n description,\n inputFields: [{ name: 'context', type: 'string', zodType: 'z.string()', description: 'Workflow context' }],\n outputFields: [{ name: 'result', type: 'string', zodType: 'z.string()', description: 'Workflow result' }],\n sourceType: 'bmad',\n sourcePath: resolvedPath,\n };\n}\n\n/**\n * Extract atom from MCP tool definition.\n */\nasync function extractFromMcp(mcpPath: string): Promise<ExtractedAtom> {\n const resolvedPath = resolveAtomPath(mcpPath, process.cwd());\n\n if (!(await fileExists(resolvedPath))) {\n throw new Error(`MCP tool definition not found: ${resolvedPath}`);\n }\n\n const content = await readFile(resolvedPath, 'utf-8');\n\n // Try to parse as JSON (MCP tool definitions are often JSON)\n let mcpDef: { name?: string; description?: string; inputSchema?: unknown };\n try {\n mcpDef = JSON.parse(content);\n } catch (err) {\n // If not JSON, warn and treat as a generic definition\n console.warn(\n fmt.yellow(`Warning: Could not parse MCP definition as JSON: ${toErrorMessage(err)}`)\n );\n mcpDef = { name: basename(resolvedPath, '.json') };\n }\n\n const name = mcpDef.name || basename(resolvedPath, '.json');\n const description = mcpDef.description || 'Extracted from MCP tool';\n\n // Extract input fields from inputSchema if present\n const inputFields: ExtractedAtom['inputFields'] = [];\n if (mcpDef.inputSchema && typeof mcpDef.inputSchema === 'object') {\n const schema = mcpDef.inputSchema as {\n properties?: Record<string, { type?: string; description?: string; enum?: string[] }>;\n required?: string[];\n };\n const required = new Set(schema.required ?? []);\n if (schema.properties) {\n for (const [key, value] of Object.entries(schema.properties)) {\n let zodType: string;\n if (value.enum) {\n zodType = `z.enum([${value.enum.map(v => JSON.stringify(v)).join(', ')}])`;\n } else {\n zodType = jsonSchemaTypeToZodType(value.type);\n }\n if (!required.has(key)) {\n zodType += '.optional()';\n }\n inputFields.push({\n name: toSnakeCase(key),\n type: value.type ?? 'unknown',\n zodType,\n description: value.description || `${key} parameter`,\n });\n }\n }\n }\n\n if (inputFields.length === 0) {\n inputFields.push({ name: 'input', type: 'string', zodType: 'z.string()', description: 'Tool input' });\n }\n\n return {\n name: toSnakeCase(name),\n description,\n inputFields,\n outputFields: [{ name: 'result', type: 'string', zodType: 'z.string()', description: 'Tool result' }],\n sourceType: 'mcp',\n sourcePath: resolvedPath,\n };\n}\n\n/**\n * Extract atom from existing code file using AST-based extraction.\n *\n * For JS/TS files, uses oxc-parser via dynamic import to extract typed\n * function signatures. Falls back to regex for non-JS/TS or parse failures.\n * The dynamic import ensures oxc-parser is only loaded when --code is used.\n */\nasync function extractFromCode(codePath: string): Promise<ExtractedAtom> {\n const resolvedPath = resolveAtomPath(codePath, process.cwd());\n\n if (!(await fileExists(resolvedPath))) {\n throw new Error(`Code file not found: ${resolvedPath}`);\n }\n\n const content = await readFile(resolvedPath, 'utf-8');\n const name = basename(resolvedPath).replace(/\\.[^.]+$/, '');\n\n // Extract description from JSDoc or first comment\n let description = 'Extracted from code';\n const jsdocMatch = content.match(/\\/\\*\\*\\s*\\n\\s*\\*\\s*([^\\n]+)/);\n if (jsdocMatch && jsdocMatch[1]) {\n description = jsdocMatch[1].trim();\n }\n\n // Try AST-based extraction for JS/TS files\n const { detectLanguage, isJavaScriptFamily, parseFile } = await import('../parser/index.js');\n const { extractSignatures } = await import('../parser/signatures.js');\n const lang = detectLanguage(resolvedPath);\n const jsFamily = lang && isJavaScriptFamily(lang);\n\n if (jsFamily) {\n try {\n\n const parseResult = await parseFile(content, resolvedPath);\n if (parseResult.success && parseResult.language !== 'python') {\n const sigs = extractSignatures(parseResult.ast, content, parseResult.comments);\n // Pick primary export: first default export, or first named export\n const primary = sigs.find(s => s.exportDefault) ?? sigs.find(s => s.exported) ?? sigs[0];\n\n if (primary) {\n const inputFields: ExtractedAtom['inputFields'] = primary.params\n .filter(p => {\n const fieldName = toSnakeCase(p.name);\n return VALID_JS_IDENTIFIER.test(fieldName);\n })\n .map(p => ({\n name: toSnakeCase(p.name),\n type: p.type ?? 'unknown',\n zodType: tsTypeToZodType(p.type),\n description: `${p.name} parameter`,\n }));\n\n if (inputFields.length === 0) {\n inputFields.push({ name: 'input', type: 'unknown', zodType: 'z.unknown()', description: 'Function input' });\n }\n\n return {\n name: toSnakeCase(name),\n description,\n inputFields,\n outputFields: [{ name: 'result', type: 'string', zodType: 'z.string()', description: 'Function result' }],\n sourceType: 'code',\n sourcePath: resolvedPath,\n };\n }\n }\n // Parse succeeded but no functions found — fall through to regex\n } catch {\n // AST parse failed — fall through to regex fallback\n }\n }\n\n // Regex fallback for non-JS/TS files or parse failures\n const inputFields: ExtractedAtom['inputFields'] = [];\n const functionMatch = content.match(/(?:function|const|let|var)\\s+\\w+\\s*[=:]\\s*(?:async\\s+)?(?:\\([^)]*\\)|[^=]+=>)/);\n if (functionMatch && functionMatch[0]) {\n const paramMatch = functionMatch[0].match(/\\(([^)]*)\\)/);\n if (paramMatch && paramMatch[1]) {\n const paramsStr = paramMatch[1];\n const params = paramsStr.split(',').map((p) => p.trim().split(':')[0]?.trim() ?? '');\n for (const param of params) {\n if (param && param !== '' && !param.startsWith('{')) {\n inputFields.push({\n name: toSnakeCase(param),\n type: 'string',\n zodType: 'z.string()',\n description: `${param} parameter`,\n });\n }\n }\n }\n }\n\n if (inputFields.length === 0) {\n inputFields.push({ name: 'input', type: 'string', zodType: 'z.string()', description: 'Function input' });\n }\n\n return {\n name: toSnakeCase(name),\n description,\n inputFields,\n outputFields: [{ name: 'result', type: 'string', zodType: 'z.string()', description: 'Function result' }],\n sourceType: 'code',\n sourcePath: resolvedPath,\n };\n}\n\n/**\n * Escape a string for use in a single-quoted TypeScript string literal.\n */\nfunction escapeForTemplate(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/`/g, '\\\\`')\n .replace(/\\$\\{/g, '\\\\${')\n .replace(/\\*\\//g, '* /')\n .replace(/\\n/g, ' ')\n .replace(/\\r/g, '');\n}\n\n/**\n * Generate atom template from extracted definition.\n */\nfunction generateAtomTemplate(extracted: ExtractedAtom): string {\n const escapedName = escapeForTemplate(extracted.name);\n const escapedDescription = escapeForTemplate(extracted.description);\n const escapedPath = escapeSourcePath(extracted.sourcePath);\n\n // Filter fields to valid JS identifiers and safe Zod types only\n const safeInputFields = extracted.inputFields\n .filter(f => VALID_JS_IDENTIFIER.test(f.name) && isSafeZodType(f.zodType));\n const safeOutputFields = extracted.outputFields\n .filter(f => VALID_JS_IDENTIFIER.test(f.name) && isSafeZodType(f.zodType));\n\n const droppedInputCount = extracted.inputFields.length - safeInputFields.length;\n const droppedOutputCount = extracted.outputFields.length - safeOutputFields.length;\n if (droppedInputCount > 0 || droppedOutputCount > 0) {\n const parts: string[] = [];\n if (droppedInputCount > 0) parts.push(`${droppedInputCount} input`);\n if (droppedOutputCount > 0) parts.push(`${droppedOutputCount} output`);\n console.error(fmt.warning(`Dropped ${parts.join(' and ')} field(s) with unsafe or invalid schema types`));\n }\n\n const inputSchema = safeInputFields\n .map((f) => ` ${f.name}: ${f.zodType}.describe('${escapeForTemplate(f.description)}'),`)\n .join('\\n');\n\n const outputSchema = safeOutputFields\n .map((f) => ` ${f.name}: ${f.zodType}.describe('${escapeForTemplate(f.description)}'),`)\n .join('\\n');\n\n const inputDestructure = safeInputFields.map((f) => f.name).join(', ');\n\n return `import { defineAtom, success, executionError, z } from 'atomism';\n\n/**\n * ${escapedName} atom\n *\n * ${escapeForTemplate(extracted.description)}\n *\n * Extracted from: ${extracted.sourceType} at ${escapedPath}\n */\nexport default defineAtom({\n name: '${escapedName}',\n description: '${escapedDescription}',\n input: z.object({\n${inputSchema}\n }),\n output: z.object({\n${outputSchema}\n }),\n tests: {\n path: './${escapedName}.test.ts',\n },\n idempotent: true,\n handler: async ({ ${inputDestructure} }) => {\n // TODO: Implement handler logic\n // Original source: ${escapedPath}\n\n return success({\n${safeOutputFields.map((f) => ` ${f.name}: '',`).join('\\n')}\n });\n },\n});\n`;\n}\n\n/**\n * Generate test template from extracted definition.\n */\nfunction generateTestTemplate(extracted: ExtractedAtom): string {\n const escapedName = escapeForTemplate(extracted.name);\n const safeInputFields = extracted.inputFields.filter(f => VALID_JS_IDENTIFIER.test(f.name));\n return `import { describe, it, expect } from 'vitest';\nimport atom from './${escapedName}.js';\n\ndescribe('${escapedName}', () => {\n describe('input validation', () => {\n${safeInputFields.map((f) => ` it.todo('validates ${f.name} field');`).join('\\n')}\n });\n\n describe('handler behavior', () => {\n it.todo('processes valid input correctly');\n it.todo('returns expected output structure');\n });\n\n describe('error handling', () => {\n it.todo('handles invalid input gracefully');\n });\n});\n`;\n}\n\n/**\n * Format extracted definition for display.\n */\nfunction formatExtractedAtom(extracted: ExtractedAtom): string {\n const lines: string[] = [];\n\n lines.push(fmt.bold('Proposed Atom Definition'));\n lines.push('─'.repeat(60));\n lines.push(` ${fmt.dim('Name:')} ${fmt.cyan(extracted.name)}`);\n lines.push(` ${fmt.dim('Source:')} ${extracted.sourceType} (${extracted.sourcePath})`);\n lines.push(` ${fmt.dim('Description:')} ${extracted.description.substring(0, 60)}${extracted.description.length > 60 ? '...' : ''}`);\n lines.push('');\n\n lines.push(fmt.bold('Input Schema'));\n lines.push('─'.repeat(60));\n for (const field of extracted.inputFields) {\n lines.push(` ${fmt.green(field.name)}: ${field.type}`);\n lines.push(` ${fmt.dim(field.description)}`);\n }\n lines.push('');\n\n lines.push(fmt.bold('Output Schema'));\n lines.push('─'.repeat(60));\n for (const field of extracted.outputFields) {\n lines.push(` ${fmt.green(field.name)}: ${field.type}`);\n lines.push(` ${fmt.dim(field.description)}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Extract command handler.\n */\nexport async function extractCommand(options: ExtractOptions): Promise<void> {\n const projectRoot = process.cwd();\n\n try {\n // Determine source type and path\n let extracted: ExtractedAtom;\n\n if (options.skill) {\n extracted = await extractFromSkill(options.skill);\n } else if (options.bmad) {\n extracted = await extractFromBmad(options.bmad);\n } else if (options.mcp) {\n extracted = await extractFromMcp(options.mcp);\n } else if (options.code) {\n extracted = await extractFromCode(options.code);\n } else {\n throw new Error(\n 'No source specified.\\n' +\n 'Use one of: --skill <path>, --bmad <path>, --mcp <path>, --code <path>'\n );\n }\n\n // Display proposed definition\n if (!options.json) {\n console.log(formatExtractedAtom(extracted));\n console.log('');\n }\n\n // If --yes not specified and not in JSON mode, show preview and exit\n if (!options.yes && !options.json) {\n console.log(fmt.yellow('Use --yes to automatically create the atom.'));\n console.log(fmt.dim('Use --json for programmatic output.'));\n return;\n }\n\n // If --yes not specified but in JSON mode, output dry-run with wouldWriteTo\n if (!options.yes && options.json) {\n const outputDir = options.output\n ? resolveAtomPath(options.output, projectRoot)\n : join(projectRoot, 'atoms');\n const result: ExtractResult & { wouldWriteTo?: { atom: string; test: string } } = {\n success: true,\n extracted,\n wouldWriteTo: {\n atom: join(outputDir, `${extracted.name}.ts`),\n test: join(outputDir, `${extracted.name}.test.ts`),\n },\n };\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n // Initialize storage if needed\n const atomicPath = join(projectRoot, ATOMIC_DIR);\n if (!(await fileExists(atomicPath))) {\n await initStorage(projectRoot);\n }\n\n // Determine output directory\n const outputDir = options.output\n ? resolveAtomPath(options.output, projectRoot)\n : join(projectRoot, 'atoms');\n\n await mkdir(outputDir, { recursive: true });\n\n // Check if files already exist (with path containment guard)\n const atomPath = join(outputDir, `${extracted.name}.ts`);\n const testPath = join(outputDir, `${extracted.name}.test.ts`);\n const resolvedOutputDir = resolve(outputDir);\n const rel = relative(resolvedOutputDir, resolve(atomPath));\n if (rel.startsWith('..') || isAbsolute(rel)) {\n throw new Error('Generated path escapes output directory');\n }\n\n if (await fileExists(atomPath)) {\n throw new Error(`Atom file already exists: ${atomPath}`);\n }\n if (await fileExists(testPath)) {\n throw new Error(`Test file already exists: ${testPath}`);\n }\n\n // Write files\n await writeFile(atomPath, generateAtomTemplate(extracted));\n await writeFile(testPath, generateTestTemplate(extracted));\n\n // Output result\n const result: ExtractResult = {\n success: true,\n extracted,\n atomPath,\n testPath,\n };\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(fmt.green('✓ Atom extracted successfully'));\n console.log(` ${fmt.dim('Atom:')} ${atomPath}`);\n console.log(` ${fmt.dim('Test:')} ${testPath}`);\n console.log('');\n console.log('Next steps:');\n console.log(` 1. Review and edit ${atomPath}`);\n console.log(` 2. Run: atomic register ${atomPath}`);\n }\n } catch (err) {\n const message = toErrorMessage(err);\n if (options.json) {\n const { deriveErrorCode } = await import('./helpers.js');\n console.log(JSON.stringify({ success: false, error: message, errorCode: deriveErrorCode(err) }, null, 2));\n } else {\n console.error(fmt.error(`Extraction failed: ${message}`));\n }\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAYA,SAAS,UAAU,MAAM,OAAO,iBAAiB;AACjD,SAAS,MAAM,UAAU,SAAS,SAAS,UAAU,kBAAkB;AA2DvE,SAAS,iBAAiB,SAAyC;AACjE,QAAM,QAAQ,QAAQ,MAAM,uBAAuB;AACnD,MAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;AACvB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,cAAsC,CAAC;AAC7C,QAAM,QAAQ,MAAM,CAAC,EAAE,MAAM,IAAI;AAEjC,aAAW,QAAQ,OAAO;AACxB,UAAM,aAAa,KAAK,QAAQ,GAAG;AACnC,QAAI,aAAa,GAAG;AAClB,YAAM,MAAM,KAAK,UAAU,GAAG,UAAU,EAAE,KAAK;AAC/C,YAAM,QAAQ,KAAK,UAAU,aAAa,CAAC,EAAE,KAAK;AAClD,kBAAY,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,YAAY,MAAsB;AACzC,SAAO,KACJ,QAAQ,kBAAkB,GAAG,EAC7B,QAAQ,mBAAmB,OAAO,EAClC,YAAY,EACZ,QAAQ,YAAY,EAAE,EACtB,QAAQ,OAAO,GAAG;AACvB;AAGA,IAAM,sBAAsB;AAY5B,SAAS,cAAc,MAAuB;AAC5C,QAAM,OAAO,KAAK,QAAQ,mBAAmB,EAAE;AAE/C,MAAI,kBAAkB,KAAK,IAAI,EAAG,QAAO;AAEzC,MAAI,iDAAiD,KAAK,IAAI,EAAG,QAAO;AAExE,MAAI,6CAA6C,KAAK,IAAI,EAAG,QAAO;AACpE,SAAO;AACT;AAKA,SAAS,gBAAgB,QAAoC;AAC3D,MAAI,CAAC,OAAQ,QAAO;AACpB,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAO,aAAO;AAAA,IACnB,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAS,aAAO;AAAA,IACrB;AACE,UAAI,OAAO,SAAS,IAAI,GAAG;AACzB,cAAM,QAAQ,gBAAgB,OAAO,MAAM,GAAG,EAAE,CAAC;AACjD,eAAO,WAAW,KAAK;AAAA,MACzB;AACA,UAAI,OAAO,WAAW,SAAS,GAAG;AAChC,cAAM,QAAQ,OAAO,MAAM,wBAAwB;AACnD,YAAI,OAAO;AACT,iBAAO,YAAY,gBAAgB,MAAM,CAAC,CAAC,CAAC,KAAK,gBAAgB,MAAM,CAAC,CAAC,CAAC;AAAA,QAC5E;AAAA,MACF;AACA,aAAO;AAAA,EACX;AACF;AAKA,SAAS,wBAAwB,YAAwC;AACvE,UAAQ,YAAY;AAAA,IAClB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAA,IAAU,KAAK;AAAW,aAAO;AAAA,IACtC,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAS,aAAO;AAAA,IACrB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAQ,aAAO;AAAA,IACpB;AAAS,aAAO;AAAA,EAClB;AACF;AAKO,SAAS,iBAAiB,MAAsB;AACrD,SAAO,KAAK,QAAQ,SAAS,MAAM;AACrC;AAKA,eAAe,iBAAiB,WAA2C;AACzE,QAAM,eAAe,gBAAgB,WAAW,QAAQ,IAAI,CAAC;AAG7D,QAAM,QAAQ,MAAM,KAAK,YAAY;AACrC,MAAI;AACJ,MAAI;AAEJ,MAAI,MAAM,YAAY,GAAG;AAEvB,gBAAY,KAAK,cAAc,UAAU;AACzC,QAAI,CAAE,MAAM,WAAW,SAAS,GAAI;AAClC,YAAM,IAAI,MAAM,wBAAwB,YAAY,EAAE;AAAA,IACxD;AACA,mBAAe,MAAM,SAAS,WAAW,OAAO;AAAA,EAClD,OAAO;AAEL,gBAAY;AACZ,mBAAe,MAAM,SAAS,WAAW,OAAO;AAAA,EAClD;AAGA,QAAM,cAAc,iBAAiB,YAAY;AACjD,QAAM,OAAO,YAAY,MAAM,KAAK,SAAS,QAAQ,SAAS,CAAC;AAC/D,QAAM,cAAc,YAAY,aAAa,KAAK;AAGlD,QAAM,cAAc,mBAAmB,YAAY;AACnD,QAAM,eAAe,oBAAoB,YAAY;AAErD,SAAO;AAAA,IACL,MAAM,YAAY,IAAI;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAMA,SAAS,qBACP,SACA,UACA,cACA,mBAC8B;AAC9B,QAAM,QAAQ,oBAAI,IAAY;AAE9B,aAAW,WAAW,UAAU;AAC9B,eAAW,SAAS,QAAQ,SAAS,OAAO,GAAG;AAC7C,YAAM,OAAO,MAAM,CAAC,GAAG,YAAY;AACnC,UAAI,QAAQ,CAAC,MAAM,IAAI,IAAI,KAAK,KAAK,SAAS,GAAG;AAC/C,cAAM,IAAI,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,CAAC,EAAE,MAAM,aAAa,MAAM,MAAM,UAAU,SAAS,cAAc,aAAa,aAAa,YAAY,CAAC;AAAA,EACnH;AAEA,QAAM,SAAuC,CAAC;AAC9C,aAAW,QAAQ,OAAO;AACxB,WAAO,KAAK,EAAE,MAAM,YAAY,IAAI,GAAG,MAAM,UAAU,SAAS,cAAc,aAAa,GAAG,IAAI,IAAI,iBAAiB,GAAG,CAAC;AAAA,EAC7H;AACA,SAAO,OAAO,MAAM,GAAG,CAAC;AAC1B;AAEA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,mBAAmB,SAA+C;AACzE,SAAO,qBAAqB,SAAS,gBAAgB,EAAE,MAAM,SAAS,aAAa,wBAAwB,GAAG,WAAW;AAC3H;AAEA,SAAS,oBAAoB,SAAgD;AAC3E,SAAO,qBAAqB,SAAS,iBAAiB,EAAE,MAAM,UAAU,aAAa,oBAAoB,GAAG,QAAQ;AACtH;AAKA,eAAe,gBAAgB,UAA0C;AACvE,QAAM,eAAe,gBAAgB,UAAU,QAAQ,IAAI,CAAC;AAE5D,MAAI,CAAE,MAAM,WAAW,YAAY,GAAI;AACrC,UAAM,IAAI,MAAM,4BAA4B,YAAY,EAAE;AAAA,EAC5D;AAEA,QAAM,UAAU,MAAM,SAAS,cAAc,OAAO;AACpD,QAAM,cAAc,iBAAiB,OAAO;AAE5C,QAAM,OAAO,YAAY,MAAM,KAAK,SAAS,cAAc,KAAK;AAChE,QAAM,cAAc,YAAY,aAAa,KAAK;AAElD,SAAO;AAAA,IACL,MAAM,YAAY,IAAI;AAAA,IACtB;AAAA,IACA,aAAa,CAAC,EAAE,MAAM,WAAW,MAAM,UAAU,SAAS,cAAc,aAAa,mBAAmB,CAAC;AAAA,IACzG,cAAc,CAAC,EAAE,MAAM,UAAU,MAAM,UAAU,SAAS,cAAc,aAAa,kBAAkB,CAAC;AAAA,IACxG,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAKA,eAAe,eAAe,SAAyC;AACrE,QAAM,eAAe,gBAAgB,SAAS,QAAQ,IAAI,CAAC;AAE3D,MAAI,CAAE,MAAM,WAAW,YAAY,GAAI;AACrC,UAAM,IAAI,MAAM,kCAAkC,YAAY,EAAE;AAAA,EAClE;AAEA,QAAM,UAAU,MAAM,SAAS,cAAc,OAAO;AAGpD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,OAAO;AAAA,EAC7B,SAAS,KAAK;AAEZ,YAAQ;AAAA,MACN,IAAI,OAAO,oDAAoD,eAAe,GAAG,CAAC,EAAE;AAAA,IACtF;AACA,aAAS,EAAE,MAAM,SAAS,cAAc,OAAO,EAAE;AAAA,EACnD;AAEA,QAAM,OAAO,OAAO,QAAQ,SAAS,cAAc,OAAO;AAC1D,QAAM,cAAc,OAAO,eAAe;AAG1C,QAAM,cAA4C,CAAC;AACnD,MAAI,OAAO,eAAe,OAAO,OAAO,gBAAgB,UAAU;AAChE,UAAM,SAAS,OAAO;AAItB,UAAM,WAAW,IAAI,IAAI,OAAO,YAAY,CAAC,CAAC;AAC9C,QAAI,OAAO,YAAY;AACrB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC5D,YAAI;AACJ,YAAI,MAAM,MAAM;AACd,oBAAU,WAAW,MAAM,KAAK,IAAI,OAAK,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,QACxE,OAAO;AACL,oBAAU,wBAAwB,MAAM,IAAI;AAAA,QAC9C;AACA,YAAI,CAAC,SAAS,IAAI,GAAG,GAAG;AACtB,qBAAW;AAAA,QACb;AACA,oBAAY,KAAK;AAAA,UACf,MAAM,YAAY,GAAG;AAAA,UACrB,MAAM,MAAM,QAAQ;AAAA,UACpB;AAAA,UACA,aAAa,MAAM,eAAe,GAAG,GAAG;AAAA,QAC1C,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,WAAW,GAAG;AAC5B,gBAAY,KAAK,EAAE,MAAM,SAAS,MAAM,UAAU,SAAS,cAAc,aAAa,aAAa,CAAC;AAAA,EACtG;AAEA,SAAO;AAAA,IACL,MAAM,YAAY,IAAI;AAAA,IACtB;AAAA,IACA;AAAA,IACA,cAAc,CAAC,EAAE,MAAM,UAAU,MAAM,UAAU,SAAS,cAAc,aAAa,cAAc,CAAC;AAAA,IACpG,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AASA,eAAe,gBAAgB,UAA0C;AACvE,QAAM,eAAe,gBAAgB,UAAU,QAAQ,IAAI,CAAC;AAE5D,MAAI,CAAE,MAAM,WAAW,YAAY,GAAI;AACrC,UAAM,IAAI,MAAM,wBAAwB,YAAY,EAAE;AAAA,EACxD;AAEA,QAAM,UAAU,MAAM,SAAS,cAAc,OAAO;AACpD,QAAM,OAAO,SAAS,YAAY,EAAE,QAAQ,YAAY,EAAE;AAG1D,MAAI,cAAc;AAClB,QAAM,aAAa,QAAQ,MAAM,6BAA6B;AAC9D,MAAI,cAAc,WAAW,CAAC,GAAG;AAC/B,kBAAc,WAAW,CAAC,EAAE,KAAK;AAAA,EACnC;AAGA,QAAM,EAAE,gBAAgB,oBAAoB,UAAU,IAAI,MAAM,OAAO,sBAAoB;AAC3F,QAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,0BAAyB;AACpE,QAAM,OAAO,eAAe,YAAY;AACxC,QAAM,WAAW,QAAQ,mBAAmB,IAAI;AAEhD,MAAI,UAAU;AACZ,QAAI;AAEF,YAAM,cAAc,MAAM,UAAU,SAAS,YAAY;AACzD,UAAI,YAAY,WAAW,YAAY,aAAa,UAAU;AAC5D,cAAM,OAAO,kBAAkB,YAAY,KAAK,SAAS,YAAY,QAAQ;AAE7E,cAAM,UAAU,KAAK,KAAK,OAAK,EAAE,aAAa,KAAK,KAAK,KAAK,OAAK,EAAE,QAAQ,KAAK,KAAK,CAAC;AAEvF,YAAI,SAAS;AACX,gBAAMA,eAA4C,QAAQ,OACvD,OAAO,OAAK;AACX,kBAAM,YAAY,YAAY,EAAE,IAAI;AACpC,mBAAO,oBAAoB,KAAK,SAAS;AAAA,UAC3C,CAAC,EACA,IAAI,QAAM;AAAA,YACT,MAAM,YAAY,EAAE,IAAI;AAAA,YACxB,MAAM,EAAE,QAAQ;AAAA,YAChB,SAAS,gBAAgB,EAAE,IAAI;AAAA,YAC/B,aAAa,GAAG,EAAE,IAAI;AAAA,UACxB,EAAE;AAEJ,cAAIA,aAAY,WAAW,GAAG;AAC5B,YAAAA,aAAY,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,SAAS,eAAe,aAAa,iBAAiB,CAAC;AAAA,UAC5G;AAEA,iBAAO;AAAA,YACL,MAAM,YAAY,IAAI;AAAA,YACtB;AAAA,YACA,aAAAA;AAAA,YACA,cAAc,CAAC,EAAE,MAAM,UAAU,MAAM,UAAU,SAAS,cAAc,aAAa,kBAAkB,CAAC;AAAA,YACxG,YAAY;AAAA,YACZ,YAAY;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAAA,IAEF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,cAA4C,CAAC;AACnD,QAAM,gBAAgB,QAAQ,MAAM,8EAA8E;AAClH,MAAI,iBAAiB,cAAc,CAAC,GAAG;AACrC,UAAM,aAAa,cAAc,CAAC,EAAE,MAAM,aAAa;AACvD,QAAI,cAAc,WAAW,CAAC,GAAG;AAC/B,YAAM,YAAY,WAAW,CAAC;AAC9B,YAAM,SAAS,UAAU,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,KAAK,EAAE;AACnF,iBAAW,SAAS,QAAQ;AAC1B,YAAI,SAAS,UAAU,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG;AACnD,sBAAY,KAAK;AAAA,YACf,MAAM,YAAY,KAAK;AAAA,YACvB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,aAAa,GAAG,KAAK;AAAA,UACvB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,WAAW,GAAG;AAC5B,gBAAY,KAAK,EAAE,MAAM,SAAS,MAAM,UAAU,SAAS,cAAc,aAAa,iBAAiB,CAAC;AAAA,EAC1G;AAEA,SAAO;AAAA,IACL,MAAM,YAAY,IAAI;AAAA,IACtB;AAAA,IACA;AAAA,IACA,cAAc,CAAC,EAAE,MAAM,UAAU,MAAM,UAAU,SAAS,cAAc,aAAa,kBAAkB,CAAC;AAAA,IACxG,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAKA,SAAS,kBAAkB,KAAqB;AAC9C,SAAO,IACJ,QAAQ,OAAO,MAAM,EACrB,QAAQ,MAAM,KAAK,EACnB,QAAQ,MAAM,KAAK,EACnB,QAAQ,SAAS,MAAM,EACvB,QAAQ,SAAS,KAAK,EACtB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AACtB;AAKA,SAAS,qBAAqB,WAAkC;AAC9D,QAAM,cAAc,kBAAkB,UAAU,IAAI;AACpD,QAAM,qBAAqB,kBAAkB,UAAU,WAAW;AAClE,QAAM,cAAc,iBAAiB,UAAU,UAAU;AAGzD,QAAM,kBAAkB,UAAU,YAC/B,OAAO,OAAK,oBAAoB,KAAK,EAAE,IAAI,KAAK,cAAc,EAAE,OAAO,CAAC;AAC3E,QAAM,mBAAmB,UAAU,aAChC,OAAO,OAAK,oBAAoB,KAAK,EAAE,IAAI,KAAK,cAAc,EAAE,OAAO,CAAC;AAE3E,QAAM,oBAAoB,UAAU,YAAY,SAAS,gBAAgB;AACzE,QAAM,qBAAqB,UAAU,aAAa,SAAS,iBAAiB;AAC5E,MAAI,oBAAoB,KAAK,qBAAqB,GAAG;AACnD,UAAM,QAAkB,CAAC;AACzB,QAAI,oBAAoB,EAAG,OAAM,KAAK,GAAG,iBAAiB,QAAQ;AAClE,QAAI,qBAAqB,EAAG,OAAM,KAAK,GAAG,kBAAkB,SAAS;AACrE,YAAQ,MAAM,IAAI,QAAQ,WAAW,MAAM,KAAK,OAAO,CAAC,+CAA+C,CAAC;AAAA,EAC1G;AAEA,QAAM,cAAc,gBACjB,IAAI,CAAC,MAAM,OAAO,EAAE,IAAI,KAAK,EAAE,OAAO,cAAc,kBAAkB,EAAE,WAAW,CAAC,KAAK,EACzF,KAAK,IAAI;AAEZ,QAAM,eAAe,iBAClB,IAAI,CAAC,MAAM,OAAO,EAAE,IAAI,KAAK,EAAE,OAAO,cAAc,kBAAkB,EAAE,WAAW,CAAC,KAAK,EACzF,KAAK,IAAI;AAEZ,QAAM,mBAAmB,gBAAgB,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AAErE,SAAO;AAAA;AAAA;AAAA,KAGJ,WAAW;AAAA;AAAA,KAEX,kBAAkB,UAAU,WAAW,CAAC;AAAA;AAAA,qBAExB,UAAU,UAAU,OAAO,WAAW;AAAA;AAAA;AAAA,WAGhD,WAAW;AAAA,kBACJ,kBAAkB;AAAA;AAAA,EAElC,WAAW;AAAA;AAAA;AAAA,EAGX,YAAY;AAAA;AAAA;AAAA,eAGC,WAAW;AAAA;AAAA;AAAA,sBAGJ,gBAAgB;AAAA;AAAA,0BAEZ,WAAW;AAAA;AAAA;AAAA,EAGnC,iBAAiB,IAAI,CAAC,MAAM,SAAS,EAAE,IAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAKhE;AAKA,SAAS,qBAAqB,WAAkC;AAC9D,QAAM,cAAc,kBAAkB,UAAU,IAAI;AACpD,QAAM,kBAAkB,UAAU,YAAY,OAAO,OAAK,oBAAoB,KAAK,EAAE,IAAI,CAAC;AAC1F,SAAO;AAAA,sBACa,WAAW;AAAA;AAAA,YAErB,WAAW;AAAA;AAAA,EAErB,gBAAgB,IAAI,CAAC,MAAM,0BAA0B,EAAE,IAAI,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAapF;AAKA,SAAS,oBAAoB,WAAkC;AAC7D,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,IAAI,KAAK,0BAA0B,CAAC;AAC/C,QAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,QAAM,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,WAAW,IAAI,KAAK,UAAU,IAAI,CAAC,EAAE;AACrE,QAAM,KAAK,KAAK,IAAI,IAAI,SAAS,CAAC,SAAS,UAAU,UAAU,KAAK,UAAU,UAAU,GAAG;AAC3F,QAAM,KAAK,KAAK,IAAI,IAAI,cAAc,CAAC,IAAI,UAAU,YAAY,UAAU,GAAG,EAAE,CAAC,GAAG,UAAU,YAAY,SAAS,KAAK,QAAQ,EAAE,EAAE;AACpI,QAAM,KAAK,EAAE;AAEb,QAAM,KAAK,IAAI,KAAK,cAAc,CAAC;AACnC,QAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,aAAW,SAAS,UAAU,aAAa;AACzC,UAAM,KAAK,KAAK,IAAI,MAAM,MAAM,IAAI,CAAC,KAAK,MAAM,IAAI,EAAE;AACtD,UAAM,KAAK,OAAO,IAAI,IAAI,MAAM,WAAW,CAAC,EAAE;AAAA,EAChD;AACA,QAAM,KAAK,EAAE;AAEb,QAAM,KAAK,IAAI,KAAK,eAAe,CAAC;AACpC,QAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,aAAW,SAAS,UAAU,cAAc;AAC1C,UAAM,KAAK,KAAK,IAAI,MAAM,MAAM,IAAI,CAAC,KAAK,MAAM,IAAI,EAAE;AACtD,UAAM,KAAK,OAAO,IAAI,IAAI,MAAM,WAAW,CAAC,EAAE;AAAA,EAChD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,eAAsB,eAAe,SAAwC;AAC3E,QAAM,cAAc,QAAQ,IAAI;AAEhC,MAAI;AAEF,QAAI;AAEJ,QAAI,QAAQ,OAAO;AACjB,kBAAY,MAAM,iBAAiB,QAAQ,KAAK;AAAA,IAClD,WAAW,QAAQ,MAAM;AACvB,kBAAY,MAAM,gBAAgB,QAAQ,IAAI;AAAA,IAChD,WAAW,QAAQ,KAAK;AACtB,kBAAY,MAAM,eAAe,QAAQ,GAAG;AAAA,IAC9C,WAAW,QAAQ,MAAM;AACvB,kBAAY,MAAM,gBAAgB,QAAQ,IAAI;AAAA,IAChD,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AAGA,QAAI,CAAC,QAAQ,MAAM;AACjB,cAAQ,IAAI,oBAAoB,SAAS,CAAC;AAC1C,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,MAAM;AACjC,cAAQ,IAAI,IAAI,OAAO,6CAA6C,CAAC;AACrE,cAAQ,IAAI,IAAI,IAAI,qCAAqC,CAAC;AAC1D;AAAA,IACF;AAGA,QAAI,CAAC,QAAQ,OAAO,QAAQ,MAAM;AAChC,YAAMC,aAAY,QAAQ,SACtB,gBAAgB,QAAQ,QAAQ,WAAW,IAC3C,KAAK,aAAa,OAAO;AAC7B,YAAMC,UAA4E;AAAA,QAChF,SAAS;AAAA,QACT;AAAA,QACA,cAAc;AAAA,UACZ,MAAM,KAAKD,YAAW,GAAG,UAAU,IAAI,KAAK;AAAA,UAC5C,MAAM,KAAKA,YAAW,GAAG,UAAU,IAAI,UAAU;AAAA,QACnD;AAAA,MACF;AACA,cAAQ,IAAI,KAAK,UAAUC,SAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,IACF;AAGA,UAAM,aAAa,KAAK,aAAa,UAAU;AAC/C,QAAI,CAAE,MAAM,WAAW,UAAU,GAAI;AACnC,YAAM,YAAY,WAAW;AAAA,IAC/B;AAGA,UAAM,YAAY,QAAQ,SACtB,gBAAgB,QAAQ,QAAQ,WAAW,IAC3C,KAAK,aAAa,OAAO;AAE7B,UAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAG1C,UAAM,WAAW,KAAK,WAAW,GAAG,UAAU,IAAI,KAAK;AACvD,UAAM,WAAW,KAAK,WAAW,GAAG,UAAU,IAAI,UAAU;AAC5D,UAAM,oBAAoB,QAAQ,SAAS;AAC3C,UAAM,MAAM,SAAS,mBAAmB,QAAQ,QAAQ,CAAC;AACzD,QAAI,IAAI,WAAW,IAAI,KAAK,WAAW,GAAG,GAAG;AAC3C,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,QAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,YAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,IACzD;AACA,QAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,YAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,IACzD;AAGA,UAAM,UAAU,UAAU,qBAAqB,SAAS,CAAC;AACzD,UAAM,UAAU,UAAU,qBAAqB,SAAS,CAAC;AAGzD,UAAM,SAAwB;AAAA,MAC5B,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC7C,OAAO;AACL,cAAQ,IAAI,IAAI,MAAM,oCAA+B,CAAC;AACtD,cAAQ,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,QAAQ,EAAE;AAC/C,cAAQ,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,QAAQ,EAAE;AAC/C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,aAAa;AACzB,cAAQ,IAAI,wBAAwB,QAAQ,EAAE;AAC9C,cAAQ,IAAI,6BAA6B,QAAQ,EAAE;AAAA,IACrD;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,GAAG;AAClC,QAAI,QAAQ,MAAM;AAChB,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,uBAAc;AACvD,cAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,SAAS,WAAW,gBAAgB,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA,IAC1G,OAAO;AACL,cAAQ,MAAM,IAAI,MAAM,sBAAsB,OAAO,EAAE,CAAC;AAAA,IAC1D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":["inputFields","outputDir","result"]}