neuron-inspector 0.1.2 → 0.2.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 CHANGED
@@ -220,6 +220,36 @@ The agent calls `neuron_perf_snapshot` and gets back Core Web Vitals, render-blo
220
220
 
221
221
  ---
222
222
 
223
+ ## Recipes — purpose-built agents
224
+
225
+ The 51 tools are primitives. A **recipe** turns them into a purpose-built agent — a QA engineer, a job applicant, a web researcher. Recipes are shareable, and they get better with every run.
226
+
227
+ ### Built-in recipes
228
+
229
+ | Recipe | What it does |
230
+ |--------|-------------|
231
+ | **[Web Researcher](recipes/web-researcher/)** | Deep-dives into topics, cross-references sources, produces reports with citations |
232
+ | **[Job Applicant](recipes/job-applicant/)** | Searches job boards, evaluates fit, writes cover letters, fills forms, tracks outcomes |
233
+ | **[QA Engineer](recipes/qa-engineer/)** | Tests web apps — finds bugs, checks a11y, audits security, builds regression suites |
234
+
235
+ ### How recipes work
236
+
237
+ A recipe is a folder with instructions (`agent.md`) and config (`recipe.yaml`). The instructions tell the AI *how* to use the browser tools for a specific purpose. The config declares variables you fill in (your resume, your target URL, your preferences).
238
+
239
+ **Recipes are alive.** Each run captures outcomes to `memory/`. After enough runs, the agent reviews what worked and updates its own strategy in `learnings.md`. A job applicant that discovers technical-tone cover letters get 3x more responses will start writing technical-tone cover letters by default.
240
+
241
+ **Recipes feed each other.** The web researcher produces reports that the job applicant reads to tailor cover letters. The QA engineer reads its own previous reports to re-check if old bugs are fixed. Output from one recipe is input to another.
242
+
243
+ ### Use a recipe
244
+
245
+ Copy a recipe's `agent.md` into your project as a CLAUDE.md (or append it), fill in the `{{variables}}` from `recipe.yaml`, and run. The recipe tells your AI agent exactly how to use the 51 tools for that purpose.
246
+
247
+ ### Build your own
248
+
249
+ See [RECIPE-SPEC.md](RECIPE-SPEC.md) for the full format. The core idea: write the instructions you'd give a skilled human, reference the tools by name, add reflect/evolve sections so the agent improves itself, and declare your variables so others can import and customize.
250
+
251
+ ---
252
+
223
253
  ## Requirements
224
254
 
225
255
  - Node.js 18+
@@ -230,6 +260,7 @@ The agent calls `neuron_perf_snapshot` and gets back Core Web Vitals, render-blo
230
260
 
231
261
  - **Extension download:** [neuron.ng/extension](https://neuron.ng/extension)
232
262
  - **npm:** [npmjs.com/package/neuron-inspector](https://www.npmjs.com/package/neuron-inspector)
263
+ - **Recipe spec:** [RECIPE-SPEC.md](RECIPE-SPEC.md)
233
264
 
234
265
  ## License
235
266
 
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Recipe MCP tools — same ToolDef shape as browser tools so they register
3
+ * through the same mcp.tool() overload. Handled locally (no extension needed).
4
+ */
5
+ import type { ToolDef } from "./tools.js";
6
+ export declare const RECIPE_TOOLS: ToolDef[];
7
+ /** Handle a recipe tool call locally (no extension needed). */
8
+ export declare function handleRecipeTool(name: string, args: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Recipe MCP tools — same ToolDef shape as browser tools so they register
3
+ * through the same mcp.tool() overload. Handled locally (no extension needed).
4
+ */
5
+ import * as recipes from "./recipes.js";
6
+ export const RECIPE_TOOLS = [
7
+ {
8
+ name: "neuron_recipe_list",
9
+ description: "List all available recipes (bundled + user-installed). Shows name, description, whether it has accumulated learnings, and run count.",
10
+ inputSchema: { type: "object", properties: {} },
11
+ },
12
+ {
13
+ name: "neuron_recipe_get",
14
+ description: "Get a recipe's full contents — agent instructions (agent.md), configuration (recipe.yaml), accumulated learnings, and variable definitions. Use this to understand what a recipe does before running it.",
15
+ inputSchema: {
16
+ type: "object",
17
+ properties: {
18
+ slug: { type: "string", description: "Recipe slug (e.g. 'web-researcher', 'qa-engineer')" },
19
+ },
20
+ required: ["slug"],
21
+ },
22
+ },
23
+ {
24
+ name: "neuron_recipe_create",
25
+ description: "Create a new recipe from scratch. Provide the slug, name, description, agent instructions (agent.md content with Strategy/Reflect/Evolve sections), and configuration (recipe.yaml content with variables/tools/pipes/limits). Saved to ~/.neuron/recipes/<slug>/.",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ slug: { type: "string", description: "URL-safe identifier (e.g. 'grant-scraper')" },
30
+ name: { type: "string", description: "Display name" },
31
+ description: { type: "string", description: "One-line description" },
32
+ agent_md: { type: "string", description: "Full agent.md content — strategy, reflect, evolve sections" },
33
+ recipe_yaml: { type: "string", description: "Full recipe.yaml content — variables, tools, pipes, limits" },
34
+ },
35
+ required: ["slug", "name", "description", "agent_md", "recipe_yaml"],
36
+ },
37
+ },
38
+ {
39
+ name: "neuron_recipe_update",
40
+ description: "Update a recipe's agent instructions, learnings, or configuration. If updating a bundled recipe, it's forked to ~/.neuron/recipes/ first. Use this after the evolve phase to persist improved strategy.",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {
44
+ slug: { type: "string", description: "Recipe slug" },
45
+ agent_md: { type: "string", description: "Updated agent.md content" },
46
+ learnings: { type: "string", description: "Updated learnings.md content" },
47
+ recipe_yaml: { type: "string", description: "Updated recipe.yaml content" },
48
+ },
49
+ required: ["slug"],
50
+ },
51
+ },
52
+ {
53
+ name: "neuron_recipe_log",
54
+ description: "Log a run outcome to a recipe's memory. Each entry captures what happened — success/failure, sources found, dead ends, quality score. The recipe's evolve phase reads these to improve its strategy.",
55
+ inputSchema: {
56
+ type: "object",
57
+ properties: {
58
+ slug: { type: "string", description: "Recipe slug" },
59
+ entry: { type: "object", description: "Run outcome data — structure varies per recipe, see the Reflect section in agent.md" },
60
+ },
61
+ required: ["slug", "entry"],
62
+ },
63
+ },
64
+ {
65
+ name: "neuron_recipe_memory",
66
+ description: "Read a recipe's run history — the outcomes captured by neuron_recipe_log. Returns the most recent entries. Use during the evolve phase to analyze what's working and what's not.",
67
+ inputSchema: {
68
+ type: "object",
69
+ properties: {
70
+ slug: { type: "string", description: "Recipe slug" },
71
+ limit: { type: "number", description: "Max entries to return (default: 20)" },
72
+ },
73
+ required: ["slug"],
74
+ },
75
+ },
76
+ {
77
+ name: "neuron_recipe_import",
78
+ description: "Import a recipe from GitHub or a local path. GitHub: 'github:user/repo' imports all recipes from the repo's recipes/ subdir. Local: absolute path to a folder with recipe.yaml. Saved to ~/.neuron/recipes/. Memory is stripped on import (local-only).",
79
+ inputSchema: {
80
+ type: "object",
81
+ properties: {
82
+ source: { type: "string", description: "GitHub repo (github:user/repo) or absolute local path to recipe folder" },
83
+ },
84
+ required: ["source"],
85
+ },
86
+ },
87
+ {
88
+ name: "neuron_recipe_export",
89
+ description: "Export a recipe's shareable contents — agent.md, recipe.yaml, and optionally learnings. The recipient imports this with neuron_recipe_import. Memory (run history) is never exported.",
90
+ inputSchema: {
91
+ type: "object",
92
+ properties: {
93
+ slug: { type: "string", description: "Recipe slug" },
94
+ include_learnings: { type: "boolean", description: "Include accumulated learnings (default: true)" },
95
+ },
96
+ required: ["slug"],
97
+ },
98
+ },
99
+ {
100
+ name: "neuron_recipe_delete",
101
+ description: "Delete a user-installed recipe and all its memory/learnings. Bundled recipes cannot be deleted.",
102
+ inputSchema: {
103
+ type: "object",
104
+ properties: {
105
+ slug: { type: "string", description: "Recipe slug to delete" },
106
+ },
107
+ required: ["slug"],
108
+ },
109
+ },
110
+ {
111
+ name: "neuron_profile_get",
112
+ description: "Read the user's profile (~/.neuron/profile.yaml). Profiles auto-fill recipe variables — name, email, location, tone, timezone, etc.",
113
+ inputSchema: { type: "object", properties: {} },
114
+ },
115
+ {
116
+ name: "neuron_profile_save",
117
+ description: "Save or update the user's profile (~/.neuron/profile.yaml). Common fields: name, email, location, timezone, tone, linkedin, github. Recipe variables with matching keys are auto-filled from this profile.",
118
+ inputSchema: {
119
+ type: "object",
120
+ properties: {
121
+ data: { type: "object", description: "Profile key-value pairs (e.g. {name: 'Jane', email: 'jane@co.com', timezone: 'US/Eastern'})" },
122
+ },
123
+ required: ["data"],
124
+ },
125
+ },
126
+ ];
127
+ /** Handle a recipe tool call locally (no extension needed). */
128
+ export async function handleRecipeTool(name, args) {
129
+ switch (name) {
130
+ case "neuron_recipe_list":
131
+ return recipes.listRecipes();
132
+ case "neuron_recipe_get": {
133
+ const result = recipes.getRecipe(args.slug);
134
+ if (!result)
135
+ throw new Error(`Recipe "${args.slug}" not found.`);
136
+ return result;
137
+ }
138
+ case "neuron_recipe_create":
139
+ return recipes.createRecipe(args.slug, args.name, args.description, args.agent_md, args.recipe_yaml);
140
+ case "neuron_recipe_update":
141
+ return recipes.updateRecipe(args.slug, {
142
+ agent_md: args.agent_md,
143
+ learnings: args.learnings,
144
+ recipe_yaml: args.recipe_yaml,
145
+ });
146
+ case "neuron_recipe_log":
147
+ return recipes.logMemory(args.slug, args.entry);
148
+ case "neuron_recipe_memory":
149
+ return recipes.getMemory(args.slug, args.limit || 20);
150
+ case "neuron_recipe_import":
151
+ return recipes.importRecipe(args.source);
152
+ case "neuron_recipe_export":
153
+ return recipes.exportRecipe(args.slug, args.include_learnings ?? true);
154
+ case "neuron_recipe_delete":
155
+ recipes.deleteRecipe(args.slug);
156
+ return { deleted: args.slug };
157
+ case "neuron_profile_get": {
158
+ const profile = recipes.getProfile();
159
+ if (!profile)
160
+ return { message: "No profile found. Create one with neuron_profile_save." };
161
+ return profile;
162
+ }
163
+ case "neuron_profile_save":
164
+ return recipes.saveProfile(args.data);
165
+ default:
166
+ throw new Error(`Unknown recipe tool: ${name}`);
167
+ }
168
+ }
169
+ //# sourceMappingURL=recipe-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe-tools.js","sourceRoot":"","sources":["../src/recipe-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Recipe manager — list, read, create, import, export, and log memory
3
+ * for self-improving agent recipes. All file operations are local.
4
+ */
5
+ interface RecipeSummary {
6
+ name: string;
7
+ slug: string;
8
+ version: string;
9
+ description: string;
10
+ author: string;
11
+ tags: string[];
12
+ location: "bundled" | "user";
13
+ path: string;
14
+ has_learnings: boolean;
15
+ has_memory: boolean;
16
+ memory_count: number;
17
+ }
18
+ export declare function listRecipes(): RecipeSummary[];
19
+ export declare function getRecipe(slug: string): {
20
+ meta: RecipeSummary;
21
+ agent_md: string;
22
+ recipe_yaml: string;
23
+ learnings: string | null;
24
+ variables: Record<string, unknown>;
25
+ } | null;
26
+ export declare function createRecipe(slug: string, name: string, description: string, agentMd: string, recipeYaml: string): {
27
+ path: string;
28
+ };
29
+ export declare function updateRecipe(slug: string, updates: {
30
+ agent_md?: string;
31
+ learnings?: string;
32
+ recipe_yaml?: string;
33
+ }): {
34
+ path: string;
35
+ };
36
+ export declare function logMemory(slug: string, entry: Record<string, unknown>): {
37
+ path: string;
38
+ };
39
+ export declare function getMemory(slug: string, limit?: number): {
40
+ entries: Record<string, unknown>[];
41
+ total: number;
42
+ };
43
+ export declare function importRecipe(source: string): {
44
+ slug: string;
45
+ path: string;
46
+ };
47
+ export declare function exportRecipe(slug: string, includeLearnings?: boolean): {
48
+ agent_md: string;
49
+ recipe_yaml: string;
50
+ learnings: string | null;
51
+ };
52
+ export declare function deleteRecipe(slug: string): void;
53
+ export declare function getProfile(): Record<string, unknown> | null;
54
+ export declare function saveProfile(data: Record<string, string>): {
55
+ path: string;
56
+ };
57
+ export {};
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Recipe manager — list, read, create, import, export, and log memory
3
+ * for self-improving agent recipes. All file operations are local.
4
+ */
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import * as os from "node:os";
8
+ import { execSync } from "node:child_process";
9
+ // ── Paths ───────────────────────────────────────────────────
10
+ /** Bundled recipes shipped with the package */
11
+ function bundledRecipesDir() {
12
+ // recipes/ sits next to src/ in the package root
13
+ const srcDir = path.dirname(new URL(import.meta.url).pathname);
14
+ return path.join(srcDir, "..", "recipes");
15
+ }
16
+ /** User's local recipe store */
17
+ function userRecipesDir() {
18
+ const dir = path.join(os.homedir(), ".neuron", "recipes");
19
+ if (!fs.existsSync(dir))
20
+ fs.mkdirSync(dir, { recursive: true });
21
+ return dir;
22
+ }
23
+ /** User profile path */
24
+ function profilePath() {
25
+ return path.join(os.homedir(), ".neuron", "profile.yaml");
26
+ }
27
+ // ── Helpers ─────────────────────────────────────────────────
28
+ function readText(filePath) {
29
+ try {
30
+ return fs.readFileSync(filePath, "utf8");
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ function readYamlish(text) {
37
+ // Minimal YAML-like parser for recipe.yaml — handles flat and simple nested keys.
38
+ // Not a full YAML parser; good enough for structured recipe metadata.
39
+ const result = {};
40
+ for (const line of text.split("\n")) {
41
+ const match = line.match(/^(\w[\w_-]*):\s*(.+)$/);
42
+ if (match) {
43
+ const val = match[2].trim();
44
+ if (val === "true")
45
+ result[match[1]] = true;
46
+ else if (val === "false")
47
+ result[match[1]] = false;
48
+ else if (/^\d+$/.test(val))
49
+ result[match[1]] = parseInt(val, 10);
50
+ else
51
+ result[match[1]] = val.replace(/^["']|["']$/g, "");
52
+ }
53
+ }
54
+ return result;
55
+ }
56
+ function parseRecipe(dir, location) {
57
+ const yamlPath = path.join(dir, "recipe.yaml");
58
+ const yamlText = readText(yamlPath);
59
+ if (!yamlText)
60
+ return null;
61
+ const meta = readYamlish(yamlText);
62
+ // Parse tags from YAML list format
63
+ const tagsMatch = yamlText.match(/^tags:\s*\[([^\]]*)\]/m);
64
+ const tags = tagsMatch
65
+ ? tagsMatch[1].split(",").map((t) => t.trim().replace(/^["']|["']$/g, "")).filter(Boolean)
66
+ : [];
67
+ const memoryDir = path.join(dir, "memory");
68
+ const memoryFiles = fs.existsSync(memoryDir)
69
+ ? fs.readdirSync(memoryDir).filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"))
70
+ : [];
71
+ const learningsPath = path.join(dir, "learnings.md");
72
+ return {
73
+ name: String(meta.name || path.basename(dir)),
74
+ slug: path.basename(dir),
75
+ version: String(meta.version || "0.0.0"),
76
+ description: String(meta.description || ""),
77
+ author: String(meta.author || "unknown"),
78
+ tags,
79
+ location,
80
+ path: dir,
81
+ has_learnings: fs.existsSync(learningsPath) && (readText(learningsPath) ?? "").length > 100,
82
+ has_memory: memoryFiles.length > 0,
83
+ memory_count: memoryFiles.length,
84
+ };
85
+ }
86
+ // ── Public API (called by MCP tool handlers) ────────────────
87
+ export function listRecipes() {
88
+ const recipes = [];
89
+ // Bundled
90
+ const bundled = bundledRecipesDir();
91
+ if (fs.existsSync(bundled)) {
92
+ for (const entry of fs.readdirSync(bundled, { withFileTypes: true })) {
93
+ if (!entry.isDirectory())
94
+ continue;
95
+ const r = parseRecipe(path.join(bundled, entry.name), "bundled");
96
+ if (r)
97
+ recipes.push(r);
98
+ }
99
+ }
100
+ // User
101
+ const user = userRecipesDir();
102
+ for (const entry of fs.readdirSync(user, { withFileTypes: true })) {
103
+ if (!entry.isDirectory())
104
+ continue;
105
+ const r = parseRecipe(path.join(user, entry.name), "user");
106
+ if (r)
107
+ recipes.push(r);
108
+ }
109
+ return recipes;
110
+ }
111
+ export function getRecipe(slug) {
112
+ // Check user dir first (overrides bundled)
113
+ const userDir = path.join(userRecipesDir(), slug);
114
+ const bundledDir = path.join(bundledRecipesDir(), slug);
115
+ const dir = fs.existsSync(userDir) ? userDir : fs.existsSync(bundledDir) ? bundledDir : null;
116
+ if (!dir)
117
+ return null;
118
+ const location = dir === userDir ? "user" : "bundled";
119
+ const meta = parseRecipe(dir, location);
120
+ if (!meta)
121
+ return null;
122
+ const agentMd = readText(path.join(dir, "agent.md")) ?? "";
123
+ const recipeYaml = readText(path.join(dir, "recipe.yaml")) ?? "";
124
+ const learnings = readText(path.join(dir, "learnings.md"));
125
+ // Parse variables from recipe.yaml (simplified)
126
+ const variables = {};
127
+ const varSection = recipeYaml.match(/^variables:\n((?:[\s].*\n)*)/m);
128
+ if (varSection) {
129
+ const varLines = varSection[1].split("\n");
130
+ let currentVar = "";
131
+ for (const line of varLines) {
132
+ const nameMatch = line.match(/^\s{2}(\w[\w_-]*):/);
133
+ if (nameMatch) {
134
+ currentVar = nameMatch[1];
135
+ variables[currentVar] = {};
136
+ }
137
+ else if (currentVar) {
138
+ const propMatch = line.match(/^\s{4}(\w+):\s*(.+)/);
139
+ if (propMatch) {
140
+ variables[currentVar][propMatch[1]] = propMatch[2].trim().replace(/^["']|["']$/g, "");
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return { meta, agent_md: agentMd, recipe_yaml: recipeYaml, learnings, variables };
146
+ }
147
+ export function createRecipe(slug, name, description, agentMd, recipeYaml) {
148
+ const dir = path.join(userRecipesDir(), slug);
149
+ if (fs.existsSync(dir)) {
150
+ throw new Error(`Recipe "${slug}" already exists at ${dir}. Use a different slug or delete the existing one.`);
151
+ }
152
+ fs.mkdirSync(dir, { recursive: true });
153
+ fs.writeFileSync(path.join(dir, "agent.md"), agentMd);
154
+ fs.writeFileSync(path.join(dir, "recipe.yaml"), recipeYaml);
155
+ fs.writeFileSync(path.join(dir, "learnings.md"), `# Learnings\n\nNo runs yet.\n`);
156
+ return { path: dir };
157
+ }
158
+ export function updateRecipe(slug, updates) {
159
+ const userDir = path.join(userRecipesDir(), slug);
160
+ const bundledDir = path.join(bundledRecipesDir(), slug);
161
+ let dir;
162
+ if (fs.existsSync(userDir)) {
163
+ dir = userDir;
164
+ }
165
+ else if (fs.existsSync(bundledDir)) {
166
+ // Fork bundled recipe to user dir before editing
167
+ fs.cpSync(bundledDir, userDir, { recursive: true });
168
+ dir = userDir;
169
+ }
170
+ else {
171
+ throw new Error(`Recipe "${slug}" not found.`);
172
+ }
173
+ if (updates.agent_md)
174
+ fs.writeFileSync(path.join(dir, "agent.md"), updates.agent_md);
175
+ if (updates.learnings)
176
+ fs.writeFileSync(path.join(dir, "learnings.md"), updates.learnings);
177
+ if (updates.recipe_yaml)
178
+ fs.writeFileSync(path.join(dir, "recipe.yaml"), updates.recipe_yaml);
179
+ return { path: dir };
180
+ }
181
+ export function logMemory(slug, entry) {
182
+ const userDir = path.join(userRecipesDir(), slug);
183
+ const bundledDir = path.join(bundledRecipesDir(), slug);
184
+ // Memory always goes to user dir
185
+ let dir;
186
+ if (fs.existsSync(userDir)) {
187
+ dir = userDir;
188
+ }
189
+ else if (fs.existsSync(bundledDir)) {
190
+ // Fork to user dir
191
+ fs.cpSync(bundledDir, userDir, { recursive: true });
192
+ dir = userDir;
193
+ }
194
+ else {
195
+ throw new Error(`Recipe "${slug}" not found.`);
196
+ }
197
+ const memDir = path.join(dir, "memory");
198
+ if (!fs.existsSync(memDir))
199
+ fs.mkdirSync(memDir, { recursive: true });
200
+ const now = new Date();
201
+ const ts = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
202
+ const count = fs.readdirSync(memDir).length + 1;
203
+ const filename = `${ts}-run-${String(count).padStart(3, "0")}.yaml`;
204
+ const filepath = path.join(memDir, filename);
205
+ // Simple YAML-like serialization
206
+ const lines = [`date: ${now.toISOString()}`];
207
+ for (const [key, value] of Object.entries(entry)) {
208
+ if (key === "date")
209
+ continue;
210
+ if (typeof value === "object" && value !== null) {
211
+ lines.push(`${key}:`);
212
+ for (const [k2, v2] of Object.entries(value)) {
213
+ lines.push(` ${k2}: ${JSON.stringify(v2)}`);
214
+ }
215
+ }
216
+ else {
217
+ lines.push(`${key}: ${JSON.stringify(value)}`);
218
+ }
219
+ }
220
+ fs.writeFileSync(filepath, lines.join("\n") + "\n");
221
+ return { path: filepath };
222
+ }
223
+ export function getMemory(slug, limit = 20) {
224
+ const userDir = path.join(userRecipesDir(), slug);
225
+ const bundledDir = path.join(bundledRecipesDir(), slug);
226
+ const dir = fs.existsSync(userDir) ? userDir : fs.existsSync(bundledDir) ? bundledDir : null;
227
+ if (!dir)
228
+ throw new Error(`Recipe "${slug}" not found.`);
229
+ const memDir = path.join(dir, "memory");
230
+ if (!fs.existsSync(memDir))
231
+ return { entries: [], total: 0 };
232
+ const files = fs.readdirSync(memDir)
233
+ .filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"))
234
+ .sort()
235
+ .reverse();
236
+ const entries = [];
237
+ for (const f of files.slice(0, limit)) {
238
+ const text = readText(path.join(memDir, f));
239
+ if (text) {
240
+ entries.push({ _file: f, ...readYamlish(text) });
241
+ }
242
+ }
243
+ return { entries, total: files.length };
244
+ }
245
+ export function importRecipe(source) {
246
+ let srcDir;
247
+ if (source.startsWith("github:")) {
248
+ // github:user/repo or github:user/repo/path
249
+ const parts = source.slice(7).split("/");
250
+ const repo = `${parts[0]}/${parts[1]}`;
251
+ const subpath = parts.slice(2).join("/");
252
+ const tmpDir = path.join(os.tmpdir(), `neuron-recipe-${Date.now()}`);
253
+ try {
254
+ execSync(`git clone --depth 1 https://github.com/${repo}.git "${tmpDir}"`, { stdio: "pipe" });
255
+ }
256
+ catch {
257
+ throw new Error(`Failed to clone https://github.com/${repo}`);
258
+ }
259
+ srcDir = subpath ? path.join(tmpDir, subpath) : tmpDir;
260
+ // If the cloned repo IS a recipe (has recipe.yaml at root), use it directly
261
+ if (!fs.existsSync(path.join(srcDir, "recipe.yaml"))) {
262
+ // Check if it's a repo with recipes/ subdir
263
+ const recipesSubdir = path.join(srcDir, "recipes");
264
+ if (fs.existsSync(recipesSubdir)) {
265
+ // Import all recipes from the repo
266
+ const imported = [];
267
+ for (const entry of fs.readdirSync(recipesSubdir, { withFileTypes: true })) {
268
+ if (!entry.isDirectory())
269
+ continue;
270
+ if (!fs.existsSync(path.join(recipesSubdir, entry.name, "recipe.yaml")))
271
+ continue;
272
+ const destDir = path.join(userRecipesDir(), entry.name);
273
+ if (fs.existsSync(destDir))
274
+ continue; // skip existing
275
+ fs.cpSync(path.join(recipesSubdir, entry.name), destDir, { recursive: true });
276
+ imported.push(entry.name);
277
+ }
278
+ // Clean up
279
+ fs.rmSync(tmpDir, { recursive: true, force: true });
280
+ if (imported.length === 0)
281
+ throw new Error("No recipes found in repository");
282
+ return { slug: imported.join(", "), path: userRecipesDir() };
283
+ }
284
+ throw new Error("No recipe.yaml found in repository root or recipes/ subdirectory");
285
+ }
286
+ }
287
+ else {
288
+ // Local path
289
+ srcDir = path.resolve(source);
290
+ }
291
+ if (!fs.existsSync(path.join(srcDir, "recipe.yaml"))) {
292
+ throw new Error(`No recipe.yaml found at ${srcDir}`);
293
+ }
294
+ const yamlText = readText(path.join(srcDir, "recipe.yaml"));
295
+ const meta = yamlText ? readYamlish(yamlText) : {};
296
+ const slug = String(meta.name || path.basename(srcDir)).toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
297
+ const destDir = path.join(userRecipesDir(), slug);
298
+ if (fs.existsSync(destDir)) {
299
+ throw new Error(`Recipe "${slug}" already exists. Delete it first or use a different name.`);
300
+ }
301
+ fs.cpSync(srcDir, destDir, { recursive: true });
302
+ // Remove memory from imported recipe (local-only)
303
+ const importedMemory = path.join(destDir, "memory");
304
+ if (fs.existsSync(importedMemory)) {
305
+ fs.rmSync(importedMemory, { recursive: true, force: true });
306
+ }
307
+ return { slug, path: destDir };
308
+ }
309
+ export function exportRecipe(slug, includeLearnings = true) {
310
+ const recipe = getRecipe(slug);
311
+ if (!recipe)
312
+ throw new Error(`Recipe "${slug}" not found.`);
313
+ return {
314
+ agent_md: recipe.agent_md,
315
+ recipe_yaml: recipe.recipe_yaml,
316
+ learnings: includeLearnings ? recipe.learnings : null,
317
+ };
318
+ }
319
+ export function deleteRecipe(slug) {
320
+ const dir = path.join(userRecipesDir(), slug);
321
+ if (!fs.existsSync(dir)) {
322
+ throw new Error(`Recipe "${slug}" not found in user recipes. Bundled recipes can't be deleted.`);
323
+ }
324
+ fs.rmSync(dir, { recursive: true, force: true });
325
+ }
326
+ export function getProfile() {
327
+ const text = readText(profilePath());
328
+ if (!text)
329
+ return null;
330
+ return readYamlish(text);
331
+ }
332
+ export function saveProfile(data) {
333
+ const dir = path.dirname(profilePath());
334
+ if (!fs.existsSync(dir))
335
+ fs.mkdirSync(dir, { recursive: true });
336
+ const lines = Object.entries(data).map(([k, v]) => `${k}: "${v}"`);
337
+ fs.writeFileSync(profilePath(), lines.join("\n") + "\n");
338
+ return { path: profilePath() };
339
+ }
340
+ //# sourceMappingURL=recipes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipes.js","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}