@autonsh/cli 0.17.1 → 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/config.js +14 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +607 -124
- 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
package/dist/task.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare class ExitError extends Error {
|
|
|
16
16
|
export declare const MODES: readonly ["research", "build", "test", "review", "deploy"];
|
|
17
17
|
export type TaskMode = (typeof MODES)[number];
|
|
18
18
|
/** Skills built-in (docs embutidas nos templates; usuário pode criar custom). */
|
|
19
|
-
export declare const SKILLS: readonly ["frontend", "react", "testing", "api", "security", "docs"];
|
|
19
|
+
export declare const SKILLS: readonly ["frontend", "react", "testing", "api", "security", "docs", "typescript", "refactoring"];
|
|
20
20
|
export type TaskSkill = (typeof SKILLS)[number];
|
|
21
21
|
/** Gate mecânico do `verify:` no task.yaml (0.13+): nome → comando shell. */
|
|
22
22
|
export interface VerifyGate {
|
|
@@ -28,6 +28,12 @@ export interface VerifyConfig {
|
|
|
28
28
|
timeoutMs: number;
|
|
29
29
|
onFail: "fail" | "warn";
|
|
30
30
|
}
|
|
31
|
+
/** Config do modo harness (loop local sem CP). */
|
|
32
|
+
export interface HarnessConfig {
|
|
33
|
+
loop: boolean;
|
|
34
|
+
maxTurns: number;
|
|
35
|
+
checkpointDir: string;
|
|
36
|
+
}
|
|
31
37
|
export interface TaskManifest {
|
|
32
38
|
name: string;
|
|
33
39
|
description?: string;
|
|
@@ -41,6 +47,8 @@ export interface TaskManifest {
|
|
|
41
47
|
mode: TaskMode;
|
|
42
48
|
invokeTimeoutMs?: number;
|
|
43
49
|
verify: VerifyConfig;
|
|
50
|
+
genesis?: string;
|
|
51
|
+
harness?: HarnessConfig;
|
|
44
52
|
legacy: boolean;
|
|
45
53
|
}
|
|
46
54
|
export declare function loadTaskManifest(dir: string): Promise<TaskManifest>;
|
package/dist/task.js
CHANGED
|
@@ -34,6 +34,8 @@ export const SKILLS = [
|
|
|
34
34
|
"api",
|
|
35
35
|
"security",
|
|
36
36
|
"docs",
|
|
37
|
+
"typescript",
|
|
38
|
+
"refactoring",
|
|
37
39
|
];
|
|
38
40
|
const MANIFESTS = ["task.yaml", "agent.yaml"];
|
|
39
41
|
export async function loadTaskManifest(dir) {
|
|
@@ -89,6 +91,23 @@ export async function loadTaskManifest(dir) {
|
|
|
89
91
|
skills.push(skill);
|
|
90
92
|
}
|
|
91
93
|
}
|
|
94
|
+
// genesis: prompt de personalidade (bloco multi-linha com | ou >)
|
|
95
|
+
const genesisMatch = raw.match(/^genesis:\s*[\|>]\s*\n((?:[ \t].*\n?)+)/m);
|
|
96
|
+
const genesis = genesisMatch?.[1]?.replace(/^[ \t]/gm, "").trim();
|
|
97
|
+
// harness: config do modo harness
|
|
98
|
+
const harness = (() => {
|
|
99
|
+
const harnessBlock = raw.match(/^harness:\s*\n((?:[ \t]+\S.*\n?)+)/m);
|
|
100
|
+
if (!harnessBlock?.[1])
|
|
101
|
+
return undefined;
|
|
102
|
+
const loop = harnessBlock[1].match(/^\s+loop:\s*(\S+)/m)?.[1];
|
|
103
|
+
const maxTurns = harnessBlock[1].match(/^\s+maxTurns:\s*(\d+)/m)?.[1];
|
|
104
|
+
const checkpointDir = harnessBlock[1].match(/^\s+checkpointDir:\s*(\S+)/m)?.[1];
|
|
105
|
+
return {
|
|
106
|
+
loop: loop?.toLowerCase() === "true",
|
|
107
|
+
maxTurns: maxTurns ? Number(maxTurns) : 10,
|
|
108
|
+
checkpointDir: checkpointDir ?? ".auton/checkpoints",
|
|
109
|
+
};
|
|
110
|
+
})();
|
|
92
111
|
// verify: (0.13+) gates mecânicos executados antes do run.
|
|
93
112
|
// Bloco: `verify:\n <nome>: "<cmd>"` + chaves opcionais timeout_ms/on-fail.
|
|
94
113
|
const verify = { gates: [], timeoutMs: 120_000, onFail: "fail" };
|
|
@@ -122,6 +141,8 @@ export async function loadTaskManifest(dir) {
|
|
|
122
141
|
mode,
|
|
123
142
|
invokeTimeoutMs,
|
|
124
143
|
verify,
|
|
144
|
+
genesis,
|
|
145
|
+
harness,
|
|
125
146
|
legacy: source === "agent.yaml",
|
|
126
147
|
};
|
|
127
148
|
}
|
package/dist/task.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,iFAAiF;AACjF,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,EAAE,EAAE,CAAC,EAAE,UAAU;IACjB,GAAG,EAAE,CAAC,EAAE,oDAAoD;IAC5D,KAAK,EAAE,CAAC,EAAE,oEAAoE;IAC9E,MAAM,EAAE,CAAC,EAAE,4DAA4D;IACvE,KAAK,EAAE,CAAC,EAAE,yCAAyC;IACnD,OAAO,EAAE,CAAC,EAAE,iDAAiD;CACrD,CAAC;AAEX,qEAAqE;AACrE,MAAM,OAAO,SAAU,SAAQ,KAAK;IACb;IAArB,YAAqB,IAAY,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QADI,SAAI,GAAJ,IAAI,CAAQ;IAEjC,CAAC;CACF;AAED,yEAAyE;AACzE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAGhF,iFAAiF;AACjF,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,UAAU;IACV,OAAO;IACP,SAAS;IACT,KAAK;IACL,UAAU;IACV,MAAM;
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TemplateSpec } from "./template-registry.js";
|
|
2
|
+
export interface RenderContext {
|
|
3
|
+
name: string;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
export interface ScaffoldResult {
|
|
7
|
+
files: string[];
|
|
8
|
+
manifest: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export declare function renderTemplate(spec: TemplateSpec, context: RenderContext, targetDir: string, options?: {
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
overwrite?: boolean;
|
|
13
|
+
}): Promise<ScaffoldResult>;
|
|
14
|
+
export declare function validateVariables(spec: TemplateSpec, provided: Record<string, unknown>): {
|
|
15
|
+
valid: boolean;
|
|
16
|
+
missing: string[];
|
|
17
|
+
extra: string[];
|
|
18
|
+
};
|
|
19
|
+
export declare function promptVariables(spec: TemplateSpec, provided?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Engine — renderiza templates com Handlebars
|
|
3
|
+
* Suporta: variáveis, conditionals, loops, partials
|
|
4
|
+
*/
|
|
5
|
+
import { readFile, readdir, writeFile, mkdir, cp } from "node:fs/promises";
|
|
6
|
+
import { join, resolve, extname, basename, dirname } from "node:path";
|
|
7
|
+
import Handlebars from "handlebars";
|
|
8
|
+
async function collectTemplateFiles(templateDir) {
|
|
9
|
+
const files = [];
|
|
10
|
+
async function walk(dir, prefix = "") {
|
|
11
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
12
|
+
for (const entry of entries) {
|
|
13
|
+
const fullPath = join(dir, entry.name);
|
|
14
|
+
const relPath = join(prefix, entry.name);
|
|
15
|
+
if (entry.isDirectory()) {
|
|
16
|
+
await walk(fullPath, relPath);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (entry.name === "template.json")
|
|
20
|
+
continue;
|
|
21
|
+
const content = await readFile(fullPath, "utf8");
|
|
22
|
+
const isTemplate = [".hbs", ".handlebars", ".tmpl", ".yaml", ".yml", ".ts", ".js", ".md", ".json"].includes(extname(entry.name))
|
|
23
|
+
|| content.includes("{{")
|
|
24
|
+
|| entry.name === "task.yaml"
|
|
25
|
+
|| entry.name === "package.json";
|
|
26
|
+
files.push({ path: relPath, content, isTemplate });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
await walk(templateDir);
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
function createHandlebarsContext(ctx, spec) {
|
|
33
|
+
return {
|
|
34
|
+
...ctx,
|
|
35
|
+
now: new Date().toISOString(),
|
|
36
|
+
year: new Date().getFullYear(),
|
|
37
|
+
template: {
|
|
38
|
+
id: spec.id,
|
|
39
|
+
name: spec.name,
|
|
40
|
+
description: spec.description,
|
|
41
|
+
category: spec.category,
|
|
42
|
+
defaultModel: spec.defaultModel,
|
|
43
|
+
defaultMode: spec.defaultMode,
|
|
44
|
+
skills: spec.skills,
|
|
45
|
+
verifyGates: spec.verifyGates,
|
|
46
|
+
hasGenesis: spec.hasGenesis,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function registerHelpers() {
|
|
51
|
+
Handlebars.registerHelper("eq", function (a, b, options) {
|
|
52
|
+
return a === b ? options.fn(this) : options.inverse(this);
|
|
53
|
+
});
|
|
54
|
+
Handlebars.registerHelper("unlessEq", function (a, b, options) {
|
|
55
|
+
return a !== b ? options.fn(this) : options.inverse(this);
|
|
56
|
+
});
|
|
57
|
+
Handlebars.registerHelper("includes", function (arr, item, options) {
|
|
58
|
+
return Array.isArray(arr) && arr.includes(item) ? options.fn(this) : options.inverse(this);
|
|
59
|
+
});
|
|
60
|
+
Handlebars.registerHelper("toUpperCase", (str) => str?.toUpperCase?.() ?? "");
|
|
61
|
+
Handlebars.registerHelper("toLowerCase", (str) => str?.toLowerCase?.() ?? "");
|
|
62
|
+
Handlebars.registerHelper("toKebabCase", (str) => str?.replace(/[^a-z0-9]+/gi, "-").toLowerCase() ?? "");
|
|
63
|
+
Handlebars.registerHelper("toPascalCase", (str) => str?.replace(/[-_\s]+(.)?/g, (_, c) => c?.toUpperCase() ?? "") ?? "");
|
|
64
|
+
Handlebars.registerHelper("default", (value, fallback) => value ?? fallback);
|
|
65
|
+
Handlebars.registerHelper("json", (obj) => JSON.stringify(obj, null, 2));
|
|
66
|
+
Handlebars.registerHelper("yaml", (obj) => {
|
|
67
|
+
if (Array.isArray(obj))
|
|
68
|
+
return obj.map(v => ` - ${v}`).join("\n");
|
|
69
|
+
if (typeof obj === "object" && obj !== null)
|
|
70
|
+
return JSON.stringify(obj, null, 2).replace(/^/gm, " ");
|
|
71
|
+
return String(obj);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
registerHelpers();
|
|
75
|
+
export async function renderTemplate(spec, context, targetDir, options = {}) {
|
|
76
|
+
const files = await collectTemplateFiles(spec.templateDir);
|
|
77
|
+
const hbsContext = createHandlebarsContext(context, spec);
|
|
78
|
+
const created = [];
|
|
79
|
+
let manifest = {};
|
|
80
|
+
for (const tf of files) {
|
|
81
|
+
const targetPath = join(targetDir, tf.path);
|
|
82
|
+
let content;
|
|
83
|
+
if (tf.isTemplate) {
|
|
84
|
+
const template = Handlebars.compile(tf.content, { noEscape: true });
|
|
85
|
+
content = template(hbsContext);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
content = tf.content;
|
|
89
|
+
}
|
|
90
|
+
if (!options.dryRun) {
|
|
91
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
92
|
+
await writeFile(targetPath, content);
|
|
93
|
+
}
|
|
94
|
+
created.push(tf.path);
|
|
95
|
+
if (basename(tf.path) === "task.yaml") {
|
|
96
|
+
try {
|
|
97
|
+
manifest = parseTaskYaml(content);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// ignora erro de parse
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!options.dryRun && spec.skills.length > 0) {
|
|
105
|
+
await copyBuiltinSkills(targetDir, spec.skills);
|
|
106
|
+
}
|
|
107
|
+
return { files: created, manifest };
|
|
108
|
+
}
|
|
109
|
+
function parseTaskYaml(content) {
|
|
110
|
+
const result = {};
|
|
111
|
+
const lines = content.split("\n");
|
|
112
|
+
let currentKey = null;
|
|
113
|
+
let currentArray = null;
|
|
114
|
+
for (const line of lines) {
|
|
115
|
+
const trimmed = line.trim();
|
|
116
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
117
|
+
continue;
|
|
118
|
+
const kvMatch = line.match(/^(\S+):\s*(.*)$/);
|
|
119
|
+
if (kvMatch) {
|
|
120
|
+
const key = kvMatch[1];
|
|
121
|
+
const value = kvMatch[2];
|
|
122
|
+
if (key) {
|
|
123
|
+
if (value && (value.startsWith("|") || value.startsWith(">"))) {
|
|
124
|
+
currentKey = key;
|
|
125
|
+
currentArray = [];
|
|
126
|
+
result[key] = "";
|
|
127
|
+
}
|
|
128
|
+
else if (value) {
|
|
129
|
+
result[key] = value.replace(/^["']|["']$/g, "");
|
|
130
|
+
currentKey = null;
|
|
131
|
+
currentArray = null;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
currentKey = key;
|
|
135
|
+
currentArray = [];
|
|
136
|
+
result[key] = currentArray;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const arrMatch = line.match(/^\s*-\s*(.+)$/);
|
|
142
|
+
if (arrMatch && currentKey && currentArray !== null && arrMatch[1]) {
|
|
143
|
+
currentArray.push(arrMatch[1].replace(/^["']|["']$/g, ""));
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (currentKey && currentArray === null && line.match(/^\s+/)) {
|
|
147
|
+
const existing = result[currentKey];
|
|
148
|
+
result[currentKey] = (typeof existing === "string" ? existing + "\n" : "") + line.trimStart();
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
currentKey = null;
|
|
152
|
+
currentArray = null;
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
async function copyBuiltinSkills(targetDir, skillNames) {
|
|
157
|
+
const skillsSrc = join(resolve(import.meta.dirname), "../templates/skills");
|
|
158
|
+
const skillsDest = join(targetDir, "skills");
|
|
159
|
+
for (const skill of skillNames) {
|
|
160
|
+
const src = join(skillsSrc, skill, "SKILL.md");
|
|
161
|
+
const dest = join(skillsDest, skill, "SKILL.md");
|
|
162
|
+
try {
|
|
163
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
164
|
+
await cp(src, dest);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// skill não existe — ignora
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export function validateVariables(spec, provided) {
|
|
172
|
+
const required = spec.variables.filter(v => v.required).map(v => v.key);
|
|
173
|
+
const providedKeys = Object.keys(provided);
|
|
174
|
+
const missing = required.filter(k => !providedKeys.includes(k));
|
|
175
|
+
const extra = providedKeys.filter(k => !spec.variables.some(v => v.key === k));
|
|
176
|
+
return { valid: missing.length === 0, missing, extra };
|
|
177
|
+
}
|
|
178
|
+
export async function promptVariables(spec, provided = {}) {
|
|
179
|
+
const result = { ...provided };
|
|
180
|
+
for (const v of spec.variables) {
|
|
181
|
+
if (!(v.key in result) && v.default !== undefined) {
|
|
182
|
+
result[v.key] = v.default;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=template-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-engine.js","sourceRoot":"","sources":["../src/template-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface TemplateVariable {
|
|
2
|
+
key: string;
|
|
3
|
+
label: string;
|
|
4
|
+
type: "string" | "select" | "boolean";
|
|
5
|
+
required: boolean;
|
|
6
|
+
default?: string;
|
|
7
|
+
options?: string[];
|
|
8
|
+
description?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TemplateSpec {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
category: "general" | "coding" | "ops" | "research" | "harness" | "custom";
|
|
15
|
+
entry: string;
|
|
16
|
+
defaultModel: string;
|
|
17
|
+
defaultMode: "build" | "research" | "test" | "review" | "deploy" | "harness";
|
|
18
|
+
skills: string[];
|
|
19
|
+
verifyGates: {
|
|
20
|
+
name: string;
|
|
21
|
+
cmd: string;
|
|
22
|
+
}[];
|
|
23
|
+
hasGenesis: boolean;
|
|
24
|
+
genesisPrompt?: string;
|
|
25
|
+
variables: TemplateVariable[];
|
|
26
|
+
source: "builtin" | "custom";
|
|
27
|
+
templateDir: string;
|
|
28
|
+
}
|
|
29
|
+
export interface TemplateRegistry {
|
|
30
|
+
list(): Promise<TemplateSpec[]>;
|
|
31
|
+
get(id: string): Promise<TemplateSpec | undefined>;
|
|
32
|
+
getByCategory(category: TemplateSpec["category"]): Promise<TemplateSpec[]>;
|
|
33
|
+
reload(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export declare function createTemplateRegistry(): Promise<TemplateRegistry>;
|
|
36
|
+
export declare function getTemplateRegistry(): Promise<TemplateRegistry>;
|
|
@@ -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
|