@autonsh/cli 0.17.2 → 0.18.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/index.js +245 -58
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts +34 -8
- package/dist/prompts.js +186 -8
- package/dist/prompts.js.map +1 -1
- package/dist/task.d.ts +9 -1
- package/dist/task.js +21 -0
- package/dist/task.js.map +1 -1
- package/dist/template-engine.d.ts +19 -0
- package/dist/template-engine.js +187 -0
- package/dist/template-engine.js.map +1 -0
- package/dist/template-registry.d.ts +36 -0
- package/dist/template-registry.js +294 -0
- package/dist/template-registry.js.map +1 -0
- package/package.json +2 -1
- package/templates/coding/agent.md +39 -0
- package/templates/coding/agent.ts +83 -0
- package/templates/coding/task.yaml +36 -0
- package/templates/harness/agent.md +43 -0
- package/templates/harness/harness.ts +145 -0
- package/templates/harness/task.yaml +15 -0
- package/templates/research/task.yaml +32 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Registry — carrega templates built-in + custom (~/.auton/templates)
|
|
3
|
+
* Fonte única de verdade para `auton init`, `auton template list`, etc.
|
|
4
|
+
*/
|
|
5
|
+
import { readFile, readdir, mkdir } from "node:fs/promises";
|
|
6
|
+
import { join, resolve, dirname } from "node:path";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
const SRC = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const BUILTIN_TEMPLATES_DIR = resolve(SRC, "../templates");
|
|
11
|
+
const USER_TEMPLATES_DIR = join(homedir(), ".auton", "templates");
|
|
12
|
+
async function parseTemplateJson(dir, source) {
|
|
13
|
+
const jsonPath = join(dir, "template.json");
|
|
14
|
+
try {
|
|
15
|
+
const raw = await readFile(jsonPath, "utf8");
|
|
16
|
+
const spec = JSON.parse(raw);
|
|
17
|
+
return {
|
|
18
|
+
...spec,
|
|
19
|
+
source,
|
|
20
|
+
templateDir: dir,
|
|
21
|
+
category: spec.category ?? "general",
|
|
22
|
+
defaultMode: spec.defaultMode ?? "build",
|
|
23
|
+
skills: spec.skills ?? [],
|
|
24
|
+
verifyGates: spec.verifyGates ?? [],
|
|
25
|
+
variables: spec.variables ?? [],
|
|
26
|
+
hasGenesis: spec.hasGenesis ?? false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return inferFromTaskYaml(dir, source);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function inferFromTaskYaml(dir, source) {
|
|
34
|
+
const taskPath = join(dir, "task.yaml");
|
|
35
|
+
try {
|
|
36
|
+
const raw = await readFile(taskPath, "utf8");
|
|
37
|
+
const name = raw.match(/^name:\s*(\S+)/m)?.[1] ?? basename(dir);
|
|
38
|
+
const entry = raw.match(/^entry:\s*(\S+)/m)?.[1] ?? "agent.ts";
|
|
39
|
+
const modelMatch = raw.match(/^models:\s*\n\s*default:\s*(\S+)/m);
|
|
40
|
+
const defaultModel = modelMatch?.[1] ?? "mock:local";
|
|
41
|
+
const modeMatch = raw.match(/^mode:\s*(\S+)/m);
|
|
42
|
+
const defaultMode = modeMatch?.[1] ?? "build";
|
|
43
|
+
const skillsBlock = raw.match(/^skills:\s*\n((?:[ \t]*- \S+\n?)+)/m);
|
|
44
|
+
const skills = skillsBlock?.[1]
|
|
45
|
+
?.split("\n")
|
|
46
|
+
.map(l => l.match(/^\s*-\s*(\S+)/)?.[1])
|
|
47
|
+
.filter((s) => Boolean(s)) ?? [];
|
|
48
|
+
const verifyBlock = raw.match(/^verify:\s*\n((?:[ \t]+\S.*\n?)+)/m);
|
|
49
|
+
const verifyGates = [];
|
|
50
|
+
if (verifyBlock?.[1]) {
|
|
51
|
+
for (const line of verifyBlock[1].split("\n")) {
|
|
52
|
+
const m = line.match(/^\s+([A-Za-z0-9_-]+):\s*["']?([^"'\n]+)["']?\s*$/);
|
|
53
|
+
if (m && m[1] && m[2] && m[1] !== "timeout_ms" && m[1] !== "on-fail") {
|
|
54
|
+
verifyGates.push({ name: m[1], cmd: m[2].trim() });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const genesisMatch = raw.match(/^genesis:\s*[\|>]\s*\n((?:[ \t].*\n?)+)/m);
|
|
59
|
+
const hasGenesis = !!genesisMatch;
|
|
60
|
+
return {
|
|
61
|
+
id: name,
|
|
62
|
+
name: name.charAt(0).toUpperCase() + name.slice(1).replace(/-/g, " "),
|
|
63
|
+
description: raw.match(/^description:\s*["']?([^"'\n]+)/m)?.[1]?.trim() ?? "",
|
|
64
|
+
category: name === "harness" ? "harness" : "general",
|
|
65
|
+
entry,
|
|
66
|
+
defaultModel,
|
|
67
|
+
defaultMode,
|
|
68
|
+
skills,
|
|
69
|
+
verifyGates,
|
|
70
|
+
hasGenesis,
|
|
71
|
+
genesisPrompt: genesisMatch?.[1]?.replace(/^[ \t]/gm, "").trim(),
|
|
72
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
73
|
+
source,
|
|
74
|
+
templateDir: dir,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function basename(dir) {
|
|
82
|
+
return dir.split("/").pop() ?? dir;
|
|
83
|
+
}
|
|
84
|
+
function getBuiltinTemplates() {
|
|
85
|
+
const builtinFallback = {
|
|
86
|
+
support: {
|
|
87
|
+
id: "support",
|
|
88
|
+
name: "Support Bot",
|
|
89
|
+
description: "Bot de suporte: prompt → LLM → responde + contador",
|
|
90
|
+
category: "general",
|
|
91
|
+
entry: "agent.ts",
|
|
92
|
+
defaultModel: "mock:local",
|
|
93
|
+
defaultMode: "build",
|
|
94
|
+
skills: [],
|
|
95
|
+
verifyGates: [],
|
|
96
|
+
hasGenesis: false,
|
|
97
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
98
|
+
},
|
|
99
|
+
"cron-digester": {
|
|
100
|
+
id: "cron-digester",
|
|
101
|
+
name: "Cron Digester",
|
|
102
|
+
description: "Digest periódico no storage",
|
|
103
|
+
category: "ops",
|
|
104
|
+
entry: "agent.ts",
|
|
105
|
+
defaultModel: "mock:local",
|
|
106
|
+
defaultMode: "build",
|
|
107
|
+
skills: [],
|
|
108
|
+
verifyGates: [],
|
|
109
|
+
hasGenesis: false,
|
|
110
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
111
|
+
},
|
|
112
|
+
"webhook-echo": {
|
|
113
|
+
id: "webhook-echo",
|
|
114
|
+
name: "Webhook Echo",
|
|
115
|
+
description: "Ecoa payload via invoke + emite evento",
|
|
116
|
+
category: "ops",
|
|
117
|
+
entry: "agent.ts",
|
|
118
|
+
defaultModel: "mock:local",
|
|
119
|
+
defaultMode: "build",
|
|
120
|
+
skills: [],
|
|
121
|
+
verifyGates: [],
|
|
122
|
+
hasGenesis: false,
|
|
123
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
124
|
+
},
|
|
125
|
+
"with-approval": {
|
|
126
|
+
id: "with-approval",
|
|
127
|
+
name: "With Approval",
|
|
128
|
+
description: "Task com gate humano (prepara → aprova → executa)",
|
|
129
|
+
category: "general",
|
|
130
|
+
entry: "agent.ts",
|
|
131
|
+
defaultModel: "mock:local",
|
|
132
|
+
defaultMode: "build",
|
|
133
|
+
skills: [],
|
|
134
|
+
verifyGates: [],
|
|
135
|
+
hasGenesis: false,
|
|
136
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
137
|
+
},
|
|
138
|
+
"api-json": {
|
|
139
|
+
id: "api-json",
|
|
140
|
+
name: "API JSON",
|
|
141
|
+
description: "Agente que retorna JSON estruturado",
|
|
142
|
+
category: "coding",
|
|
143
|
+
entry: "agent.ts",
|
|
144
|
+
defaultModel: "ollama:qwen2.5-coder:14b-instruct-q4_K_M",
|
|
145
|
+
defaultMode: "build",
|
|
146
|
+
skills: ["api"],
|
|
147
|
+
verifyGates: [{ name: "typecheck", cmd: "tsc --noEmit" }],
|
|
148
|
+
hasGenesis: false,
|
|
149
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
150
|
+
},
|
|
151
|
+
"multi-agent": {
|
|
152
|
+
id: "multi-agent",
|
|
153
|
+
name: "Multi Agent",
|
|
154
|
+
description: "Coordenação de múltiplos agentes",
|
|
155
|
+
category: "ops",
|
|
156
|
+
entry: "agent.ts",
|
|
157
|
+
defaultModel: "ollama:qwen2.5-coder:14b-instruct-q4_K_M",
|
|
158
|
+
defaultMode: "build",
|
|
159
|
+
skills: [],
|
|
160
|
+
verifyGates: [],
|
|
161
|
+
hasGenesis: false,
|
|
162
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
163
|
+
},
|
|
164
|
+
coding: {
|
|
165
|
+
id: "coding",
|
|
166
|
+
name: "Coding Agent",
|
|
167
|
+
description: "Engenheiro TypeScript sênior — refatorar, testar, migrar",
|
|
168
|
+
category: "coding",
|
|
169
|
+
entry: "agent.ts",
|
|
170
|
+
defaultModel: "ollama:qwen2.5-coder:14b-instruct-q4_K_M",
|
|
171
|
+
defaultMode: "build",
|
|
172
|
+
skills: ["typescript", "refactoring", "testing"],
|
|
173
|
+
verifyGates: [
|
|
174
|
+
{ name: "typecheck", cmd: "tsc --noEmit" },
|
|
175
|
+
{ name: "test", cmd: "vitest run" },
|
|
176
|
+
{ name: "lint", cmd: "eslint ." },
|
|
177
|
+
],
|
|
178
|
+
hasGenesis: true,
|
|
179
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
180
|
+
},
|
|
181
|
+
harness: {
|
|
182
|
+
id: "harness",
|
|
183
|
+
name: "Harness Local",
|
|
184
|
+
description: "Loop agêntico local (sem CP), checkpoints persistentes",
|
|
185
|
+
category: "harness",
|
|
186
|
+
entry: "harness.ts",
|
|
187
|
+
defaultModel: "ollama:qwen2.5-coder:14b-instruct-q4_K_M",
|
|
188
|
+
defaultMode: "harness",
|
|
189
|
+
skills: [],
|
|
190
|
+
verifyGates: [
|
|
191
|
+
{ name: "typecheck", cmd: "tsc --noEmit" },
|
|
192
|
+
{ name: "test", cmd: "vitest run" },
|
|
193
|
+
],
|
|
194
|
+
hasGenesis: false,
|
|
195
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
196
|
+
},
|
|
197
|
+
research: {
|
|
198
|
+
id: "research",
|
|
199
|
+
name: "Research",
|
|
200
|
+
description: "Pesquisa e análise — modo research",
|
|
201
|
+
category: "research",
|
|
202
|
+
entry: "agent.ts",
|
|
203
|
+
defaultModel: "ollama:qwen2.5-coder:14b-instruct-q4_K_M",
|
|
204
|
+
defaultMode: "research",
|
|
205
|
+
skills: ["docs"],
|
|
206
|
+
verifyGates: [],
|
|
207
|
+
hasGenesis: false,
|
|
208
|
+
variables: [{ key: "name", label: "Nome do agente", type: "string", required: true }],
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
return Object.entries(builtinFallback).map(([id, spec]) => ({
|
|
212
|
+
...spec,
|
|
213
|
+
id,
|
|
214
|
+
source: "builtin",
|
|
215
|
+
templateDir: join(BUILTIN_TEMPLATES_DIR, id),
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
export async function createTemplateRegistry() {
|
|
219
|
+
let cache = [];
|
|
220
|
+
let loaded = false;
|
|
221
|
+
async function loadAll() {
|
|
222
|
+
const specs = [];
|
|
223
|
+
// 1. Built-in templates
|
|
224
|
+
try {
|
|
225
|
+
const builtinDirs = await readdir(BUILTIN_TEMPLATES_DIR, { withFileTypes: true });
|
|
226
|
+
for (const entry of builtinDirs) {
|
|
227
|
+
if (!entry.isDirectory())
|
|
228
|
+
continue;
|
|
229
|
+
if (entry.name === "modes" || entry.name === "skills")
|
|
230
|
+
continue;
|
|
231
|
+
const spec = await parseTemplateJson(join(BUILTIN_TEMPLATES_DIR, entry.name), "builtin");
|
|
232
|
+
if (spec)
|
|
233
|
+
specs.push(spec);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
specs.push(...getBuiltinTemplates());
|
|
238
|
+
}
|
|
239
|
+
// 2. Custom templates (~/.auton/templates)
|
|
240
|
+
try {
|
|
241
|
+
await mkdir(USER_TEMPLATES_DIR, { recursive: true });
|
|
242
|
+
const customDirs = await readdir(USER_TEMPLATES_DIR, { withFileTypes: true });
|
|
243
|
+
for (const entry of customDirs) {
|
|
244
|
+
if (!entry.isDirectory())
|
|
245
|
+
continue;
|
|
246
|
+
const spec = await parseTemplateJson(join(USER_TEMPLATES_DIR, entry.name), "custom");
|
|
247
|
+
if (spec)
|
|
248
|
+
specs.push(spec);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// diretório não existe ou vazio — ok
|
|
253
|
+
}
|
|
254
|
+
// Dedupe por id (custom vence builtin)
|
|
255
|
+
const seen = new Set();
|
|
256
|
+
const deduped = [];
|
|
257
|
+
for (const s of specs) {
|
|
258
|
+
if (!seen.has(s.id)) {
|
|
259
|
+
seen.add(s.id);
|
|
260
|
+
deduped.push(s);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return deduped;
|
|
264
|
+
}
|
|
265
|
+
const registry = {
|
|
266
|
+
async list() {
|
|
267
|
+
if (!loaded) {
|
|
268
|
+
cache = await loadAll();
|
|
269
|
+
loaded = true;
|
|
270
|
+
}
|
|
271
|
+
return cache;
|
|
272
|
+
},
|
|
273
|
+
async get(id) {
|
|
274
|
+
const all = await registry.list();
|
|
275
|
+
return all.find((t) => t.id === id);
|
|
276
|
+
},
|
|
277
|
+
async getByCategory(category) {
|
|
278
|
+
const all = await registry.list();
|
|
279
|
+
return all.filter((t) => t.category === category);
|
|
280
|
+
},
|
|
281
|
+
async reload() {
|
|
282
|
+
loaded = false;
|
|
283
|
+
cache = await loadAll();
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
return registry;
|
|
287
|
+
}
|
|
288
|
+
let _registry = null;
|
|
289
|
+
export async function getTemplateRegistry() {
|
|
290
|
+
if (!_registry)
|
|
291
|
+
_registry = await createTemplateRegistry();
|
|
292
|
+
return _registry;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=template-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-registry.js","sourceRoot":"","sources":["../src/template-registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autonsh/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "auton CLI. Run autonomous tasks in one command.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"@clack/prompts": "^1.7.0",
|
|
23
23
|
"boxen": "^8.0.1",
|
|
24
24
|
"cli-progress": "^3.12.0",
|
|
25
|
+
"handlebars": "^4.7.8",
|
|
25
26
|
"log-symbols": "^7.0.1",
|
|
26
27
|
"ora": "^9.4.1",
|
|
27
28
|
"picocolors": "^1.1.1",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Coding Agent — Engenheiro TypeScript Sênior
|
|
2
|
+
|
|
3
|
+
Você refatora, testa, migra e corrige código TypeScript.
|
|
4
|
+
|
|
5
|
+
## Princípios Invioláveis
|
|
6
|
+
1. **Entenda antes de mudar** — leia, trace dependências, entenda o fluxo
|
|
7
|
+
2. **Mudanças atômicas** — um arquivo por vez, typecheck a cada passo
|
|
8
|
+
3. **Tipos estritos** — `strict: true`, `noImplicitAny`, `exactOptionalPropertyTypes`
|
|
9
|
+
4. **Testes obrigatórios** — unit + integration para lógica de negócio
|
|
10
|
+
5. **Sem breaking changes** — API pública só com migração + depreciação
|
|
11
|
+
6. **Performance consciente** — `const`, `readonly`, evite alocações
|
|
12
|
+
7. **Documentação "por que"** — JSDoc em exports, comentários de decisão
|
|
13
|
+
|
|
14
|
+
## Fluxo por Task
|
|
15
|
+
```
|
|
16
|
+
PLAN → analise impacto, liste arquivos, defina testes
|
|
17
|
+
IMPLEMENT → edite um arquivo, tsc --noEmit, commit mental
|
|
18
|
+
TEST → vitest run, coverage > 80%
|
|
19
|
+
VERIFY → goal atendido? gaps? evidência
|
|
20
|
+
CHECKPOINT→ salve diff, testes, coverage
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Ferramentas
|
|
24
|
+
- `ctx.tools.read(file)` — ler
|
|
25
|
+
- `ctx.tools.write(file, content)` — escrever
|
|
26
|
+
- `ctx.tools.patch(file, old, new)` — editar cirúrgico
|
|
27
|
+
- `ctx.tools.exec(cmd)` — rodar tsc, vitest, eslint
|
|
28
|
+
- `ctx.tools.list(dir)` — explorar
|
|
29
|
+
- `ctx.storage` — KV persistente
|
|
30
|
+
- `ctx.work.add(type, title, payload)` — findings/artifacts
|
|
31
|
+
|
|
32
|
+
## Resposta (JSON)
|
|
33
|
+
```json
|
|
34
|
+
{ "file": "src/auth.ts", "content": "...", "reason": "adicionar Zod schema" }
|
|
35
|
+
```
|
|
36
|
+
ou finalização:
|
|
37
|
+
```json
|
|
38
|
+
{ "done": true, "summary": "Refatorado auth.ts + 12 testes + OpenAPI atualizado" }
|
|
39
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, existsSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { agent, TASK_DONE_EVENT } from "@autonsh/runtime";
|
|
4
|
+
|
|
5
|
+
function readdirSyncSafe(dir: string): string[] {
|
|
6
|
+
try { return readdirSync(dir); } catch { return []; }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function readFileSafe(file: string): string {
|
|
10
|
+
try { return readFileSync(file, "utf8"); } catch { return ""; }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function writeFileSafe(file: string, content: string): void {
|
|
14
|
+
writeFileSync(file, content, "utf8");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default agent(async (ctx) => {
|
|
18
|
+
const goal = ((ctx.input as { prompt?: string } | undefined)?.prompt ?? "").trim();
|
|
19
|
+
if (!goal) {
|
|
20
|
+
await ctx.events.emit(TASK_DONE_EVENT, { result: "goal vazio", evidence: {} });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Carrega agent.md (genesis) + skills
|
|
25
|
+
const agentMd = readFileSafe("agent.md");
|
|
26
|
+
const skillDocs = readdirSyncSafe("skills")
|
|
27
|
+
.filter((d) => existsSync(join("skills", d, "SKILL.md")))
|
|
28
|
+
.map((d) => `# skill: ${d}\n${readFileSafe(join("skills", d, "SKILL.md"))}`)
|
|
29
|
+
.join("\n\n");
|
|
30
|
+
const systemPrompt = `${agentMd}\n\n${skillDocs}`;
|
|
31
|
+
|
|
32
|
+
await ctx.logger.info("task iniciada", { goal });
|
|
33
|
+
|
|
34
|
+
// 1. PLAN — analisa código, propõe plano
|
|
35
|
+
const plan = await ctx.llm.chat({
|
|
36
|
+
system: `Você é um engenheiro sênior TypeScript.\n${systemPrompt}\n\nAnalise o codebase e proponha um PLANO detalhado para: ${goal}\nListe: arquivos a tocar, testes a criar, riscos.`,
|
|
37
|
+
prompt: goal,
|
|
38
|
+
});
|
|
39
|
+
await ctx.logger.info("plano", { plan });
|
|
40
|
+
|
|
41
|
+
// 2. IMPLEMENT — executa mudanças arquivo a arquivo
|
|
42
|
+
// Para simplicidade: pede ao LLM para gerar os diffs/patches
|
|
43
|
+
const implement = await ctx.llm.chat({
|
|
44
|
+
system: `Execute o plano. Use ctx.tools para ler/escrever/editar arquivos.\nFaça UMA mudança por vez. Rode tsc --noEmit após cada arquivo.\nResponda JSON: { file, content, reason } ou { done: true, summary }`,
|
|
45
|
+
prompt: plan,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
let parsed: { file?: string; content?: string; reason?: string; done?: boolean; summary?: string };
|
|
49
|
+
try { parsed = JSON.parse(implement.trim()); } catch { parsed = { done: true, summary: implement }; }
|
|
50
|
+
|
|
51
|
+
if (!parsed.done && parsed.file && parsed.content) {
|
|
52
|
+
await ctx.tools.write(parsed.file, parsed.content);
|
|
53
|
+
await ctx.logger.info("arquivo escrito", { file: parsed.file, reason: parsed.reason });
|
|
54
|
+
|
|
55
|
+
// Typecheck incremental
|
|
56
|
+
const tc = await ctx.tools.exec("tsc --noEmit").catch((e) => e.message);
|
|
57
|
+
await ctx.logger.info("typecheck", { result: tc });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 3. TESTS — roda testes
|
|
61
|
+
const testResult = await ctx.tools.exec("vitest run --reporter=json").catch((e) => e.message);
|
|
62
|
+
await ctx.logger.info("testes", { result: testResult });
|
|
63
|
+
|
|
64
|
+
// 4. VERIFY — validação final
|
|
65
|
+
const verify = await ctx.llm.chat({
|
|
66
|
+
system: "Verifique: goal atendido? Testes passam? Typecheck limpo? Responda JSON: { pass: boolean, gaps: string[] }",
|
|
67
|
+
prompt: `Goal: ${goal}\nPlan: ${plan}\nTestes: ${testResult}`,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
let verified: { pass: boolean; gaps: string[] };
|
|
71
|
+
try { verified = JSON.parse(verify.trim()); } catch { verified = { pass: false, gaps: ["parse error"] }; }
|
|
72
|
+
|
|
73
|
+
await ctx.logger.info("verificacao", { pass: verified.pass, gaps: verified.gaps });
|
|
74
|
+
|
|
75
|
+
// Work context
|
|
76
|
+
await ctx.work.add("finding", "implementação", { goal, plan, verify: verified });
|
|
77
|
+
await ctx.work.add("artifact", "mudanças", { files: parsed.file ? [parsed.file] : [] });
|
|
78
|
+
|
|
79
|
+
await ctx.events.emit(TASK_DONE_EVENT, {
|
|
80
|
+
result: verified.pass ? "Goal atendido" : `Gaps: ${verified.gaps.join(", ")}`,
|
|
81
|
+
evidence: { plan, testResult, verify: verified, filesChanged: parsed.file ? [parsed.file] : [] },
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: coding
|
|
2
|
+
description: Agente de código — refatorar, testar, migrar, corrigir
|
|
3
|
+
goal: ""
|
|
4
|
+
entry: agent.ts
|
|
5
|
+
models:
|
|
6
|
+
default: ollama:qwen2.5-coder:14b-instruct-q4_K_M
|
|
7
|
+
env:
|
|
8
|
+
- GITHUB_TOKEN
|
|
9
|
+
mode: build
|
|
10
|
+
skills:
|
|
11
|
+
- typescript
|
|
12
|
+
- refactoring
|
|
13
|
+
- testing
|
|
14
|
+
verify:
|
|
15
|
+
typecheck: "tsc --noEmit"
|
|
16
|
+
test: "vitest run"
|
|
17
|
+
lint: "eslint ."
|
|
18
|
+
genesis: |
|
|
19
|
+
Você é um engenheiro de software sênior especializado em TypeScript.
|
|
20
|
+
|
|
21
|
+
Princípios:
|
|
22
|
+
1. Entenda o código ANTES de mudar — leia, trace dependências
|
|
23
|
+
2. Mudanças pequenas, atômicas, testáveis
|
|
24
|
+
3. Tipos estritos: `strict: true`, `noImplicitAny`, `exactOptionalPropertyTypes`
|
|
25
|
+
4. Testes obrigatórios: unit + integration para lógica de negócio
|
|
26
|
+
5. Nunca quebre API pública sem migração + depreciação
|
|
27
|
+
6. Performance: evite alocações desnecessárias, use `const`, `readonly`
|
|
28
|
+
7. Documentação: JSDoc em exports públicos, comentários "por que" não "o que"
|
|
29
|
+
|
|
30
|
+
Fluxo por task:
|
|
31
|
+
- PLAN: analise impacto, liste arquivos, defina testes
|
|
32
|
+
- IMPLEMENT: edite um arquivo por vez, rode typecheck a cada passo
|
|
33
|
+
- VERIFY: tsc --noEmit → vitest run → eslint
|
|
34
|
+
- CHECKPOINT: salve evidência (diff, testes, coverage)
|
|
35
|
+
|
|
36
|
+
Responda em PT-BR. Seja conciso.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Harness Agent — Loop Local
|
|
2
|
+
|
|
3
|
+
Você é um agente autônomo que roda **local** (sem Control Plane).
|
|
4
|
+
Seu ciclo: **PLAN → ACT → VERIFY → CHECKPOINT** até `done: true`.
|
|
5
|
+
|
|
6
|
+
## Princípios
|
|
7
|
+
- **Pequenos passos**: uma ação por turno, verificável
|
|
8
|
+
- **Checkpoint sempre**: estado salvo em `.auton/checkpoints/` para resume
|
|
9
|
+
- **Ferramentas primeiro**: use `ctx.tools` para ler/escrever/correr código
|
|
10
|
+
- **Verificação honesta**: se não passou, explica o que falta
|
|
11
|
+
|
|
12
|
+
## Ferramentas disponíveis
|
|
13
|
+
- `ctx.tools.list(dir)` — lista arquivos
|
|
14
|
+
- `ctx.tools.read(file)` — lê arquivo
|
|
15
|
+
- `ctx.tools.write(file, content)` — escreve arquivo
|
|
16
|
+
- `ctx.tools.exec(cmd)` — roda comando shell (tsc, vitest, etc.)
|
|
17
|
+
- `ctx.tools.patch(file, oldStr, newStr)` — edita cirúrgico
|
|
18
|
+
- `ctx.storage.get/set(key, value)` — KV persistente
|
|
19
|
+
- `ctx.work.add(type, title, payload)` — work context (findings/artifacts)
|
|
20
|
+
|
|
21
|
+
## Formato de resposta (JSON)
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"plan": "Uma frase: o que vou fazer agora",
|
|
25
|
+
"action": "comando ou código para ctx.tools.exec / ctx.tools.write",
|
|
26
|
+
"done": false
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
Se `done: true`, o loop para e emite `TASK:DONE`.
|
|
30
|
+
|
|
31
|
+
## Modo harness
|
|
32
|
+
- `loop: true` — continua até `done: true` ou `maxTurns`
|
|
33
|
+
- `maxTurns: 10` — segurança contra loops infinitos
|
|
34
|
+
- `checkpointDir: ".auton/checkpoints"` — resume automático no próximo `auton run`
|
|
35
|
+
|
|
36
|
+
## Exemplo
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"plan": "Ler src/auth.ts para entender a estrutura",
|
|
40
|
+
"action": "read src/auth.ts",
|
|
41
|
+
"done": false
|
|
42
|
+
}
|
|
43
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Harness local — loop agêntico sem Control Plane.
|
|
4
|
+
* Roda: plan → act → verify → checkpoint → done.
|
|
5
|
+
* Checkpoints em .auton/checkpoints/ (resume no próximo run).
|
|
6
|
+
*/
|
|
7
|
+
import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
|
|
8
|
+
import { join, resolve } from "node:path";
|
|
9
|
+
import { createLlm, createStorage, createTools } from "@autonsh/runtime";
|
|
10
|
+
|
|
11
|
+
const GOAL = process.env.AUTON_GOAL ?? process.argv.slice(2).join(" ") ?? "";
|
|
12
|
+
const CHECKPOINT_DIR = ".auton/checkpoints";
|
|
13
|
+
const MAX_TURNS = Number(process.env.AUTON_MAX_TURNS ?? 10);
|
|
14
|
+
|
|
15
|
+
async function main(): Promise<void> {
|
|
16
|
+
if (!GOAL) {
|
|
17
|
+
console.error("Erro: goal não fornecido. Use AUTON_GOAL ou passe como argumento.");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Carrega agent.md como system prompt base
|
|
22
|
+
const agentMd = await readFile("agent.md", "utf8").catch(() => "");
|
|
23
|
+
const systemPrompt = `Você é um agente autônomo em modo harness (local).
|
|
24
|
+
${agentMd}
|
|
25
|
+
|
|
26
|
+
Objetivo: ${GOAL}
|
|
27
|
+
|
|
28
|
+
Loop: planeje → execute → verifique → checkpoint.
|
|
29
|
+
Responda em JSON: { "plan": "...", "action": "...", "done": false }`;
|
|
30
|
+
|
|
31
|
+
const llm = createLlm({ model: process.env.AUTON_MODEL });
|
|
32
|
+
const storage = createStorage({ dir: ".auton/storage" });
|
|
33
|
+
const tools = createTools({ cwd: process.cwd() });
|
|
34
|
+
|
|
35
|
+
// Resume checkpoint se existir
|
|
36
|
+
let turn = 0;
|
|
37
|
+
let context = "";
|
|
38
|
+
const checkpoints = await listCheckpoints();
|
|
39
|
+
if (checkpoints.length > 0) {
|
|
40
|
+
const latest = checkpoints[checkpoints.length - 1];
|
|
41
|
+
const data = JSON.parse(await readFile(latest, "utf8"));
|
|
42
|
+
turn = data.turn ?? 0;
|
|
43
|
+
context = data.context ?? "";
|
|
44
|
+
console.log(`[harness] Resumindo checkpoint turno ${turn}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(`[harness] Iniciando: ${GOAL}`);
|
|
48
|
+
|
|
49
|
+
while (turn < MAX_TURNS) {
|
|
50
|
+
turn++;
|
|
51
|
+
console.log(`[harness] Turno ${turn}/${MAX_TURNS}`);
|
|
52
|
+
|
|
53
|
+
// 1. PLAN
|
|
54
|
+
const planResp = await llm.chat({
|
|
55
|
+
system: systemPrompt + `\n\nContexto anterior:\n${context}`,
|
|
56
|
+
prompt: "Planeje o próximo passo. Responda JSON: { plan, action, done }",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
let parsed: { plan: string; action: string; done: boolean };
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(planResp.trim());
|
|
62
|
+
} catch {
|
|
63
|
+
parsed = { plan: planResp, action: "", done: false };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(`[harness] Plan: ${parsed.plan}`);
|
|
67
|
+
if (parsed.done) {
|
|
68
|
+
console.log("[harness] Task concluída pelo agente");
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 2. ACT (executa action via tools se houver, senão LLM)
|
|
73
|
+
let result: string;
|
|
74
|
+
if (parsed.action) {
|
|
75
|
+
try {
|
|
76
|
+
result = await tools.exec(parsed.action);
|
|
77
|
+
console.log(`[harness] Action executada`);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
result = `Erro ao executar action: ${(e as Error).message}`;
|
|
80
|
+
console.log(`[harness] ${result}`);
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
const actResp = await llm.chat({
|
|
84
|
+
system: systemPrompt + `\n\nContexto:\n${context}`,
|
|
85
|
+
prompt: `Execute: ${parsed.plan}`,
|
|
86
|
+
});
|
|
87
|
+
result = actResp;
|
|
88
|
+
console.log(`[harness] LLM executou diretamente`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 3. VERIFY
|
|
92
|
+
const verifyResp = await llm.chat({
|
|
93
|
+
system: "Verifique se o resultado atende o objetivo. Responda JSON: { pass: boolean, feedback: string }",
|
|
94
|
+
prompt: `Objetivo: ${GOAL}\nResultado: ${result}`,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
let verified: { pass: boolean; feedback: string };
|
|
98
|
+
try {
|
|
99
|
+
verified = JSON.parse(verifyResp.trim());
|
|
100
|
+
} catch {
|
|
101
|
+
verified = { pass: verifyResp.toLowerCase().includes("sim"), feedback: verifyResp };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log(`[harness] Verify: ${verified.pass ? "PASS" : "FAIL"} - ${verified.feedback}`);
|
|
105
|
+
|
|
106
|
+
// 4. CHECKPOINT
|
|
107
|
+
context += `\nTurno ${turn}:\nPlan: ${parsed.plan}\nResult: ${result}\nVerify: ${verified.feedback}\n`;
|
|
108
|
+
await saveCheckpoint(turn, context, result, verified.pass);
|
|
109
|
+
|
|
110
|
+
if (verified.pass) {
|
|
111
|
+
console.log("[harness] Verificação passou - task concluída");
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Continua loop com feedback
|
|
116
|
+
context += `Feedback: ${verified.feedback}\n`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Salva resultado final
|
|
120
|
+
await storage.set("harness:result", { goal: GOAL, turns: turn, context, finalOutput: context });
|
|
121
|
+
console.log("[TASK:DONE]", JSON.stringify({ result: context, evidence: { turns: turn } }));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function listCheckpoints(): Promise<string[]> {
|
|
125
|
+
try {
|
|
126
|
+
const files = await readdir(CHECKPOINT_DIR);
|
|
127
|
+
return files
|
|
128
|
+
.filter((f) => f.endsWith(".json"))
|
|
129
|
+
.map((f) => join(CHECKPOINT_DIR, f))
|
|
130
|
+
.sort();
|
|
131
|
+
} catch {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function saveCheckpoint(turn: number, context: string, result: string, pass: boolean): Promise<void> {
|
|
137
|
+
await mkdir(CHECKPOINT_DIR, { recursive: true });
|
|
138
|
+
const file = join(CHECKPOINT_DIR, `turn-${turn}-${Date.now()}.json`);
|
|
139
|
+
await writeFile(file, JSON.stringify({ turn, context, result, pass, timestamp: Date.now() }, null, 2));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
main().catch((e) => {
|
|
143
|
+
console.error("[harness] Erro fatal:", e);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
});
|