@molecule/api-ai-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Pure tool schema definitions — name, description, and JSON Schema parameters.
3
+ * No execution logic, no imports beyond types.
4
+ *
5
+ * @module
6
+ */
7
+ /**
8
+ * Canonical tool schemas shared by the agent runtime and documentation.
9
+ */
10
+ export const TOOL_SCHEMAS = {
11
+ list_files: {
12
+ name: 'list_files',
13
+ description: 'List files and directories at a given path. Returns entry names with type indicators.',
14
+ parameters: {
15
+ type: 'object',
16
+ properties: {
17
+ path: {
18
+ type: 'string',
19
+ description: "Directory path to list. Omit or use '/' for project root. Supports relative or absolute paths.",
20
+ },
21
+ },
22
+ required: [],
23
+ },
24
+ },
25
+ read_file: {
26
+ name: 'read_file',
27
+ description: 'Read the full content of a file as text. Always read a file before editing it.',
28
+ parameters: {
29
+ type: 'object',
30
+ properties: {
31
+ path: {
32
+ type: 'string',
33
+ description: 'Path to the file to read (relative or absolute).',
34
+ },
35
+ },
36
+ required: ['path'],
37
+ },
38
+ },
39
+ write_file: {
40
+ name: 'write_file',
41
+ description: 'Create or overwrite a file with full content. Use edit_file for small targeted changes instead.',
42
+ parameters: {
43
+ type: 'object',
44
+ properties: {
45
+ path: {
46
+ type: 'string',
47
+ description: 'Path to the file to write.',
48
+ },
49
+ content: {
50
+ type: 'string',
51
+ description: 'Full file content to write.',
52
+ },
53
+ },
54
+ required: ['path', 'content'],
55
+ },
56
+ },
57
+ edit_file: {
58
+ name: 'edit_file',
59
+ description: 'Make targeted search-and-replace edits to a file. Preferred over write_file for small changes. Each old_string must match exactly once in the file.',
60
+ parameters: {
61
+ type: 'object',
62
+ properties: {
63
+ path: {
64
+ type: 'string',
65
+ description: 'Path to the file to edit.',
66
+ },
67
+ replacements: {
68
+ type: 'array',
69
+ description: 'List of search-and-replace operations to apply sequentially.',
70
+ items: {
71
+ type: 'object',
72
+ properties: {
73
+ old_string: {
74
+ type: 'string',
75
+ description: 'Exact string to find. Must match exactly once in the file.',
76
+ },
77
+ new_string: {
78
+ type: 'string',
79
+ description: 'Replacement string.',
80
+ },
81
+ },
82
+ required: ['old_string', 'new_string'],
83
+ },
84
+ },
85
+ },
86
+ required: ['path', 'replacements'],
87
+ },
88
+ },
89
+ search_files: {
90
+ name: 'search_files',
91
+ description: 'Search for a text pattern across files using grep. Returns matching lines with file paths and line numbers.',
92
+ parameters: {
93
+ type: 'object',
94
+ properties: {
95
+ pattern: {
96
+ type: 'string',
97
+ description: 'Text or regex pattern to search for.',
98
+ },
99
+ path: {
100
+ type: 'string',
101
+ description: 'Directory to search in. Defaults to project root.',
102
+ },
103
+ include: {
104
+ type: 'string',
105
+ description: "File glob pattern to filter files (e.g. '*.ts', '*.tsx'). Optional.",
106
+ },
107
+ },
108
+ required: ['pattern'],
109
+ },
110
+ },
111
+ find_files: {
112
+ name: 'find_files',
113
+ description: "Find files by name or glob pattern recursively. Excludes node_modules and .git. Use for discovering files by name (e.g. '*.tsx', 'Dashboard*', 'index.*').",
114
+ parameters: {
115
+ type: 'object',
116
+ properties: {
117
+ pattern: {
118
+ type: 'string',
119
+ description: "File name or glob pattern (e.g. '*.tsx', 'Dashboard*').",
120
+ },
121
+ path: {
122
+ type: 'string',
123
+ description: 'Directory to search in. Defaults to project root.',
124
+ },
125
+ },
126
+ required: ['pattern'],
127
+ },
128
+ },
129
+ create_directory: {
130
+ name: 'create_directory',
131
+ description: 'Create a directory and any necessary parent directories.',
132
+ parameters: {
133
+ type: 'object',
134
+ properties: {
135
+ path: {
136
+ type: 'string',
137
+ description: 'Directory path to create.',
138
+ },
139
+ },
140
+ required: ['path'],
141
+ },
142
+ },
143
+ rename_file: {
144
+ name: 'rename_file',
145
+ description: 'Rename or move a file or directory.',
146
+ parameters: {
147
+ type: 'object',
148
+ properties: {
149
+ old_path: {
150
+ type: 'string',
151
+ description: 'Current path of the file or directory.',
152
+ },
153
+ new_path: {
154
+ type: 'string',
155
+ description: 'New path for the file or directory.',
156
+ },
157
+ },
158
+ required: ['old_path', 'new_path'],
159
+ },
160
+ },
161
+ delete_file: {
162
+ name: 'delete_file',
163
+ description: 'Delete a file.',
164
+ parameters: {
165
+ type: 'object',
166
+ properties: {
167
+ path: {
168
+ type: 'string',
169
+ description: 'Path to the file to delete.',
170
+ },
171
+ },
172
+ required: ['path'],
173
+ },
174
+ },
175
+ exec_command: {
176
+ name: 'exec_command',
177
+ description: 'Run a shell command and return its output. Use for build checks, npm commands, verification, etc.',
178
+ parameters: {
179
+ type: 'object',
180
+ properties: {
181
+ command: {
182
+ type: 'string',
183
+ description: 'Shell command to execute.',
184
+ },
185
+ cwd: {
186
+ type: 'string',
187
+ description: 'Working directory. Defaults to project root.',
188
+ },
189
+ },
190
+ required: ['command'],
191
+ },
192
+ },
193
+ save_plan: {
194
+ name: 'save_plan',
195
+ description: 'Save an implementation plan as a markdown file in .agents/plans/.',
196
+ parameters: {
197
+ type: 'object',
198
+ properties: {
199
+ name: {
200
+ type: 'string',
201
+ description: 'Short descriptive name for the plan.',
202
+ },
203
+ content: {
204
+ type: 'string',
205
+ description: 'Full plan content in markdown. MUST be a checklist: every actionable step is a `- [ ]` checkbox (grouped under short headings) so each one can be flipped to `- [x]` in this file as it is completed.',
206
+ },
207
+ },
208
+ required: ['name', 'content'],
209
+ },
210
+ },
211
+ load_skill: {
212
+ name: 'load_skill',
213
+ description: 'Load a skill guide by name. Returns the full SKILL.md content for detailed reference on a topic.',
214
+ parameters: {
215
+ type: 'object',
216
+ properties: {
217
+ name: {
218
+ type: 'string',
219
+ description: 'Skill name (e.g. "api-patterns", "styling") or relative path to SKILL.md.',
220
+ },
221
+ },
222
+ required: ['name'],
223
+ },
224
+ },
225
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Composable system prompt builder for AI agents.
3
+ *
4
+ * Produces the coding-rules and tool-usage sections that any agent needs.
5
+ * Consumers wrap this with domain-specific sections (Synthase adds sandbox/IDE rules,
6
+ * polish pipeline adds design/ClassMap rules).
7
+ *
8
+ * @module
9
+ */
10
+ import type { ExecutionBackend, SkillEntry } from './types.js';
11
+ import type { PromptContext } from './types.js';
12
+ /**
13
+ * Re-export SkillEntry as DiscoveredSkill for backwards compatibility.
14
+ * @deprecated Use SkillEntry from types.js instead.
15
+ */
16
+ export type DiscoveredSkill = SkillEntry;
17
+ /**
18
+ * Discover skills from a project directory.
19
+ *
20
+ * Scans `.agents/skills/` and `.claude/skills/` for SKILL.md files.
21
+ * Reads the YAML frontmatter of each to extract `name:` and `description:` fields.
22
+ *
23
+ * @param backend - Execution backend to use for filesystem access
24
+ * @returns Array of discovered skills with name, description, and path
25
+ */
26
+ export declare function discoverSkills(backend: ExecutionBackend): Promise<SkillEntry[]>;
27
+ /**
28
+ * Build a coding-focused system prompt from composable sections.
29
+ *
30
+ * Returns a string that includes:
31
+ * - Agent identity
32
+ * - Available tools listing
33
+ * - Coding best practices
34
+ * - Tool argument formatting guidance
35
+ * - Project docs (if provided)
36
+ * - Discovered skills listing (if provided)
37
+ * - Inline skills (if provided)
38
+ * - Custom sections (if provided)
39
+ *
40
+ * @param ctx - Prompt construction inputs (tools, docs, skills, etc.).
41
+ * @returns Fully assembled system prompt text for the coding agent.
42
+ */
43
+ export declare function buildAgentPrompt(ctx: PromptContext): string;
44
+ //# sourceMappingURL=system-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAkB/C;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,CAAA;AAExC;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAoDrF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgE3D"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Composable system prompt builder for AI agents.
3
+ *
4
+ * Produces the coding-rules and tool-usage sections that any agent needs.
5
+ * Consumers wrap this with domain-specific sections (Synthase adds sandbox/IDE rules,
6
+ * polish pipeline adds design/ClassMap rules).
7
+ *
8
+ * @module
9
+ */
10
+ import { TOOL_SCHEMAS } from './schemas.js';
11
+ /** Tool descriptions for the prompt, keyed by tool name. */
12
+ const TOOL_DESCRIPTIONS = {
13
+ list_files: 'Browse the file tree',
14
+ read_file: 'Read any source file',
15
+ write_file: 'Create or overwrite files (full content)',
16
+ edit_file: 'Make targeted search-and-replace edits (preferred for small changes)',
17
+ search_files: 'Search for text patterns across files (grep)',
18
+ find_files: 'Find files by name/glob pattern recursively',
19
+ create_directory: 'Create directories (with parents)',
20
+ rename_file: 'Rename or move files and directories',
21
+ delete_file: 'Remove files',
22
+ exec_command: 'Run shell commands (build checks, npm, verification)',
23
+ save_plan: 'Save an implementation plan as markdown',
24
+ load_skill: 'Load a skill guide for detailed reference on a topic',
25
+ };
26
+ /**
27
+ * Discover skills from a project directory.
28
+ *
29
+ * Scans `.agents/skills/` and `.claude/skills/` for SKILL.md files.
30
+ * Reads the YAML frontmatter of each to extract `name:` and `description:` fields.
31
+ *
32
+ * @param backend - Execution backend to use for filesystem access
33
+ * @returns Array of discovered skills with name, description, and path
34
+ */
35
+ export async function discoverSkills(backend) {
36
+ const root = backend.projectRoot;
37
+ const skills = [];
38
+ const skillDirs = ['.agents/skills', '.claude/skills'];
39
+ for (const skillDir of skillDirs) {
40
+ const dirPath = `${root}/${skillDir}`;
41
+ let entries;
42
+ try {
43
+ entries = await backend.readDir(dirPath);
44
+ }
45
+ catch (_error) {
46
+ continue; // directory doesn't exist — skill dirs are optional
47
+ }
48
+ for (const entry of entries) {
49
+ if (entry.type !== 'directory')
50
+ continue;
51
+ const skillMdPath = `${dirPath}/${entry.name}/SKILL.md`;
52
+ let content;
53
+ try {
54
+ content = await backend.readFile(skillMdPath);
55
+ }
56
+ catch (_error) {
57
+ continue; // no SKILL.md in this subdirectory — individual skill files are optional
58
+ }
59
+ // Parse YAML frontmatter (--- delimited block at file start)
60
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
61
+ if (!frontmatterMatch) {
62
+ // No frontmatter — use directory name as skill name, first heading as description
63
+ const headingMatch = content.match(/^#\s+(.+)/m);
64
+ skills.push({
65
+ name: entry.name,
66
+ description: headingMatch ? headingMatch[1].trim() : entry.name,
67
+ path: `${skillDir}/${entry.name}/SKILL.md`,
68
+ });
69
+ continue;
70
+ }
71
+ const frontmatter = frontmatterMatch[1];
72
+ const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
73
+ const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
74
+ skills.push({
75
+ name: nameMatch ? nameMatch[1].trim() : entry.name,
76
+ description: descMatch ? descMatch[1].trim() : entry.name,
77
+ path: `${skillDir}/${entry.name}/SKILL.md`,
78
+ });
79
+ }
80
+ }
81
+ return skills;
82
+ }
83
+ /**
84
+ * Build a coding-focused system prompt from composable sections.
85
+ *
86
+ * Returns a string that includes:
87
+ * - Agent identity
88
+ * - Available tools listing
89
+ * - Coding best practices
90
+ * - Tool argument formatting guidance
91
+ * - Project docs (if provided)
92
+ * - Discovered skills listing (if provided)
93
+ * - Inline skills (if provided)
94
+ * - Custom sections (if provided)
95
+ *
96
+ * @param ctx - Prompt construction inputs (tools, docs, skills, etc.).
97
+ * @returns Fully assembled system prompt text for the coding agent.
98
+ */
99
+ export function buildAgentPrompt(ctx) {
100
+ const sections = [];
101
+ // Identity
102
+ sections.push(`You are ${ctx.agentName}, an AI coding agent with full access to the project at \`${ctx.projectRoot}\`.`);
103
+ // Tool listing
104
+ const toolLines = ctx.tools
105
+ .filter((name) => TOOL_DESCRIPTIONS[name] || TOOL_SCHEMAS[name])
106
+ .map((name) => `- **${name}** — ${TOOL_DESCRIPTIONS[name] || TOOL_SCHEMAS[name]?.description || ''}`);
107
+ if (toolLines.length > 0) {
108
+ sections.push(`\n## Available Tools\n\n${toolLines.join('\n')}`);
109
+ }
110
+ // Coding rules
111
+ sections.push(`
112
+ ## Coding Rules
113
+
114
+ 1. **Always read before editing.** Use read_file to understand the current content before making changes with edit_file or write_file. Never guess file contents.
115
+ 2. **Use edit_file for small changes.** When modifying a few lines in an existing file, use edit_file with precise search-and-replace. Use write_file only for new files or complete rewrites.
116
+ 3. **Implement fully.** Do not stop partway through a task. Do not describe remaining work — just do it. Do not ask "would you like me to continue?" — always continue.
117
+ 4. **Verify your changes.** After editing, use exec_command to run build checks or type-checks to catch errors immediately. Fix any errors before moving on.
118
+ 5. **Search before inventing.** Use search_files and find_files to discover existing patterns, utilities, and conventions before writing new code. Reuse what exists.
119
+ 6. **Keep changes minimal.** Fix what was asked. Do not refactor surrounding code, add comments to unchanged code, or "improve" things that weren't requested.
120
+
121
+ ## Tool Argument Formatting
122
+
123
+ When passing file content to write_file or edit_file, use real newlines in the JSON string value — NOT literal \\\\n escape sequences. Your tool arguments are JSON-parsed, so a JSON string \`"line1\\nline2"\` produces actual newlines. Never double-escape.
124
+
125
+ For edit_file: each old_string must match **exactly once** in the file. If it matches 0 times, you have the wrong string. If it matches multiple times, include more surrounding context to make it unique.`);
126
+ // Project docs
127
+ if (ctx.projectDocs) {
128
+ sections.push(`\n## Project Guidelines\n\n${ctx.projectDocs}`);
129
+ }
130
+ // Discovered skills (on-demand via load_skill)
131
+ if (ctx.discoveredSkills?.length) {
132
+ const skillLines = ctx.discoveredSkills.map((s) => `- **${s.name}** — ${s.description} \u2192 \`${s.path}\``);
133
+ sections.push(`\n## Available Skills\n\nThe project has detailed skill guides. Use \`load_skill\` to read them when relevant:\n${skillLines.join('\n')}`);
134
+ }
135
+ // Inline skills (full content injected directly)
136
+ if (ctx.skills?.length) {
137
+ sections.push(`\n## Reference\n\n${ctx.skills.join('\n\n')}`);
138
+ }
139
+ // Custom sections
140
+ if (ctx.customSections?.length) {
141
+ for (const section of ctx.customSections) {
142
+ sections.push(`\n${section}`);
143
+ }
144
+ }
145
+ return sections.join('\n');
146
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Tool factory — builds AITool[] from schemas + ExecutionBackend.
3
+ *
4
+ * Each tool's execute() delegates to the backend for I/O,
5
+ * with shared validation, path resolution, and output formatting.
6
+ *
7
+ * @module
8
+ */
9
+ import type { AITool } from '@molecule/api-ai';
10
+ import type { ExecutionBackend, ToolBuildConfig } from './types.js';
11
+ /**
12
+ * Build a complete set of AI agent tools bound to an execution backend.
13
+ *
14
+ * @param backend - The execution environment (sandbox or local filesystem)
15
+ * @param config - Optional configuration for security, callbacks, and tool selection
16
+ * @returns Array of AITool objects ready to pass to an AI provider
17
+ */
18
+ export declare function buildTools(backend: ExecutionBackend, config?: ToolBuildConfig): AITool[];
19
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAG9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAoBnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CA0nBxF"}