daedalion 0.0.1 → 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 (88) hide show
  1. package/README.md +20 -5
  2. package/bin/daedalion.js +12 -5
  3. package/dist/commands/build.d.ts +3 -0
  4. package/dist/commands/build.d.ts.map +1 -0
  5. package/dist/commands/build.js +167 -0
  6. package/dist/commands/build.js.map +1 -0
  7. package/dist/commands/clean.d.ts +2 -0
  8. package/dist/commands/clean.d.ts.map +1 -0
  9. package/dist/commands/clean.js +106 -0
  10. package/dist/commands/clean.js.map +1 -0
  11. package/dist/commands/init.d.ts +3 -0
  12. package/dist/commands/init.d.ts.map +1 -0
  13. package/dist/commands/init.js +83 -0
  14. package/dist/commands/init.js.map +1 -0
  15. package/dist/commands/validate.d.ts +2 -0
  16. package/dist/commands/validate.d.ts.map +1 -0
  17. package/dist/commands/validate.js +119 -0
  18. package/dist/commands/validate.js.map +1 -0
  19. package/dist/config.d.ts +5 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +101 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/generators/agent.d.ts +3 -0
  24. package/dist/generators/agent.d.ts.map +1 -0
  25. package/dist/generators/agent.js +105 -0
  26. package/dist/generators/agent.js.map +1 -0
  27. package/dist/generators/instructions.d.ts +3 -0
  28. package/dist/generators/instructions.d.ts.map +1 -0
  29. package/{src → dist}/generators/instructions.js +42 -52
  30. package/dist/generators/instructions.js.map +1 -0
  31. package/dist/generators/prompt.d.ts +4 -0
  32. package/dist/generators/prompt.d.ts.map +1 -0
  33. package/{src → dist}/generators/prompt.js +96 -102
  34. package/dist/generators/prompt.js.map +1 -0
  35. package/dist/generators/skill.d.ts +3 -0
  36. package/dist/generators/skill.d.ts.map +1 -0
  37. package/dist/generators/skill.js +89 -0
  38. package/dist/generators/skill.js.map +1 -0
  39. package/dist/generators/tools.d.ts +3 -0
  40. package/dist/generators/tools.d.ts.map +1 -0
  41. package/dist/generators/tools.js +192 -0
  42. package/dist/generators/tools.js.map +1 -0
  43. package/dist/generators/workflow.d.ts +3 -0
  44. package/dist/generators/workflow.d.ts.map +1 -0
  45. package/{src → dist}/generators/workflow.js +47 -53
  46. package/dist/generators/workflow.js.map +1 -0
  47. package/dist/index.d.ts +16 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/{src → dist}/index.js +1 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/parsers/proposal.d.ts +3 -0
  52. package/dist/parsers/proposal.d.ts.map +1 -0
  53. package/dist/parsers/proposal.js +45 -0
  54. package/dist/parsers/proposal.js.map +1 -0
  55. package/dist/parsers/spec.d.ts +3 -0
  56. package/dist/parsers/spec.d.ts.map +1 -0
  57. package/dist/parsers/spec.js +87 -0
  58. package/dist/parsers/spec.js.map +1 -0
  59. package/dist/parsers/tasks.d.ts +4 -0
  60. package/dist/parsers/tasks.d.ts.map +1 -0
  61. package/dist/parsers/tasks.js +39 -0
  62. package/dist/parsers/tasks.js.map +1 -0
  63. package/dist/types.d.ts +107 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +2 -0
  66. package/dist/types.js.map +1 -0
  67. package/dist/utils.d.ts +5 -0
  68. package/dist/utils.d.ts.map +1 -0
  69. package/dist/utils.js +46 -0
  70. package/dist/utils.js.map +1 -0
  71. package/dist/version.d.ts +3 -0
  72. package/dist/version.d.ts.map +1 -0
  73. package/dist/version.js +47 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +18 -3
  76. package/src/commands/build.js +0 -198
  77. package/src/commands/clean.js +0 -85
  78. package/src/commands/init.js +0 -88
  79. package/src/commands/validate.js +0 -141
  80. package/src/config.js +0 -50
  81. package/src/generators/agent.js +0 -121
  82. package/src/generators/skill.js +0 -105
  83. package/src/generators/tools.js +0 -183
  84. package/src/parsers/proposal.js +0 -52
  85. package/src/parsers/spec.js +0 -105
  86. package/src/parsers/tasks.js +0 -46
  87. package/src/utils.js +0 -51
  88. package/src/version.js +0 -60
@@ -0,0 +1,39 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ export function parseTasks(tasksPath, maxItems = 10) {
3
+ if (!existsSync(tasksPath)) {
4
+ return { groups: [], items: [], hasMore: false };
5
+ }
6
+ const content = readFileSync(tasksPath, 'utf-8');
7
+ return summarizeTasks(content, maxItems);
8
+ }
9
+ export function summarizeTasks(content, maxItems = 10) {
10
+ const lines = content.split('\n');
11
+ const groups = [];
12
+ const items = [];
13
+ let currentGroup = null;
14
+ let totalItems = 0;
15
+ for (const line of lines) {
16
+ const headingMatch = line.match(/^(#{1,3})\s+(.+)$/);
17
+ if (headingMatch) {
18
+ currentGroup = headingMatch[2].trim();
19
+ if (!groups.includes(currentGroup)) {
20
+ groups.push(currentGroup);
21
+ }
22
+ continue;
23
+ }
24
+ const taskMatch = line.match(/^-\s+(\[[ x]\])?\s*(.+)$/);
25
+ if (taskMatch && !line.match(/^\s{2,}-/)) {
26
+ totalItems++;
27
+ if (items.length < maxItems) {
28
+ const taskText = taskMatch[2].trim();
29
+ items.push(taskText);
30
+ }
31
+ }
32
+ }
33
+ return {
34
+ groups,
35
+ items,
36
+ hasMore: totalItems > maxItems
37
+ };
38
+ }
39
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/parsers/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAG9C,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE,WAAmB,EAAE;IACjE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,OAAO,GAAW,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzD,OAAO,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,WAAmB,EAAE;IACnE,MAAM,KAAK,GAAa,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,UAAU,GAAW,CAAC,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,YAAY,GAA4B,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC9E,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC5B,CAAC;YACD,SAAS;QACX,CAAC;QAED,MAAM,SAAS,GAA4B,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAClF,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,UAAU,EAAE,CAAC;YACb,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAW,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM;QACN,KAAK;QACL,OAAO,EAAE,UAAU,GAAG,QAAQ;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,107 @@
1
+ /** Result returned by every generator */
2
+ export interface GeneratedFile {
3
+ path: string;
4
+ content: string;
5
+ }
6
+ /** Common options passed through commands and generators */
7
+ export interface BuildOptions {
8
+ dryRun?: boolean;
9
+ verbose?: boolean;
10
+ force?: boolean;
11
+ withTools?: boolean;
12
+ }
13
+ /** Init command options */
14
+ export interface InitOptions {
15
+ agentTarget?: string;
16
+ withExample?: boolean;
17
+ target?: string;
18
+ }
19
+ /** Parsed spec from openspec/specs/{domain}/spec.md */
20
+ export interface Spec {
21
+ path: string;
22
+ domain: string;
23
+ title: string;
24
+ frontmatter: Record<string, unknown>;
25
+ requirements: Requirement[];
26
+ }
27
+ export interface Requirement {
28
+ name: string;
29
+ description: string;
30
+ scenarios: Scenario[];
31
+ }
32
+ export interface Scenario {
33
+ name: string;
34
+ steps: string[];
35
+ }
36
+ /** Parsed proposal from openspec/changes/{change}/proposal.md */
37
+ export interface Proposal {
38
+ path: string;
39
+ changeName: string;
40
+ title: string;
41
+ frontmatter: Record<string, unknown>;
42
+ why: string | null;
43
+ what: string | null;
44
+ }
45
+ /** Parsed task list from openspec/changes/{change}/tasks.md */
46
+ export interface TasksSummary {
47
+ groups: string[];
48
+ items: string[];
49
+ hasMore: boolean;
50
+ }
51
+ /** Tool definition from spec frontmatter */
52
+ export interface ToolDef {
53
+ name: string;
54
+ description?: string;
55
+ inputs?: ToolInput[];
56
+ outputs?: ToolOutput[];
57
+ requirements?: (string | number)[];
58
+ language?: string;
59
+ }
60
+ export interface ToolInput {
61
+ name: string;
62
+ type?: string;
63
+ description?: string;
64
+ }
65
+ export interface ToolOutput {
66
+ type?: string;
67
+ }
68
+ /** daedalion.yaml configuration */
69
+ export interface DaedalionConfig {
70
+ version: number;
71
+ target: string;
72
+ openspec: string;
73
+ output: string;
74
+ ci: {
75
+ auto_commit: boolean;
76
+ commit_message: string;
77
+ };
78
+ agents: {
79
+ target: 'ide' | 'sdk';
80
+ tools: string[] | null;
81
+ };
82
+ tools?: {
83
+ language?: string;
84
+ };
85
+ }
86
+ /** Manifest written by build, read by clean */
87
+ export interface Manifest {
88
+ version: number;
89
+ generatedAt: string;
90
+ files: string[];
91
+ }
92
+ /** Validation error */
93
+ export interface ValidationError {
94
+ rule: string;
95
+ message: string;
96
+ }
97
+ /** Change parsed from openspec/changes/{change}/ */
98
+ export interface ParsedChange {
99
+ proposal: Proposal;
100
+ tasks: TasksSummary;
101
+ }
102
+ /** Validate-only change reference */
103
+ export interface ChangeReference {
104
+ changeName: string;
105
+ path: string;
106
+ }
107
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export declare function ensureDir(filePath: string): void;
2
+ export declare function extractFirstHeading(content: string): string | null;
3
+ export declare function extractDescription(content: string): string | null;
4
+ export declare function slugify(text: string): string;
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAKhD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGlE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA4BjE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C"}
package/dist/utils.js ADDED
@@ -0,0 +1,46 @@
1
+ import { mkdirSync, existsSync } from 'fs';
2
+ import { dirname } from 'path';
3
+ export function ensureDir(filePath) {
4
+ const dir = dirname(filePath);
5
+ if (!existsSync(dir)) {
6
+ mkdirSync(dir, { recursive: true });
7
+ }
8
+ }
9
+ export function extractFirstHeading(content) {
10
+ const match = content.match(/^#\s+(.+)$/m);
11
+ return match ? match[1].trim() : null;
12
+ }
13
+ export function extractDescription(content) {
14
+ const lines = content.split('\n');
15
+ let inFrontmatter = false;
16
+ const description = [];
17
+ for (const line of lines) {
18
+ if (line.trim() === '---') {
19
+ if (inFrontmatter) {
20
+ inFrontmatter = false;
21
+ continue;
22
+ }
23
+ inFrontmatter = true;
24
+ continue;
25
+ }
26
+ if (inFrontmatter)
27
+ continue;
28
+ if (line.startsWith('#'))
29
+ continue;
30
+ if (line.trim() && !line.startsWith('##')) {
31
+ description.push(line.trim());
32
+ if (description.length >= 2)
33
+ break;
34
+ }
35
+ if (line.startsWith('##'))
36
+ break;
37
+ }
38
+ return description.join(' ').slice(0, 200) || null;
39
+ }
40
+ export function slugify(text) {
41
+ return text
42
+ .toLowerCase()
43
+ .replace(/[^a-z0-9]+/g, '-')
44
+ .replace(/^-|-$/g, '');
45
+ }
46
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,GAAG,GAAW,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,KAAK,GAA4B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,KAAK,GAAa,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,aAAa,GAAY,KAAK,CAAC;IACnC,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,aAAa,EAAE,CAAC;gBAClB,aAAa,GAAG,KAAK,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,aAAa,GAAG,IAAI,CAAC;YACrB,SAAS;QACX,CAAC;QAED,IAAI,aAAa;YAAE,SAAS;QAE5B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAEnC,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9B,IAAI,WAAW,CAAC,MAAM,IAAI,CAAC;gBAAE,MAAM;QACrC,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM;IACnC,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const VERSION: string;
2
+ export declare function getVersionString(): string;
3
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC;AAE3C,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC"}
@@ -0,0 +1,47 @@
1
+ import { execSync } from 'child_process';
2
+ import { readFileSync } from 'fs';
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join } from 'path';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ // Read version from package.json
8
+ const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
9
+ export const VERSION = pkg.version;
10
+ export function getVersionString() {
11
+ const commitHash = getCommitHash();
12
+ if (commitHash && !isReleaseBuild()) {
13
+ return `${VERSION}-dev+${commitHash}`;
14
+ }
15
+ return VERSION;
16
+ }
17
+ function getCommitHash() {
18
+ try {
19
+ return execSync('git rev-parse --short HEAD', {
20
+ encoding: 'utf-8',
21
+ stdio: ['pipe', 'pipe', 'ignore'],
22
+ timeout: 5000,
23
+ windowsHide: true
24
+ }).trim();
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ function isReleaseBuild() {
31
+ if (__dirname.includes('node_modules')) {
32
+ return true;
33
+ }
34
+ try {
35
+ execSync('git describe --exact-match --tags HEAD', {
36
+ encoding: 'utf-8',
37
+ stdio: ['pipe', 'pipe', 'ignore'],
38
+ timeout: 5000,
39
+ windowsHide: true
40
+ });
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAW,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAW,OAAO,CAAC,UAAU,CAAC,CAAC;AAE9C,iCAAiC;AACjC,MAAM,GAAG,GAAwB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACvG,MAAM,CAAC,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC;AAE3C,MAAM,UAAU,gBAAgB;IAC9B,MAAM,UAAU,GAAkB,aAAa,EAAE,CAAC;IAClD,IAAI,UAAU,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACpC,OAAO,GAAG,OAAO,QAAQ,UAAU,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,4BAA4B,EAAE;YAC5C,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;YACjC,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,cAAc;IACrB,IAAI,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,QAAQ,CAAC,wCAAwC,EAAE;YACjD,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;YACjC,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,13 +1,21 @@
1
1
  {
2
2
  "name": "daedalion",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "OpenSpec-to-Agent compiler for GitHub Copilot",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
5
13
  "bin": {
6
14
  "daedalion": "./bin/daedalion.js"
7
15
  },
8
16
  "files": [
9
17
  "bin/",
10
- "src/",
18
+ "dist/",
11
19
  "templates/"
12
20
  ],
13
21
  "type": "module",
@@ -15,9 +23,13 @@
15
23
  "node": ">=20"
16
24
  },
17
25
  "scripts": {
26
+ "build": "tsc",
27
+ "dev": "tsx src/index.ts",
18
28
  "test": "vitest run",
19
29
  "test:watch": "vitest",
20
- "test:coverage": "vitest run --coverage"
30
+ "test:coverage": "vitest run --coverage",
31
+ "prepublishOnly": "npm run build && npm test",
32
+ "typecheck": "tsc --noEmit"
21
33
  },
22
34
  "keywords": [
23
35
  "openspec",
@@ -36,6 +48,9 @@
36
48
  "yaml": "^2.3.0"
37
49
  },
38
50
  "devDependencies": {
51
+ "@types/node": "^25.3.0",
52
+ "tsx": "^4.21.0",
53
+ "typescript": "^5.9.3",
39
54
  "vitest": "^1.0.0"
40
55
  }
41
56
  }
@@ -1,198 +0,0 @@
1
- import { existsSync, readdirSync, statSync, writeFileSync } from 'fs';
2
- import { join, relative } from 'path';
3
- import chalk from 'chalk';
4
- import { VERSION } from '../version.js';
5
- import { glob } from 'glob';
6
- import { loadConfig, resolveOpenspecPath, resolveOutputPath } from '../config.js';
7
- import { parseSpec } from '../parsers/spec.js';
8
- import { parseProposal } from '../parsers/proposal.js';
9
- import { parseTasks } from '../parsers/tasks.js';
10
- import { generateSkill } from '../generators/skill.js';
11
- import { generateAgent } from '../generators/agent.js';
12
- import { generatePrompt, generateCyclePrompt } from '../generators/prompt.js';
13
- import { generateWorkflow } from '../generators/workflow.js';
14
- import { generateInstructions } from '../generators/instructions.js';
15
- import { generateTools } from '../generators/tools.js';
16
- import { ensureDir } from '../utils.js';
17
-
18
- const MANIFEST_FILENAME = '.daedalion-manifest.json';
19
-
20
- export async function build(cwd, options = {}) {
21
- console.log();
22
- console.log(chalk.bold(` Daedalion v${VERSION}`));
23
- console.log();
24
-
25
- const config = loadConfig(cwd);
26
- const openspecDir = resolveOpenspecPath(cwd, config);
27
- const outputDir = resolveOutputPath(cwd, config);
28
-
29
- if (!existsSync(openspecDir)) {
30
- throw new Error(`OpenSpec directory not found: ${openspecDir}\n Run 'daedalion init' first.`);
31
- }
32
-
33
- const generatedFiles = [];
34
-
35
- // Parse specs
36
- console.log(' Parsing specs...');
37
- const specs = await findAndParseSpecs(openspecDir, options);
38
- for (const spec of specs) {
39
- console.log(chalk.gray(` ✓ ${relative(cwd, spec.path)}`));
40
- }
41
-
42
- // Parse changes
43
- console.log();
44
- console.log(' Parsing changes...');
45
- const changes = await findAndParseChanges(openspecDir, options);
46
- for (const change of changes) {
47
- console.log(chalk.gray(` ✓ ${relative(cwd, change.proposal.path)}`));
48
- }
49
-
50
- // Aggregate tasks from all changes for skills
51
- const allTasks = aggregateTasks(changes);
52
-
53
- // Generate outputs
54
- console.log();
55
- console.log(' Generating...');
56
-
57
- // Generate skills and agents from specs
58
- for (const spec of specs) {
59
- const tasks = allTasks[spec.domain] || null;
60
- const skillResult = generateSkill(spec, tasks, outputDir, options);
61
- generatedFiles.push(skillResult);
62
- logGenerated(skillResult.path, cwd, options);
63
-
64
- const agentResult = generateAgent(spec, outputDir, options, config);
65
- generatedFiles.push(agentResult);
66
- logGenerated(agentResult.path, cwd, options);
67
- }
68
-
69
- // Generate tool stubs if --with-tools flag is set
70
- if (options.withTools) {
71
- console.log(chalk.gray(` (generating tool stubs)`));
72
- for (const spec of specs) {
73
- const toolResults = generateTools(spec, outputDir, config, options);
74
- for (const toolResult of toolResults) {
75
- generatedFiles.push(toolResult);
76
- logGenerated(toolResult.path, cwd, options);
77
- }
78
- }
79
- }
80
-
81
- // Generate prompts from changes
82
- for (const change of changes) {
83
- const domain = findDomainForChange(change, specs);
84
- const promptResult = generatePrompt(change.proposal, change.tasks, domain, outputDir, options);
85
- generatedFiles.push(promptResult);
86
- logGenerated(promptResult.path, cwd, options);
87
- }
88
-
89
- // Generate OpenSpec cycle prompt
90
- const cyclePromptResult = generateCyclePrompt(outputDir, options);
91
- generatedFiles.push(cyclePromptResult);
92
- logGenerated(cyclePromptResult.path, cwd, options);
93
-
94
- // Generate workflow
95
- const workflowResult = generateWorkflow(config, outputDir, options);
96
- generatedFiles.push(workflowResult);
97
- logGenerated(workflowResult.path, cwd, options);
98
-
99
- // Generate copilot-instructions.md
100
- const instructionsResult = generateInstructions(openspecDir, outputDir, options);
101
- generatedFiles.push(instructionsResult);
102
- logGenerated(instructionsResult.path, cwd, options);
103
-
104
- // Write manifest of generated files (for clean command)
105
- if (!options.dryRun) {
106
- writeManifest(outputDir, generatedFiles, cwd);
107
- }
108
-
109
- console.log();
110
- if (options.dryRun) {
111
- console.log(chalk.yellow(` Dry run complete. ${generatedFiles.length} files would be generated.`));
112
- } else {
113
- console.log(chalk.green(` Done. ${generatedFiles.length} files generated.`));
114
- }
115
- console.log();
116
-
117
- return generatedFiles;
118
- }
119
-
120
- function writeManifest(outputDir, generatedFiles, cwd) {
121
- const manifestPath = join(outputDir, MANIFEST_FILENAME);
122
- const manifest = {
123
- version: 1,
124
- generatedAt: new Date().toISOString(),
125
- files: generatedFiles.map(f => relative(cwd, f.path))
126
- };
127
- ensureDir(manifestPath);
128
- writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
129
- }
130
-
131
- async function findAndParseSpecs(openspecDir, options) {
132
- const specsDir = join(openspecDir, 'specs');
133
- if (!existsSync(specsDir)) {
134
- return [];
135
- }
136
-
137
- const specFiles = await glob('*/spec.md', { cwd: specsDir });
138
- return specFiles.map(file => parseSpec(join(specsDir, file)));
139
- }
140
-
141
- async function findAndParseChanges(openspecDir, options) {
142
- const changesDir = join(openspecDir, 'changes');
143
- if (!existsSync(changesDir)) {
144
- return [];
145
- }
146
-
147
- const changes = [];
148
- const changeDirs = readdirSync(changesDir).filter(name => {
149
- const fullPath = join(changesDir, name);
150
- return statSync(fullPath).isDirectory();
151
- });
152
-
153
- for (const changeDir of changeDirs) {
154
- const proposalPath = join(changesDir, changeDir, 'proposal.md');
155
- const tasksPath = join(changesDir, changeDir, 'tasks.md');
156
-
157
- if (existsSync(proposalPath)) {
158
- changes.push({
159
- proposal: parseProposal(proposalPath),
160
- tasks: parseTasks(tasksPath)
161
- });
162
- }
163
- }
164
-
165
- return changes;
166
- }
167
-
168
- function aggregateTasks(changes) {
169
- const tasksByDomain = {};
170
- for (const change of changes) {
171
- // For now, associate all tasks with a generic key
172
- // In a real implementation, you might parse domain from proposal
173
- if (!tasksByDomain['default']) {
174
- tasksByDomain['default'] = { groups: [], items: [], hasMore: false };
175
- }
176
- tasksByDomain['default'].items.push(...change.tasks.items);
177
- tasksByDomain['default'].hasMore = tasksByDomain['default'].hasMore || change.tasks.hasMore;
178
- }
179
- return tasksByDomain;
180
- }
181
-
182
- function findDomainForChange(change, specs) {
183
- // Try to match change to a spec domain
184
- // For now, use the first spec's domain or 'default'
185
- if (specs.length > 0) {
186
- return specs[0].domain;
187
- }
188
- return 'default';
189
- }
190
-
191
- function logGenerated(filePath, cwd, options) {
192
- const relativePath = relative(cwd, filePath);
193
- if (options.dryRun) {
194
- console.log(chalk.yellow(` → ${relativePath}`));
195
- } else {
196
- console.log(chalk.green(` ✓ ${relativePath}`));
197
- }
198
- }
@@ -1,85 +0,0 @@
1
- import { existsSync, rmSync, readdirSync, readFileSync } from 'fs';
2
- import { join, dirname } from 'path';
3
- import chalk from 'chalk';
4
- import { VERSION } from '../version.js';
5
- import { loadConfig, resolveOutputPath } from '../config.js';
6
-
7
- const MANIFEST_FILENAME = '.daedalion-manifest.json';
8
-
9
- export async function clean(cwd) {
10
- console.log();
11
- console.log(chalk.bold(` Daedalion v${VERSION} - Clean`));
12
- console.log();
13
-
14
- const config = loadConfig(cwd);
15
- const outputDir = resolveOutputPath(cwd, config);
16
-
17
- if (!existsSync(outputDir)) {
18
- console.log(chalk.yellow(' No output directory found. Nothing to clean.'));
19
- console.log();
20
- return;
21
- }
22
-
23
- const manifestPath = join(outputDir, MANIFEST_FILENAME);
24
-
25
- if (!existsSync(manifestPath)) {
26
- console.log(chalk.yellow(' No manifest found. Run `daedalion build` first to generate a manifest.'));
27
- console.log(chalk.gray(' (Clean requires a manifest to avoid deleting non-Daedalion files)'));
28
- console.log();
29
- return;
30
- }
31
-
32
- const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
33
- const filesToRemove = manifest.files || [];
34
-
35
- let removed = 0;
36
- const cleanedDirs = new Set();
37
-
38
- for (const relativePath of filesToRemove) {
39
- const fullPath = join(cwd, relativePath);
40
-
41
- if (existsSync(fullPath)) {
42
- rmSync(fullPath, { force: true });
43
- console.log(chalk.green(` ✓ Removed ${relativePath}`));
44
- removed++;
45
-
46
- // Track parent directories for cleanup
47
- cleanedDirs.add(dirname(fullPath));
48
- }
49
- }
50
-
51
- // Remove the manifest itself
52
- rmSync(manifestPath, { force: true });
53
- console.log(chalk.green(` ✓ Removed .github/${MANIFEST_FILENAME}`));
54
-
55
- // Clean up empty directories (skills/domain/, agents/, etc.)
56
- for (const dir of cleanedDirs) {
57
- cleanEmptyDirs(dir, outputDir);
58
- }
59
-
60
- console.log();
61
- if (removed > 0) {
62
- console.log(chalk.green(` Done. ${removed} files removed.`));
63
- } else {
64
- console.log(chalk.yellow(' No generated files found to clean.'));
65
- }
66
- console.log();
67
- }
68
-
69
- // Recursively remove empty directories up to (but not including) the output dir
70
- function cleanEmptyDirs(dir, stopAt) {
71
- if (dir === stopAt || !existsSync(dir)) {
72
- return;
73
- }
74
-
75
- try {
76
- const contents = readdirSync(dir);
77
- if (contents.length === 0) {
78
- rmSync(dir, { recursive: true, force: true });
79
- // Check parent directory too
80
- cleanEmptyDirs(dirname(dir), stopAt);
81
- }
82
- } catch {
83
- // Directory might have been removed already
84
- }
85
- }