@prateek_ai/agents-maker 1.0.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/LICENSE +21 -0
- package/README.md +659 -0
- package/agents/architect_agent.md +175 -0
- package/agents/code_agent.md +178 -0
- package/agents/compression_agent.md +226 -0
- package/agents/execution_agent.md +157 -0
- package/agents/orchestrator.md +406 -0
- package/agents/reviewer_agent.md +134 -0
- package/agents/ui_agent.md +147 -0
- package/agents/ux_agent.md +144 -0
- package/bin/cli.js +79 -0
- package/config/agents.yaml +388 -0
- package/config/domain_profiles.yaml +394 -0
- package/config/project.yaml.example +16 -0
- package/config/token_policies.yaml +325 -0
- package/context_loaders/__init__.py +15 -0
- package/context_loaders/__pycache__/__init__.cpython-314.pyc +0 -0
- package/context_loaders/__pycache__/file_chunker.cpython-314.pyc +0 -0
- package/context_loaders/__pycache__/project_summary.cpython-314.pyc +0 -0
- package/context_loaders/__pycache__/repo_tree.cpython-314.pyc +0 -0
- package/context_loaders/file_chunker.py +252 -0
- package/context_loaders/project_summary.py +369 -0
- package/context_loaders/repo_tree.py +203 -0
- package/package.json +46 -0
- package/quickstart.ps1 +252 -0
- package/quickstart.sh +232 -0
- package/requirements.txt +3 -0
- package/skills/analyze_repo.md +86 -0
- package/skills/animated_website.md +285 -0
- package/skills/compare_approaches.md +86 -0
- package/skills/define_data_schema.md +99 -0
- package/skills/design_api.md +126 -0
- package/skills/improve_copy.md +69 -0
- package/skills/review_code.md +83 -0
- package/skills/review_layout.md +89 -0
- package/skills/suggest_next.md +105 -0
- package/skills/summarize_history.md +89 -0
- package/skills/write_process_map.md +105 -0
- package/skills/write_tests.md +97 -0
- package/token_optimization/__pycache__/compressor.cpython-314.pyc +0 -0
- package/token_optimization/compressor.py +502 -0
- package/token_optimization/output_styles.md +80 -0
- package/tools/__pycache__/domain_utils.cpython-314.pyc +0 -0
- package/tools/__pycache__/generate_claude_md.cpython-314.pyc +0 -0
- package/tools/__pycache__/validate_kit.cpython-314.pyc +0 -0
- package/tools/domain_utils.py +141 -0
- package/tools/generate_claude_md.py +269 -0
- package/tools/generate_platform_configs.py +467 -0
- package/tools/generate_prompt.py +461 -0
- package/tools/init_project.py +454 -0
- package/tools/test_kit.py +363 -0
- package/tools/validate_kit.py +504 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
generate_platform_configs.py — Wire agents-maker into every AI platform you use.
|
|
4
|
+
|
|
5
|
+
Generates native config files for Claude Code, GitHub Copilot, Cursor, and Antigravity
|
|
6
|
+
from your project's domain/stack/phase. Commit the generated files — they are project
|
|
7
|
+
config, not private state.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python agents-maker/tools/generate_platform_configs.py
|
|
11
|
+
python agents-maker/tools/generate_platform_configs.py --platforms claude copilot cursor
|
|
12
|
+
python agents-maker/tools/generate_platform_configs.py --dry-run
|
|
13
|
+
python agents-maker/tools/generate_platform_configs.py --path /your/project
|
|
14
|
+
|
|
15
|
+
Generated files:
|
|
16
|
+
CLAUDE.md Claude Code (auto-read every session)
|
|
17
|
+
.github/copilot-instructions.md GitHub Copilot (workspace instructions)
|
|
18
|
+
.cursor/rules Cursor (persistent AI rules)
|
|
19
|
+
.agkit/agents.yaml Antigravity agkit (agent pipeline config)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
__version__ = "1.0.0"
|
|
25
|
+
|
|
26
|
+
import argparse
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
import tempfile
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
SCRIPT_DIR = Path(__file__).resolve().parent # agents-maker/tools/
|
|
33
|
+
KIT_DIR = SCRIPT_DIR.parent # agents-maker/
|
|
34
|
+
sys.path.insert(0, str(KIT_DIR))
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
import yaml as _yaml_probe # noqa: F401 — ensures pyyaml is installed
|
|
38
|
+
except ImportError:
|
|
39
|
+
print("[ERROR] pyyaml is required: pip install pyyaml", file=sys.stderr)
|
|
40
|
+
sys.exit(1)
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
from tools.generate_claude_md import (
|
|
44
|
+
_AGENT_ROLES,
|
|
45
|
+
_PHASE_AGENTS,
|
|
46
|
+
_PHASE_LABELS,
|
|
47
|
+
_parse_phase,
|
|
48
|
+
build_claude_md,
|
|
49
|
+
)
|
|
50
|
+
except ImportError:
|
|
51
|
+
from generate_claude_md import (
|
|
52
|
+
_AGENT_ROLES,
|
|
53
|
+
_PHASE_AGENTS,
|
|
54
|
+
_PHASE_LABELS,
|
|
55
|
+
_parse_phase,
|
|
56
|
+
build_claude_md,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
from tools.domain_utils import _load_yaml
|
|
61
|
+
except ImportError:
|
|
62
|
+
from domain_utils import _load_yaml
|
|
63
|
+
|
|
64
|
+
PLATFORMS = ["claude", "copilot", "cursor", "antigravity"]
|
|
65
|
+
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
# Helpers shared across builders
|
|
68
|
+
# ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
def _active_agents(domain: str, phase: str) -> list[str]:
|
|
71
|
+
phase_map = _PHASE_AGENTS.get(phase, {"_all": ["orchestrator"]})
|
|
72
|
+
return phase_map.get(domain, phase_map["_all"])
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _agent_list_str(agents: list[str]) -> str:
|
|
76
|
+
return ", ".join(f"{a} ({_AGENT_ROLES.get(a, 'specialist')})" for a in agents)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _py(kit_rel: str, tool: str) -> str:
|
|
80
|
+
"""Return a shell-safe 'python ...' invocation. Quotes the full path when it contains spaces."""
|
|
81
|
+
path = f"{kit_rel}/tools/{tool}"
|
|
82
|
+
return f'python "{path}"' if " " in path else f"python {path}"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _yaml_str(value: str) -> str:
|
|
86
|
+
"""Return a YAML-safe scalar: quoted if it contains spaces or YAML special characters."""
|
|
87
|
+
if " " in value or any(c in value for c in ":{}[]#&*!|>'\"%@`"):
|
|
88
|
+
return f'"{value}"'
|
|
89
|
+
return value
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _atomic_write(path: Path, content: str) -> None:
|
|
93
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
94
|
+
with tempfile.NamedTemporaryFile(
|
|
95
|
+
"w", dir=path.parent, delete=False, suffix=".tmp", encoding="utf-8"
|
|
96
|
+
) as f:
|
|
97
|
+
f.write(content)
|
|
98
|
+
tmp = f.name
|
|
99
|
+
os.replace(tmp, path)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# ---------------------------------------------------------------------------
|
|
103
|
+
# Builder: GitHub Copilot — .github/copilot-instructions.md
|
|
104
|
+
# ---------------------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
def build_copilot_md(
|
|
107
|
+
project_name: str,
|
|
108
|
+
domain: str,
|
|
109
|
+
confidence: str,
|
|
110
|
+
stack: list[str],
|
|
111
|
+
phase: str,
|
|
112
|
+
kit_rel_path: str,
|
|
113
|
+
) -> str:
|
|
114
|
+
stack_str = ", ".join(stack) if stack else "unknown"
|
|
115
|
+
phase_label = _PHASE_LABELS.get(phase, phase)
|
|
116
|
+
agents = _active_agents(domain, phase)
|
|
117
|
+
regen_cmd = _py(kit_rel_path, "generate_platform_configs.py")
|
|
118
|
+
|
|
119
|
+
all_agents = [
|
|
120
|
+
"orchestrator (routing — always active)",
|
|
121
|
+
"architect_agent (system design, API contracts)",
|
|
122
|
+
"code_agent (software + analytics implementation)",
|
|
123
|
+
"execution_agent (docs, research, marketing, ops)",
|
|
124
|
+
"ui_agent (layout, components, design tokens)",
|
|
125
|
+
"ux_agent (flows, onboarding, funnel critique)",
|
|
126
|
+
"reviewer_agent (QA, severity-rated review)",
|
|
127
|
+
"compression_agent (context compression, resumption)",
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
f"# agents-maker — GitHub Copilot Instructions\n"
|
|
132
|
+
f"# Auto-generated: {regen_cmd}\n"
|
|
133
|
+
f"# Regenerate after domain/phase changes.\n"
|
|
134
|
+
f"\n"
|
|
135
|
+
f"## Project Context\n"
|
|
136
|
+
f"Project: {project_name} | Domain: {domain} (confidence: {confidence}) | Stack: {stack_str}\n"
|
|
137
|
+
f"Current phase: {phase_label} (`{phase}`)\n"
|
|
138
|
+
f"\n"
|
|
139
|
+
f"## Agent Routing\n"
|
|
140
|
+
f"This project uses the agents-maker multi-agent framework.\n"
|
|
141
|
+
f"Active agents for this phase: {_agent_list_str(agents)}.\n"
|
|
142
|
+
f"\n"
|
|
143
|
+
f"Full agent roster:\n"
|
|
144
|
+
+ "".join(f"- {a}\n" for a in all_agents)
|
|
145
|
+
+ f"\n"
|
|
146
|
+
f"## Response Instructions\n"
|
|
147
|
+
f"- Apply domain routing (`{domain}`) before every suggestion.\n"
|
|
148
|
+
f"- Match output style to the current phase ({phase_label}):\n"
|
|
149
|
+
f" - implementation → working code with inline comments only\n"
|
|
150
|
+
f" - solution_design → structured tables and diagrams\n"
|
|
151
|
+
f" - review_refinement → severity-rated findings (CRITICAL / HIGH / MEDIUM / LOW)\n"
|
|
152
|
+
f"- After every substantive response, suggest 3 ranked next steps.\n"
|
|
153
|
+
f"- Prefer concise, structured output. Avoid explanatory prose when code or bullets suffice.\n"
|
|
154
|
+
f"\n"
|
|
155
|
+
f"## Kit Location\n"
|
|
156
|
+
f"{kit_rel_path}/\n"
|
|
157
|
+
f"Regenerate: `{regen_cmd}`\n"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# ---------------------------------------------------------------------------
|
|
162
|
+
# Builder: Cursor — .cursor/rules
|
|
163
|
+
# ---------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
def build_cursor_rules(
|
|
166
|
+
project_name: str,
|
|
167
|
+
domain: str,
|
|
168
|
+
confidence: str,
|
|
169
|
+
stack: list[str],
|
|
170
|
+
phase: str,
|
|
171
|
+
kit_rel_path: str,
|
|
172
|
+
) -> str:
|
|
173
|
+
stack_str = ", ".join(stack) if stack else "unknown"
|
|
174
|
+
phase_label = _PHASE_LABELS.get(phase, phase)
|
|
175
|
+
agents = _active_agents(domain, phase)
|
|
176
|
+
regen_cmd = _py(kit_rel_path, "generate_platform_configs.py")
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
f"# agents-maker — Cursor Rules\n"
|
|
180
|
+
f"# Auto-generated: {regen_cmd}\n"
|
|
181
|
+
f"# Regenerate after domain/phase changes.\n"
|
|
182
|
+
f"\n"
|
|
183
|
+
f"## Active Domain\n"
|
|
184
|
+
f"{domain} (confidence: {confidence})\n"
|
|
185
|
+
f"\n"
|
|
186
|
+
f"## Stack\n"
|
|
187
|
+
f"{stack_str}\n"
|
|
188
|
+
f"\n"
|
|
189
|
+
f"## Current Phase\n"
|
|
190
|
+
f"{phase_label} (`{phase}`)\n"
|
|
191
|
+
f"\n"
|
|
192
|
+
f"## Agent Routing\n"
|
|
193
|
+
f"All tasks in this project route through the agents-maker multi-agent framework.\n"
|
|
194
|
+
f"Orchestrator is always active. Specialist agents for this phase: {_agent_list_str(agents)}.\n"
|
|
195
|
+
f"\n"
|
|
196
|
+
f"## Instructions\n"
|
|
197
|
+
f"- Apply domain routing and phase context from agents-maker before every task.\n"
|
|
198
|
+
f"- Match output style to phase: implementation → code; design → tables; review → severity ratings.\n"
|
|
199
|
+
f"- After every response: append a [Companion] block with 3 ranked next steps.\n"
|
|
200
|
+
f"- Include a `Command:` line the user can copy to continue the workflow.\n"
|
|
201
|
+
f"- Keep responses token-efficient. Prefer bullets over prose.\n"
|
|
202
|
+
f"\n"
|
|
203
|
+
f"## Kit Location\n"
|
|
204
|
+
f"{kit_rel_path}/\n"
|
|
205
|
+
f"Regenerate: `{regen_cmd}`\n"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ---------------------------------------------------------------------------
|
|
210
|
+
# Builder: Antigravity — .agkit/agents.yaml
|
|
211
|
+
# ---------------------------------------------------------------------------
|
|
212
|
+
|
|
213
|
+
_AGENT_DESCRIPTIONS: dict[str, str] = {
|
|
214
|
+
"orchestrator": "Phase driver — detects domain, routes tasks, drives 6-phase lifecycle",
|
|
215
|
+
"architect_agent": "System design, API contracts, solution architecture, research plans",
|
|
216
|
+
"code_agent": "Software + analytics implementation, refactoring, test generation",
|
|
217
|
+
"execution_agent": "Non-code output — docs, research, marketing copy, SOPs, runbooks",
|
|
218
|
+
"ui_agent": "Component hierarchy, layout, design tokens, accessibility",
|
|
219
|
+
"ux_agent": "Flow critique, onboarding sequences, funnel analysis, friction ID",
|
|
220
|
+
"reviewer_agent": "Severity-rated QA review for any domain (CRITICAL/HIGH/MEDIUM/LOW)",
|
|
221
|
+
"compression_agent": "Token budget enforcement, context compression, cross-session resumption",
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
_AGENT_PHASES: dict[str, list[str]] = {
|
|
225
|
+
"orchestrator": ["task_framing", "requirements", "solution_design", "implementation", "review_refinement", "handoff"],
|
|
226
|
+
"architect_agent": ["requirements", "solution_design"],
|
|
227
|
+
"code_agent": ["implementation", "review_refinement"],
|
|
228
|
+
"execution_agent": ["implementation"],
|
|
229
|
+
"ui_agent": ["solution_design", "review_refinement"],
|
|
230
|
+
"ux_agent": ["solution_design", "review_refinement"],
|
|
231
|
+
"reviewer_agent": ["review_refinement"],
|
|
232
|
+
"compression_agent": ["handoff"],
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
_AGENT_DOMAINS: dict[str, list[str]] = {
|
|
236
|
+
"orchestrator": ["software", "content", "research", "data_analytics", "product_design", "marketing", "ops_process", "general"],
|
|
237
|
+
"architect_agent": ["software", "content", "research", "data_analytics", "product_design", "marketing", "ops_process", "general"],
|
|
238
|
+
"code_agent": ["software", "data_analytics"],
|
|
239
|
+
"execution_agent": ["content", "research", "marketing", "ops_process", "product_design", "general"],
|
|
240
|
+
"ui_agent": ["product_design", "software"],
|
|
241
|
+
"ux_agent": ["product_design", "marketing"],
|
|
242
|
+
"reviewer_agent": ["software", "content", "research", "data_analytics", "product_design", "marketing", "ops_process", "general"],
|
|
243
|
+
"compression_agent": ["software", "content", "research", "data_analytics", "product_design", "marketing", "ops_process", "general"],
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
_AGENT_ORDER = [
|
|
247
|
+
"orchestrator", "architect_agent", "code_agent", "execution_agent",
|
|
248
|
+
"ui_agent", "ux_agent", "reviewer_agent", "compression_agent",
|
|
249
|
+
]
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def build_agkit_yaml(
|
|
253
|
+
project_name: str,
|
|
254
|
+
domain: str,
|
|
255
|
+
stack: list[str],
|
|
256
|
+
phase: str,
|
|
257
|
+
kit_rel_path: str,
|
|
258
|
+
) -> str:
|
|
259
|
+
regen_cmd = _py(kit_rel_path, "generate_platform_configs.py")
|
|
260
|
+
stack_list = stack if stack else ["unknown"]
|
|
261
|
+
|
|
262
|
+
lines: list[str] = [
|
|
263
|
+
"# agents-maker — Antigravity agkit config",
|
|
264
|
+
f"# Auto-generated: {regen_cmd}",
|
|
265
|
+
"# Regenerate after domain/phase changes.",
|
|
266
|
+
f"# See {kit_rel_path}/platforms/antigravity.md for integration guide.",
|
|
267
|
+
"",
|
|
268
|
+
"kit_version: \"1.0\"",
|
|
269
|
+
"",
|
|
270
|
+
"project:",
|
|
271
|
+
f" name: {project_name}",
|
|
272
|
+
f" domain: {domain}",
|
|
273
|
+
f" stack: [{', '.join(stack_list)}]",
|
|
274
|
+
f" phase: {phase}",
|
|
275
|
+
"",
|
|
276
|
+
"agents:",
|
|
277
|
+
]
|
|
278
|
+
|
|
279
|
+
for agent_id in _AGENT_ORDER:
|
|
280
|
+
desc = _AGENT_DESCRIPTIONS.get(agent_id, agent_id)
|
|
281
|
+
phases = _AGENT_PHASES.get(agent_id, [])
|
|
282
|
+
domains = _AGENT_DOMAINS.get(agent_id, [])
|
|
283
|
+
always = agent_id == "orchestrator"
|
|
284
|
+
|
|
285
|
+
lines.append(f" {agent_id}:")
|
|
286
|
+
lines.append(f" role: {_AGENT_ROLES.get(agent_id, 'specialist')}")
|
|
287
|
+
lines.append(f" description: \"{desc}\"")
|
|
288
|
+
lines.append(f" system_prompt_file: {_yaml_str(kit_rel_path + '/agents/' + agent_id + '.md')}")
|
|
289
|
+
if always:
|
|
290
|
+
lines.append(" always_active: true")
|
|
291
|
+
else:
|
|
292
|
+
lines.append(f" active_phases: [{', '.join(phases)}]")
|
|
293
|
+
lines.append(f" active_domains: [{', '.join(domains)}]")
|
|
294
|
+
lines.append("")
|
|
295
|
+
|
|
296
|
+
lines += [
|
|
297
|
+
"context:",
|
|
298
|
+
" inject_globally:",
|
|
299
|
+
f" - {_yaml_str(kit_rel_path + '/config/agents.yaml')}",
|
|
300
|
+
f" - {_yaml_str(kit_rel_path + '/config/domain_profiles.yaml')}",
|
|
301
|
+
f" - {_yaml_str(kit_rel_path + '/config/token_policies.yaml')}",
|
|
302
|
+
" inject_per_session:",
|
|
303
|
+
f" - {_yaml_str(kit_rel_path + '/project_state.md')}",
|
|
304
|
+
"",
|
|
305
|
+
"skills:",
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
skills = [
|
|
309
|
+
("analyze_repo", "Any session starting with a code repo"),
|
|
310
|
+
("design_api", "API design, schema, contract decisions"),
|
|
311
|
+
("review_code", "Code review, QA, security audit"),
|
|
312
|
+
("review_layout", "UI/UX critique, layout and accessibility"),
|
|
313
|
+
("improve_copy", "Writing quality, tone, clarity"),
|
|
314
|
+
("write_tests", "Test generation, coverage, edge cases"),
|
|
315
|
+
("summarize_history", "Cross-session compression and handoff"),
|
|
316
|
+
("suggest_next", "Auto-fires after every deliverable"),
|
|
317
|
+
("compare_approaches","Structured decision table for trade-offs"),
|
|
318
|
+
("animated_website", "CSS/GSAP/Framer Motion animation code"),
|
|
319
|
+
("write_process_map", "SOP/runbook: steps + RACI + exceptions"),
|
|
320
|
+
("define_data_schema","ER sketch + metric definitions + data dictionary"),
|
|
321
|
+
]
|
|
322
|
+
for key, trigger in skills:
|
|
323
|
+
lines.append(f" {key}:")
|
|
324
|
+
lines.append(f" skill_file: {_yaml_str(kit_rel_path + '/skills/' + key + '.md')}")
|
|
325
|
+
lines.append(f" trigger: \"{trigger}\"")
|
|
326
|
+
lines.append("")
|
|
327
|
+
|
|
328
|
+
return "\n".join(lines)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
# ---------------------------------------------------------------------------
|
|
332
|
+
# Orchestrator
|
|
333
|
+
# ---------------------------------------------------------------------------
|
|
334
|
+
|
|
335
|
+
_PLATFORM_PATHS: dict[str, str] = {
|
|
336
|
+
"claude": "CLAUDE.md",
|
|
337
|
+
"copilot": ".github/copilot-instructions.md",
|
|
338
|
+
"cursor": ".cursor/rules",
|
|
339
|
+
"antigravity": ".agkit/agents.yaml",
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def generate_all(
|
|
344
|
+
project_root: Path,
|
|
345
|
+
kit_dir: Path,
|
|
346
|
+
platforms: list[str],
|
|
347
|
+
dry_run: bool,
|
|
348
|
+
) -> None:
|
|
349
|
+
project_cfg = _load_yaml(kit_dir / "config" / "project.yaml")
|
|
350
|
+
if not project_cfg:
|
|
351
|
+
print("[WARN] config/project.yaml not found — run init_project.py first.", file=sys.stderr)
|
|
352
|
+
|
|
353
|
+
domain = project_cfg.get("primary_domain", "general")
|
|
354
|
+
stack = project_cfg.get("stack", [])
|
|
355
|
+
if isinstance(stack, str):
|
|
356
|
+
stack = [s.strip() for s in stack.split(",") if s.strip()]
|
|
357
|
+
project_name = project_cfg.get("project_name", project_root.name)
|
|
358
|
+
confidence = "high" if project_cfg.get("primary_domain") else "low"
|
|
359
|
+
|
|
360
|
+
state_path = kit_dir / "project_state.md"
|
|
361
|
+
phase = _parse_phase(state_path.read_text(encoding="utf-8")) if state_path.exists() else "task_framing"
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
kit_rel = kit_dir.relative_to(project_root)
|
|
365
|
+
kit_rel_path = str(kit_rel).replace("\\", "/")
|
|
366
|
+
except ValueError:
|
|
367
|
+
kit_rel_path = "agents-maker"
|
|
368
|
+
|
|
369
|
+
builders: dict[str, tuple[str, str]] = {}
|
|
370
|
+
|
|
371
|
+
if "claude" in platforms:
|
|
372
|
+
content = build_claude_md(project_name, domain, confidence, stack, phase, kit_rel_path)
|
|
373
|
+
builders["claude"] = (_PLATFORM_PATHS["claude"], content)
|
|
374
|
+
|
|
375
|
+
if "copilot" in platforms:
|
|
376
|
+
content = build_copilot_md(project_name, domain, confidence, stack, phase, kit_rel_path)
|
|
377
|
+
builders["copilot"] = (_PLATFORM_PATHS["copilot"], content)
|
|
378
|
+
|
|
379
|
+
if "cursor" in platforms:
|
|
380
|
+
content = build_cursor_rules(project_name, domain, confidence, stack, phase, kit_rel_path)
|
|
381
|
+
builders["cursor"] = (_PLATFORM_PATHS["cursor"], content)
|
|
382
|
+
|
|
383
|
+
if "antigravity" in platforms:
|
|
384
|
+
content = build_agkit_yaml(project_name, domain, stack, phase, kit_rel_path)
|
|
385
|
+
builders["antigravity"] = (_PLATFORM_PATHS["antigravity"], content)
|
|
386
|
+
|
|
387
|
+
if dry_run:
|
|
388
|
+
for platform, (rel_path, content) in builders.items():
|
|
389
|
+
print(f"\n{'='*60}")
|
|
390
|
+
print(f" [{platform.upper()}] → {rel_path}")
|
|
391
|
+
print(f"{'='*60}")
|
|
392
|
+
print(content)
|
|
393
|
+
return
|
|
394
|
+
|
|
395
|
+
print()
|
|
396
|
+
written: list[str] = []
|
|
397
|
+
for platform, (rel_path, content) in builders.items():
|
|
398
|
+
out_path = project_root / rel_path
|
|
399
|
+
try:
|
|
400
|
+
_atomic_write(out_path, content)
|
|
401
|
+
print(f" [DONE] {rel_path} ({platform})")
|
|
402
|
+
written.append(rel_path)
|
|
403
|
+
except OSError as e:
|
|
404
|
+
print(f" [FAIL] {rel_path}: {e}", file=sys.stderr)
|
|
405
|
+
|
|
406
|
+
print()
|
|
407
|
+
print(f"Domain: {domain} (confidence: {confidence}) | Stack: {', '.join(stack) if stack else 'unknown'} | Phase: {phase}")
|
|
408
|
+
print()
|
|
409
|
+
if written:
|
|
410
|
+
print("Commit these files — they are project config, not private state:")
|
|
411
|
+
for f in written:
|
|
412
|
+
print(f" git add {f}")
|
|
413
|
+
print()
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
# ---------------------------------------------------------------------------
|
|
417
|
+
# Main
|
|
418
|
+
# ---------------------------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
def main() -> None:
|
|
421
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
422
|
+
|
|
423
|
+
parser = argparse.ArgumentParser(
|
|
424
|
+
description="Generate platform config files for Claude Code, Copilot, Cursor, and Antigravity.",
|
|
425
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
426
|
+
epilog=(
|
|
427
|
+
"Examples:\n"
|
|
428
|
+
" python agents-maker/tools/generate_platform_configs.py\n"
|
|
429
|
+
" python agents-maker/tools/generate_platform_configs.py --platforms claude copilot\n"
|
|
430
|
+
" python agents-maker/tools/generate_platform_configs.py --dry-run\n"
|
|
431
|
+
" python agents-maker/tools/generate_platform_configs.py --path /my/project\n"
|
|
432
|
+
),
|
|
433
|
+
)
|
|
434
|
+
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
|
|
435
|
+
parser.add_argument(
|
|
436
|
+
"--platforms",
|
|
437
|
+
nargs="+",
|
|
438
|
+
choices=PLATFORMS,
|
|
439
|
+
default=PLATFORMS,
|
|
440
|
+
metavar="PLATFORM",
|
|
441
|
+
help=f"Platforms to generate configs for (default: all). Choices: {', '.join(PLATFORMS)}",
|
|
442
|
+
)
|
|
443
|
+
parser.add_argument(
|
|
444
|
+
"--dry-run",
|
|
445
|
+
action="store_true",
|
|
446
|
+
help="Print generated configs to stdout without writing any files.",
|
|
447
|
+
)
|
|
448
|
+
parser.add_argument(
|
|
449
|
+
"--path",
|
|
450
|
+
help="Project root directory (default: parent of agents-maker/).",
|
|
451
|
+
)
|
|
452
|
+
args = parser.parse_args()
|
|
453
|
+
|
|
454
|
+
if args.path:
|
|
455
|
+
project_root = Path(args.path).resolve()
|
|
456
|
+
else:
|
|
457
|
+
project_root = KIT_DIR.parent
|
|
458
|
+
|
|
459
|
+
if not project_root.exists() or not project_root.is_dir():
|
|
460
|
+
print(f"[ERROR] Project root does not exist or is not a directory: {project_root}", file=sys.stderr)
|
|
461
|
+
sys.exit(1)
|
|
462
|
+
|
|
463
|
+
generate_all(project_root, KIT_DIR, args.platforms, args.dry_run)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
if __name__ == "__main__":
|
|
467
|
+
main()
|