@patricksardinha/agentkit-cli 0.2.0 → 0.4.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/AGENT_WORKFLOW.md +129 -55
- package/CLAUDE.md +59 -34
- package/PLAYBOOK.md +192 -0
- package/PROJECT_BLUEPRINT.md +52 -0
- package/README.md +248 -167
- package/agents/agent-1-infra/skills.md +46 -0
- package/agents/agent-2-detectors/skills.md +38 -0
- package/agents/agent-3-generators/skills.md +43 -0
- package/agents/agent-4-commands/skills.md +37 -0
- package/dist/cli.cjs +208 -156
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +208 -156
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/add.ts +22 -15
- package/src/commands/init.ts +2 -2
- package/src/generators/claudeMdGenerator.ts +3 -14
- package/src/generators/playbookGenerator.ts +136 -36
- package/src/generators/workflowGenerator.ts +9 -36
- package/tests/commands/add.test.ts +1 -1
- package/tests/generators/blueprintSupport.test.ts +35 -30
- package/tests/generators/claudeMdGenerator.test.ts +48 -0
- package/tests/generators/playbookGenerator.test.ts +140 -48
- package/tests/generators/workflowGenerator.test.ts +40 -0
package/dist/cli.js
CHANGED
|
@@ -91,25 +91,6 @@ async function isGitRepo(projectPath) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
// src/utils/blueprintParser.ts
|
|
95
|
-
function parseBlueprint(content) {
|
|
96
|
-
const features = [];
|
|
97
|
-
const sectionRegex = /^## (.+)$/gm;
|
|
98
|
-
const sections = [];
|
|
99
|
-
let m;
|
|
100
|
-
while ((m = sectionRegex.exec(content)) !== null) {
|
|
101
|
-
sections.push({ name: m[1].trim(), start: m.index });
|
|
102
|
-
}
|
|
103
|
-
for (let i = 0; i < sections.length; i++) {
|
|
104
|
-
const section = sections[i];
|
|
105
|
-
const end = i + 1 < sections.length ? sections[i + 1].start : content.length;
|
|
106
|
-
const body = content.slice(section.start, end);
|
|
107
|
-
const items = [...body.matchAll(/^[-*]\s+(.+)$/gm)].map((r) => r[1].trim());
|
|
108
|
-
features.push({ name: section.name, items });
|
|
109
|
-
}
|
|
110
|
-
return features;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
94
|
// src/templates/react.ts
|
|
114
95
|
function claudeMd(stack) {
|
|
115
96
|
const lang = stack.hasTypeScript ? "TypeScript" : "JavaScript";
|
|
@@ -544,73 +525,17 @@ function generateClaudeMd(stack, blueprintContent) {
|
|
|
544
525
|
base = claudeMd7(stack);
|
|
545
526
|
}
|
|
546
527
|
if (!blueprintContent) return base;
|
|
547
|
-
const
|
|
548
|
-
if (features.length === 0) return base;
|
|
549
|
-
const featureLines = features.map((f, i) => {
|
|
550
|
-
const sub = f.items.length > 0 ? "\n" + f.items.map((it) => ` - ${it}`).join("\n") : "";
|
|
551
|
-
return `${i + 1}. **${f.name}**${sub}`;
|
|
552
|
-
}).join("\n");
|
|
553
|
-
const featureSection = `
|
|
554
|
-
## Features (Blueprint)
|
|
555
|
-
|
|
556
|
-
${featureLines}
|
|
557
|
-
`;
|
|
528
|
+
const blueprintNote = "\n> A PROJECT_BLUEPRINT.md is present \u2014 Claude Code will read it during Phase 0.\n";
|
|
558
529
|
const conventionsIdx = base.indexOf("\n## Conventions");
|
|
559
530
|
if (conventionsIdx !== -1) {
|
|
560
|
-
return base.slice(0, conventionsIdx) +
|
|
561
|
-
}
|
|
562
|
-
return base + featureSection;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// src/utils/agentParser.ts
|
|
566
|
-
function toSlug(name) {
|
|
567
|
-
return name.toLowerCase().replace(/[·•&]/g, " ").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
568
|
-
}
|
|
569
|
-
function getFieldValue(lines, pattern) {
|
|
570
|
-
for (const line of lines) {
|
|
571
|
-
const m = line.match(pattern);
|
|
572
|
-
if (m) return (m[1] ?? "").trim();
|
|
573
|
-
}
|
|
574
|
-
return "";
|
|
575
|
-
}
|
|
576
|
-
function extractAgentsFromWorkflow(content) {
|
|
577
|
-
const agents = [];
|
|
578
|
-
const blocks = content.split(/(?=^### Agent \d)/m).filter((b) => /^### Agent \d/.test(b.trimStart()));
|
|
579
|
-
for (const block of blocks) {
|
|
580
|
-
const lines = block.split("\n");
|
|
581
|
-
const headerMatch = lines[0].match(/^### Agent (\d+)\s*[·•]\s*(.+)$/);
|
|
582
|
-
if (!headerMatch) continue;
|
|
583
|
-
const number = parseInt(headerMatch[1], 10);
|
|
584
|
-
const name = headerMatch[2].trim();
|
|
585
|
-
const fullName = `Agent ${number} \xB7 ${name}`;
|
|
586
|
-
const slug = toSlug(name);
|
|
587
|
-
const scope = getFieldValue(lines, /Périmètre\s*:\s*(.+)/);
|
|
588
|
-
const criterion = getFieldValue(lines, /Critère[s]?\s*:\s*(.+)/);
|
|
589
|
-
const outputs = [];
|
|
590
|
-
const produitIdx = lines.findIndex((l) => /Produit\s*:/.test(l));
|
|
591
|
-
if (produitIdx !== -1) {
|
|
592
|
-
const inlineVal = (lines[produitIdx].match(/Produit\s*:\s*(.+)/)?.[1] ?? "").trim();
|
|
593
|
-
if (inlineVal) {
|
|
594
|
-
outputs.push(inlineVal);
|
|
595
|
-
} else {
|
|
596
|
-
for (let i = produitIdx + 1; i < lines.length; i++) {
|
|
597
|
-
const line = lines[i];
|
|
598
|
-
if (/^\s+[-]/.test(line)) {
|
|
599
|
-
outputs.push(line.trim().replace(/^-\s*/, ""));
|
|
600
|
-
} else if (line.trim() !== "" && !/^\s/.test(line)) {
|
|
601
|
-
break;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
agents.push({ number, name, fullName, slug, scope, outputs, criterion });
|
|
531
|
+
return base.slice(0, conventionsIdx) + blueprintNote + base.slice(conventionsIdx);
|
|
607
532
|
}
|
|
608
|
-
return
|
|
533
|
+
return base + blueprintNote;
|
|
609
534
|
}
|
|
610
535
|
|
|
611
536
|
// src/generators/workflowGenerator.ts
|
|
612
|
-
function generateWorkflow(stack, blueprintContent) {
|
|
613
|
-
if (blueprintContent) return
|
|
537
|
+
function generateWorkflow(stack, blueprintContent, projectName) {
|
|
538
|
+
if (blueprintContent) return blueprintPlaceholder(projectName ?? stack.framework);
|
|
614
539
|
switch (stack.framework) {
|
|
615
540
|
case "react":
|
|
616
541
|
return workflow(stack);
|
|
@@ -628,100 +553,177 @@ function generateWorkflow(stack, blueprintContent) {
|
|
|
628
553
|
return workflow7(stack);
|
|
629
554
|
}
|
|
630
555
|
}
|
|
631
|
-
function
|
|
632
|
-
|
|
633
|
-
const agentBlocks = features.map((feature, i) => {
|
|
634
|
-
const n = i + 1;
|
|
635
|
-
const slug = toSlug(feature.name);
|
|
636
|
-
const outputLines = feature.items.length > 0 ? feature.items.map((item) => ` - ${item}`).join("\n") : ` - src/${slug}/`;
|
|
637
|
-
return `### Agent ${n} \xB7 ${feature.name}
|
|
638
|
-
P\xE9rim\xE8tre : Impl\xE9menter la fonctionnalit\xE9 ${feature.name.toLowerCase()}
|
|
639
|
-
Produit :
|
|
640
|
-
${outputLines}
|
|
641
|
-
Crit\xE8re : npm test (tests ${feature.name.toLowerCase()} passent)`;
|
|
642
|
-
});
|
|
643
|
-
const ciN = features.length + 1;
|
|
644
|
-
agentBlocks.push(
|
|
645
|
-
`### Agent ${ciN} \xB7 Tests & CI
|
|
646
|
-
P\xE9rim\xE8tre : Couverture de tests compl\xE8te et configuration du pipeline CI
|
|
647
|
-
Produit :
|
|
648
|
-
- tests/
|
|
649
|
-
- .github/workflows/
|
|
650
|
-
Crit\xE8re : npm test passe, pipeline CI vert`
|
|
651
|
-
);
|
|
652
|
-
return `# Agent Workflow \u2014 ${stack.framework} (Blueprint)
|
|
556
|
+
function blueprintPlaceholder(projectName) {
|
|
557
|
+
return `# AGENT_WORKFLOW.md \u2014 ${projectName}
|
|
653
558
|
|
|
654
|
-
|
|
655
|
-
|
|
559
|
+
> This file will be filled in by Claude Code during Phase 0.
|
|
560
|
+
> Claude Code will read PROJECT_BLUEPRINT.md, propose a decomposition,
|
|
561
|
+
> and replace this content after human validation.
|
|
656
562
|
|
|
657
|
-
|
|
563
|
+
---
|
|
658
564
|
|
|
659
|
-
|
|
565
|
+
*Waiting for Phase 0 decomposition...*
|
|
660
566
|
`;
|
|
661
567
|
}
|
|
662
568
|
|
|
663
569
|
// src/generators/playbookGenerator.ts
|
|
664
|
-
function generatePlaybook({ agents, projectName }) {
|
|
570
|
+
function generatePlaybook({ agents, projectName, hasBlueprint }) {
|
|
665
571
|
const agentBlocks = agents.map((a) => agentBlock(a)).join("\n---\n\n");
|
|
572
|
+
const phase0 = hasBlueprint ? `## Phase 0 \u2014 Agent Decomposition (run this first)
|
|
573
|
+
|
|
574
|
+
> A \`PROJECT_BLUEPRINT.md\` was provided.
|
|
575
|
+
> Claude Code reads it and decomposes the project into specialized agents
|
|
576
|
+
> before writing a single line of code.
|
|
577
|
+
|
|
578
|
+
**Read these files in order:**
|
|
579
|
+
1. \`CLAUDE.md\`
|
|
580
|
+
2. \`PROJECT_BLUEPRINT.md\`
|
|
581
|
+
|
|
582
|
+
**Then decompose the project into agents** following these rules:
|
|
583
|
+
|
|
584
|
+
- One agent = one coherent technical layer (never mix two layers)
|
|
585
|
+
- Each agent must have a runnable success criterion (\`npm test\`, \`cargo build\`\u2026)
|
|
586
|
+
- Agents must be ordered by dependency (no feature without infra first)
|
|
587
|
+
- Maximum 6 agents \u2014 if you have more, group related ones
|
|
588
|
+
- Always respect this order:
|
|
589
|
+
1. Infra & Configuration
|
|
590
|
+
2. Data layer (DB schema, models, services)
|
|
591
|
+
3. External integrations (auth, APIs, local services like Ollama)
|
|
592
|
+
4. UI & pages
|
|
593
|
+
5. Advanced features (RAG, export, realtime\u2026)
|
|
594
|
+
6. Build & release (CI/CD, packaging, installers)
|
|
595
|
+
|
|
596
|
+
**Write the result directly into \`AGENT_WORKFLOW.md\`** \u2014 replace its current
|
|
597
|
+
content with your decomposition.
|
|
598
|
+
|
|
599
|
+
**Then ask for human validation:**
|
|
600
|
+
> "I have decomposed the project into N agents: [list them].
|
|
601
|
+
> Should I proceed with execution?"
|
|
602
|
+
|
|
603
|
+
Wait for confirmation before moving to Phase 1.
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
` : `## Phase 0 \u2014 Project Discovery (run this first)
|
|
608
|
+
|
|
609
|
+
> No \`PROJECT_BLUEPRINT.md\` was provided.
|
|
610
|
+
> Before writing any code, Claude Code asks the user what they want to build,
|
|
611
|
+
> then decomposes the project into agents \u2014 exactly as if a blueprint had been provided.
|
|
612
|
+
|
|
613
|
+
**Ask the user these questions and wait for their answers:**
|
|
614
|
+
|
|
615
|
+
1. What is this project? (one sentence describing the goal)
|
|
616
|
+
2. What are the main features you want to build? (list them)
|
|
617
|
+
3. Are there any tech constraints or architecture preferences?
|
|
618
|
+
(e.g. offline-only, specific DB, no auth, specific framework)
|
|
619
|
+
|
|
620
|
+
**Once you have the answers, decompose the project into agents**
|
|
621
|
+
following these rules:
|
|
622
|
+
|
|
623
|
+
- One agent = one coherent technical layer (never mix two layers)
|
|
624
|
+
- Each agent must have a runnable success criterion (\`npm test\`, \`cargo build\`\u2026)
|
|
625
|
+
- Agents must be ordered by dependency (no feature without infra first)
|
|
626
|
+
- Maximum 6 agents \u2014 if you have more, group related ones
|
|
627
|
+
- Always respect this order:
|
|
628
|
+
1. Infra & Configuration
|
|
629
|
+
2. Data layer (DB schema, models, services)
|
|
630
|
+
3. External integrations (auth, APIs, local services like Ollama)
|
|
631
|
+
4. UI & pages
|
|
632
|
+
5. Advanced features (RAG, export, realtime\u2026)
|
|
633
|
+
6. Build & release (CI/CD, packaging, installers)
|
|
634
|
+
|
|
635
|
+
**Write the result directly into \`AGENT_WORKFLOW.md\`** \u2014 replace its current
|
|
636
|
+
content with your decomposition.
|
|
637
|
+
|
|
638
|
+
**Then ask for human validation:**
|
|
639
|
+
> "I have decomposed the project into N agents: [list them].
|
|
640
|
+
> Should I proceed with execution?"
|
|
641
|
+
|
|
642
|
+
Wait for confirmation before moving to Phase 1.
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
`;
|
|
666
647
|
return `# PLAYBOOK.md \u2014 ${projectName}
|
|
667
648
|
|
|
668
|
-
>
|
|
649
|
+
> **One instruction to give Claude Code:**
|
|
650
|
+
> "Read PLAYBOOK.md and execute the procedure."
|
|
651
|
+
>
|
|
652
|
+
> Claude Code handles the rest autonomously \u2014 project discovery or blueprint reading,
|
|
653
|
+
> agent decomposition, execution, success validation, retries, and human escalation.
|
|
654
|
+
> No API key required. No additional cost beyond your LLM subscription.
|
|
669
655
|
|
|
670
|
-
|
|
656
|
+
---
|
|
671
657
|
|
|
672
|
-
|
|
673
|
-
1. Lire \`CLAUDE.md\`
|
|
674
|
-
2. Lire \`agents/agent-{N}-{slug}/skills.md\` (le fichier de l'agent courant)
|
|
658
|
+
## Global Execution Rules
|
|
675
659
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
- Apr\xE8s 3 \xE9checs cons\xE9cutifs \u2192 pause et demander validation humaine
|
|
681
|
-
- **Ne jamais passer \xE0 l'agent suivant sans crit\xE8re valid\xE9**
|
|
660
|
+
Before each agent:
|
|
661
|
+
1. Read \`CLAUDE.md\`
|
|
662
|
+
2. Read \`agents/agent-{N}-{slug}/skills.md\` (current agent's file)
|
|
663
|
+
3. Read the agent's section in \`AGENT_WORKFLOW.md\`
|
|
682
664
|
|
|
683
|
-
|
|
665
|
+
After each agent:
|
|
666
|
+
- Run the success criterion command
|
|
667
|
+
- \u2705 Passes \u2192 announce "\u2705 Agent N complete" and move to the next
|
|
668
|
+
- \u274C Fails \u2192 analyze the root cause, fix, rerun (max 3 attempts)
|
|
669
|
+
- After 3 consecutive failures \u2192 stop and ask for human validation
|
|
670
|
+
|
|
671
|
+
**Never move to the next agent without a passing success criterion.**
|
|
672
|
+
**Stay strictly within your current agent's defined scope.**
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
${phase0}## Phase 1 \u2014 Execution
|
|
684
677
|
|
|
685
678
|
${agentBlocks}
|
|
686
679
|
|
|
687
|
-
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## Future Iterations
|
|
683
|
+
|
|
684
|
+
When a new agent is added via \`agentkit add --feature <description>\`:
|
|
685
|
+
1. A new agent block is appended to \`AGENT_WORKFLOW.md\`
|
|
686
|
+
2. The folder \`agents/agent-{N}-{slug}/\` is created with \`skills.md\`
|
|
687
|
+
3. This \`PLAYBOOK.md\` is regenerated to include the new agent
|
|
688
|
+
4. Execution resumes at the new agent only \u2014 completed agents are not rerun
|
|
688
689
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
2. Le dossier \`agents/agent-{N}-{slug}/\` est cr\xE9\xE9 avec \`skills.md\` et \`context.md\`
|
|
692
|
-
3. Ce \`PLAYBOOK.md\` est r\xE9g\xE9n\xE9r\xE9 automatiquement pour inclure le nouvel agent
|
|
693
|
-
4. L'ex\xE9cution reprend \xE0 ce nouvel agent uniquement \u2014 les agents pr\xE9c\xE9dents ne sont pas r\xE9ex\xE9cut\xE9s
|
|
690
|
+
When you receive the instruction to continue after an iteration:
|
|
691
|
+
> "Read PLAYBOOK.md and execute only the agents that haven't been completed yet."
|
|
694
692
|
|
|
695
|
-
|
|
693
|
+
---
|
|
696
694
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
- **
|
|
695
|
+
## Human Validation Required
|
|
696
|
+
|
|
697
|
+
Stop and wait for confirmation in these situations:
|
|
698
|
+
- **3 consecutive failures** on the same success criterion
|
|
699
|
+
- **Missing external dependency**: API key, env variable, unavailable service
|
|
700
|
+
- **Conflict** between the detected stack and the user's stated constraints
|
|
701
|
+
- **Destructive operation**: overwriting files not listed in deliverables
|
|
702
|
+
- **End of Phase 0**: agent decomposition must be validated before execution
|
|
701
703
|
`;
|
|
702
704
|
}
|
|
703
705
|
function agentBlock(agent) {
|
|
704
706
|
const skillsPath = `agents/agent-${agent.number}-${agent.slug}/skills.md`;
|
|
705
|
-
const outputLines = agent.outputs.length > 0 ? agent.outputs.map((o) => `- ${o}`).join("\n") : "- (
|
|
706
|
-
return `### ${agent.
|
|
707
|
+
const outputLines = agent.outputs.length > 0 ? agent.outputs.map((o) => `- ${o}`).join("\n") : "- (see skills.md for details)";
|
|
708
|
+
return `### Agent ${agent.number} \xB7 ${agent.name}
|
|
707
709
|
|
|
708
|
-
**
|
|
710
|
+
**Scope**: ${agent.scope}
|
|
709
711
|
|
|
710
|
-
**Skills
|
|
712
|
+
**Skills**: \`${skillsPath}\`
|
|
711
713
|
|
|
712
|
-
**
|
|
714
|
+
**Deliverables**:
|
|
713
715
|
${outputLines}
|
|
714
716
|
|
|
715
|
-
**
|
|
717
|
+
**Success criterion**:
|
|
716
718
|
\`\`\`bash
|
|
717
719
|
${agent.criterion || "npm run build && npm test"}
|
|
718
720
|
\`\`\`
|
|
719
721
|
|
|
720
|
-
**
|
|
721
|
-
1.
|
|
722
|
-
2.
|
|
723
|
-
3.
|
|
724
|
-
4.
|
|
722
|
+
**On failure**:
|
|
723
|
+
1. Read the full error output
|
|
724
|
+
2. Fix the root cause \u2014 not the symptoms
|
|
725
|
+
3. Rerun the success criterion (max 3 attempts)
|
|
726
|
+
4. After 3 failures \u2192 ask for human validation
|
|
725
727
|
`;
|
|
726
728
|
}
|
|
727
729
|
|
|
@@ -775,6 +777,52 @@ ${outputLines}
|
|
|
775
777
|
`;
|
|
776
778
|
}
|
|
777
779
|
|
|
780
|
+
// src/utils/agentParser.ts
|
|
781
|
+
function toSlug(name) {
|
|
782
|
+
return name.toLowerCase().replace(/[·•&]/g, " ").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
783
|
+
}
|
|
784
|
+
function getFieldValue(lines, pattern) {
|
|
785
|
+
for (const line of lines) {
|
|
786
|
+
const m = line.match(pattern);
|
|
787
|
+
if (m) return (m[1] ?? "").trim();
|
|
788
|
+
}
|
|
789
|
+
return "";
|
|
790
|
+
}
|
|
791
|
+
function extractAgentsFromWorkflow(content) {
|
|
792
|
+
const agents = [];
|
|
793
|
+
const blocks = content.split(/(?=^### Agent \d)/m).filter((b) => /^### Agent \d/.test(b.trimStart()));
|
|
794
|
+
for (const block of blocks) {
|
|
795
|
+
const lines = block.split("\n");
|
|
796
|
+
const headerMatch = lines[0].match(/^### Agent (\d+)\s*[·•]\s*(.+)$/);
|
|
797
|
+
if (!headerMatch) continue;
|
|
798
|
+
const number = parseInt(headerMatch[1], 10);
|
|
799
|
+
const name = headerMatch[2].trim();
|
|
800
|
+
const fullName = `Agent ${number} \xB7 ${name}`;
|
|
801
|
+
const slug = toSlug(name);
|
|
802
|
+
const scope = getFieldValue(lines, /Périmètre\s*:\s*(.+)/);
|
|
803
|
+
const criterion = getFieldValue(lines, /Critère[s]?\s*:\s*(.+)/);
|
|
804
|
+
const outputs = [];
|
|
805
|
+
const produitIdx = lines.findIndex((l) => /Produit\s*:/.test(l));
|
|
806
|
+
if (produitIdx !== -1) {
|
|
807
|
+
const inlineVal = (lines[produitIdx].match(/Produit\s*:\s*(.+)/)?.[1] ?? "").trim();
|
|
808
|
+
if (inlineVal) {
|
|
809
|
+
outputs.push(inlineVal);
|
|
810
|
+
} else {
|
|
811
|
+
for (let i = produitIdx + 1; i < lines.length; i++) {
|
|
812
|
+
const line = lines[i];
|
|
813
|
+
if (/^\s+[-]/.test(line)) {
|
|
814
|
+
outputs.push(line.trim().replace(/^-\s*/, ""));
|
|
815
|
+
} else if (line.trim() !== "" && !/^\s/.test(line)) {
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
agents.push({ number, name, fullName, slug, scope, outputs, criterion });
|
|
822
|
+
}
|
|
823
|
+
return agents;
|
|
824
|
+
}
|
|
825
|
+
|
|
778
826
|
// src/utils/logger.ts
|
|
779
827
|
import chalk from "chalk";
|
|
780
828
|
var logger = {
|
|
@@ -874,9 +922,9 @@ function registerInit(program2) {
|
|
|
874
922
|
}
|
|
875
923
|
const genSpinner = ora("G\xE9n\xE9ration des fichiers\u2026").start();
|
|
876
924
|
const claudeMdContent = generateClaudeMd(stack, blueprintContent);
|
|
877
|
-
const workflowContent = generateWorkflow(stack, blueprintContent);
|
|
925
|
+
const workflowContent = generateWorkflow(stack, blueprintContent, projectName);
|
|
878
926
|
const agents = extractAgentsFromWorkflow(workflowContent);
|
|
879
|
-
const playbookContent = generatePlaybook({ agents, projectName });
|
|
927
|
+
const playbookContent = generatePlaybook({ agents, projectName, hasBlueprint: !!blueprintContent });
|
|
880
928
|
await writeFile2(claudeMdPath, claudeMdContent, "utf-8");
|
|
881
929
|
await writeFile2(workflowPath, workflowContent, "utf-8");
|
|
882
930
|
await writeFile2(playbookPath, playbookContent, "utf-8");
|
|
@@ -904,7 +952,7 @@ async function addFeatureToProject(description, projectDir) {
|
|
|
904
952
|
try {
|
|
905
953
|
workflowContent = await readFile3(workflowPath, "utf-8");
|
|
906
954
|
} catch {
|
|
907
|
-
throw new Error(`AGENT_WORKFLOW.md
|
|
955
|
+
throw new Error(`AGENT_WORKFLOW.md not found in ${projectDir} \u2014 run agentkit init first`);
|
|
908
956
|
}
|
|
909
957
|
const existingAgents = extractAgentsFromWorkflow(workflowContent);
|
|
910
958
|
const nextNumber = existingAgents.length + 1;
|
|
@@ -938,7 +986,11 @@ Crit\xE8re : npm run build && npm test
|
|
|
938
986
|
} catch {
|
|
939
987
|
}
|
|
940
988
|
const allAgents = [...existingAgents, newAgent];
|
|
941
|
-
const playbookContent = generatePlaybook({
|
|
989
|
+
const playbookContent = generatePlaybook({
|
|
990
|
+
agents: allAgents,
|
|
991
|
+
projectName,
|
|
992
|
+
hasBlueprint: false
|
|
993
|
+
});
|
|
942
994
|
await writeFile3(playbookPath, playbookContent, "utf-8");
|
|
943
995
|
return {
|
|
944
996
|
agent: newAgent,
|
|
@@ -946,13 +998,13 @@ Crit\xE8re : npm run build && npm test
|
|
|
946
998
|
};
|
|
947
999
|
}
|
|
948
1000
|
function registerAdd(program2) {
|
|
949
|
-
const addCmd = program2.command("add").description("
|
|
1001
|
+
const addCmd = program2.command("add").description("Add resources to the agentkit project").option("--feature <description>", "Add an agent from a feature description and regenerate PLAYBOOK.md").action(async (options) => {
|
|
950
1002
|
if (options.feature) {
|
|
951
1003
|
try {
|
|
952
1004
|
const result = await addFeatureToProject(options.feature, process.cwd());
|
|
953
|
-
logger.success(`Agent
|
|
954
|
-
logger.success(`
|
|
955
|
-
logger.success("PLAYBOOK.md :
|
|
1005
|
+
logger.success(`Agent added : ${result.agent.fullName}`);
|
|
1006
|
+
logger.success(`Folder created : agents/agent-${result.agent.number}-${result.agent.slug}/`);
|
|
1007
|
+
logger.success("PLAYBOOK.md : regenerated");
|
|
956
1008
|
} catch (err) {
|
|
957
1009
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
958
1010
|
process.exit(1);
|
|
@@ -961,14 +1013,14 @@ function registerAdd(program2) {
|
|
|
961
1013
|
addCmd.help();
|
|
962
1014
|
}
|
|
963
1015
|
});
|
|
964
|
-
addCmd.command("agent").description("
|
|
1016
|
+
addCmd.command("agent").description("Add a new agent to AGENT_WORKFLOW.md (interactive)").action(async () => {
|
|
965
1017
|
const cwd = process.cwd();
|
|
966
1018
|
const workflowPath = join5(cwd, "AGENT_WORKFLOW.md");
|
|
967
1019
|
let existing = "";
|
|
968
1020
|
try {
|
|
969
1021
|
existing = await readFile3(workflowPath, "utf-8");
|
|
970
1022
|
} catch {
|
|
971
|
-
logger.error("AGENT_WORKFLOW.md
|
|
1023
|
+
logger.error("AGENT_WORKFLOW.md not found \u2014 run agentkit init first");
|
|
972
1024
|
process.exit(1);
|
|
973
1025
|
}
|
|
974
1026
|
const agentCount = (existing.match(/^### Agent \d+/gm) ?? []).length;
|
|
@@ -977,23 +1029,23 @@ function registerAdd(program2) {
|
|
|
977
1029
|
{
|
|
978
1030
|
type: "input",
|
|
979
1031
|
name: "name",
|
|
980
|
-
message: `
|
|
1032
|
+
message: `Agent name (e.g. "Agent ${nextNumber} \xB7 Feature X"):`,
|
|
981
1033
|
default: `Agent ${nextNumber}`
|
|
982
1034
|
},
|
|
983
1035
|
{
|
|
984
1036
|
type: "input",
|
|
985
1037
|
name: "scope",
|
|
986
|
-
message: "
|
|
1038
|
+
message: "Scope (one sentence):"
|
|
987
1039
|
},
|
|
988
1040
|
{
|
|
989
1041
|
type: "input",
|
|
990
1042
|
name: "outputs",
|
|
991
|
-
message: "
|
|
1043
|
+
message: "Deliverables (comma-separated):"
|
|
992
1044
|
},
|
|
993
1045
|
{
|
|
994
1046
|
type: "input",
|
|
995
1047
|
name: "criterion",
|
|
996
|
-
message: "
|
|
1048
|
+
message: "Success criterion:"
|
|
997
1049
|
}
|
|
998
1050
|
]);
|
|
999
1051
|
const outputLines = answers.outputs.split(",").map((o) => ` - ${o.trim()}`).join("\n");
|
|
@@ -1005,7 +1057,7 @@ ${outputLines}
|
|
|
1005
1057
|
Crit\xE8re : ${answers.criterion}
|
|
1006
1058
|
`;
|
|
1007
1059
|
await writeFile3(workflowPath, existing + agentSection, "utf-8");
|
|
1008
|
-
logger.success(`Agent "${answers.name}"
|
|
1060
|
+
logger.success(`Agent "${answers.name}" added to AGENT_WORKFLOW.md`);
|
|
1009
1061
|
});
|
|
1010
1062
|
}
|
|
1011
1063
|
|