clayton-forge 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.
- package/dist/commands/new.d.ts +2 -0
- package/dist/commands/new.js +286 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +121 -0
- package/dist/commands/test.d.ts +2 -0
- package/dist/commands/test.js +136 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +134 -0
- package/package.json +26 -0
- package/package.json:Zone.Identifier +0 -0
- package/src/commands/new.ts +281 -0
- package/src/commands/new.ts:Zone.Identifier +0 -0
- package/src/commands/run.ts +97 -0
- package/src/commands/run.ts:Zone.Identifier +0 -0
- package/src/commands/test.ts +122 -0
- package/src/commands/test.ts:Zone.Identifier +0 -0
- package/src/index.ts +115 -0
- package/src/index.ts:Zone.Identifier +0 -0
- package/tsconfig.json +9 -0
- package/tsconfig.json:Zone.Identifier +0 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.commandNew = commandNew;
|
|
40
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const ora_1 = __importDefault(require("ora"));
|
|
45
|
+
// ─────────────────────────────────────────────
|
|
46
|
+
// Helpers de display
|
|
47
|
+
// ─────────────────────────────────────────────
|
|
48
|
+
function header() {
|
|
49
|
+
console.log("");
|
|
50
|
+
console.log(chalk_1.default.bold.white(" ╔═══════════════════════════════════╗"));
|
|
51
|
+
console.log(chalk_1.default.bold.white(" ║") + chalk_1.default.bold.cyan(" CLAYTON FORGE — new ") + chalk_1.default.bold.white("║"));
|
|
52
|
+
console.log(chalk_1.default.bold.white(" ╚═══════════════════════════════════╝"));
|
|
53
|
+
console.log("");
|
|
54
|
+
console.log(chalk_1.default.gray(" Let's create your agent. Answer a few questions."));
|
|
55
|
+
console.log(chalk_1.default.gray(" Press Ctrl+C at any time to cancel.\n"));
|
|
56
|
+
}
|
|
57
|
+
// ─────────────────────────────────────────────
|
|
58
|
+
// Wizard
|
|
59
|
+
// ─────────────────────────────────────────────
|
|
60
|
+
async function commandNew(targetDir) {
|
|
61
|
+
header();
|
|
62
|
+
const answers = await inquirer_1.default.prompt([
|
|
63
|
+
{
|
|
64
|
+
type: "input",
|
|
65
|
+
name: "name",
|
|
66
|
+
message: chalk_1.default.white("Agent name") + chalk_1.default.gray(" (kebab-case, e.g. invoice-classifier):"),
|
|
67
|
+
validate: (v) => /^[a-z][a-z0-9-]*$/.test(v) || "Use lowercase letters, numbers, and hyphens only",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
type: "input",
|
|
71
|
+
name: "description",
|
|
72
|
+
message: chalk_1.default.white("What does this agent do?"),
|
|
73
|
+
validate: (v) => v.trim().length > 5 || "Please write a short description",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: "list",
|
|
77
|
+
name: "type",
|
|
78
|
+
message: chalk_1.default.white("Agent type:"),
|
|
79
|
+
choices: [
|
|
80
|
+
{ name: "reactive — receives input → processes → responds", value: "reactive" },
|
|
81
|
+
{ name: "proactive — acts on triggers without waiting for input", value: "proactive" },
|
|
82
|
+
{ name: "pipeline — sequential steps, each feeding the next", value: "pipeline" },
|
|
83
|
+
{ name: "orchestrator— coordinates other agents", value: "orchestrator" },
|
|
84
|
+
{ name: "worker — executed by an orchestrator", value: "worker" },
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: "list",
|
|
89
|
+
name: "llm_provider",
|
|
90
|
+
message: chalk_1.default.white("LLM provider:"),
|
|
91
|
+
choices: [
|
|
92
|
+
{ name: "anthropic (Claude — requires ANTHROPIC_API_KEY)", value: "anthropic" },
|
|
93
|
+
{ name: "openai (GPT — requires OPENAI_API_KEY)", value: "openai" },
|
|
94
|
+
{ name: "ollama (local — requires Ollama running)", value: "ollama" },
|
|
95
|
+
{ name: "lmstudio (local — requires LM Studio running)", value: "lmstudio" },
|
|
96
|
+
{ name: "openai-compatible (any OpenAI-compatible API)", value: "openai-compatible" },
|
|
97
|
+
{ name: "none (rule-based, no LLM)", value: "none" },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
type: "input",
|
|
102
|
+
name: "llm_model",
|
|
103
|
+
message: chalk_1.default.white("Model name:"),
|
|
104
|
+
when: (a) => a.llm_provider !== "none",
|
|
105
|
+
default: (a) => {
|
|
106
|
+
const defaults = {
|
|
107
|
+
anthropic: "claude-sonnet-4-6",
|
|
108
|
+
openai: "gpt-4o-mini",
|
|
109
|
+
ollama: "llama3",
|
|
110
|
+
lmstudio: "local-model",
|
|
111
|
+
"openai-compatible": "default",
|
|
112
|
+
};
|
|
113
|
+
return defaults[a.llm_provider] ?? "";
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
type: "list",
|
|
118
|
+
name: "output_format",
|
|
119
|
+
message: chalk_1.default.white("Output format:"),
|
|
120
|
+
choices: [
|
|
121
|
+
{ name: "text — plain text response", value: "text" },
|
|
122
|
+
{ name: "json — structured JSON (add output schema)", value: "json" },
|
|
123
|
+
{ name: "markdown — formatted markdown", value: "markdown" },
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: "list",
|
|
128
|
+
name: "trust_level",
|
|
129
|
+
message: chalk_1.default.white("Trust level:"),
|
|
130
|
+
choices: [
|
|
131
|
+
{ name: "0 — sandboxed (no external access)", value: 0 },
|
|
132
|
+
{ name: "1 — read-only (reads data, no writes)", value: 1 },
|
|
133
|
+
{ name: "2 — write (reads and writes)", value: 2 },
|
|
134
|
+
{ name: "3 — admin (full control)", value: 3 },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
]);
|
|
138
|
+
// Destino
|
|
139
|
+
const projectName = answers.name;
|
|
140
|
+
const dest = targetDir ? path.resolve(targetDir, projectName) : path.resolve(process.cwd(), projectName);
|
|
141
|
+
// Verificar se pasta já existe
|
|
142
|
+
if (fs.existsSync(dest)) {
|
|
143
|
+
console.log(chalk_1.default.red(`\n✗ Directory already exists: ${dest}`));
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
const spinner = (0, ora_1.default)("Creating your agent...").start();
|
|
147
|
+
try {
|
|
148
|
+
// Criar pasta
|
|
149
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
150
|
+
// Gerar agent.yaml
|
|
151
|
+
const apiKeyVar = getApiKeyVar(answers.llm_provider);
|
|
152
|
+
const agentYaml = buildAgentYaml(answers, apiKeyVar);
|
|
153
|
+
fs.writeFileSync(path.join(dest, "agent.yaml"), agentYaml);
|
|
154
|
+
// Gerar agent.test.yaml
|
|
155
|
+
const testYaml = buildTestYaml(answers.name);
|
|
156
|
+
fs.writeFileSync(path.join(dest, "agent.test.yaml"), testYaml);
|
|
157
|
+
// Gerar README.md
|
|
158
|
+
const readme = buildReadme(answers);
|
|
159
|
+
fs.writeFileSync(path.join(dest, "README.md"), readme);
|
|
160
|
+
// Gerar .env.example
|
|
161
|
+
if (apiKeyVar) {
|
|
162
|
+
fs.writeFileSync(path.join(dest, ".env.example"), `${apiKeyVar}=your-api-key-here\n`);
|
|
163
|
+
}
|
|
164
|
+
spinner.succeed(chalk_1.default.green("Agent created!"));
|
|
165
|
+
// Summary
|
|
166
|
+
console.log("");
|
|
167
|
+
console.log(chalk_1.default.bold(" 📁 " + dest));
|
|
168
|
+
console.log(chalk_1.default.gray(" ├── agent.yaml"));
|
|
169
|
+
console.log(chalk_1.default.gray(" ├── agent.test.yaml"));
|
|
170
|
+
console.log(chalk_1.default.gray(" ├── README.md"));
|
|
171
|
+
if (apiKeyVar)
|
|
172
|
+
console.log(chalk_1.default.gray(" └── .env.example"));
|
|
173
|
+
console.log("");
|
|
174
|
+
console.log(chalk_1.default.bold.cyan(" Next steps:"));
|
|
175
|
+
console.log(chalk_1.default.white(` $ cd ${projectName}`));
|
|
176
|
+
if (apiKeyVar)
|
|
177
|
+
console.log(chalk_1.default.white(` $ cp .env.example .env # add your API key`));
|
|
178
|
+
console.log(chalk_1.default.white(` $ cforge run # execute the agent`));
|
|
179
|
+
console.log(chalk_1.default.white(` $ cforge test # run tests`));
|
|
180
|
+
console.log("");
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
spinner.fail("Failed to create agent");
|
|
184
|
+
console.error(err);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// ─────────────────────────────────────────────
|
|
189
|
+
// Builders
|
|
190
|
+
// ─────────────────────────────────────────────
|
|
191
|
+
function getApiKeyVar(provider) {
|
|
192
|
+
const map = {
|
|
193
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
194
|
+
openai: "OPENAI_API_KEY",
|
|
195
|
+
};
|
|
196
|
+
return map[provider] ?? null;
|
|
197
|
+
}
|
|
198
|
+
function buildAgentYaml(answers, apiKeyVar) {
|
|
199
|
+
const lines = [
|
|
200
|
+
`name: "${answers.name}"`,
|
|
201
|
+
`version: "1.0.0"`,
|
|
202
|
+
`description: "${answers.description}"`,
|
|
203
|
+
`type: ${answers.type}`,
|
|
204
|
+
`trust_level: ${answers.trust_level}`,
|
|
205
|
+
``,
|
|
206
|
+
`llm:`,
|
|
207
|
+
` provider: ${answers.llm_provider}`,
|
|
208
|
+
];
|
|
209
|
+
if (answers.llm_provider !== "none") {
|
|
210
|
+
lines.push(` model: ${answers.llm_model}`);
|
|
211
|
+
if (apiKeyVar) {
|
|
212
|
+
lines.push(` api_key: "\${${apiKeyVar}}"`);
|
|
213
|
+
}
|
|
214
|
+
lines.push(` temperature: 0.1`);
|
|
215
|
+
lines.push(` max_tokens: 1000`);
|
|
216
|
+
}
|
|
217
|
+
lines.push(``);
|
|
218
|
+
lines.push(`prompt:`);
|
|
219
|
+
lines.push(` system: |`);
|
|
220
|
+
lines.push(` You are ${answers.description}.`);
|
|
221
|
+
lines.push(` Be concise, accurate, and helpful.`);
|
|
222
|
+
lines.push(` user_template: "{{input}}"`);
|
|
223
|
+
lines.push(` variables:`);
|
|
224
|
+
lines.push(` - name: input`);
|
|
225
|
+
lines.push(` required: true`);
|
|
226
|
+
lines.push(` description: "The user's input"`);
|
|
227
|
+
lines.push(``);
|
|
228
|
+
lines.push(`output:`);
|
|
229
|
+
lines.push(` format: ${answers.output_format}`);
|
|
230
|
+
lines.push(``);
|
|
231
|
+
lines.push(`tests:`);
|
|
232
|
+
lines.push(` - file: agent.test.yaml`);
|
|
233
|
+
lines.push(``);
|
|
234
|
+
return lines.join("\n");
|
|
235
|
+
}
|
|
236
|
+
function buildTestYaml(agentName) {
|
|
237
|
+
return [
|
|
238
|
+
`agent: "${agentName}"`,
|
|
239
|
+
``,
|
|
240
|
+
`cases:`,
|
|
241
|
+
` - name: "basic test"`,
|
|
242
|
+
` input:`,
|
|
243
|
+
` input: "Hello, world!"`,
|
|
244
|
+
` expected_contains:`,
|
|
245
|
+
` - "Hello" # adjust to match your agent's expected output`,
|
|
246
|
+
` timeout_ms: 30000`,
|
|
247
|
+
``,
|
|
248
|
+
].join("\n");
|
|
249
|
+
}
|
|
250
|
+
function buildReadme(answers) {
|
|
251
|
+
return [
|
|
252
|
+
`# ${answers.name}`,
|
|
253
|
+
``,
|
|
254
|
+
`> ${answers.description}`,
|
|
255
|
+
``,
|
|
256
|
+
`## Overview`,
|
|
257
|
+
``,
|
|
258
|
+
`| Field | Value |`,
|
|
259
|
+
`|-------|-------|`,
|
|
260
|
+
`| **Type** | ${answers.type} |`,
|
|
261
|
+
`| **LLM** | ${answers.llm_provider}${answers.llm_model ? ` / ${answers.llm_model}` : ""} |`,
|
|
262
|
+
`| **Output** | ${answers.output_format} |`,
|
|
263
|
+
`| **Trust Level** | ${answers.trust_level} |`,
|
|
264
|
+
``,
|
|
265
|
+
`## Usage`,
|
|
266
|
+
``,
|
|
267
|
+
`\`\`\`bash`,
|
|
268
|
+
`cforge run # execute the agent`,
|
|
269
|
+
`cforge test # run test suite`,
|
|
270
|
+
`\`\`\``,
|
|
271
|
+
``,
|
|
272
|
+
`## Configuration`,
|
|
273
|
+
``,
|
|
274
|
+
`Edit \`agent.yaml\` to customize the agent's behavior.`,
|
|
275
|
+
``,
|
|
276
|
+
`## Tests`,
|
|
277
|
+
``,
|
|
278
|
+
`Edit \`agent.test.yaml\` to add test cases.`,
|
|
279
|
+
``,
|
|
280
|
+
`---`,
|
|
281
|
+
``,
|
|
282
|
+
`Built with [Clayton Forge](https://github.com/devclaytonn10/clayton-forge)`,
|
|
283
|
+
``,
|
|
284
|
+
].join("\n");
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=new.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.commandRun = commandRun;
|
|
40
|
+
const readline = __importStar(require("readline"));
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
const ora_1 = __importDefault(require("ora"));
|
|
43
|
+
// ─────────────────────────────────────────────
|
|
44
|
+
// cforge run [agent-dir]
|
|
45
|
+
// ─────────────────────────────────────────────
|
|
46
|
+
async function commandRun(agentDir, inputArg) {
|
|
47
|
+
const { parseAgentFile, findAgentFile, executeAgent } = await Promise.resolve().then(() => __importStar(require("@clayton-forge/core")));
|
|
48
|
+
// 1. Find agent.yaml
|
|
49
|
+
const searchDir = agentDir ? require("path").resolve(agentDir) : process.cwd();
|
|
50
|
+
const agentPath = require("fs").existsSync(require("path").join(searchDir, "agent.yaml"))
|
|
51
|
+
? require("path").join(searchDir, "agent.yaml")
|
|
52
|
+
: findAgentFile(searchDir);
|
|
53
|
+
if (!agentPath) {
|
|
54
|
+
console.error(chalk_1.default.red("✗ No agent.yaml found. Run this command inside an agent directory."));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
// 2. Parse
|
|
58
|
+
let agent;
|
|
59
|
+
try {
|
|
60
|
+
agent = parseAgentFile(agentPath);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
console.error(chalk_1.default.red("✗ Invalid agent.yaml:"), err instanceof Error ? err.message : err);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
console.log("");
|
|
67
|
+
console.log(chalk_1.default.bold.cyan(` ▶ ${agent.name}`) + chalk_1.default.gray(` v${agent.version}`));
|
|
68
|
+
console.log(chalk_1.default.gray(` ${agent.description ?? ""}`));
|
|
69
|
+
console.log(chalk_1.default.gray(` Provider: ${agent.llm.provider}${agent.llm.model ? ` / ${agent.llm.model}` : ""}`));
|
|
70
|
+
console.log("");
|
|
71
|
+
// 3. Collect input
|
|
72
|
+
const requiredVars = agent.prompt.variables.filter((v) => v.required);
|
|
73
|
+
const variables = {};
|
|
74
|
+
if (inputArg && requiredVars.length <= 1) {
|
|
75
|
+
// Se só tem uma variável obrigatória, usa o argumento direto
|
|
76
|
+
const varName = requiredVars[0]?.name ?? "input";
|
|
77
|
+
variables[varName] = inputArg;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// Interactive input
|
|
81
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
82
|
+
const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
|
|
83
|
+
for (const variable of agent.prompt.variables) {
|
|
84
|
+
if (variable.required || !variable.default) {
|
|
85
|
+
const defaultHint = variable.default ? chalk_1.default.gray(` (default: ${variable.default})`) : "";
|
|
86
|
+
const descHint = variable.description ? chalk_1.default.gray(` — ${variable.description}`) : "";
|
|
87
|
+
const value = await question(` ${chalk_1.default.white(variable.name)}${descHint}${defaultHint}: `);
|
|
88
|
+
variables[variable.name] = value || variable.default || "";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
rl.close();
|
|
92
|
+
}
|
|
93
|
+
console.log("");
|
|
94
|
+
// 4. Execute
|
|
95
|
+
const spinner = (0, ora_1.default)("Running agent...").start();
|
|
96
|
+
const result = await executeAgent(agent, { variables });
|
|
97
|
+
if (result.success) {
|
|
98
|
+
spinner.succeed(chalk_1.default.green(`Done`) + chalk_1.default.gray(` (${result.duration_ms}ms)`));
|
|
99
|
+
console.log("");
|
|
100
|
+
console.log(chalk_1.default.bold(" Output:"));
|
|
101
|
+
console.log("");
|
|
102
|
+
// Format output based on type
|
|
103
|
+
const lines = result.output.split("\n");
|
|
104
|
+
for (const line of lines) {
|
|
105
|
+
console.log(" " + line);
|
|
106
|
+
}
|
|
107
|
+
if (result.llm_response?.usage) {
|
|
108
|
+
const { input_tokens, output_tokens } = result.llm_response.usage;
|
|
109
|
+
console.log("");
|
|
110
|
+
console.log(chalk_1.default.gray(` Tokens: ${input_tokens ?? "?"} in / ${output_tokens ?? "?"} out`));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
spinner.fail(chalk_1.default.red("Execution failed"));
|
|
115
|
+
console.log("");
|
|
116
|
+
console.error(chalk_1.default.red(" Error:"), result.error);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
console.log("");
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.commandTest = commandTest;
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const ora_1 = __importDefault(require("ora"));
|
|
44
|
+
// ─────────────────────────────────────────────
|
|
45
|
+
// cforge test [agent-dir]
|
|
46
|
+
// ─────────────────────────────────────────────
|
|
47
|
+
async function commandTest(agentDir) {
|
|
48
|
+
const { parseAgentFile, parseTestFile, runTestSuite, findAgentFile } = await Promise.resolve().then(() => __importStar(require("@clayton-forge/core")));
|
|
49
|
+
// 1. Find agent.yaml
|
|
50
|
+
const searchDir = agentDir ? path.resolve(agentDir) : process.cwd();
|
|
51
|
+
const agentYamlPath = fs.existsSync(path.join(searchDir, "agent.yaml"))
|
|
52
|
+
? path.join(searchDir, "agent.yaml")
|
|
53
|
+
: findAgentFile(searchDir);
|
|
54
|
+
if (!agentYamlPath) {
|
|
55
|
+
console.error(chalk_1.default.red("✗ No agent.yaml found."));
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
// 2. Parse agent
|
|
59
|
+
let agent;
|
|
60
|
+
try {
|
|
61
|
+
agent = parseAgentFile(agentYamlPath);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.error(chalk_1.default.red("✗ Invalid agent.yaml:"), err instanceof Error ? err.message : err);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
// 3. Find test files
|
|
68
|
+
const agentDir2 = path.dirname(agentYamlPath);
|
|
69
|
+
const testFiles = (agent.tests ?? []).map((t) => path.resolve(agentDir2, t.file));
|
|
70
|
+
// Fallback: tenta agent.test.yaml se não há tests declarados
|
|
71
|
+
if (testFiles.length === 0) {
|
|
72
|
+
const fallback = path.join(agentDir2, "agent.test.yaml");
|
|
73
|
+
if (fs.existsSync(fallback))
|
|
74
|
+
testFiles.push(fallback);
|
|
75
|
+
}
|
|
76
|
+
if (testFiles.length === 0) {
|
|
77
|
+
console.error(chalk_1.default.red("✗ No test files found. Create agent.test.yaml first."));
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
console.log("");
|
|
81
|
+
console.log(chalk_1.default.bold.cyan(` ⚗ Testing: ${agent.name}`) + chalk_1.default.gray(` v${agent.version}`));
|
|
82
|
+
console.log(chalk_1.default.gray(` Provider: ${agent.llm.provider}${agent.llm.model ? ` / ${agent.llm.model}` : ""}`));
|
|
83
|
+
console.log("");
|
|
84
|
+
let totalPassed = 0;
|
|
85
|
+
let totalFailed = 0;
|
|
86
|
+
for (const testFile of testFiles) {
|
|
87
|
+
// 4. Parse test suite
|
|
88
|
+
let suite;
|
|
89
|
+
try {
|
|
90
|
+
suite = parseTestFile(testFile);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(chalk_1.default.red(`✗ Invalid test file ${testFile}:`), err instanceof Error ? err.message : err);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
console.log(chalk_1.default.gray(` File: ${path.basename(testFile)}`));
|
|
97
|
+
console.log(chalk_1.default.gray(` Cases: ${suite.cases.length}`));
|
|
98
|
+
console.log("");
|
|
99
|
+
// 5. Run
|
|
100
|
+
const spinner = (0, ora_1.default)("Running tests...").start();
|
|
101
|
+
const summary = await runTestSuite(agent, suite);
|
|
102
|
+
spinner.stop();
|
|
103
|
+
// 6. Display results
|
|
104
|
+
for (const result of summary.results) {
|
|
105
|
+
if (result.passed) {
|
|
106
|
+
console.log(chalk_1.default.green(" ✓ PASS") +
|
|
107
|
+
chalk_1.default.white(` ${result.name}`) +
|
|
108
|
+
chalk_1.default.gray(` (${result.duration_ms}ms)`));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(chalk_1.default.red(" ✗ FAIL") +
|
|
112
|
+
chalk_1.default.white(` ${result.name}`) +
|
|
113
|
+
chalk_1.default.gray(` (${result.duration_ms}ms)`));
|
|
114
|
+
for (const failure of result.failures) {
|
|
115
|
+
console.log(chalk_1.default.red(" ↳ " + failure));
|
|
116
|
+
}
|
|
117
|
+
if (result.error) {
|
|
118
|
+
console.log(chalk_1.default.red(" Error: " + result.error));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
totalPassed += summary.passed;
|
|
123
|
+
totalFailed += summary.failed;
|
|
124
|
+
console.log("");
|
|
125
|
+
console.log(chalk_1.default.gray(" ─────────────────────────────────────"));
|
|
126
|
+
const statusColor = summary.failed === 0 ? chalk_1.default.green : chalk_1.default.red;
|
|
127
|
+
console.log(statusColor(` ${summary.passed}/${summary.total} passed`) +
|
|
128
|
+
chalk_1.default.gray(` · ${summary.duration_ms}ms`));
|
|
129
|
+
}
|
|
130
|
+
console.log("");
|
|
131
|
+
// Final exit code
|
|
132
|
+
if (totalFailed > 0) {
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=test.js.map
|
package/dist/index.d.ts
ADDED