tempo-agent 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/README.md +129 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +136 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/controller/runPipeline.d.ts +3 -0
- package/dist/controller/runPipeline.d.ts.map +1 -0
- package/dist/controller/runPipeline.js +109 -0
- package/dist/controller/runPipeline.js.map +1 -0
- package/dist/executor/claudeClient.d.ts +2 -0
- package/dist/executor/claudeClient.d.ts.map +1 -0
- package/dist/executor/claudeClient.js +33 -0
- package/dist/executor/claudeClient.js.map +1 -0
- package/dist/executor/runStep.d.ts +10 -0
- package/dist/executor/runStep.d.ts.map +1 -0
- package/dist/executor/runStep.js +97 -0
- package/dist/executor/runStep.js.map +1 -0
- package/dist/ideation/compile.d.ts +2 -0
- package/dist/ideation/compile.d.ts.map +1 -0
- package/dist/ideation/compile.js +90 -0
- package/dist/ideation/compile.js.map +1 -0
- package/dist/spec/schema.d.ts +56 -0
- package/dist/spec/schema.d.ts.map +1 -0
- package/dist/spec/schema.js +17 -0
- package/dist/spec/schema.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +40 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/validator/runValidation.d.ts +6 -0
- package/dist/validator/runValidation.d.ts.map +1 -0
- package/dist/validator/runValidation.js +50 -0
- package/dist/validator/runValidation.js.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Tempo
|
|
2
|
+
|
|
3
|
+
AI-driven code generation CLI. Give Tempo a goal, and it writes, validates, and retries code changes step by step using Claude.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g tempo-agent
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
Set your Anthropic API key:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export ANTHROPIC_API_KEY=your-key-here
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### 1. Initialize a project
|
|
22
|
+
|
|
23
|
+
Run this inside any existing project:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
tempo init
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Creates a `.tempo/` directory with config and folders for scores, sessions, and ideation files.
|
|
30
|
+
|
|
31
|
+
### 2. Write an ideation file
|
|
32
|
+
|
|
33
|
+
Create a markdown file in `.tempo/ideation/my-feature.md`:
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
# Goal
|
|
37
|
+
Build a REST API for a todo list
|
|
38
|
+
|
|
39
|
+
# Context
|
|
40
|
+
- Use Express.js
|
|
41
|
+
- Use TypeScript
|
|
42
|
+
- Store data in memory
|
|
43
|
+
|
|
44
|
+
# Ideas
|
|
45
|
+
- Add pagination
|
|
46
|
+
- Add filtering by status
|
|
47
|
+
|
|
48
|
+
# Final Plan
|
|
49
|
+
1. Create Express server entry point
|
|
50
|
+
2. Add todo routes (GET, POST, PUT, DELETE)
|
|
51
|
+
3. Add in-memory store module
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 3. Compile it into a score
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
tempo compile my-feature.md
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Generates `.tempo/scores/my-feature.json` — a structured execution plan.
|
|
61
|
+
|
|
62
|
+
### 4. Edit the score
|
|
63
|
+
|
|
64
|
+
Open `.tempo/scores/my-feature.json` and fill in `files_allowed` for each step — the list of files Claude is permitted to create or modify:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"steps": [
|
|
69
|
+
{
|
|
70
|
+
"id": 1,
|
|
71
|
+
"description": "Create Express server entry point",
|
|
72
|
+
"files_allowed": ["src/index.ts"]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 5. Run it
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
tempo run my-feature
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Tempo will:
|
|
85
|
+
- Send each step to Claude with the current file contents
|
|
86
|
+
- Write Claude's response back to disk
|
|
87
|
+
- Run lint, build, and tests
|
|
88
|
+
- Retry up to 3 times on failure, feeding errors back to Claude
|
|
89
|
+
- Save a full session log to `.tempo/sessions/`
|
|
90
|
+
|
|
91
|
+
## Config
|
|
92
|
+
|
|
93
|
+
`.tempo/config.json` controls which commands are used for validation:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"testCommand": "npm test",
|
|
98
|
+
"buildCommand": "npm run build",
|
|
99
|
+
"lintCommand": "npm run lint"
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Set any value to `null` to skip that step.
|
|
104
|
+
|
|
105
|
+
## Session History
|
|
106
|
+
|
|
107
|
+
Every run is saved to `.tempo/sessions/session-{timestamp}/`:
|
|
108
|
+
|
|
109
|
+
| File | Contents |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `step-N.md` | Prompt sent, files used, Claude response, result |
|
|
112
|
+
| `errors-step-N.md` | Validation errors and retry attempts |
|
|
113
|
+
| `diff-N.patch` | Git diff after each step |
|
|
114
|
+
|
|
115
|
+
Add to your `.gitignore`:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
.tempo/sessions/
|
|
119
|
+
.tempo/runs/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## How it works
|
|
123
|
+
|
|
124
|
+
1. Reads the files listed in `files_allowed` for the current step
|
|
125
|
+
2. Sends them to Claude with the step instruction
|
|
126
|
+
3. Claude returns full file replacements
|
|
127
|
+
4. Tempo writes them to disk
|
|
128
|
+
5. Runs validation — if it fails, sends the errors back to Claude and retries
|
|
129
|
+
6. Moves to the next step once validation passes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const schema_1 = require("../spec/schema");
|
|
11
|
+
const runPipeline_1 = require("../controller/runPipeline");
|
|
12
|
+
const compile_1 = require("../ideation/compile");
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
function printHelp() {
|
|
15
|
+
console.log(chalk_1.default.bold('\nTempo — AI-driven code generation CLI\n'));
|
|
16
|
+
console.log('Usage:');
|
|
17
|
+
console.log(' tempo init Initialize .tempo/ in current directory');
|
|
18
|
+
console.log(' tempo compile <file> Compile a markdown ideation file to a score');
|
|
19
|
+
console.log(' tempo run <score-name> Run a score from .tempo/scores/<name>.json');
|
|
20
|
+
console.log('');
|
|
21
|
+
}
|
|
22
|
+
function cmdInit() {
|
|
23
|
+
const tempoDir = path_1.default.join(cwd, '.tempo');
|
|
24
|
+
const dirs = ['ideation', 'scores', 'sessions', 'runs'];
|
|
25
|
+
fs_1.default.mkdirSync(tempoDir, { recursive: true });
|
|
26
|
+
for (const d of dirs) {
|
|
27
|
+
fs_1.default.mkdirSync(path_1.default.join(tempoDir, d), { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
const configPath = path_1.default.join(tempoDir, 'config.json');
|
|
30
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
31
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify({
|
|
32
|
+
testCommand: 'npm test',
|
|
33
|
+
buildCommand: 'npm run build',
|
|
34
|
+
lintCommand: 'npm run lint',
|
|
35
|
+
}, null, 2), 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
const rulesPath = path_1.default.join(tempoDir, 'rules.md');
|
|
38
|
+
if (!fs_1.default.existsSync(rulesPath)) {
|
|
39
|
+
fs_1.default.writeFileSync(rulesPath, `# Tempo Rules
|
|
40
|
+
|
|
41
|
+
## Code Style
|
|
42
|
+
- Use TypeScript
|
|
43
|
+
- Use async/await
|
|
44
|
+
- Keep functions small and focused
|
|
45
|
+
|
|
46
|
+
## Safety
|
|
47
|
+
- Only modify files listed in files_allowed
|
|
48
|
+
- Never delete files not explicitly listed
|
|
49
|
+
|
|
50
|
+
## .gitignore suggestions
|
|
51
|
+
Add these to your .gitignore:
|
|
52
|
+
.tempo/sessions/
|
|
53
|
+
.tempo/runs/
|
|
54
|
+
`, 'utf-8');
|
|
55
|
+
}
|
|
56
|
+
console.log(chalk_1.default.green('✓ Initialized .tempo/ directory'));
|
|
57
|
+
console.log(chalk_1.default.blue(' .tempo/config.json — validation commands'));
|
|
58
|
+
console.log(chalk_1.default.blue(' .tempo/rules.md — agent behavior rules'));
|
|
59
|
+
console.log(chalk_1.default.blue(' .tempo/ideation/ — place your .md ideation files here'));
|
|
60
|
+
console.log(chalk_1.default.blue(' .tempo/scores/ — compiled score JSONs'));
|
|
61
|
+
console.log(chalk_1.default.blue(' .tempo/sessions/ — execution history per run'));
|
|
62
|
+
console.log('');
|
|
63
|
+
console.log(chalk_1.default.yellow('Tip: add .tempo/sessions/ and .tempo/runs/ to your .gitignore'));
|
|
64
|
+
}
|
|
65
|
+
function cmdCompile(args) {
|
|
66
|
+
const fileName = args[0];
|
|
67
|
+
if (!fileName) {
|
|
68
|
+
console.error(chalk_1.default.red('Usage: tempo compile <file>'));
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const filePath = path_1.default.isAbsolute(fileName)
|
|
72
|
+
? fileName
|
|
73
|
+
: path_1.default.join(cwd, '.tempo', 'ideation', fileName);
|
|
74
|
+
try {
|
|
75
|
+
const outPath = (0, compile_1.compileIdeation)(filePath, cwd);
|
|
76
|
+
console.log(chalk_1.default.green(`✓ Score compiled → ${outPath}`));
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.error(chalk_1.default.red(`Error: ${err.message}`));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function cmdRun(args) {
|
|
84
|
+
const scoreName = args[0];
|
|
85
|
+
if (!scoreName) {
|
|
86
|
+
console.error(chalk_1.default.red('Usage: tempo run <score-name>'));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
const scorePath = path_1.default.join(cwd, '.tempo', 'scores', `${scoreName}.json`);
|
|
90
|
+
if (!fs_1.default.existsSync(scorePath)) {
|
|
91
|
+
console.error(chalk_1.default.red(`Score not found: ${scorePath}`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
let raw;
|
|
95
|
+
try {
|
|
96
|
+
raw = JSON.parse(fs_1.default.readFileSync(scorePath, 'utf-8'));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
console.error(chalk_1.default.red('Failed to parse score JSON'));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
const parsed = schema_1.SpecSchema.safeParse(raw);
|
|
103
|
+
if (!parsed.success) {
|
|
104
|
+
console.error(chalk_1.default.red('Invalid score:'));
|
|
105
|
+
console.error(parsed.error.format());
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
await (0, runPipeline_1.runPipeline)(parsed.data, cwd);
|
|
109
|
+
}
|
|
110
|
+
async function main() {
|
|
111
|
+
const [, , command, ...args] = process.argv;
|
|
112
|
+
if (!command || command === 'help' || command === '--help') {
|
|
113
|
+
printHelp();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
switch (command) {
|
|
117
|
+
case 'init':
|
|
118
|
+
cmdInit();
|
|
119
|
+
break;
|
|
120
|
+
case 'compile':
|
|
121
|
+
cmdCompile(args);
|
|
122
|
+
break;
|
|
123
|
+
case 'run':
|
|
124
|
+
await cmdRun(args);
|
|
125
|
+
break;
|
|
126
|
+
default:
|
|
127
|
+
console.error(chalk_1.default.red(`Unknown command: ${command}`));
|
|
128
|
+
printHelp();
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
main().catch((err) => {
|
|
133
|
+
console.error(chalk_1.default.red('Fatal error:'), err.message);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runPipeline.d.ts","sourceRoot":"","sources":["../../src/controller/runPipeline.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AA2EtC,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkExE"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runPipeline = runPipeline;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const execa_1 = __importDefault(require("execa"));
|
|
10
|
+
const runStep_1 = require("../executor/runStep");
|
|
11
|
+
const runValidation_1 = require("../validator/runValidation");
|
|
12
|
+
const logger_1 = require("../utils/logger");
|
|
13
|
+
const MAX_RETRIES = 3;
|
|
14
|
+
function ensureHistoryDir(cwd, runTimestamp) {
|
|
15
|
+
const dir = path_1.default.join(cwd, '.tempo', 'sessions', `session-${runTimestamp}`);
|
|
16
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
17
|
+
return dir;
|
|
18
|
+
}
|
|
19
|
+
function saveStepHistory(historyDir, stepId, instruction, filesAllowed, claudeResponse, result) {
|
|
20
|
+
const content = `# Step ${stepId}
|
|
21
|
+
|
|
22
|
+
## Instruction Sent to Claude
|
|
23
|
+
|
|
24
|
+
\`\`\`
|
|
25
|
+
${instruction}
|
|
26
|
+
\`\`\`
|
|
27
|
+
|
|
28
|
+
## Files Allowed
|
|
29
|
+
|
|
30
|
+
${filesAllowed.map((f) => `- ${f}`).join('\n')}
|
|
31
|
+
|
|
32
|
+
## Claude Response
|
|
33
|
+
|
|
34
|
+
\`\`\`
|
|
35
|
+
${claudeResponse}
|
|
36
|
+
\`\`\`
|
|
37
|
+
|
|
38
|
+
## Result
|
|
39
|
+
|
|
40
|
+
${result}
|
|
41
|
+
`;
|
|
42
|
+
fs_1.default.writeFileSync(path_1.default.join(historyDir, `step-${stepId}.md`), content, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
function saveErrors(historyDir, stepId, errors, retries) {
|
|
45
|
+
const content = `# Errors for Step ${stepId}
|
|
46
|
+
|
|
47
|
+
Retries attempted: ${retries}
|
|
48
|
+
|
|
49
|
+
## Raw Output
|
|
50
|
+
|
|
51
|
+
\`\`\`
|
|
52
|
+
${errors}
|
|
53
|
+
\`\`\`
|
|
54
|
+
`;
|
|
55
|
+
fs_1.default.writeFileSync(path_1.default.join(historyDir, `errors-step-${stepId}.md`), content, 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
async function captureAndSaveDiff(historyDir, stepId, cwd) {
|
|
58
|
+
try {
|
|
59
|
+
const result = await (0, execa_1.default)('git', ['diff'], { cwd, reject: false });
|
|
60
|
+
if (result.stdout) {
|
|
61
|
+
fs_1.default.writeFileSync(path_1.default.join(historyDir, `diff-${stepId}.patch`), result.stdout, 'utf-8');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// git not available — skip diff
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function runPipeline(spec, cwd) {
|
|
69
|
+
const runTimestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
70
|
+
const historyDir = ensureHistoryDir(cwd, runTimestamp);
|
|
71
|
+
(0, logger_1.logInfo)(`Starting pipeline: ${spec.goal}`);
|
|
72
|
+
(0, logger_1.logInfo)(`Session: .tempo/sessions/session-${runTimestamp}`);
|
|
73
|
+
let passed = 0;
|
|
74
|
+
let failed = 0;
|
|
75
|
+
for (const step of spec.steps) {
|
|
76
|
+
(0, logger_1.logStep)(step.id, step.description);
|
|
77
|
+
let lastErrors = '';
|
|
78
|
+
let succeeded = false;
|
|
79
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
80
|
+
const extraContext = attempt > 1
|
|
81
|
+
? `Fix only these errors:\n${lastErrors}`
|
|
82
|
+
: undefined;
|
|
83
|
+
const stepResult = await (0, runStep_1.runStep)(step, spec, cwd, extraContext);
|
|
84
|
+
await captureAndSaveDiff(historyDir, step.id, cwd);
|
|
85
|
+
const validation = await (0, runValidation_1.runValidation)(cwd);
|
|
86
|
+
if (validation.success) {
|
|
87
|
+
(0, logger_1.logSuccess)(`Step ${step.id} passed validation`);
|
|
88
|
+
saveStepHistory(historyDir, step.id, stepResult.instruction, stepResult.filesAllowed, stepResult.claudeResponse, 'success');
|
|
89
|
+
succeeded = true;
|
|
90
|
+
passed++;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
lastErrors = validation.errors;
|
|
94
|
+
(0, logger_1.logRetry)(attempt, MAX_RETRIES, validation.errors);
|
|
95
|
+
if (attempt === MAX_RETRIES) {
|
|
96
|
+
saveErrors(historyDir, step.id, validation.errors, attempt);
|
|
97
|
+
saveStepHistory(historyDir, step.id, stepResult.instruction, stepResult.filesAllowed, stepResult.claudeResponse, 'failure');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!succeeded) {
|
|
101
|
+
(0, logger_1.logFailure)(`Step ${step.id} failed after ${MAX_RETRIES} retries. Stopping pipeline.`);
|
|
102
|
+
failed++;
|
|
103
|
+
(0, logger_1.logSummary)(passed, failed, spec.steps.length);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
(0, logger_1.logSummary)(passed, failed, spec.steps.length);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=runPipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runPipeline.js","sourceRoot":"","sources":["../../src/controller/runPipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeClient.d.ts","sourceRoot":"","sources":["../../src/executor/claudeClient.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B1F"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callClaude = callClaude;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const CLAUDE_API_URL = 'https://api.anthropic.com/v1/messages';
|
|
9
|
+
const DEFAULT_MODEL = 'claude-sonnet-4-6';
|
|
10
|
+
async function callClaude(systemPrompt, userPrompt) {
|
|
11
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new Error('ANTHROPIC_API_KEY environment variable is not set');
|
|
14
|
+
}
|
|
15
|
+
const response = await axios_1.default.post(CLAUDE_API_URL, {
|
|
16
|
+
model: DEFAULT_MODEL,
|
|
17
|
+
max_tokens: 8192,
|
|
18
|
+
system: systemPrompt,
|
|
19
|
+
messages: [{ role: 'user', content: userPrompt }],
|
|
20
|
+
}, {
|
|
21
|
+
headers: {
|
|
22
|
+
'x-api-key': apiKey,
|
|
23
|
+
'anthropic-version': '2023-06-01',
|
|
24
|
+
'content-type': 'application/json',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
const block = response.data.content?.[0];
|
|
28
|
+
if (!block || block.type !== 'text') {
|
|
29
|
+
throw new Error('Unexpected response format from Claude API');
|
|
30
|
+
}
|
|
31
|
+
return block.text;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=claudeClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeClient.js","sourceRoot":"","sources":["../../src/executor/claudeClient.ts"],"names":[],"mappings":";;;;;AAKA,gCA4BC;AAjCD,kDAA0B;AAE1B,MAAM,cAAc,GAAG,uCAAuC,CAAC;AAC/D,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAEnC,KAAK,UAAU,UAAU,CAAC,YAAoB,EAAE,UAAkB;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,cAAc,EACd;QACE,KAAK,EAAE,aAAa;QACpB,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;KAClD,EACD;QACE,OAAO,EAAE;YACP,WAAW,EAAE,MAAM;YACnB,mBAAmB,EAAE,YAAY;YACjC,cAAc,EAAE,kBAAkB;SACnC;KACF,CACF,CAAC;IAEF,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC,IAAc,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Step, Spec } from '../spec/schema';
|
|
2
|
+
export interface StepResult {
|
|
3
|
+
stepId: number;
|
|
4
|
+
instruction: string;
|
|
5
|
+
filesAllowed: string[];
|
|
6
|
+
claudeResponse: string;
|
|
7
|
+
filesWritten: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function runStep(step: Step, spec: Spec, cwd: string, extraContext?: string): Promise<StepResult>;
|
|
10
|
+
//# sourceMappingURL=runStep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runStep.d.ts","sourceRoot":"","sources":["../../src/executor/runStep.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAqB5C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AA0CD,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,UAAU,CAAC,CAoCrB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runStep = runStep;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const claudeClient_1 = require("./claudeClient");
|
|
10
|
+
const logger_1 = require("../utils/logger");
|
|
11
|
+
const SYSTEM_PROMPT = `You are an expert software engineer. You will receive:
|
|
12
|
+
1. A task description
|
|
13
|
+
2. The contents of files you are allowed to modify
|
|
14
|
+
3. Project constraints
|
|
15
|
+
|
|
16
|
+
Respond ONLY with complete file replacements in this exact format for each file:
|
|
17
|
+
|
|
18
|
+
===FILE: path/to/file.ts===
|
|
19
|
+
<full file content here>
|
|
20
|
+
===END===
|
|
21
|
+
|
|
22
|
+
Rules:
|
|
23
|
+
- Output FULL file content, never partial edits
|
|
24
|
+
- Only output files listed in "files_allowed"
|
|
25
|
+
- Do not add explanations outside the file blocks
|
|
26
|
+
- Preserve existing code that is not being changed`;
|
|
27
|
+
function readAllowedFiles(filesAllowed, cwd) {
|
|
28
|
+
const contents = {};
|
|
29
|
+
for (const filePath of filesAllowed) {
|
|
30
|
+
const abs = path_1.default.resolve(cwd, filePath);
|
|
31
|
+
if (fs_1.default.existsSync(abs)) {
|
|
32
|
+
contents[filePath] = fs_1.default.readFileSync(abs, 'utf-8');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
contents[filePath] = '(file does not exist yet — create it)';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return contents;
|
|
39
|
+
}
|
|
40
|
+
function parseClaudeResponse(response) {
|
|
41
|
+
const files = {};
|
|
42
|
+
const regex = /===FILE: (.+?)===\n([\s\S]*?)===END===/g;
|
|
43
|
+
let match;
|
|
44
|
+
while ((match = regex.exec(response)) !== null) {
|
|
45
|
+
const filePath = match[1].trim();
|
|
46
|
+
const content = match[2];
|
|
47
|
+
files[filePath] = content;
|
|
48
|
+
}
|
|
49
|
+
return files;
|
|
50
|
+
}
|
|
51
|
+
function writeFiles(files, cwd, allowed) {
|
|
52
|
+
const written = [];
|
|
53
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
54
|
+
if (!allowed.includes(filePath)) {
|
|
55
|
+
(0, logger_1.logInfo)(`Skipping non-allowed file: ${filePath}`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const abs = path_1.default.resolve(cwd, filePath);
|
|
59
|
+
fs_1.default.mkdirSync(path_1.default.dirname(abs), { recursive: true });
|
|
60
|
+
fs_1.default.writeFileSync(abs, content, 'utf-8');
|
|
61
|
+
written.push(filePath);
|
|
62
|
+
}
|
|
63
|
+
return written;
|
|
64
|
+
}
|
|
65
|
+
async function runStep(step, spec, cwd, extraContext) {
|
|
66
|
+
const fileContents = readAllowedFiles(step.files_allowed, cwd);
|
|
67
|
+
const fileSection = Object.entries(fileContents)
|
|
68
|
+
.map(([f, c]) => `### ${f}\n\`\`\`\n${c}\n\`\`\``)
|
|
69
|
+
.join('\n\n');
|
|
70
|
+
const instruction = `
|
|
71
|
+
Goal: ${spec.goal}
|
|
72
|
+
|
|
73
|
+
Constraints:
|
|
74
|
+
${spec.constraints.map((c) => `- ${c}`).join('\n')}
|
|
75
|
+
|
|
76
|
+
Step ${step.id}: ${step.description}
|
|
77
|
+
|
|
78
|
+
Files you may modify:
|
|
79
|
+
${step.files_allowed.join(', ')}
|
|
80
|
+
|
|
81
|
+
Current file contents:
|
|
82
|
+
${fileSection}
|
|
83
|
+
${extraContext ? `\nAdditional context:\n${extraContext}` : ''}
|
|
84
|
+
`.trim();
|
|
85
|
+
(0, logger_1.logInfo)(`Sending step ${step.id} to Claude...`);
|
|
86
|
+
const claudeResponse = await (0, claudeClient_1.callClaude)(SYSTEM_PROMPT, instruction);
|
|
87
|
+
const parsedFiles = parseClaudeResponse(claudeResponse);
|
|
88
|
+
const filesWritten = writeFiles(parsedFiles, cwd, step.files_allowed);
|
|
89
|
+
return {
|
|
90
|
+
stepId: step.id,
|
|
91
|
+
instruction,
|
|
92
|
+
filesAllowed: step.files_allowed,
|
|
93
|
+
claudeResponse,
|
|
94
|
+
filesWritten,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=runStep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runStep.js","sourceRoot":"","sources":["../../src/executor/runStep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/ideation/compile.ts"],"names":[],"mappings":"AAoFA,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBrE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.compileIdeation = compileIdeation;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function parseMarkdown(content) {
|
|
10
|
+
const sections = {
|
|
11
|
+
goal: '',
|
|
12
|
+
context: '',
|
|
13
|
+
ideas: [],
|
|
14
|
+
finalPlan: '',
|
|
15
|
+
};
|
|
16
|
+
const sectionMap = {
|
|
17
|
+
goal: 'goal',
|
|
18
|
+
context: 'context',
|
|
19
|
+
ideas: 'ideas',
|
|
20
|
+
'final plan': 'finalPlan',
|
|
21
|
+
};
|
|
22
|
+
const lines = content.split('\n');
|
|
23
|
+
let currentSection = null;
|
|
24
|
+
const buffer = [];
|
|
25
|
+
function flush() {
|
|
26
|
+
if (!currentSection)
|
|
27
|
+
return;
|
|
28
|
+
const text = buffer.join('\n').trim();
|
|
29
|
+
if (currentSection === 'ideas') {
|
|
30
|
+
sections.ideas = text
|
|
31
|
+
.split('\n')
|
|
32
|
+
.map((l) => l.replace(/^[-*]\s*/, '').trim())
|
|
33
|
+
.filter(Boolean);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
sections[currentSection] = text;
|
|
37
|
+
}
|
|
38
|
+
buffer.length = 0;
|
|
39
|
+
}
|
|
40
|
+
for (const line of lines) {
|
|
41
|
+
const headingMatch = line.match(/^#{1,3}\s+(.+)/);
|
|
42
|
+
if (headingMatch) {
|
|
43
|
+
flush();
|
|
44
|
+
const heading = headingMatch[1].toLowerCase().trim();
|
|
45
|
+
currentSection = sectionMap[heading] ?? null;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
buffer.push(line);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
flush();
|
|
52
|
+
return sections;
|
|
53
|
+
}
|
|
54
|
+
function buildSpec(parsed, name) {
|
|
55
|
+
const planLines = parsed.finalPlan.split('\n').filter(Boolean);
|
|
56
|
+
const steps = planLines
|
|
57
|
+
.map((line, i) => ({
|
|
58
|
+
id: i + 1,
|
|
59
|
+
description: line.replace(/^\d+[.)]\s*/, '').trim(),
|
|
60
|
+
files_allowed: [],
|
|
61
|
+
}))
|
|
62
|
+
.filter((s) => s.description.length > 0);
|
|
63
|
+
return {
|
|
64
|
+
goal: parsed.goal || name,
|
|
65
|
+
constraints: parsed.context
|
|
66
|
+
.split('\n')
|
|
67
|
+
.map((l) => l.replace(/^[-*]\s*/, '').trim())
|
|
68
|
+
.filter(Boolean),
|
|
69
|
+
steps: steps.length > 0
|
|
70
|
+
? steps
|
|
71
|
+
: [{ id: 1, description: parsed.finalPlan || 'Implement the plan', files_allowed: [] }],
|
|
72
|
+
tests: [],
|
|
73
|
+
definition_of_done: parsed.ideas,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function compileIdeation(filePath, cwd) {
|
|
77
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
78
|
+
throw new Error(`File not found: ${filePath}`);
|
|
79
|
+
}
|
|
80
|
+
const content = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
81
|
+
const name = path_1.default.basename(filePath, path_1.default.extname(filePath));
|
|
82
|
+
const parsed = parseMarkdown(content);
|
|
83
|
+
const spec = buildSpec(parsed, name);
|
|
84
|
+
const specsDir = path_1.default.join(cwd, '.tempo', 'scores');
|
|
85
|
+
fs_1.default.mkdirSync(specsDir, { recursive: true });
|
|
86
|
+
const outPath = path_1.default.join(specsDir, `${name}.json`);
|
|
87
|
+
fs_1.default.writeFileSync(outPath, JSON.stringify(spec, null, 2), 'utf-8');
|
|
88
|
+
return outPath;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/ideation/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const StepSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodNumber;
|
|
4
|
+
description: z.ZodString;
|
|
5
|
+
files_allowed: z.ZodArray<z.ZodString, "many">;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
id: number;
|
|
8
|
+
description: string;
|
|
9
|
+
files_allowed: string[];
|
|
10
|
+
}, {
|
|
11
|
+
id: number;
|
|
12
|
+
description: string;
|
|
13
|
+
files_allowed: string[];
|
|
14
|
+
}>;
|
|
15
|
+
export declare const SpecSchema: z.ZodObject<{
|
|
16
|
+
goal: z.ZodString;
|
|
17
|
+
constraints: z.ZodArray<z.ZodString, "many">;
|
|
18
|
+
steps: z.ZodArray<z.ZodObject<{
|
|
19
|
+
id: z.ZodNumber;
|
|
20
|
+
description: z.ZodString;
|
|
21
|
+
files_allowed: z.ZodArray<z.ZodString, "many">;
|
|
22
|
+
}, "strip", z.ZodTypeAny, {
|
|
23
|
+
id: number;
|
|
24
|
+
description: string;
|
|
25
|
+
files_allowed: string[];
|
|
26
|
+
}, {
|
|
27
|
+
id: number;
|
|
28
|
+
description: string;
|
|
29
|
+
files_allowed: string[];
|
|
30
|
+
}>, "many">;
|
|
31
|
+
tests: z.ZodArray<z.ZodString, "many">;
|
|
32
|
+
definition_of_done: z.ZodArray<z.ZodString, "many">;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
goal: string;
|
|
35
|
+
constraints: string[];
|
|
36
|
+
steps: {
|
|
37
|
+
id: number;
|
|
38
|
+
description: string;
|
|
39
|
+
files_allowed: string[];
|
|
40
|
+
}[];
|
|
41
|
+
tests: string[];
|
|
42
|
+
definition_of_done: string[];
|
|
43
|
+
}, {
|
|
44
|
+
goal: string;
|
|
45
|
+
constraints: string[];
|
|
46
|
+
steps: {
|
|
47
|
+
id: number;
|
|
48
|
+
description: string;
|
|
49
|
+
files_allowed: string[];
|
|
50
|
+
}[];
|
|
51
|
+
tests: string[];
|
|
52
|
+
definition_of_done: string[];
|
|
53
|
+
}>;
|
|
54
|
+
export type Step = z.infer<typeof StepSchema>;
|
|
55
|
+
export type Spec = z.infer<typeof SpecSchema>;
|
|
56
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/spec/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,UAAU;;;;;;;;;;;;EAIrB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMrB,CAAC;AAEH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpecSchema = exports.StepSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
exports.StepSchema = zod_1.z.object({
|
|
6
|
+
id: zod_1.z.number(),
|
|
7
|
+
description: zod_1.z.string(),
|
|
8
|
+
files_allowed: zod_1.z.array(zod_1.z.string()),
|
|
9
|
+
});
|
|
10
|
+
exports.SpecSchema = zod_1.z.object({
|
|
11
|
+
goal: zod_1.z.string(),
|
|
12
|
+
constraints: zod_1.z.array(zod_1.z.string()),
|
|
13
|
+
steps: zod_1.z.array(exports.StepSchema),
|
|
14
|
+
tests: zod_1.z.array(zod_1.z.string()),
|
|
15
|
+
definition_of_done: zod_1.z.array(zod_1.z.string()),
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/spec/schema.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAEX,QAAA,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IACjC,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE;IACvB,aAAa,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;CACnC,CAAC,CAAC;AAEU,QAAA,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,WAAW,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAChC,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,kBAAU,CAAC;IAC1B,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAC1B,kBAAkB,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;CACxC,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function logStep(stepId: number, description: string): void;
|
|
2
|
+
export declare function logSuccess(message: string): void;
|
|
3
|
+
export declare function logFailure(message: string): void;
|
|
4
|
+
export declare function logRetry(attempt: number, max: number, errors: string): void;
|
|
5
|
+
export declare function logInfo(message: string): void;
|
|
6
|
+
export declare function logSummary(passed: number, failed: number, total: number): void;
|
|
7
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAG3E;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAU9E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logStep = logStep;
|
|
7
|
+
exports.logSuccess = logSuccess;
|
|
8
|
+
exports.logFailure = logFailure;
|
|
9
|
+
exports.logRetry = logRetry;
|
|
10
|
+
exports.logInfo = logInfo;
|
|
11
|
+
exports.logSummary = logSummary;
|
|
12
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
13
|
+
function logStep(stepId, description) {
|
|
14
|
+
console.log(chalk_1.default.cyan(`\n[STEP ${stepId}] ${description}`));
|
|
15
|
+
}
|
|
16
|
+
function logSuccess(message) {
|
|
17
|
+
console.log(chalk_1.default.green(`✓ ${message}`));
|
|
18
|
+
}
|
|
19
|
+
function logFailure(message) {
|
|
20
|
+
console.log(chalk_1.default.red(`✗ ${message}`));
|
|
21
|
+
}
|
|
22
|
+
function logRetry(attempt, max, errors) {
|
|
23
|
+
console.log(chalk_1.default.yellow(`↻ Retry ${attempt}/${max}`));
|
|
24
|
+
console.log(chalk_1.default.yellow(` Errors: ${errors.slice(0, 200)}...`));
|
|
25
|
+
}
|
|
26
|
+
function logInfo(message) {
|
|
27
|
+
console.log(chalk_1.default.blue(`ℹ ${message}`));
|
|
28
|
+
}
|
|
29
|
+
function logSummary(passed, failed, total) {
|
|
30
|
+
console.log(chalk_1.default.bold('\n─────────────────────────────'));
|
|
31
|
+
console.log(chalk_1.default.bold('Pipeline Summary'));
|
|
32
|
+
console.log(chalk_1.default.bold('─────────────────────────────'));
|
|
33
|
+
console.log(`Total steps : ${total}`);
|
|
34
|
+
console.log(chalk_1.default.green(`Passed : ${passed}`));
|
|
35
|
+
if (failed > 0) {
|
|
36
|
+
console.log(chalk_1.default.red(`Failed : ${failed}`));
|
|
37
|
+
}
|
|
38
|
+
console.log(chalk_1.default.bold('─────────────────────────────\n'));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;;;AAEA,0BAEC;AAED,gCAEC;AAED,gCAEC;AAED,4BAGC;AAED,0BAEC;AAED,gCAUC;AAjCD,kDAA0B;AAE1B,SAAgB,OAAO,CAAC,MAAc,EAAE,WAAmB;IACzD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,WAAW,MAAM,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,SAAgB,UAAU,CAAC,OAAe;IACxC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,SAAgB,UAAU,CAAC,OAAe;IACxC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,QAAQ,CAAC,OAAe,EAAE,GAAW,EAAE,MAAc;IACnE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,WAAW,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,aAAa,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,SAAgB,OAAO,CAAC,OAAe;IACrC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,SAAgB,UAAU,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;IACtE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC,CAAC;IACpD,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runValidation.d.ts","sourceRoot":"","sources":["../../src/validator/runValidation.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAyBD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuB1E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runValidation = runValidation;
|
|
7
|
+
const execa_1 = __importDefault(require("execa"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const logger_1 = require("../utils/logger");
|
|
11
|
+
async function runCommand(command, cwd) {
|
|
12
|
+
const [cmd, ...args] = command.split(' ');
|
|
13
|
+
try {
|
|
14
|
+
const result = await (0, execa_1.default)(cmd, args, { cwd, reject: false });
|
|
15
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
16
|
+
return { ok: result.exitCode === 0, output };
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return { ok: false, output: String(err) };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function loadConfig(cwd) {
|
|
23
|
+
const configPath = path_1.default.join(cwd, '.tempo', 'config.json');
|
|
24
|
+
if (!fs_1.default.existsSync(configPath))
|
|
25
|
+
return {};
|
|
26
|
+
return JSON.parse(fs_1.default.readFileSync(configPath, 'utf-8'));
|
|
27
|
+
}
|
|
28
|
+
async function runValidation(cwd) {
|
|
29
|
+
const config = loadConfig(cwd);
|
|
30
|
+
const errors = [];
|
|
31
|
+
const commands = [
|
|
32
|
+
{ label: 'lint', cmd: config.lintCommand },
|
|
33
|
+
{ label: 'build', cmd: config.buildCommand },
|
|
34
|
+
{ label: 'test', cmd: config.testCommand },
|
|
35
|
+
];
|
|
36
|
+
for (const { label, cmd } of commands) {
|
|
37
|
+
if (!cmd)
|
|
38
|
+
continue;
|
|
39
|
+
(0, logger_1.logInfo)(`Running ${label}: ${cmd}`);
|
|
40
|
+
const { ok, output } = await runCommand(cmd, cwd);
|
|
41
|
+
if (!ok) {
|
|
42
|
+
errors.push(`[${label}] ${output}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
success: errors.length === 0,
|
|
47
|
+
errors: errors.join('\n\n'),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=runValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runValidation.js","sourceRoot":"","sources":["../../src/validator/runValidation.ts"],"names":[],"mappings":";;;;;AAiCA,sCAuBC;AAxDD,kDAA0B;AAC1B,4CAAoB;AACpB,gDAAwB;AACxB,4CAA0C;AAa1C,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,GAAW;IACpD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,eAAK,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC3D,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1D,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,QAAQ,GAAsD;QAClE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE;QAC1C,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,YAAY,EAAE;QAC5C,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE;KAC3C,CAAC;IAEF,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAA,gBAAO,EAAC,WAAW,KAAK,KAAK,GAAG,EAAE,CAAC,CAAC;QACpC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAClD,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;KAC5B,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tempo-agent",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A modular CLI tool for AI-driven code generation and validation",
|
|
5
|
+
"main": "dist/cli/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"tempo": "dist/cli/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "ts-node src/cli/index.ts",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/cli/index.js",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18.0.0"
|
|
20
|
+
},
|
|
21
|
+
"keywords": ["cli", "tempo", "orchestrator", "claude", "ai"],
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"axios": "^1.7.2",
|
|
25
|
+
"chalk": "^4.1.2",
|
|
26
|
+
"execa": "^5.1.1",
|
|
27
|
+
"zod": "^3.23.8"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^20.14.0",
|
|
31
|
+
"ts-node": "^10.9.2",
|
|
32
|
+
"typescript": "^5.4.5"
|
|
33
|
+
}
|
|
34
|
+
}
|