bash-tool 1.3.5 → 1.3.7

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
@@ -167,14 +167,80 @@ const customSandbox: Sandbox = {
167
167
  // Your implementation here
168
168
  return "";
169
169
  },
170
- async writeFile(path, content) {
171
- // Your implementation here
170
+ async writeFiles(files) {
171
+ // Your implementation here - files is Array<{path, content}>
172
172
  },
173
173
  };
174
174
 
175
175
  const { tools } = await createBashTool({ sandbox: customSandbox });
176
176
  ```
177
177
 
178
+ ## Skills (Experimental)
179
+
180
+ Skills are modular capabilities that extend agent functionality. Each skill is a directory containing a `SKILL.md` file with instructions and optional scripts.
181
+
182
+ ```typescript
183
+ import {
184
+ experimental_createSkillTool as createSkillTool,
185
+ createBashTool,
186
+ } from "bash-tool";
187
+ import { ToolLoopAgent } from "ai";
188
+
189
+ // Discover skills and get files to upload
190
+ const { loadSkill, files, instructions } = await createSkillTool({
191
+ skillsDirectory: "./skills",
192
+ });
193
+
194
+ // Create bash tool with skill files
195
+ const { tools } = await createBashTool({
196
+ files,
197
+ extraInstructions: instructions,
198
+ });
199
+
200
+ // Use both tools with an agent
201
+ const agent = new ToolLoopAgent({
202
+ model,
203
+ tools: { loadSkill, ...tools },
204
+ });
205
+ ```
206
+
207
+ ### Skill Directory Structure
208
+
209
+ ```
210
+ skills/
211
+ ├── csv/
212
+ │ ├── SKILL.md # Required: instructions with YAML frontmatter
213
+ │ ├── analyze.sh # Optional: scripts the agent can run
214
+ │ └── filter.sh
215
+ └── text/
216
+ ├── SKILL.md
217
+ └── search.sh
218
+ ```
219
+
220
+ ### SKILL.md Format
221
+
222
+ ```markdown
223
+ ---
224
+ name: csv
225
+ description: Analyze and transform CSV files
226
+ ---
227
+
228
+ # CSV Processing
229
+
230
+ Use `./skills/csv/analyze.sh <file>` to analyze a CSV file.
231
+ ```
232
+
233
+ ### How It Works
234
+
235
+ 1. `createSkillTool` discovers skills and returns:
236
+ - `loadSkill` - Tool for the agent to load a skill's instructions on demand
237
+ - `files` - All skill files to pass to `createBashTool`
238
+ - `instructions` - Extra instructions listing available skills
239
+
240
+ 2. The agent sees skill names in the `loadSkill` tool description
241
+ 3. When the agent needs a skill, it calls `loadSkill("csv")` to get detailed instructions
242
+ 4. The agent uses `bash` to run scripts from `./skills/csv/`
243
+
178
244
  ## AI Agent Instructions
179
245
 
180
246
  For AI agents working with bash-tool, additional guidance is available in `AGENTS.md`:
package/dist/AGENTS.md CHANGED
@@ -38,7 +38,7 @@ const result = await agent.generate({
38
38
  ## Key Behaviors
39
39
 
40
40
  1. **Default sandbox is just-bash** - Install `just-bash` or provide your own sandbox
41
- 2. **Working directory defaults to `./workspace`** - All files written relative to `destination`
41
+ 2. **Working directory defaults to `/workspace`** - All files written relative to `destination`
42
42
  3. **Files are written before tools are returned** - Sandbox is pre-populated
43
43
  4. **Tool descriptions include file list** - LLM sees available files in bash tool description
44
44
  5. **No `stop()` method** - Sandbox lifecycle is managed externally
@@ -83,11 +83,11 @@ const { tools } = await createBashTool({ sandbox: existingSandbox });
83
83
  const { tools } = await createBashTool({
84
84
  onBeforeBashCall: ({ command }) => {
85
85
  console.log("Running:", command);
86
- // Return modified command or undefined to proceed unchanged
86
+ return undefined; // Or return { command: modifiedCommand } to change it
87
87
  },
88
88
  onAfterBashCall: ({ command, result }) => {
89
89
  console.log(`Exit: ${result.exitCode}`);
90
- // Return modified result or undefined to proceed unchanged
90
+ return undefined; // Or return { result: modifiedResult } to change it
91
91
  },
92
92
  });
93
93
  ```
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export type { JustBashLike } from "./sandbox/just-bash.js";
2
+ export { experimental_createSkillTool } from "./skill-tool.js";
3
+ export type { CreateSkillToolOptions, DiscoveredSkill, Skill, SkillMetadata, SkillToolkit, } from "./skills/types.js";
2
4
  export { createBashTool } from "./tool.js";
3
5
  export { DEFAULT_MAX_OUTPUT_LENGTH } from "./tools/bash.js";
4
6
  export type { BashToolCategory, BashToolInfo, FileFormat, ToolPromptOptions, } from "./tools-prompt.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,OAAO,EACP,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EACV,sBAAsB,EACtB,eAAe,EACf,KAAK,EACL,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,OAAO,EACP,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { experimental_createSkillTool } from "./skill-tool.js";
1
2
  export { createBashTool } from "./tool.js";
2
3
  export { DEFAULT_MAX_OUTPUT_LENGTH } from "./tools/bash.js";
3
4
  export { bashTools, createToolPrompt, detectFormat, discoverAvailableTools, getToolsByCategory, getToolsForFormat, toolsByFormat, } from "./tools-prompt.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAO5D,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAQ/D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAO5D,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { CreateSkillToolOptions, SkillToolkit } from "./skills/types.js";
2
+ /**
3
+ * Creates a skill toolkit for AI agents.
4
+ *
5
+ * Skills are modular capabilities that extend agent functionality.
6
+ * Each skill is a directory containing a SKILL.md file with instructions
7
+ * and optional scripts/resources.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import {
12
+ * experimental_createSkillTool as createSkillTool,
13
+ * createBashTool,
14
+ * } from "bash-tool";
15
+ *
16
+ * // Discover skills and get files
17
+ * const { loadSkill, skills, files, instructions } = await createSkillTool({
18
+ * skillsDirectory: "./skills",
19
+ * });
20
+ *
21
+ * // Create bash tool with skill files
22
+ * const { tools, sandbox } = await createBashTool({
23
+ * files,
24
+ * extraInstructions: instructions,
25
+ * });
26
+ *
27
+ * // Use with AI SDK
28
+ * const result = await generateText({
29
+ * model,
30
+ * tools: { loadSkill, ...tools },
31
+ * prompt: "Process this data using the csv skill",
32
+ * });
33
+ * ```
34
+ */
35
+ export declare function experimental_createSkillTool(options: CreateSkillToolOptions): Promise<SkillToolkit>;
36
+ //# sourceMappingURL=skill-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-tool.d.ts","sourceRoot":"","sources":["../src/skill-tool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EAEtB,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAmDvB"}
@@ -0,0 +1,103 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { discoverSkills, listSkillFiles } from "./skills/parser.js";
4
+ import { createLoadSkillTool } from "./tools/load-skill.js";
5
+ const DEFAULT_DESTINATION = "skills";
6
+ /**
7
+ * Creates a skill toolkit for AI agents.
8
+ *
9
+ * Skills are modular capabilities that extend agent functionality.
10
+ * Each skill is a directory containing a SKILL.md file with instructions
11
+ * and optional scripts/resources.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import {
16
+ * experimental_createSkillTool as createSkillTool,
17
+ * createBashTool,
18
+ * } from "bash-tool";
19
+ *
20
+ * // Discover skills and get files
21
+ * const { loadSkill, skills, files, instructions } = await createSkillTool({
22
+ * skillsDirectory: "./skills",
23
+ * });
24
+ *
25
+ * // Create bash tool with skill files
26
+ * const { tools, sandbox } = await createBashTool({
27
+ * files,
28
+ * extraInstructions: instructions,
29
+ * });
30
+ *
31
+ * // Use with AI SDK
32
+ * const result = await generateText({
33
+ * model,
34
+ * tools: { loadSkill, ...tools },
35
+ * prompt: "Process this data using the csv skill",
36
+ * });
37
+ * ```
38
+ */
39
+ export async function experimental_createSkillTool(options) {
40
+ const { skillsDirectory, destination = DEFAULT_DESTINATION } = options;
41
+ // Discover all skills and collect their files
42
+ // sandboxDestination uses explicit relative path (e.g., "./skills") - works with any destination
43
+ const relativeDestination = `./${destination}`;
44
+ const discoveredSkills = await discoverSkills({
45
+ skillsDirectory,
46
+ sandboxDestination: relativeDestination,
47
+ });
48
+ // Enrich skills with file lists and collect all files
49
+ const skills = [];
50
+ const allFiles = {};
51
+ for (const skill of discoveredSkills) {
52
+ const skillFiles = await listSkillFiles(skill.localPath);
53
+ // Add to skills with file list
54
+ skills.push({
55
+ ...skill,
56
+ files: skillFiles,
57
+ });
58
+ // Read and collect all files for this skill
59
+ const skillDirName = path.basename(skill.localPath);
60
+ for (const file of skillFiles) {
61
+ const localFilePath = path.join(skill.localPath, file);
62
+ const relativeFilePath = `./${path.posix.join(destination, skillDirName, file)}`;
63
+ try {
64
+ const content = await fs.readFile(localFilePath, "utf-8");
65
+ allFiles[relativeFilePath] = content;
66
+ }
67
+ catch {
68
+ // Skip files that can't be read as text
69
+ }
70
+ }
71
+ }
72
+ // Create loadSkill tool
73
+ const loadSkill = createLoadSkillTool({ skills });
74
+ // Generate instructions for bash tool
75
+ const instructions = generateSkillInstructions(skills);
76
+ return {
77
+ loadSkill,
78
+ skills,
79
+ files: allFiles,
80
+ instructions,
81
+ };
82
+ }
83
+ /**
84
+ * Generate bash tool instructions that include skill paths.
85
+ */
86
+ function generateSkillInstructions(skills) {
87
+ if (skills.length === 0) {
88
+ return "";
89
+ }
90
+ const lines = [
91
+ "SKILL DIRECTORIES:",
92
+ "Skills are available at the following paths:",
93
+ ];
94
+ for (const skill of skills) {
95
+ lines.push(` ${skill.sandboxPath}/ - ${skill.name}: ${skill.description}`);
96
+ }
97
+ lines.push("");
98
+ lines.push("To use a skill:");
99
+ lines.push(" 1. Call loadSkill to get the skill's instructions");
100
+ lines.push(" 2. Run scripts from the skill directory with bash");
101
+ return lines.join("\n");
102
+ }
103
+ //# sourceMappingURL=skill-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-tool.js","sourceRoot":"","sources":["../src/skill-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { DiscoveredSkill, SkillMetadata } from "./types.js";
2
+ /**
3
+ * Parse YAML frontmatter from SKILL.md content using gray-matter.
4
+ */
5
+ export declare function parseFrontmatter(content: string): SkillMetadata | null;
6
+ /**
7
+ * Extract the body (instructions) from SKILL.md content.
8
+ * This is everything after the frontmatter.
9
+ */
10
+ export declare function extractBody(content: string): string;
11
+ export interface DiscoverSkillsOptions {
12
+ /** Local directory containing skill subdirectories */
13
+ skillsDirectory: string;
14
+ /** Base path in sandbox where skills will be uploaded */
15
+ sandboxDestination: string;
16
+ }
17
+ /**
18
+ * Discover all skills in a directory.
19
+ * Looks for subdirectories containing SKILL.md files.
20
+ */
21
+ export declare function discoverSkills(options: DiscoverSkillsOptions): Promise<DiscoveredSkill[]>;
22
+ /**
23
+ * Read and parse a SKILL.md file, returning both metadata and body.
24
+ */
25
+ export declare function readSkillMd(skillMdPath: string): Promise<{
26
+ metadata: SkillMetadata;
27
+ body: string;
28
+ } | null>;
29
+ /**
30
+ * List files in a skill directory (for listing available scripts).
31
+ */
32
+ export declare function listSkillFiles(skillPath: string): Promise<string[]>;
33
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/skills/parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAqBtE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,eAAe,EAAE,CAAC,CA0C5B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAgB3D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBzE"}
@@ -0,0 +1,125 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import matter from "gray-matter";
4
+ /**
5
+ * Parse YAML frontmatter from SKILL.md content using gray-matter.
6
+ */
7
+ export function parseFrontmatter(content) {
8
+ try {
9
+ const { data } = matter(content);
10
+ // Validate required fields
11
+ if (typeof data.name !== "string" ||
12
+ typeof data.description !== "string" ||
13
+ !data.name ||
14
+ !data.description) {
15
+ return null;
16
+ }
17
+ return {
18
+ name: data.name,
19
+ description: data.description,
20
+ };
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /**
27
+ * Extract the body (instructions) from SKILL.md content.
28
+ * This is everything after the frontmatter.
29
+ */
30
+ export function extractBody(content) {
31
+ try {
32
+ const { content: body } = matter(content);
33
+ return body.trim();
34
+ }
35
+ catch {
36
+ return content.trim();
37
+ }
38
+ }
39
+ /**
40
+ * Discover all skills in a directory.
41
+ * Looks for subdirectories containing SKILL.md files.
42
+ */
43
+ export async function discoverSkills(options) {
44
+ const { skillsDirectory, sandboxDestination } = options;
45
+ const skills = [];
46
+ const absoluteDir = path.resolve(skillsDirectory);
47
+ let entries;
48
+ try {
49
+ entries = await fs.readdir(absoluteDir);
50
+ }
51
+ catch (error) {
52
+ throw new Error(`Failed to read skills directory: ${absoluteDir}. ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ for (const entryName of entries) {
55
+ const skillDir = path.join(absoluteDir, entryName);
56
+ // Check if it's a directory
57
+ try {
58
+ const stat = await fs.stat(skillDir);
59
+ if (!stat.isDirectory())
60
+ continue;
61
+ }
62
+ catch {
63
+ continue;
64
+ }
65
+ const skillMdPath = path.join(skillDir, "SKILL.md");
66
+ try {
67
+ const content = await fs.readFile(skillMdPath, "utf-8");
68
+ const metadata = parseFrontmatter(content);
69
+ if (metadata) {
70
+ skills.push({
71
+ ...metadata,
72
+ localPath: skillDir,
73
+ sandboxPath: `${sandboxDestination}/${entryName}`,
74
+ });
75
+ }
76
+ }
77
+ catch { }
78
+ }
79
+ return skills;
80
+ }
81
+ /**
82
+ * Read and parse a SKILL.md file, returning both metadata and body.
83
+ */
84
+ export async function readSkillMd(skillMdPath) {
85
+ try {
86
+ const content = await fs.readFile(skillMdPath, "utf-8");
87
+ const metadata = parseFrontmatter(content);
88
+ if (!metadata) {
89
+ return null;
90
+ }
91
+ return {
92
+ metadata,
93
+ body: extractBody(content),
94
+ };
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ /**
101
+ * List files in a skill directory (for listing available scripts).
102
+ */
103
+ export async function listSkillFiles(skillPath) {
104
+ const files = [];
105
+ async function walkDir(dir, prefix = "") {
106
+ const entries = await fs.readdir(dir, { withFileTypes: true });
107
+ for (const entry of entries) {
108
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
109
+ if (entry.isDirectory()) {
110
+ await walkDir(path.join(dir, entry.name), relativePath);
111
+ }
112
+ else {
113
+ files.push(relativePath);
114
+ }
115
+ }
116
+ }
117
+ try {
118
+ await walkDir(skillPath);
119
+ }
120
+ catch {
121
+ // Return empty if directory doesn't exist
122
+ }
123
+ return files;
124
+ }
125
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/skills/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { createLoadSkillTool } from "../tools/load-skill.js";
2
+ /**
3
+ * Skill metadata parsed from SKILL.md frontmatter.
4
+ */
5
+ export interface SkillMetadata {
6
+ /** Unique skill name (lowercase, hyphens allowed) */
7
+ name: string;
8
+ /** Description of what the skill does and when to use it */
9
+ description: string;
10
+ }
11
+ /**
12
+ * Base skill info from discovery (without file list).
13
+ */
14
+ export interface DiscoveredSkill extends SkillMetadata {
15
+ /** Absolute path to the skill directory on disk */
16
+ localPath: string;
17
+ /** Path to the skill directory in the sandbox */
18
+ sandboxPath: string;
19
+ }
20
+ /**
21
+ * Full skill representation with file list.
22
+ */
23
+ export interface Skill extends DiscoveredSkill {
24
+ /** List of files in the skill directory (relative paths) */
25
+ files: string[];
26
+ }
27
+ /**
28
+ * Options for creating a skill toolkit.
29
+ */
30
+ export interface CreateSkillToolOptions {
31
+ /**
32
+ * Path to the directory containing skill subdirectories.
33
+ * Each subdirectory should contain a SKILL.md file.
34
+ * @example "./skills" or "/path/to/skills"
35
+ */
36
+ skillsDirectory: string;
37
+ /**
38
+ * Relative path within the workspace where skills will be placed.
39
+ * @default "skills"
40
+ * @example "skills" -> files at ./skills/...
41
+ */
42
+ destination?: string;
43
+ }
44
+ /**
45
+ * Return type from createSkillTool.
46
+ */
47
+ export interface SkillToolkit {
48
+ /** Tool to load a skill's instructions into context */
49
+ loadSkill: ReturnType<typeof createLoadSkillTool>;
50
+ /** Registry of discovered skills */
51
+ skills: Skill[];
52
+ /** Files to pass to createBashTool (path -> content) */
53
+ files: Record<string, string>;
54
+ /** Extra instructions to pass to createBashTool */
55
+ instructions: string;
56
+ }
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,KAAM,SAAQ,eAAe;IAC5C,4DAA4D;IAC5D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,SAAS,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;IAClD,oCAAoC;IACpC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import type { Skill } from "../skills/types.js";
2
+ export interface CreateLoadSkillToolOptions {
3
+ /** Registry of discovered skills */
4
+ skills: Skill[];
5
+ }
6
+ export declare function createLoadSkillTool(options: CreateLoadSkillToolOptions): import("ai").Tool<{
7
+ skillName: string;
8
+ }, {
9
+ success: boolean;
10
+ error: string;
11
+ skill?: undefined;
12
+ instructions?: undefined;
13
+ files?: undefined;
14
+ } | {
15
+ success: boolean;
16
+ skill: {
17
+ name: string;
18
+ description: string;
19
+ path: string;
20
+ };
21
+ instructions: string;
22
+ files: string[];
23
+ error?: undefined;
24
+ }>;
25
+ //# sourceMappingURL=load-skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-skill.d.ts","sourceRoot":"","sources":["../../src/tools/load-skill.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAMhD,MAAM,WAAW,0BAA0B;IACzC,oCAAoC;IACpC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;GAmDtE"}
@@ -0,0 +1,74 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { tool } from "ai";
4
+ import { z } from "zod";
5
+ import { extractBody } from "../skills/parser.js";
6
+ const loadSkillSchema = z.object({
7
+ skillName: z.string().describe("The name of the skill to load"),
8
+ });
9
+ function generateDescription(skills) {
10
+ const lines = [
11
+ "Load a skill's instructions to learn how to use it.",
12
+ "You can load multiple skills - each call returns that skill's instructions.",
13
+ "",
14
+ "Available skills:",
15
+ ];
16
+ if (skills.length === 0) {
17
+ lines.push(" (no skills found)");
18
+ }
19
+ else {
20
+ for (const skill of skills) {
21
+ lines.push(` - ${skill.name}: ${skill.description}`);
22
+ }
23
+ }
24
+ lines.push("");
25
+ lines.push("After loading a skill, use the bash tool to run its scripts from the skill's directory.");
26
+ return lines.join("\n");
27
+ }
28
+ export function createLoadSkillTool(options) {
29
+ const { skills } = options;
30
+ // Create a map for quick lookup
31
+ const skillMap = new Map();
32
+ for (const skill of skills) {
33
+ skillMap.set(skill.name, skill);
34
+ }
35
+ return tool({
36
+ description: generateDescription(skills),
37
+ inputSchema: loadSkillSchema,
38
+ execute: async ({ skillName }) => {
39
+ const skill = skillMap.get(skillName);
40
+ if (!skill) {
41
+ const availableNames = skills.map((s) => s.name).join(", ");
42
+ return {
43
+ success: false,
44
+ error: `Skill "${skillName}" not found. Available skills: ${availableNames || "none"}`,
45
+ };
46
+ }
47
+ // Read the SKILL.md from local filesystem
48
+ const skillMdPath = path.join(skill.localPath, "SKILL.md");
49
+ try {
50
+ const content = await fs.readFile(skillMdPath, "utf-8");
51
+ const body = extractBody(content);
52
+ // Get files list (excluding SKILL.md)
53
+ const files = skill.files.filter((f) => f !== "SKILL.md");
54
+ return {
55
+ success: true,
56
+ skill: {
57
+ name: skill.name,
58
+ description: skill.description,
59
+ path: skill.sandboxPath,
60
+ },
61
+ instructions: body,
62
+ files,
63
+ };
64
+ }
65
+ catch (error) {
66
+ return {
67
+ success: false,
68
+ error: `Failed to read skill "${skillName}": ${error instanceof Error ? error.message : String(error)}`,
69
+ };
70
+ }
71
+ },
72
+ });
73
+ }
74
+ //# sourceMappingURL=load-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-skill.js","sourceRoot":"","sources":["../../src/tools/load-skill.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -22,7 +22,7 @@ export interface BeforeBashCallInput {
22
22
  }
23
23
  /**
24
24
  * Output from onBeforeBashCall callback.
25
- * Return undefined or the original input to proceed unchanged.
25
+ * Return nothing to proceed unchanged.
26
26
  */
27
27
  export interface BeforeBashCallOutput {
28
28
  /** The (potentially modified) command to execute */
@@ -39,7 +39,7 @@ export interface AfterBashCallInput {
39
39
  }
40
40
  /**
41
41
  * Output from onAfterBashCall callback.
42
- * Return undefined or the original result to proceed unchanged.
42
+ * Return nothing to proceed unchanged.
43
43
  */
44
44
  export interface AfterBashCallOutput {
45
45
  /** The (potentially modified) result */
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.3.5",
6
+ "version": "1.3.7",
7
7
  "description": "Generic bash tool for AI agents, compatible with AI SDK",
8
8
  "type": "module",
9
9
  "main": "dist/index.js",
@@ -44,14 +44,15 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "fast-glob": "^3.3.2",
47
+ "gray-matter": "^4.0.3",
47
48
  "zod": "^3.23.8"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@biomejs/biome": "^2.3.11",
51
52
  "@types/node": "^22.10.0",
52
- "@vercel/sandbox": "^1.1.6",
53
+ "@vercel/sandbox": "^1.2.0",
53
54
  "ai": "^6.0.13",
54
- "just-bash": "^2.5.0",
55
+ "just-bash": "^2.5.1",
55
56
  "knip": "^5.80.0",
56
57
  "typescript": "^5.7.0",
57
58
  "vitest": "^2.1.0"
@@ -69,10 +70,9 @@
69
70
  "optional": true
70
71
  }
71
72
  },
72
- "packageManager": "pnpm@8.15.9+sha512.499434c9d8fdd1a2794ebf4552b3b25c0a633abcee5bb15e7b5de90f32f47b513aca98cd5cfd001c31f0db454bc3804edccd578501e4ca293a6816166bbd9f81",
73
73
  "scripts": {
74
74
  "build": "tsc -p tsconfig.build.json && sed '1,/^-->/d' AGENTS.npm.md > dist/AGENTS.md",
75
- "typecheck": "tsc --noEmit",
75
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.examples.json",
76
76
  "test": "vitest --exclude 'src/tool.vercel.integration.test.ts'",
77
77
  "test:run": "vitest run --exclude 'src/tool.vercel.integration.test.ts'",
78
78
  "test:vercel": "vitest run src/tool.vercel.integration.test.ts --sequence.concurrent",
@@ -80,6 +80,6 @@
80
80
  "lint:fix": "biome check --write .",
81
81
  "format": "biome format --write .",
82
82
  "knip": "knip",
83
- "validate": "pnpm run lint && pnpm run knip && pnpm run typecheck && pnpm run test:run"
83
+ "validate": "pnpm run lint && pnpm run knip && pnpm run typecheck && pnpm run build && pnpm run test:run"
84
84
  }
85
85
  }